一.双向链式存储: node
①简述:要是节点中包含两个指针部分,一个指向前驱元,一个指向后继元,Java中LinkedList集合类的实现就是双向链表网络
(如下图片为网络收集,侵删)this
②特色:数据是非连续的,链表的运输必须从头指针开始;spa
③单链表相关操做:指针
A.插入操做code
B.删除操做blog
④代码实现: 索引
1 public class DoubleLinkedList<T> { 2 3 private int size;//链表大小 4 //因为是双向,头尾任意选择一端便可 5 private Node<T> head;//链表的头节点 6 private Node<T> tail;//链表的尾节点 7 8 /** 9 * 内部类:节点 10 * @param <T> 11 */ 12 public static class Node<T>{ 13 private Node prev; 14 private Node next; 15 private T data; 16 17 public Node(T data){ 18 this.data = data; 19 } 20 21 private Node(){} 22 } 23 24 /** 25 * 添加到链尾 26 * @param data 27 */ 28 public void add(T data){ 29 add(size, data); 30 } 31 32 /** 33 * 添加到任意index处 34 * @param index 35 * @param data 36 */ 37 public void add(int index, T data){ 38 Node<T> node = new Node<>(data); 39 if(isEmpty()){//链表为空 40 head = node; 41 tail = node; 42 }else { 43 if(index > size - 1){//索引超出当前链表大小,则添加到链尾 44 Node<T> temp = tail; 45 tail = node; 46 temp.next = tail; 47 tail.prev = temp; 48 }else {//原index位置处有值,索引位置大于index的元素向链尾移动(实际并非移动,只是看上去) 49 Node<T> origin = getNode(index); 50 Node<T> prev = origin.prev; 51 prev.next = node; 52 node.prev = prev; 53 node.next = origin; 54 origin.prev = node; 55 } 56 } 57 58 size++; 59 } 60 61 /** 62 * 更新index位置处元素的值 63 * @param index 64 * @param data 65 */ 66 public void set(int index, T data){ 67 if(index > size - 1 || index < 0){ 68 throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); 69 } 70 getNode(index).data = data; 71 } 72 73 /** 74 * 删除index位置处的元素 75 * @param index 76 */ 77 public void delete(int index){ 78 if(index > size - 1 || index < 0){ 79 throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); 80 } 81 if(index == 0){//删除链头 82 head = head.next; 83 head.prev = null; 84 }else if(index == size -1){//删除链尾 85 tail = tail.prev; 86 tail.next = null; 87 }else {//普通节点 88 Node<T> node = getNode(index); 89 Node prev = node.prev; 90 Node next = node.next; 91 prev.next = next; 92 next.prev = prev; 93 node.prev = null; 94 node.next = null; 95 } 96 size--; 97 } 98 99 /** 100 * 获取index位置处的元素的值 101 * @param index 102 * @return 103 */ 104 public T getValue(int index){ 105 return getNode(index) == null ? null : getNode(index).data; 106 } 107 108 public T getValue(Node<T> node){ 109 return node == null ? null : node.data; 110 } 111 112 /** 113 * 获取节点node的上一个节点 114 * @param node 115 * @return 116 */ 117 public Node<T> getPrevNode(Node<T> node){ 118 return node == null ? null : node.prev; 119 } 120 121 /** 122 * 获取节点node的下一个节点 123 * @param node 124 * @return 125 */ 126 public Node<T> getNextNode(Node<T> node){ 127 return node == null ? null : node.next; 128 } 129 130 public Node<T> getHeadNode(){ 131 return head; 132 } 133 134 public Node<T> getTailNode(){ 135 return tail; 136 } 137 138 /** 139 * 获取index位置处的元素 140 * @param index 141 * @return 142 */ 143 public Node<T> getNode(int index){ 144 145 if (isEmpty() && (index > size - 1)) { 146 throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); 147 } 148 Node<T> result = head; 149 int n = 0; 150 while (n < index) {//注意这里是 n < index, 而不是n <= index 151 result = result.next; 152 n++; 153 } 154 return result; 155 } 156 157 /** 158 * 获取值为data的元素在链表中的位置(第一次出现的位置,可能含有多个) 159 * @param data 160 * @return 161 */ 162 public int indexOf(T data){ 163 if(isEmpty() || data == null){ 164 return -1; 165 } 166 167 int n = 0; 168 Node<T> node = head; 169 while (n < size){ 170 if(data.equals(node.data)){ 171 return n; 172 } 173 n++; 174 } 175 176 return -1; 177 } 178 179 /** 180 * 判断是否有值为data的元素 181 * @param data 182 * @return 183 */ 184 public boolean containValue(T data){ 185 return indexOf(data) != -1; 186 } 187 188 /** 189 * 获取链表的大小 190 * @return 191 */ 192 public int size(){ 193 return size; 194 } 195 196 /** 197 * 判断链表是否为空 198 * @return 199 */ 200 public boolean isEmpty(){ 201 return size == 0; 202 } 203 204 205 }