双向链表
- 双向链表的图示
2. 操作图示
- 双向链表头插法:
-
双向链表尾插法:
- 双向链表插入:在某个节点后面插入新的节点
- 双向链表删除:头部删除方法
- 双向链表删除:尾部删除
-
双向链表删除:删除某个特定节点
3 ADT
3.1双向链表节点的声明
class Link{ public long dData; public Link right;//指向下一个节点 public Link left;//指向上一个节点 ... }
3.2 双向链表所包含的方法
1)遍历(前向遍历,后向遍历) 6.1.1 displayForward(); displayBackward();//从表尾开始 通过每个元素的previous域 一步步向前到达表头 2)插入 insertFirst();//在表头插入 O[1] insertLast();//在表尾插入 O[1] insertAfter();//在某一个特定元素后面插入 O[N] 3)删除 delteFirst();//O[1] deleteLast();//O[1] deleteKey();//O[N]
4 代码
4.1 双向链表的节点
public class DoubleLinkNode { public int iData;//data public double dData;//data public DoubleLinkNode next; //reference to next link public DoubleLinkNode pre;//reference to the previous link //constructor public DoubleLinkNode(int id,double dd){ iData = id; dData = dd; } public void displayLink(){ //display itself System.out.println ("iData : "+iData+" dData:"+dData); } }//end class DoubleLinkNode
4.2 双向链表
public class DoubleLinkList { private static DoubleLinkNode first; private static DoubleLinkNode last; //ref to first link on list public void LinkList(){ first = null; last = first; // constructor : no items on list yet } public boolean isEmpty(){ return first==null; } //前向遍历 public void displayForward(){ System.out.println(" DoubleLinkList (first-->last): "); DoubleLinkNode current = first; while (current!=null){ current.displayLink(); current=current.next; } System.out.println(""); } //后向遍历 public void displayBackward(){ System.out.println(" DoubleLinkList (first-->last): "); DoubleLinkNode current = last; while (last!=null){ current.displayLink(); current=current.pre; } System.out.println(""); } //查找结点 public DoubleLinkNode findNode(DoubleLinkNode node){ DoubleLinkNode current = first; while (current!=null){ // current.displayLink(); if(current.dData ==node.dData && current.iData ==node.iData ){ return current; } current = current.next; } return null; } //表头插入 public void insertFirst(DoubleLinkNode node){ if( isEmpty()){ first = node; last = node; return; } node.next=first; first.pre = node; first =node; } //表尾插入 public void insertLast(DoubleLinkNode node){ if( isEmpty()){ first = node; last = node; return; } node.next = null; node.pre = last; last.next = node; last = node; } //删除 表头删除 public DoubleLinkNode deleteFrist(){ DoubleLinkNode temp = first; if( !isEmpty()){ first.pre = null; first= first.next; } return temp; } // 删除 表尾删除 public DoubleLinkNode deleteLast(){ DoubleLinkNode temp = first; if( !isEmpty()){ last= last.pre; last.next = null; } return temp; } //删除指定元素 public DoubleLinkNode deleteKey(DoubleLinkNode node){ //找到该指定元素 DoubleLinkNode current = first; DoubleLinkNode pre = null; while (current!=null){ // current.displayLink(); if(current.dData ==node.dData && current.iData ==node.iData ){ //just find the key that need be deleted pre.next = current.next; current.next = pre; return current; } pre = current; current = current.next; } return null; } //特定节点后面插入 node1 某个节点 node 2 待插入的节点 public boolean insertAfter(DoubleLinkNode node1,DoubleLinkNode newNode){ //find the specail node DoubleLinkNode current = first; DoubleLinkNode pre = null; while (current!=null){ // current.displayLink(); if(current.dData ==node1.dData && current.iData ==node1.iData ){ pre=current; current = current.next; break; } pre=current; current = current.next; } if(current!=null){ newNode.next = current; current.pre = newNode; newNode.pre = pre; pre.next = newNode; return true; } return false; } }
5 双向链表应用 ===>双端队列
作为双端队列的基础.在双端队列中,可以从任何一头插入和删除,双向链表提供了这个能力.
5.1 双端队列基本操作
insertLeft();
insertRight();
removeLeft();
removeRight();
isEmpty();
display();
5.2 代码
public class Dqueue { //双端链表 private DoubleLinkList list; public Dqueue(){ this.list = new DoubleLinkList(); } //insert from the front direction public void insertLeft(DoubleLinkNode node) { list.insertFirst(node); } //insert from the back direction public void insertRight(DoubleLinkNode node) { list.insertLast(node); } //delete from the front direction public DoubleLinkNode removeLeft() { return list.deleteFrist(); } //delete from the back direction public DoubleLinkNode removeRight(){ return list.deleteLast(); } public boolean isEmpty(){return list.isEmpty();} public void display() {list.displayForward();} }
public class DqueueApp { private static Dqueue que=new Dqueue(); //constructor public DqueueApp(){ que = new Dqueue(); } public static void main(String[] args) { que.insertLeft(new DoubleLinkNode(1,1.1)); que.insertLeft(new DoubleLinkNode(3,3.3)); que.insertLeft(new DoubleLinkNode(2,2.2)); que.display(); } }
6 总结
6.1 双向链表 VS 单链表
1 单链表缺陷:
沿链表的反向遍历困难。
链表正向遍历:current = current.next;
2 双向链表优势:
允许向前遍历,也允许向后遍历整个链表。
6.2 双向链表的缺陷
每插入或者删除一个链结点时候,要处理四个链结点的引用(单链表处理两个)
两个连接前一个节点,两个连接后一个节点。
链结点占用空间也大一点(多了两个引用)
6.3 双向链表 VS 双端链表
双端链表:保持一个对链表最后一个元素的引用
双向链表不必是双端链表,但这种方式是有用的(可以进行队尾删除)。