两种双向链表的首项插入与删除效率比较
2014-12-26 15:21
363 查看
这里说的两种双向链表是指带“sentinel”与不带“sentinel”的,其中带"sentinel"的多了一个"sentinel"节点,以空间换取了时间。两种链表如下图:
1.不带sentinel的:
下面是构造方法以及在首项插入和删除方法,从代码中可以看出没有sentinel的DList在插入时需要处理链表为空的情况,删除的时候需要处理链表为空以及链表只有一个元素的情况,比较麻烦。
2.下边是带sentinel的链表:
下边是构造方法以及首先插入与删除方法,注意构造方法中head的prev和next在链表没有元素的情况下是指向自身的,这一点非常重要,如果设置为null,就失去了这种链表的优势,还需要像第一种链表一样在插入和删除的时候考虑多种情况。
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--; }
相关文章推荐
- QLinkedList和std::forward_list(都是双向链表,不支持operator[],好处可能是插入和删除都比较快)
- 双向链表实现 插入删除
- 如何使用c语言实现双向链表的插入删除操作
- (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作
- 双向链表的创建/插入/删除
- 双向链表的创建、结点的插入、删除与打印
- 双向链表建立、插入和删除
- java建立双向链表,插入结点,删除节点
- (C语言版)链表(四)——实现双向循环链表创建、插入、删除、释放内存等简单操作
- 双向链表的建立插入删除
- 双向链表 删除节点 插入节点
- 双向循环链表的插入删除
- 双向非循环递增链表——插入,删除,清空
- 双向非循环递增链表——插入,删除,清空
- (C++版)链表(三)——实现双向链表的创建、插入、删除等简单操作
- 双向循环链表的插入和删除
- 有序插入时,数组与链表效率比较
- C语言实现双向链表删除节点、插入节点、双向输出等操作
- 双向链表插入与删除
- (C++版)链表(四)——实现双向循环链表创建、插入、删除等简单操作