首页 > 其他 > 详细

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

时间:2014-05-18 18:42:07      阅读:618      评论:0      收藏:0      [点我收藏+]

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

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

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

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

bubuko.com,布布扣

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

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<datas.length; i++) {
			p = new Node(datas[i]);
			r.setRightLink(p);
			p.setLeftLink(r);
			p.setRightLink(headNode);
			r = p;
			length++;
		}
		headNode.setLeftLink(r);
	}
	
	/**
	 * 打印带有头结点的双向循环链表
	 */
	public void printDoubleLink() {
		Node p = headNode.getRightLink();
		while(p != headNode) {
			System.out.print(p.getData() + " ");
			p = p.getRightLink();
		}
		System.out.println();
	}
	
	/**
	 * 在双向循环链表的pos位置后面插入数据域为item的结点
	 * 
	 * @param pos 表示插入元素的位置。计算位置时,头结点的位置为0
	 * @param item 表示插入结点的数据域
	 * @return 插入成功返回true;否则返回false
	 */
	public boolean insertItem(int pos, Object item) {
		if(pos < 0 || pos > 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;
	}
}



数据结构之双向链表(包含双向循环链表),布布扣,bubuko.com

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

原文:http://blog.csdn.net/bbewx/article/details/26058003

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!