一、线性表简介
线性表简单地说就是数据元素的序列,即一对一关系;
二、ArrayList简单实现
读取:O(1)
插入、删除:O(n)
代码实现:
package org.xiazdong.list; public class MyArrayList<T> { private static final int DEFAULT_LENGTH = 10; private T[]t; private int length; public MyArrayList(){ t = (T[])new Object[DEFAULT_LENGTH]; length = 0; } public MyArrayList(int length){ t = (T[])new Object[length]; length = 0; } public MyArrayList(T[]arr){ this(arr.length*2); for(int i=0;i<arr.length;i++){ t[i] = arr[i]; } } public boolean isEmpty(){ return length == 0; } public void makeEmpty(){ t = (T[])new Object[t.length]; length = 0; } public T get(int i)throws ArrayIndexOutOfBoundsException{ if(i<0||i>=length){ throw new ArrayIndexOutOfBoundsException("数组越界"); } else{ return t[i]; } } public boolean contains(T e){ for(T elem:t){ if(elem.equals(e)){ return true; } } return false; } public boolean insert(T e){ if(e==null){ return false; } //如果容量不够,则扩充 if(length>=t.length){ larger(length*2); } t[length++] = e; return true; } public boolean remove(T e){ int pos = -1; for(int i=0;i<length;i++){ if(t[i].equals(e)){ pos = i; } } if(pos == -1){ return false; } else{ for(int j=pos;j<length-1;j++){ t[j] = t[j+1]; t[j+1] = null; } length--; return true; } } public boolean remove(int i){ if(i<0||i>=length){ throw new ArrayIndexOutOfBoundsException(); } else{ for(int j=i;j<length-1;j++){ t[j]= t[j+1]; t[j+1] = null; } length--; return true; } } public boolean insert(int i,T e){ if(i<0||i>length){ throw new ArrayIndexOutOfBoundsException(); } if(length>=t.length){ larger(length*2); } for(int j=t.length-1;j>=i;j--){ t[j+1]= t[j]; } t[i] = e; length++; return true; } private void larger(int len){ T[]tmp = (T[])new Object[len]; for(int i=0;i<t.length;i++){ tmp[i] = t[i]; } t = tmp; } public String toString(){ StringBuilder buf = new StringBuilder(); for(int i=0;i<length;i++){ buf.append(t[i]).append(" "); } return buf.toString(); } public int find(T e){ for(int i=0;i<length;i++){ if(t[i].equals(e)){ return i; } } return -1; } public int getSize(){ return length; } }
三、LinkedList简单实现
读取:O(n)
插入、删除:O(1)
头指针:第一个节点的存储地址;
头结点:在第一个数据节点前添加一个头结点,可以存储链表的长度,为了方便链表操作,因为比如:
代码实现:
package org.xiazdong.list; /** * * * * @author xzdong * * @param <T> */ public class MyLinkedList<T> { /** * first.elem存储链表长度 */ private BeginNode first; public MyLinkedList(){ first = new BeginNode(0,null); } public void insert(T elem){ Node n = new Node(elem,null); Node current = first; while(current.next!=null){ current = current.next; } current.next = n; first.elem++; } public void insert(int i,T elem){ if(i<0||i>first.elem){ throw new ArrayIndexOutOfBoundsException(); } Node current = first; Node n = new Node(elem,null); int count = 0; while(current.next!=null&&count<i){ current = current.next; count++; } n.next = current.next; current.next = n; first.elem++; } public boolean remove(int i,T elem){ if(first.elem==0){ return false; } if(i<0||i>first.elem){ throw new ArrayIndexOutOfBoundsException(); } //1.找到位置 Node current = first; int count = 0; while(current.next!=null&&count<i){ current = current.next; count++; } //2.模版代码 current.next = current.next.next; first.elem--; return true; } public boolean isEmpty(){ return first.elem==0; } public void makeEmpty(){ first.next=null; } public int getSize(){ return first.elem; } public int find(T elem){ Node current = first; int index = 0; while(current.next!=null){ current = current.next; if(current.elem.equals(elem)){ return index; } else{ index++; } } return -1; } public boolean remove(T elem){ if(first.elem==0){ return false; } Node current = first.next; Node beforeCurrent = first; while(!current.elem.equals(elem)){ if(current.next==null){ return false; } beforeCurrent = current; current = current.next; } if(current.elem.equals(elem)){ beforeCurrent.next = current.next; first.elem--; return true; } else{ return false; } } public T get(int i){ if(i<0||i>first.elem){ throw new ArrayIndexOutOfBoundsException(); } int count = 0; Node current = first; while(current.next!=null&&count<i){ current = current.next; count++; } return current.next.elem; } public String toString(){ StringBuilder buf = new StringBuilder(); if(first.elem==0){ return ""; } Node current = first.next; while(current!=null){ buf.append(current.elem).append(" "); current = current.next; } return buf.toString(); } class Node{ public Node(){ elem = null; next = null; } public Node(T elem,Node next){ this.elem = elem; this.next = next; } private T elem; Node next; } class BeginNode extends Node{ int elem; public BeginNode(int elem,Node next){ this.elem = elem; this.next = next; } } }
四、两种实现的比较
数组实现 | 链表实现 | |
优点 | 读取快 | 不需要预先分配、插入删除方便 |
缺点 | 预先分配大小、插入删除麻烦 | 读取慢 |
循环链表实现
循环链表就是尾指针指向头指针,形成一个循环;
代码实现:
package org.xiazdong.list; /** * * * * @author xzdong * * @param <T> */ public class MyCircularLinkedList<T> { /** * first.elem存储链表长度 */ private BeginNode first; public MyCircularLinkedList(){ first = new BeginNode(0,null); first.next = first; } public void insert(T elem){ Node n = new Node(elem,first); Node current = first; while(current.next!=first){ current = current.next; } current.next = n; first.elem++; } public void insert(int i,T elem){ if(i<0||i>first.elem){ throw new ArrayIndexOutOfBoundsException(); } Node current = first; Node n = new Node(elem,null); int count = 0; while(current.next!=null&&count<i){ current = current.next; count++; } n.next = current.next; current.next = n; first.elem++; } public boolean remove(int i,T elem){ if(first.elem==0){ return false; } if(i<0||i>first.elem){ throw new ArrayIndexOutOfBoundsException(); } //1.找到位置 Node current = first; int count = 0; while(current.next!=first&&count<i){ current = current.next; count++; } //2.模版代码 current.next = current.next.next; first.elem--; return true; } public boolean isEmpty(){ return first.elem==0; } public void makeEmpty(){ first.next=first; } public int getSize(){ return first.elem; } public int find(T elem){ Node current = first; int index = 0; while(current.next!=first){ current = current.next; if(current.elem.equals(elem)){ return index; } else{ index++; } } return -1; } public boolean remove(T elem){ if(first.elem==0){ return false; } Node current = first.next; Node beforeCurrent = first; while(!current.elem.equals(elem)){ if(current.next==first){ return false; } beforeCurrent = current; current = current.next; } if(current.elem.equals(elem)){ beforeCurrent.next = current.next; first.elem--; return true; } else{ return false; } } public T get(int i){ if(i<0||i>first.elem){ throw new ArrayIndexOutOfBoundsException(); } int count = 0; Node current = first; while(current.next!=first&&count<i){ current = current.next; count++; } return current.next.elem; } public String toString(){ StringBuilder buf = new StringBuilder(); if(first.elem==0){ return ""; } Node current = first.next; while(current!=first){ buf.append(current.elem).append(" "); current = current.next; } return buf.toString(); } class Node{ public Node(){ elem = null; next = null; } public Node(T elem,Node next){ this.elem = elem; this.next = next; } private T elem; Node next; } class BeginNode extends Node{ int elem; public BeginNode(int elem,Node next){ this.elem = elem; this.next = next; } } }
双向链表介绍
在单链表的基础上,每个节点增加pre指针,指向前驱;