因为在学习数据结构,准备把java的集合框架底层源码,好好的过一遍,所以先按照自己的想法把单链表的类给写出来了;
写该类的目的:
1.练习递归
2.为深入理解java集合框架底层源码打好基础
学习的视频看的慕课网liuyubobo老师的课程:Java玩转数据结构 从入门到进阶
废话不多说,一下为源代码:
1 public class LinkedList<E extends Comparable<E>> { 2 //链表节点内部类 3 private class Node{ 4 E e; 5 Node next; 6 public Node(E _e,Node _next){ 7 this.e = _e; 8 this.next = _next; 9 } 10 public Node(E _e){ 11 this(_e, null); 12 } 13 public Node(){ 14 this(null, null); 15 } 16 } 17 //头节点 18 private Node head; 19 //链表实际存储大小 20 private int size; 21 //无参构造函数 22 public LinekedList(){ 23 this.head = null; 24 this.size = 0; 25 } 26 //判断链表是否为空 27 public boolean isEmpty(){ 28 return this.size == 0; 29 } 30 public int size(){ 31 return this.size; 32 } 33 //在链表头添加节点 34 public void addFirst(E e){ 35 add(0, e); 36 } 37 //在链表尾添加节点 38 public void addLast(E e){ 39 add(size, e); 40 } 41 //在链表指定位置添加节点 42 public void add(int index,E e){ 43 if (index < 0 || index > size) { 44 throw new IllegalArgumentException("Index is error."); 45 } 46 head = add(index, e, head); 47 } 48 //通过递归实现链表的添加 49 private Node add(int index,E e,Node node){ 50 if (index == 0 && node == null) { 51 this.size++; 52 return new Node(e); 53 } 54 if (index == 0) { 55 this.size++; 56 Node newNode = new Node(e); 57 //newNode.next = node.next; 58 newNode.next = node; 59 //node.next = newNode; 60 return newNode; 61 } 62 node.next = add(index - 1, e, node.next); 63 return node; 64 } 65 /** 66 * 用于根据索引查找对应的节点, 67 * @param index 68 * @param node 69 * @return 相应的节点对象 70 */ 71 private Node getElementByIndex(int index,Node node){ 72 if (index == 0 && node != null) { 73 return node; 74 } 75 Node ret = getElementByIndex(index - 1, node.next); 76 return ret; 77 } 78 //删除链表头节点 79 public E removeFirst(){ 80 return remove(0); 81 } 82 //删除链表尾结点 83 public E removeLast(){ 84 return remove(size - 1); 85 } 86 //删除指定位置节点,并返回删除节点值 87 public E remove(int index){ 88 if (isEmpty()) { 89 throw new IllegalArgumentException("List is empty."); 90 } 91 if (index < 0 || index >= size) { 92 throw new IllegalArgumentException("Index is error."); 93 } 94 Node ret = getElementByIndex(index, head); 95 head = remove(index, head); 96 return ret.e; 97 } 98 //递归删除节点值 99 private Node remove(int index,Node node){ 100 if (node == null) { 101 return node; 102 } 103 if (index == 0) { 104 Node delNode = node; 105 node = delNode.next; 106 delNode.next = null; 107 this.size--; 108 return node; 109 } 110 node.next = remove(index - 1, node.next); 111 return node; 112 } 113 //修改指定位置节点的值,通过递归实现 114 public void set(int index,E e){ 115 if (isEmpty()) { 116 throw new IllegalArgumentException("List is empty."); 117 } 118 if (index < 0 || index >= size) { 119 throw new IllegalArgumentException("Index is error."); 120 } 121 set(index, e, head); 122 } 123 private void set(int index,E e,Node node){ 124 if (node == null) { 125 return; 126 } 127 if (index == 0) { 128 node.e = e; 129 } 130 set(index - 1, e, node.next); 131 return; 132 } 133 //获取链表头节点的值 134 public E getFirst(){ 135 return get(0); 136 } 137 //获取链表尾结点的值 138 public E getLast(){ 139 return get(size - 1); 140 } 141 //获取链表制定位置的值,通过递归实现 142 public E get(int index){ 143 if (isEmpty()) { 144 throw new IllegalArgumentException("List is empty."); 145 } 146 if (index < 0 || index >= size) { 147 throw new IllegalArgumentException("Index is error."); 148 } 149 return get(index, head).e; 150 } 151 private Node get(int index,Node node){ 152 if (node == null) { 153 return node; 154 } 155 if (index == 0) { 156 return node; 157 } 158 Node ret = get(index - 1, node.next); 159 return ret; 160 } 161 //查询链表中的节点是否包含值e 162 public boolean contains(E e){ 163 return contains(e, head); 164 } 165 private boolean contains(E e,Node node){ 166 if (node == null) { 167 return false; 168 } 169 if (node.e == e) { 170 return true; 171 } 172 return contains(e, node.next); 173 } 174 //重写Object类的toString方法:也是通过链表天然的递归性,来访问 175 //链表的每一个节点 176 @Override 177 public String toString() { 178 StringBuilder res = new StringBuilder(); 179 res.append("Font -> "); 180 linkToString(head, res); 181 return res.toString(); 182 } 183 private void linkToString(Node node,StringBuilder res){ 184 if (node == null) { 185 res.append("NULL"); 186 return; 187 } 188 res.append(node.e + " -> "); 189 linkToString(node.next, res); 190 return; 191 } 192 193 /*public static void main(String[] args) { 194 LinekedList<Integer> ll = new LinekedList<>(); 195 for (int i = 0; i < 13; i++) { 196 ll.addLast(i); 197 System.out.println(ll.toString()); 198 } 199 System.out.println("------------------"); 200 for (int i = 0; i < 11; i++) { 201 Integer ii = ll.removeFirst(); 202 System.out.println(ii); 203 System.out.println(ll.toString()); 204 } 205 206 }*/ 207 }
有一些方法测了,但是有些方法没测,有需要可以自行参考(不保证准确啊...)
该类主要包含链表的增删改查,里面加了索引主要是为了好理解(注:链表是没有索引的).
因为,才刚开始熟悉递归以及数据结构,所以需要各位大佬的多多指正
有建议的可以在评论中指出.