数据结构之双向链表(包含双向循环链表)

2014-11-23 21:26:26 · 作者: · 浏览: 14

双向(循环)链表是线性表的链式存储结构的又一种形式。

在之前已经讲述了单向链表和循环链表。相比于单向链表只能从头结点出发遍历整个链表的局限性,循环链表使得可以从任意一个结点遍历整个链表

但是,不管单向链表也好,循环链表也罢,都只能从一个方向遍历链表,即只能查找结点的下一个结点(后继结点),而不能查找结点的上一个结点(前驱结点)。鉴于上述问题,引入了双向链表。由于双向循环链表包含双向链表的所有功能操作。因此,我们只讲述双向循环链表。

与单向链表不同,双向链表的结点构造如下图所示。即一个结点由三个部分组成,数据域DATA,左指针域llink和右指针域rlink。其中,数据域用来存放结点数据信息,左指针域用来指向前驱结点,右指针域用来指向后继结点。双向循环链表有一个特性:p->llink->rlink = p->rlink->llink = p。

\

用来表示双向链表结点的代码如下:

public class Node {
	private Object data;
	private Node lLink, rLink;
	
	//构造函数
	public Node() {
		this.data = null;
		this.lLink = null;
		this.rLink = null;
	}
	//构造函数重载
	public Node(Object data) {
		this.data = data;
		this.lLink = null;
		this.rLink = null;
	}
	public Node(Object data, Node lLink, Node rLink) {
		this.data = data;
		this.lLink = lLink;
		this.rLink = rLink;
	}
	
	//读结点数据
	public Object getData() {
		return data;
	}
	//写结点数据
	public void setData(Object data) {
		this.data = data;
	}
	//获取结点的前驱结点
	public Node getLeftLink() {
		return lLink;
	}
	//获取结点的后继结点
	public Node getRightLink() {
		return rLink;
	}
	//设置结点的前驱结点
	public void setLeftLink(Node lLink) {
		this.lLink = lLink;
	}
	//设置结点的后继结点
	public void setRightLink(Node rLink) {
		this.rLink = rLink;
	}
}

在带有头结点的双向循环链表类代码如下。在代码示例中,仅介绍了双向循环链表的创建、插入元素、删除元素和打印链表的操作。

public class DoubleLink {
	/**
	 * 带有头结点的双向循环链表的头结点
	 */
	private Node headNode = new Node();
	/**
	 * 链表长度
	 */
	private int length = 0;
	
	/**
	 * 创建一个带有头结点的双向链表
	 * 
	 * @param datas 数组,用来表示双向链表中各个结点的数据域
	 */
	public void createDoubleLink(Object[] datas) {
		Node p, r;
		r = headNode;
		for(int i=0; i
  
    length) {
			return false;
		}
		else {
			Node p = new Node(item);
			if(pos == 0) {
				p.setLeftLink(headNode);
				p.setRightLink(headNode.getRightLink());
				headNode.getRightLink().setLeftLink(p);
				headNode.setRightLink(p);
			} else if (pos == length) {
				p.setLeftLink(headNode.getLeftLink());
				p.setRightLink(headNode);
				headNode.getLeftLink().setRightLink(p);
				headNode.setLeftLink(p);
			} else {
				int count = 1;
				Node r = headNode.getRightLink();
				while(count < pos) {
					r = r.getRightLink();
					count++;
				}
				p.setLeftLink(r);
				p.setRightLink(r.getRightLink());
				r.getRightLink().setLeftLink(p);
				r.setRightLink(p);
			}
			return true;
		}
	}
	
	/**
	 * 删除带头结点的双向链表中第一次出现数据域为item的结点
	 * 
	 * @param item 删除结点的数据域
	 * @return 删除成功,返回true;否则,返回false
	 */
	public boolean deleteItem(Object item) {
		Node p = headNode.getRightLink(), r = headNode;
		while(p != headNode) {
			if(p.getData() == item) {
				r.setRightLink(p.getRightLink());
				p.getRightLink().setLeftLink(r);
				return true;
			}
			else {
				r = p;
				p = p.getRightLink();
			}
		}
		return false;
	}
}