一、鏈表:
二、鏈表的兩種實現:
1.不適用虛擬頭節點
不用虛擬頭節點在添加元素的操作上要單獨考慮在鏈表的頭添加元素。而加了虛擬頭節點可以統一處理,關鍵是要找到要添加節點的前一個節點
1 public class LinkedList<E> { 2 3 private class Node{ 4 public E e; 5 public Node next; 6 7 public Node(E e, Node next){ 8 this.e = e; 9 this.next = next; 10 } 11 12 public Node(E e){ 13 this(e, null); 14 } 15 16 public Node(){ 17 this(null, null); 18 } 19 20 @Override 21 public String toString(){ 22 return e.toString(); 23 } 24 } 25 26 private Node head; 27 private int size; 28 29 public LinkedList(){ 30 head = null; 31 size = 0; 32 } 33 34 // 獲取鏈表中的元素個數 35 public int getSize(){ 36 return size; 37 } 38 39 // 返回鏈表是否為空 40 public boolean isEmpty(){ 41 return size == 0; 42 } 43 44 // 在鏈表頭添加新的元素e 45 public void addFirst(E e){ 46 // Node node = new Node(e); 47 // node.next = head; 48 // head = node; 49 50 head = new Node(e, head); 51 size ++; 52 } 53 54 // 在鏈表的index(0-based)位置添加新的元素e 55 // 在鏈表中不是一個常用的操作,練習用:) 56 public void add(int index, E e){ 57 58 if(index < 0 || index > size) 59 throw new IllegalArgumentException("Add failed. Illegal index."); 60 61 if(index == 0) 62 addFirst(e); 63 else{ 64 Node prev = head; 65 for(int i = 0 ; i < index - 1 ; i ++) 66 prev = prev.next; 67 68 // Node node = new Node(e); 69 // node.next = prev.next; 70 // prev.next = node; 71 72 prev.next = new Node(e, prev.next); 73 size ++; 74 } 75 } 76 77 // 在鏈表末尾添加新的元素e 78 public void addLast(E e){ 79 add(size, e); 80 } 81 }
2.使用虛擬頭節點
(今后所有的鏈表操作都使用虛擬頭節點)
1 public class LinkedList<E> { 2 3 private class Node{ 4 public E e; 5 public Node next; 6 7 public Node(E e, Node next){ 8 this.e = e; 9 this.next = next; 10 } 11 12 public Node(E e){ 13 this(e, null); 14 } 15 16 public Node(){ 17 this(null, null); 18 } 19 20 @Override 21 public String toString(){ 22 return e.toString(); 23 } 24 } 25 26 private Node dummyHead; 27 private int size; 28 29 public LinkedList(){ 30 dummyHead = new Node(); 31 size = 0; 32 } 33 34 // 獲取鏈表中的元素個數 35 public int getSize(){ 36 return size; 37 } 38 39 // 返回鏈表是否為空 40 public boolean isEmpty(){ 41 return size == 0; 42 } 43 44 // 在鏈表的index(0-based)位置添加新的元素e 45 // 在鏈表中不是一個常用的操作,練習用:) 46 public void add(int index, E e){ 47 48 if(index < 0 || index > size) 49 throw new IllegalArgumentException("Add failed. Illegal index."); 50 51 Node prev = dummyHead; 52 for(int i = 0 ; i < index ; i ++) 53 prev = prev.next; 54 55 prev.next = new Node(e, prev.next); 56 size ++; 57 } 58 59 // 在鏈表頭添加新的元素e 60 public void addFirst(E e){ 61 add(0, e); 62 } 63 64 // 在鏈表末尾添加新的元素e 65 public void addLast(E e){ 66 add(size, e); 67 } 68 69 // 獲得鏈表的第index(0-based)個位置的元素 70 // 在鏈表中不是一個常用的操作,練習用:) 71 public E get(int index){ 72 73 if(index < 0 || index >= size) 74 throw new IllegalArgumentException("Get failed. Illegal index."); 75 76 Node cur = dummyHead.next; 77 for(int i = 0 ; i < index ; i ++) 78 cur = cur.next; 79 return cur.e; 80 } 81 82 // 獲得鏈表的第一個元素 83 public E getFirst(){ 84 return get(0); 85 } 86 87 // 獲得鏈表的最后一個元素 88 public E getLast(){ 89 return get(size - 1); 90 } 91 92 // 修改鏈表的第index(0-based)個位置的元素為e 93 // 在鏈表中不是一個常用的操作,練習用:) 94 public void set(int index, E e){ 95 if(index < 0 || index >= size) 96 throw new IllegalArgumentException("Set failed. Illegal index."); 97 98 Node cur = dummyHead.next; 99 for(int i = 0 ; i < index ; i ++) 100 cur = cur.next; 101 cur.e = e; 102 } 103 104 // 查找鏈表中是否有元素e 105 public boolean contains(E e){ 106 Node cur = dummyHead.next; 107 while(cur != null){ 108 if(cur.e.equals(e)) 109 return true; 110 cur = cur.next; 111 } 112 return false; 113 } 114 115 @Override 116 public String toString(){ 117 StringBuilder res = new StringBuilder(); 118 119 // Node cur = dummyHead.next; 120 // while(cur != null){ 121 // res.append(cur + "->"); 122 // cur = cur.next; 123 // } 124 for(Node cur = dummyHead.next ; cur != null ; cur = cur.next) 125 res.append(cur + "->"); 126 res.append("NULL"); 127 128 return res.toString(); 129 } 130 }
三、鏈表的增、刪、查、改、遍歷
1 public class LinkedList<E> { 2 3 private class Node{ 4 public E e; 5 public Node next; 6 7 public Node(E e, Node next){ 8 this.e = e; 9 this.next = next; 10 } 11 12 public Node(E e){ 13 this(e, null); 14 } 15 16 public Node(){ 17 this(null, null); 18 } 19 20 @Override 21 public String toString(){ 22 return e.toString(); 23 } 24 } 25 26 private Node dummyHead; 27 private int size; 28 29 public LinkedList(){ 30 dummyHead = new Node(); 31 size = 0; 32 } 33 34 // 獲取鏈表中的元素個數 35 public int getSize(){ 36 return size; 37 } 38 39 // 返回鏈表是否為空 40 public boolean isEmpty(){ 41 return size == 0; 42 } 43 44 // 在鏈表的index(0-based)位置添加新的元素e 45 // 在鏈表中不是一個常用的操作,練習用:) 46 public void add(int index, E e){ 47 48 if(index < 0 || index > size) 49 throw new IllegalArgumentException("Add failed. Illegal index."); 50 51 Node prev = dummyHead; 52 for(int i = 0 ; i < index ; i ++) 53 prev = prev.next; 54 55 prev.next = new Node(e, prev.next); 56 size ++; 57 } 58 59 // 在鏈表頭添加新的元素e 60 public void addFirst(E e){ 61 add(0, e); 62 } 63 64 // 在鏈表末尾添加新的元素e 65 public void addLast(E e){ 66 add(size, e); 67 } 68 69 // 獲得鏈表的第index(0-based)個位置的元素 70 // 在鏈表中不是一個常用的操作,練習用:) 71 public E get(int index){ 72 73 if(index < 0 || index >= size) 74 throw new IllegalArgumentException("Get failed. Illegal index."); 75 76 Node cur = dummyHead.next; 77 for(int i = 0 ; i < index ; i ++) 78 cur = cur.next; 79 return cur.e; 80 } 81 82 // 獲得鏈表的第一個元素 83 public E getFirst(){ 84 return get(0); 85 } 86 87 // 獲得鏈表的最后一個元素 88 public E getLast(){ 89 return get(size - 1); 90 } 91 92 // 修改鏈表的第index(0-based)個位置的元素為e 93 // 在鏈表中不是一個常用的操作,練習用:) 94 public void set(int index, E e){ 95 if(index < 0 || index >= size) 96 throw new IllegalArgumentException("Set failed. Illegal index."); 97 98 Node cur = dummyHead.next; 99 for(int i = 0 ; i < index ; i ++) 100 cur = cur.next; 101 cur.e = e; 102 } 103 104 // 查找鏈表中是否有元素e 105 public boolean contains(E e){ 106 Node cur = dummyHead.next; 107 while(cur != null){ 108 if(cur.e.equals(e)) 109 return true; 110 cur = cur.next; 111 } 112 return false; 113 } 114 115 // 從鏈表中刪除index(0-based)位置的元素, 返回刪除的元素 116 // 在鏈表中不是一個常用的操作,練習用:) 117 public E remove(int index){ 118 if(index < 0 || index >= size) 119 throw new IllegalArgumentException("Remove failed. Index is illegal."); 120 121 Node prev = dummyHead; 122 for(int i = 0 ; i < index ; i ++) 123 prev = prev.next; 124 125 Node retNode = prev.next; 126 prev.next = retNode.next; 127 retNode.next = null; 128 size --; 129 130 return retNode.e; 131 } 132 133 // 從鏈表中刪除第一個元素, 返回刪除的元素 134 public E removeFirst(){ 135 return remove(0); 136 } 137 138 // 從鏈表中刪除最后一個元素, 返回刪除的元素 139 public E removeLast(){ 140 return remove(size - 1); 141 } 142 143 // 從鏈表中刪除元素e 144 public void removeElement(E e){ 145 146 Node prev = dummyHead; 147 while(prev.next != null){ 148 if(prev.next.e.equals(e)) 149 break; 150 prev = prev.next; 151 } 152 153 if(prev.next != null){ 154 Node delNode = prev.next; 155 prev.next = delNode.next; 156 delNode.next = null; 157 size --; 158 } 159 } 160 161 @Override 162 public String toString(){ 163 StringBuilder res = new StringBuilder(); 164 165 Node cur = dummyHead.next; 166 while(cur != null){ 167 res.append(cur + "->"); 168 cur = cur.next; 169 } 170 res.append("NULL"); 171 172 return res.toString(); 173 } 174 }
四、時間復雜度分析