本教程的内容基本来自于《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