博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

双向链表学习笔记

Posted on 2011-09-25 21:21  袁立  阅读(263)  评论(0编辑  收藏  举报

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.总结

双向链表弥补了单向链表的不足,可以双向获取相邻节点,比如删除最后一个节点时就不需要遍历整个链表,而可以直接操作最后一个节点。