1.链表接口定义
package com.ncs.datastructure.linklist; public interface ILinkList { /** * 链表是否为空 * @return */ public abstract boolean isEmpty(); /** * 在链表的第一个节点前插入节点 * @param data */ public abstract void addToHead(Object data); /** * 在链表的最后一个节点追加节点 * @param data */ public abstract void addToTail(Object data); /** * 删除链表中的第一个节点 * @return */ public abstract Object deleteFromHead(); /** * 删除链表中的最后一个节点 * @return */ public abstract Object deleteFromTail(); /** * 链表中是否存在指定的节点 * @param data * @return */ public abstract boolean isContains(Object data); /** * 删除指定的节点 * @param data */ public abstract void deleteNode(Object data); }
2.双向链表的简单实现
package com.ncs.datastructure.linklist; import com.ncs.datastructure.linklist.SingleLinkList.Node; /** * 双向链表的简单实现 * @author yuanli * */ public class DoubleLinkList implements ILinkList { /** * 之所以定义为内部类,是因为用户并不关心链表节点的结构,而只关心链表存储的数据 * @author yuanli * */ public class Node { //数据域 private Object data; //前驱节点 private Node prev; //后继节点 private Node next; public Node() { super(); } public Node(Object data) { this(data, null, null); } public Node(Object data, Node prev, Node next) { super(); this.data = data; this.prev = prev; this.next = next; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public Node getPrev() { return prev; } public void setPrev(Node prev) { this.prev = prev; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } } //表示链表的第一个节点 protected Node head; //表示链表的最后一个节点 protected Node tail; public void addToHead(Object data) { if (this.head == null) { this.head = new Node(data); if (this.tail == null ) this.tail = this.head; } else { Node temp = new Node(data,null,this.head); this.head.prev = temp; this.head = temp; } } public void addToTail(Object data) { if (!isEmpty()) { this.tail = new Node(data, this.tail, null); this.tail.prev.next = this.tail; } else { this.tail = this.head = new Node(data); } } public Object deleteFromHead() { Node delete = null; if (this.head == this.tail) { delete = this.head; this.head = this.tail = null; } else { delete = this.head; this.head = this.head.next; this.head.prev = null; } return delete; } public Object deleteFromTail() { Node delete = null; if (this.head == this.tail) { delete = this.head; this.head = this.tail = null; } else { delete = this.tail; this.tail = this.tail.prev; this.tail.next = null; } return delete; } public void deleteNode(Object data) { if (!isEmpty()) { //如果只有一个节点 if (this.head == this.tail) { this.head = this.tail = null; return; } //如果是删除第一个节点 if (this.head.data.equals(data)) { this.deleteFromHead(); return; } //如果是删除最后一个节点 if (this.tail.data.equals(data)) { this.deleteFromTail(); return; } //删除中间节点 for (Node temp = this.head; temp.next != null; temp = temp.next) { if (temp.data.equals(data)) { // Node prev = temp.prev; // Node next = temp.next; // prev.next = next; // next.prev = prev; temp.prev.next = temp.next; temp.next.prev = temp.prev; } } } } public boolean isContains(Object data) { if (!isEmpty()) { Node temp = this.head; for (; temp.next != null; temp = temp.next) { if (temp.data.equals(data)) { return true; } } } return false; } public boolean isEmpty() { return this.head == null; } /** * 遍历链表的所有节点,并打印出节点数据信息 */ public void printAll() { Node temp = this.head; for (; temp != null; temp = temp.next) { System.out.println("node data is " + temp.data); } } /** * @param args */ public static void main(String[] args) { //实例化一个单向链表对象 DoubleLinkList dll = new DoubleLinkList(); //向单向链表中添加节点 dll.addToHead("node1"); dll.addToTail("node2"); dll.addToTail("node3"); dll.addToTail("node4"); dll.addToTail("node5"); //输出所有节点数据 dll.printAll(); //删除第一个节点 dll.deleteFromHead(); //删除最后一个节点 dll.deleteFromTail(); //输出所有节点数据 dll.printAll(); //链表中是否包含指定的节点 boolean isExsist = dll.isContains("node11"); System.out.println(isExsist); //删除指定的节点 dll.deleteNode("node3"); dll.printAll(); } }
3.总结
双向链表弥补了单向链表的不足,可以双向获取相邻节点,比如删除最后一个节点时就不需要遍历整个链表,而可以直接操作最后一个节点。