一、链表的实现
之前实现的容量可变化的“动态”数据结构,实则也是由静态数组实现的,只不过人为的加入了resize()方法来进行扩容和缩容。
而链表确实真正意义上的动态数据结构。
链表的实现由Node节点来实现。一个Node包括:
- 包含的内容 E e
- 指向下一个节点 Node next
二、实现内容
链表的增删改查
链表的增删改查都是一个从头结点依次查询的过程。增删改查都可以实现,实现方法见详细代码。
三、具体代码实现
链表的实现
遇到的问题与调试解决
- 在实现过程中,由于在链表头插入元素不方便,而引入了虚拟头结点dummyHead。
虚拟头结点指的是一个内容E为空的,next指向链表第一个实结点的结点。它的意义是让在链表头插入结点更加容易和递推结点的逻辑更加易懂。 - 在增删改查的方法实现中,一定要认真考虑for循环中 i的终止条件是什么。特别提出如果需要遍历整个链表 则可以用while(prev.next!=null)作为循环,这样更容易理解。
链表的代码
package linklist;
import array.Array;
public class LinkList<E> {
private class Node {
public E e;
public Node next;
public Node(E e, Node next) {
this.e = e;
this.next = next;
}
public Node(E e) {
this.e = e;
this.next = null;
}
public Node() {
this.next = null;
this.e = null;
}
@Override
public String toString() {
return e.toString();
}
}
private Node dummyHead;
private int size;
public LinkList() {
this.dummyHead = new Node(null, null);
this.size = 0;
}
public int getSize() {
return size;
}
public boolean isEmpty() {
if (size == 0)
return true;
return false;
}
public void addFirst(E e) {
dummyHead.next = new Node(e, dummyHead.next);
size++;
}
public void add(int index, E e) {
if (index < 0 || index > size)
throw new IllegalArgumentException("index is wrong");
Node node = new Node(e);
Node prev = dummyHead;
for (int i = 0; i < index; i++) {
prev = prev.next;
}
prev.next = new Node(e, prev.next);
size++;
}
public void addLast(E e) {
add(size, e);
}
public E getIndex(int index) {
if (index < 0 || index >= size)
throw new IllegalArgumentException("index is wrong");
Node cur = dummyHead.next;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
return cur.e;
}
public void set(int index, E e) {
if (index < 0 || index >= size)
throw new IllegalArgumentException("index is wrong");
E cur = getIndex(index);
cur = e;
}
public boolean contains(E e) {
Node cur = dummyHead.next;
for (int i = 0; i < size; i++) {
if (cur.e == e)
return true;
cur = cur.next;
}
return false;
}
@Override
public String toString() {
StringBuilder res = new StringBuilder();
res.append(String.format("链表的大小为%d,具体为", size));
Node cur = dummyHead.next;
while (cur != null) {
res.append(cur.e);
res.append("->");
cur=cur.next;
}
res.append("null");
return res.toString();
}
public E remove(int index){
if (index < 0 || index >= size)
throw new IllegalArgumentException("index is wrong");
Node prev=dummyHead;
for (int i=0;i<index;i++){
prev=prev.next;
}
Node node=prev.next;
prev.next=node.next;
node.next=null;
size--;
return node.e;
}
public E removeFirst(){
return remove(0);
}
public E removeLast(){
return remove(size-1);
}
public static void main(String[] args) {
LinkList<Integer> linkedList = new LinkList<>();
for (int i = 0; i < 5; i++) {
linkedList.addFirst(i);
System.out.println(linkedList.toString());
}
linkedList.add(2, 666);
System.out.println(linkedList);
linkedList.remove(2);
System.out.println(linkedList);
linkedList.removeFirst();
System.out.println(linkedList);
linkedList.removeLast();
System.out.println(linkedList);
}
}
运行测试结果:
链表的大小为1,具体为0->null
链表的大小为2,具体为1->0->null
链表的大小为3,具体为2->1->0->null
链表的大小为4,具体为3->2->1->0->null
链表的大小为5,具体为4->3->2->1->0->null
链表的大小为6,具体为4->3->666->2->1->0->null
链表的大小为5,具体为4->3->2->1->0->null
链表的大小为4,具体为3->2->1->0->null
链表的大小为3,具体为3->2->1->null