您的位置:首页 > 其它

两种双向链表的首项插入与删除效率比较

2014-12-26 15:21 363 查看
这里说的两种双向链表是指带“sentinel”与不带“sentinel”的,其中带"sentinel"的多了一个"sentinel"节点,以空间换取了时间。两种链表如下图:

1.不带sentinel的:



下面是构造方法以及在首项插入和删除方法,从代码中可以看出没有sentinel的DList在插入时需要处理链表为空的情况,删除的时候需要处理链表为空以及链表只有一个元素的情况,比较麻烦。

public class DList1 {

/**
*  head references the first node.
*  tail references the last node.
*/

protected DListNode1 head;
protected DListNode1 tail;
protected long size;

/* DList1 invariants:
*  1)  head.prev == null.
*  2)  tail.next == null.
*  3)  For any DListNode1 x in a DList, if x.next == y and x.next != null,
*      then y.prev == x.
*  4)  For any DListNode1 x in a DList, if x.prev == y and x.prev != null,
*      then y.next == x.
*  5)  The tail can be accessed from the head by a sequence of "next"
*      references.
*  6)  size is the number of DListNode1s that can be accessed from the
*      head by a sequence of "next" references.
*/

/**
*  DList1() constructor for an empty DList1.
*/
public DList1() {
head = null;
tail = null;
size = 0;
}

/**
*  DList1() constructor for a one-node DList1.
*/
public DList1(int a) {
head = new DListNode1();
tail = head;
head.item = a;
size = 1;
}

/**
*  DList1() constructor for a two-node DList1.
*/
public DList1(int a, int b) {
head = new DListNode1();
head.item = a;
tail = new DListNode1();
tail.item = b;
head.next = tail;
tail.prev = head;
size = 2;
}

/**
*  insertFront() inserts an item at the front of a DList1.
*/
public void insertFront(int i) {
DListNode1 insertItem = new DListNode1(i);
if(head == null){
head = insertItem;
tail = insertItem;
}else{
insertItem.next = head;
head.prev = insertItem;
head = insertItem;
}
size++;
}

/**
*  removeFront() removes the first item (and node) from a DList1.  If the
*  list is empty, do nothing.
*/
public void removeFront() {
if(size == 0){
return;
}
if(size == 1){
head = null;
tail = null;
}else{
head.next.prev = null;
head = head.next;
}
size--;
}


2.下边是带sentinel的链表:



下边是构造方法以及首先插入与删除方法,注意构造方法中head的prev和next在链表没有元素的情况下是指向自身的,这一点非常重要,如果设置为null,就失去了这种链表的优势,还需要像第一种链表一样在插入和删除的时候考虑多种情况。

public class DList2 {

/**
*  head references the sentinel node.
*
*/

protected DListNode2 head;
protected long size;

/* DList2 invariants:
*  1)  head != null.
*  2)  For any DListNode2 x in a DList2, x.next != null.
*  3)  For any DListNode2 x in a DList2, x.prev != null.
*  4)  For any DListNode2 x in a DList2, if x.next == y, then y.prev == x.
*  5)  For any DListNode2 x in a DList2, if x.prev == y, then y.next == x.
*  6)  size is the number of DListNode2s, NOT COUNTING the sentinel
*      (denoted by "head"), that can be accessed from the sentinel by
*      a sequence of "next" references.
*/

/**
*  DList2() constructor for an empty DList2.
*/
public DList2() {
head = new DListNode2();
head.item = Integer.MIN_VALUE;
head.next = head;
head.prev = head;
size = 0;
}

/**
*  DList2() constructor for a one-node DList2.
*/
public DList2(int a) {
head = new DListNode2();
head.item = Integer.MIN_VALUE;
head.next = new DListNode2();
head.next.item = a;
head.prev = head.next;
head.next.prev = head;
head.prev.next = head;
size = 1;
}

/**
*  DList2() constructor for a two-node DList2.
*/
public DList2(int a, int b) {
head = new DListNode2();
head.item = Integer.MIN_VALUE;
head.next = new DListNode2();
head.next.item = a;
head.prev = new DListNode2();
head.prev.item = b;
head.next.prev = head;
head.next.next = head.prev;
head.prev.next = head;
head.prev.prev = head.next;
size = 2;
}

/**
*  insertFront() inserts an item at the front of a DList2.
*/
public void insertFront(int i) {
DListNode2 insertItem = new DListNode2(i);
head.next.prev = insertItem;
insertItem.next = head.next;
insertItem.prev = head;
head.next = insertItem;
size++;
}

/**
*  removeFront() removes the first item (and first non-sentinel node) from
*  a DList2.  If the list is empty, do nothing.
*/
public void removeFront() {
if(size == 0){
return;
}
DListNode2 remove = head.next;
head.next = remove.next;
remove.next.prev = head;
size--;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: