如果为每个节点保留两个引用prev和next,让prev指向当前节点的前驱,next指向后驱,即构成了双向链表
1:双向链表查找
可以从前查找,也可以从后查找,到底应该选择哪一个,我们可以通过index的值判断它更接近header还是tail,一般来讲,如果index<size/2,可以判断位置更靠近header,应该从header处开始查找
2:插入
和单链表相似,只不过每次要修改两个方向的指针。
3:删除
1 package consume; 2 3 public class DuLinkList <T>{ 4 //Node节点 5 private class Node{ 6 private T element;//元素 7 private Node prev;//前驱 8 private Node next;//后驱 9 public Node(){ 10 11 } 12 public Node(T element,Node prev,Node next){ 13 this.element=element; 14 this.prev=prev; 15 this.next=next; 16 } 17 } 18 private Node header;//头结点 19 private Node tail;//尾节点 20 private int size;//节点数 21 public DuLinkList(){ 22 header=null; 23 tail=null; 24 } 25 public DuLinkList(T element){ 26 header=new Node(element, null, null); 27 tail=header; 28 size++; 29 } 30 //获取节点数 31 public int length(){ 32 return size; 33 } 34 //取索引为index的节点 35 public Node getNodeByIndex(int index){ 36 if(index<0||index>size-1){ 37 throw new IndexOutOfBoundsException("越界"); 38 } 39 if(index<=size/2){ 40 Node current=header; 41 for(int i=0;i<=size/2&¤t!=null;i++,current=current.next){ 42 if(i==index){ 43 return current; 44 } 45 } 46 }else{ 47 Node current=tail; 48 for(int i=size-1;i>size/2&¤t!=null;i--,current=current.prev){ 49 if(i==index){ 50 return current; 51 } 52 } 53 } 54 return null; 55 } 56 //得到索引为index的值 57 public T get(int index){ 58 return getNodeByIndex(index).element;//调用上一个方法 59 } 60 //得到职位element的索引 61 public int locate(T element){ 62 Node current=header; 63 for(int i=0;i<size&¤t!=null;i++,current=current.next){ 64 if(current.element.equals(element)){ 65 return i; 66 } 67 } 68 return -1; 69 } 70 //插入 71 public void insert(T element,int index){ 72 //当为空链表时,尾插法 73 if(header==null){ 74 add(element); 75 }else{ 76 //在头插入 77 if(index==0){ 78 addAtHeader(element);//头插法 79 }else{ 80 Node prev=getNodeByIndex(index-1);//获取插入位置的上一个节点 81 Node next=prev.next;//即将插入的下一个节点 82 Node newNode=new Node(element, prev, next); 83 prev.next=newNode; 84 next.prev=newNode; 85 size++; 86 } 87 } 88 } 89 //尾差法 90 public void add(T element){ 91 if(header==null){ 92 header=new Node(element,null,null); 93 tail=header; 94 }else{ 95 Node newNode=new Node(element,tail,null); 96 tail.next=newNode; 97 tail=newNode; 98 } 99 size++; 100 } 101 //头插法 102 public void addAtHeader(T element){ 103 header=new Node(element, null, header); 104 if(tail==null){ 105 tail=header; 106 } 107 size++; 108 } 109 //删除 110 public T delete(int index){ 111 if(index<0||index>size-1){ 112 throw new IndexOutOfBoundsException("越界"); 113 } 114 Node del=null; 115 if(index==0){ 116 del=header; 117 header=header.next; 118 header.prev=null; 119 }else{ 120 Node prev=getNodeByIndex(index-1); 121 del=prev.next; 122 prev.next=del.next; 123 del.next.prev=prev; 124 del.prev=null; 125 del.next=null; 126 } 127 size--; 128 return del.element; 129 } 130 public T remove(){ 131 return delete(size-1); 132 } 133 public boolean empty(){ 134 return size==0; 135 } 136 public void clear(){ 137 header=null; 138 tail=null; 139 size=0; 140 } 141 }