java数据结构:双向链表结构与实现

本教程的内容基本来自于《Java数据结构与算法》

单向链表的缺点在于每个节点只能知道自己与下一个节点,无法寻找到上一个节点。而双向链表可以解决这个问题,通过在节点内部添加一个previous指针,指向它的前一节点。

双向链表示意图

双向链表

图中所示为双向链表,与单向链表相比,只不过是多引入了一个指向前一节点的previous指针而已。

优点:支持向前遍历,也支持向后遍历;
缺点:在对链表进行增删的时候需要对2个以上指针进行操作。

节点类的定义如下

class Link
{
	public long dData;         //节点存储的数据
	public Link next;          //指向下一节点的指针
	public Link previous;      //指向前一节点的指针
	
	public Link(long d)
	{
		this.dData = d;
	}
	
	public void displayLink()
	{
		System.out.print(dData+" ");
	}
}

双向链表类的定义

class DoublyLinkList
{
	private Link first;
	
	public DoublyLinkList()
	{ this.first = null; }
	
	public boolean isEmpty()
	{ return (this.first==null); }
	
	......
}

主要方法有

public void insertFirst(long dd);       			//从头部插入元素
public Link deleteFirst();              			//删除头节点
public boolean insertAfter(long key, long dd);   	//在指定节点key后插入节点
public Link deleteKey(long key); 					//删除指定节点
public void displayForward();                       //向前遍历

1.从头部插入元素

头部插入元素

从图中看到总共分三步

1.first.previous -----> newLink
2.newLink.next ----> 旧first
3.first ----> newLink

代码如下

public void insertFirst(long dd)
{
	Link newLink = new Link(dd);                //新建节点
	if(!isEmpty())
		this.first.previous = newLink;          //第一步
	newLink.next = this.first;                  //第二步
	this.first = newLink;	                    //第三步
}

2.删除头节点

删除头节点
删除头结点比较简单,只需两步即可

1.first.next.previous -----> null
2.first -----> first.next

public Link deleteFirst()
{
	Link temp = this.first;               //返回删除的节点
	this.first.next.previous = null;      //第一步
	this.first = this.first.next;         //第二步
	return temp;
}

3.指定位置插入节点

指定位置插入节点

current表示找到的指定位置,插入节点主要分四步

1.current.next.previous -----> newLink
2.newLink.next -----> current.next
3.newLink.previous -----> current
4.current.next -----> newLink

代码如下

public boolean insertAfter(long key, long dd)
{
	//遍历链表查找节点key
	Link current = first;
	while(current.dData!=key)
	{
		current = current.next;
		if(current==null)
			return false;                  //没找到返回false
	}
	//在current后插入新节点
	Link newLink = new Link(dd);
	if(current.next!=null)
		current.next.previous = newLink;   //第一步
	newLink.next = current.next;           //第二步
	newLink.previous = current;            //第三步
	current.next = newLink;                //第四步
	return true;
}

4.删除指定节点

删除指定节点

current表示找到的指定位置,插入节点主要分两步

1.current.previous.next -----> current.next
2.current.next.previous -----> current.previous

代码如下

public Link deleteKey(long key)
{
	//遍历链表查找节点
	Link current = this.first;
	while(current.dData!=key)
	{
		current = current.next;
		if(current==null)
			return null;
	}
	//如果是头节点,则按照删除头节点的方式删除节点
	if(current==this.first)
		this.first = this.first.next;
	//否则
	else
	{
		current.previous.next = current.next;            //第一步
		if(current.next!=null)
			current.next.previous = current.previous;    //第二步
	}
	return current;
}

5.向前遍历

这部分和单链表一样

public void displayForward()
{
	Link current = this.first;
	System.out.print("List (first-->last): ");
	while(current != null)
	{
		current.displayLink();
		current = current.next;
	}
	System.out.println("");
}

6.如果是双端口的链表,还支持后向遍历,这里没有展开。

github完整代码

https://github.com/gamersover/data_structure_java/blob/master/LinkList/DoublyLinkListApp.java

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值