1,使用Node内部类来表示单链表的节点,这样就不需要为Node类的字段添加get方法和set方法就能访问这些字段,要知道内部类的这个用法。
2,public boolean deleteByElement(T element) 该方法删除链表中第一个元素值为element的元素。在该类结构下,这个方法实在是不好实现。
3,判断链表是否为空时,使用了断言,这样更能找到程序中的逻辑错误。如,链表为空,但 size 不为 0 的情况。
1 public class LinkList<T> { 2 private class Node{ 3 private T data; 4 private Node next; 5 private Node(){ 6 7 } 8 private Node(T data, Node next){ 9 this.data = data; 10 this.next = next; 11 } 12 } 13 14 private Node header;//保存链表的头结点 15 private Node tail;//保存链表的尾结点,采用尾插法添加结点时,不需要遍历整个链表 16 private int size;//保存链表中已包含的节点数 17 18 public LinkList(){ 19 header = tail = null; 20 } 21 public LinkList(T element){ 22 header = new Node(element, null); 23 tail = header; 24 size++; 25 } 26 27 public int length(){ 28 return size; 29 } 30 31 //获得索引为index处的元素值,注意:索引从0开始 32 public T get(int index){ 33 return getNodeByIndex(index).data; 34 } 35 private Node getNodeByIndex(int index){ 36 if(index < 0 || index > size - 1) 37 throw new IndexOutOfBoundsException("单链表越界"); 38 Node current = header; 39 for(int i = 0; (i < size) && (current != null); i++, current = current.next) 40 if(i == index) 41 return current; 42 return null; 43 } 44 45 //返回链表中指定元素的索引,若指定元素不存在,返回-1 46 public int locate(T element){ 47 Node current = header; 48 for(int i = 0; i < size && current != null; i++, current = current.next) 49 if(current.data.equals(element)) 50 return i; 51 return -1; 52 } 53 54 public void insert(T element, int index){ 55 if(index < 0 || index > size) 56 throw new IndexOutOfBoundsException("单链表索引越界"); 57 if(header == null)//链表是空链表时 58 add(element); 59 else{ 60 if(index == 0)//在表头插入 61 addAtHeader(element); 62 else{ 63 Node prev = getNodeByIndex(index - 1);//获取插入结点的前驱 64 prev.next = new Node(element, prev.next); 65 size++; 66 } 67 } 68 } 69 70 //采用尾插法为链表增加新节点 71 public void add(T element){ 72 if(header == null){ 73 header = new Node(element, null); 74 tail = header; 75 } 76 else{ 77 Node newNode = new Node(element, null); 78 tail.next = newNode; 79 tail = newNode; 80 } 81 size++; 82 } 83 84 //采用头插法为链表增加新节点 85 public void addAtHeader(T element){ 86 header = new Node(element, header);//新建的结点的next 需要指向 header结点 87 if(tail == header)//如果插入之前是空链表 88 tail = header; 89 size++; 90 } 91 92 public T delete(int index){ 93 if(index < 0 || index > size - 1) 94 throw new IndexOutOfBoundsException("链表索引越界"); 95 Node del; 96 //待删除的是header节点 97 if(index == 0){ 98 del = header; 99 header = header.next; 100 } 101 else{ 102 Node prev = getNodeByIndex(index - 1);//获取待删节点的前驱 103 del = prev.next;//del 指向待删除的节点 104 prev.next = del.next; 105 } 106 del.next = null;//将待删节点从链表中脱离出去 107 size--; 108 return del.data; 109 } 110 111 //根据指定的元素来删除节点 112 public boolean deleteByElement(T element){ 113 //链表为空 114 if(empty()){ 115 return false; 116 } 117 //待删元素为第一个元素 118 else if(header.data.equals(element)){ 119 Node del = header; 120 header = header.next; 121 if(tail == header)//说明整个链表中只有一个元素,tail也应当置null 122 tail = null; 123 del.next = null; 124 size --; 125 return true; 126 } 127 //待删元素为链表中其他元素 128 else{ 129 Node del = header.next; 130 Node prev = header; 131 while(del != null){ 132 if(del.data.equals(element)){ 133 if(tail == del)//如果待删元素是最后一个元素,需要将tail指针指向其前驱 134 tail = prev; 135 prev.next = del.next; 136 del.next = null; 137 size--; 138 return true; 139 } 140 //若没有找到element,则继续下一轮的循环 141 prev = del; 142 del = del.next; 143 } 144 return false; 145 } 146 } 147 148 //删除链表中的最后一个元素 149 public T remove(){ 150 return delete(size - 1); 151 } 152 153 //判断链表是否为空 154 public boolean empty(){ 155 boolean result; 156 if(size == 0){ 157 assert header == null;//当出现链表为空,但size不为0时,使用断言能够帮助找到逻辑错误 158 result = true; 159 } 160 else{ 161 assert header != null; 162 result = false; 163 } 164 return result; 165 //return size == 0; 166 } 167 168 //清空链表 169 public void clear(){ 170 header = tail = null; 171 size = 0; 172 } 173 174 public String toString(){ 175 if(empty()) 176 return "[]"; 177 else{ 178 StringBuilder sb = new StringBuilder("["); 179 for(Node current = header; current != null; current = current.next) 180 sb.append(current.data.toString() + ", "); 181 int len = sb.length(); 182 //注意删除最后添加的两个多余的字符 183 return sb.delete(len - 2, len).append("]").toString(); 184 } 185 } 186 }