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.总结
双向链表弥补了单向链表的不足,可以双向获取相邻节点,比如删除最后一个节点时就不需要遍历整个链表,而可以直接操作最后一个节点。