数据结构与算法之链表4---双向链表
2014-09-25 00:00
573 查看
在单链表的删除中,由于单向链表中只包含指向其后继节点的引用,所以无法立即访问到它的前驱节点。所以在删除的方法中我们借助一个循环来寻找tail的前驱节点。尽管这个前驱节点可以说可见不可达,但是为了删除它仍然不得不扫描整个链表才能恰好停在tail的前一个节点处。对一个长链表,或者是需要频繁执行这个删除方法的情况,会严重妨碍处理链表的速度。为了避免这个问题,可以重新定义链表,使表中每一个节点有两个引用雨,一个指向其前驱节点,一个指向其后继节点。这种链表叫做双向链表。
二、双向链表的基本操作的实现(重点讲解删除和插入)
插入:双向链表的插入需要一下步骤:将e节点插入到a和b中
具体实现过程如下:
1)创建一个空节点
2)将其info域设置为e
3)将e的前驱节点指向a
4)将e的后继节点指向b
5)将b的前驱节点指向e
6)将a的后继节点指向e
注意:步骤3)和步骤4)可以调换顺序,但是步骤5)不能先执行否则会使得a.next提前变成了s,使得插入工作无法进行。我们可以理解为,先搞定s的前趋和后继,再搞定后节点的前趋,最后解决前节点的后继。
删除节点
删除节点需要考虑以下的几种情况:
1)在一个空链表中删除一个节点
2)在表尾删除节点
3)在表中删除节点
4)在表头删除节点
5)在只含有一个节点的链表中删除一个节点
删除的代码如下:
双向链表的基本操作完整代码如下:
一、双向链表的类的定义
class DoubleLinkNode{ public int info; public DoubleLinkNode next; public DoubleLinkNode prev; public DoubleLinkNode(int e1) {this(e1,null,null); } public DoubleLinkNode(int e1,DoubleLinkNode next, DoubleLinkNode prev){ this.info=e1;this.next=next;this.prev=prev; } }
二、双向链表的基本操作的实现(重点讲解删除和插入)
插入:双向链表的插入需要一下步骤:将e节点插入到a和b中
具体实现过程如下:
1)创建一个空节点
2)将其info域设置为e
3)将e的前驱节点指向a
4)将e的后继节点指向b
5)将b的前驱节点指向e
6)将a的后继节点指向e
注意:步骤3)和步骤4)可以调换顺序,但是步骤5)不能先执行否则会使得a.next提前变成了s,使得插入工作无法进行。我们可以理解为,先搞定s的前趋和后继,再搞定后节点的前趋,最后解决前节点的后继。
/* * 在指定位置后插入一个节点 */public void add(int e1, int insertData){ DoubleLinkNode tmp=head; while(tmp!=null){if(tmp.info==e1){ DoubleLinkNode insert=new DoubleLinkNode(insertData); insert.prev=tmp; insert.next=tmp.next; tmp.next.prev=insert; tmp.next=insert; } } }/* * 在头部插入一个节点 */public void addToHead(int e1){ if(!isEmpty()) { head=new DoubleLinkNode(e1, head, null); head.next.prev=head; } else{ head=tail=new D 3ff0 oubleLinkNode(e1); } }/* * 在尾部插入一个节点 */public void addToTail(int e1){ if(!isEmpty()){ tail=new DoubleLinkNode(e1, null, tail); tail.prev.next=tail; }else{ head=tail=new DoubleLinkNode(e1); } }
删除节点
删除节点需要考虑以下的几种情况:
1)在一个空链表中删除一个节点
2)在表尾删除节点
3)在表中删除节点
4)在表头删除节点
5)在只含有一个节点的链表中删除一个节点
删除的代码如下:
/* * 在表尾删除一个节点:时间复杂度O(1) */public int deleteFromTail() {if(!isEmpty()) {int e1=tail.info;if(head==tail)//只有一个节点的情况 head=tail=null;else{ tail=tail.prev; tail.next=null; }return e1; }return 0; }/* * 在表中删除节点:时间复杂度O(n) */public int delete(int e1){ DoubleLinkNode tmp=head;int data; if(tmp!=null){for(tmp=head;tmp!=null&&tmp.info!=e1;tmp=tmp.next); tmp.prev.next=tmp.next; tmp.next.prev=tmp.prev; data=tmp.info;return data; }return 0; }/* * 在表头删除节点:时间复杂度O(1) */public int deleteFromHead() {if(!isEmpty()) {int e1=head.info;if(head==tail) head=tail=null;else{ head=head.next; head.prev=null; }return e1; }return 0; }
双向链表的基本操作完整代码如下:
package com.linkedlist;public class DoubleLinkedList { private DoubleLinkNode head,tail; public DoubleLinkedList(){
head=tail=null;
} /* * 判断链表是否为空 */public boolean isEmpty(){return head==null;
}/* * 置空链表 */public void setToNull()
{
head=tail=null;
} /* * 在指定位置后插入一个节点:时间复杂度O(n) */public void add(int e1, int insertData){
DoubleLinkNode tmp=head; if(tmp!=null){for(tmp=head;tmp!=null;tmp=tmp.next)if(tmp.info==e1){
DoubleLinkNode insert=new DoubleLinkNode(insertData);
insert.prev=tmp;
insert.next=tmp.next;
tmp.next.prev=insert;
tmp.next=insert;
}
}
}/* * 在头部插入一个节点:时间复杂度O(1) */public void addToHead(int e1){ if(!isEmpty())
{
head=new DoubleLinkNode(e1, head, null);
head.next.prev=head;
} else{
head=tail=new DoubleLinkNode(e1);
}
}/* * 在尾部插入一个节点:时间复杂度O(1) */public void addToTail(int e1){ if(!isEmpty()){
tail=new DoubleLinkNode(e1, null, tail);
tail.prev.next=tail;
}else{
head=tail=new DoubleLinkNode(e1);
}
}/* * 在表尾删除一个节点:时间复杂度O(1) */public int deleteFromTail() {if(!isEmpty()) {int e1=tail.info;if(head==tail)//只有一个节点的情况 head=tail=null;else{ tail=tail.prev; tail.next=null; }return e1; }return 0; }/* * 在表中删除节点:时间复杂度O(n) */public int delete(int e1){ DoubleLinkNode tmp=head;int data; if(tmp!=null){for(tmp=head;tmp!=null&&tmp.info!=e1;tmp=tmp.next); tmp.prev.next=tmp.next; tmp.next.prev=tmp.prev; data=tmp.info;return data; }return 0; }/* * 在表头删除节点:时间复杂度O(1) */public int deleteFromHead() {if(!isEmpty()) {int e1=head.info;if(head==tail) head=tail=null;else{ head=head.next; head.prev=null; }return e1; }return 0; }/* * 查找:时间复杂度O(n) */public int find(int e1)
{
DoubleLinkNode tmp; for(tmp=head;tmp!=null&&tmp.info!=e1;tmp=tmp.next);if(tmp==null)return 0;elsereturn tmp.info;
}/* * 遍历节点:时间复杂度O(n) */public void printAll(){ for(DoubleLinkNode tmp=head;tmp!=null;tmp=tmp.next)
{
System.out.print(tmp.info+" ");
}
} public static void main(String[] args){
DoubleLinkedList list=new DoubleLinkedList(); int[] a=new int[10]; for(int i=0;i<10;i++)
{
a[i]=i+1;
} for(int i=0;i<10;i++)
{
list.addToTail(a[i]);
}
System.out.println("新的双向链表如下:");
list.printAll();
list.add(5, 11);
System.out.println("插入11后的链表如下:");
list.printAll();
list.delete(6);
System.out.println("删除6后的链表如下:");
list.printAll();
}
}class DoubleLinkNode{ public int info; public DoubleLinkNode next=null; public DoubleLinkNode prev=null; public DoubleLinkNode(int e1)
{this.info=e1;
} public DoubleLinkNode(int e1,DoubleLinkNode next, DoubleLinkNode prev){ this.info=e1;this.next=next;this.prev=prev;
}
}
相关文章推荐
- 《Delphi 算法与数据结构》学习与感悟[10]: 双向链表
- 数据结构 P36-37 算法实现 双向循环链表的插入与删除
- C++类模板 实现双向循环链表的基本算法 《数据结构》(C++版 北京科海)中摘抄
- 线性表16:双向链表 - 数据结构和算法21
- 数据结构和算法-009 双向链表
- 左程云_算法与数据结构 — 链表问题 — 04反转单向和双向链表
- 算法与数据结构之四----双向链表
- 线性表16:双向链表 - 数据结构和算法21
- Linux c 算法与数据结构--双向链表
- 数据结构高分笔记 算法2-18~2-19:双向循环链表
- 数据结构 算法面试100题 之 二叉树转换成双向链表
- 算法与数据结构面试题(1)-把二元查找树转变成排序的双向链表
- 微软等数据结构+算法面试100题(43)-- 把二元查找树转变成排序的双向链表
- 线性表16:双向链表 – 数据结构和算法21
- 面经 常见数据结构的算法 - 双向链表
- Linux c 算法与数据结构--双向链表
- 数据结构之双向带头节点带环链表的实现
- 【数据结构】双向链表的创建和读取
- HNCU1328:算法2-18~2-19:双向循环链表
- 数据结构学习笔记 --- 线性表 (双向链表、循环链表)