线性表—双链表
1.基础知识
a.双链表结点的结构:其由前序元素地址,数据域,后继元素地址组成。
b.双链表结点的连接
方法:先声明该结点,可以在内部也可以利用其特性来表明前序结点和后继结点是什么,之后同时还需要说明“其前序结点的后继地址为该结点”和”其后继结点的前序地址为该结点。
(本质:双向)
2.循环双链表的实现
线性表接口LList
双链表结点类:
循环双链表:
循环双链表 测试类:
运行结果:
提醒:实现源码下载链接:
http://www.cnblogs.com/tanlon/p/4028622.html
3.排序循环双链表
概念:该表就是插入一个值为x结点,首先要查找插入位置,从双链表的第一个结点开始,将元素x依次与当前结点的data值比较大小,一旦找到一个比
x值大或者等值结点p,则将x插入在p结点之前。
注意:其先查找插入位置,其时间复杂度为O(n),之后再插入,其时间复杂度为O(1)。
代码实例:
public class SortedDoublyLinkedList<T extends Comparable<T>> extends CirDoublyLinkedList<T>
{
//默认构造方法,构造空循环双链表。调用父类默认构造方法,构造空循环双链表
public SortedDoublyLinkedList(){super();}
public SortedDoublyLinkedList(T[] element) //将数组中所有对象插入构造排序单链表
{ super();
for(int i=0;i<element.length;i++){
this.insert(element[i]); //插入,根据值的大小决定插入位置
}
//深拷贝构造方法,调用父类同参数的构造方法
public SortedDoublyLinkedList(SortedDoublyLinkedList<T> list){ super(list); }
public void insert(T x) //根据指定对象的大小插入在合适位置
{
if(x==null)
return; //不能插入空对象
if(this.head.prev!=head&&this.head.prev.data.compareTo(x)<0)
{ //先判断其是否为最大值,如果是,最大值插入在头结点之前,即插入在链尾,时间复杂度O(1)(这也是根本目的,因为如果是最大,那就没必要再遍历一遍了,浪费时间,效率底下,算法就是追求效率)
DLinkNode<T> q=new DLinkNode<T>(x,head.prev,head);
head.prev.next=q;
head.prev=q;
}
//下面这个就是先寻找位置,然后再插入的步骤
DLinkNode<T> p=this.head.next;
while(p!=head&&p.data.compareTo(x)<0{ //compareTo(x)意思就是p的数据和x比较如果比x小,返回小于0的数,否则,大于或等于0。目的就是为了排序而寻找插入位置
p=p.next;}
DLinkNode<T> q=new DLinkNode<T>(x.p.prev,p);//插在p结点之前
p.prev.next=q;
p.prev=q;
}
public void remove(T x) //删除首次出现的值为x结点,若未找到则不删除。时间复杂度为Q(n)
{
if(x==null){ return;}
DLinkNode<T> p=this.head.next;
while(p!=head&&p.data.compareTo(x)<0){ //将p定位到待删除的结点
p=p.next;}
if(p!=head&&p.data.compare(x)==0){
p.prev.next=p.next; //删除p结点自己
p.next.prev=p.prev;
}
}
}
}