双链表--双端队列
1) 双链表在最前端和最后端各设置一个哑节点。这两个节点分别称为头结点和尾节点。头结点的next指向首节点,首节点的prev指向头结点。头结点其他域为null。尾节点的prev指向末节点,末节点的next指向尾节点。尾节点其他域为null。
在链表为空时,头结点和尾节点已经存在了,并且此时头结点的next指向尾节点,尾节点的prev指向头结点。另外,再插入和删除时,有些修改指针指向的代码顺序不能修改。双链表实现代码如下:
1 /** 2 * Created by hfz on 2016/8/3. 3 */ 4 /* 5 双链表在最前端和最后端各设置一个哑节点。这两个节点分别称为头结点和尾节点。 6 头结点的next指向首节点,首节点的prev指向头结点。头结点其他域为null 7 尾节点的prev指向末节点,末节点的next指向尾节点。尾节点其他域为null。 8 在链表为空时,头结点和尾节点已经存在了,并且此时头结点的next指向尾节点,尾节点的prev指向头结点。 9 另外,再插入和删除时,有些修改指针指向的代码顺序不能修改。 10 */ 11 public class DList { 12 private DNode headNode; 13 private DNode tailNode; 14 private int size; 15 /* 16 */ 17 public DList(){ 18 headNode=new DNode(); 19 tailNode=new DNode(); 20 headNode.setNext(tailNode); 21 tailNode.setPrev(headNode); 22 size=0; 23 } 24 /* 25 以下方法对链表为空时,同样适用,不必做特殊处理 26 */ 27 28 public void addAtHeader(Object obj){//以下修改指针指向的代码顺序不能修改 29 DNode node=new DNode(obj,headNode,headNode.getNext()); 30 headNode.getNext().setPrev(node); 31 headNode.setNext(node); 32 size++; 33 System.out.println(String.format("在头结点插入%s",(String)obj)); 34 } 35 /* 36 以下方法当链表只有一个元素时同样适用,不用做特殊处理。 37 */ 38 public void removeAtHeader(){ 39 if(size>0){ 40 DNode removedNode=headNode.getNext(); 41 removedNode.getNext().setPrev(headNode); 42 headNode.setNext(removedNode.getNext()); 43 size--; 44 System.out.println(String.format("在头结点删除%s", (String)removedNode.getEle())); 45 } 46 else{ 47 System.out.println("链表为空,无元素可删除!"); 48 } 49 } 50 /* 51 以下方法对链表为空时,同样适用,不必做特殊处理 52 */ 53 public void addAtTail(Object obj){ 54 DNode node =new DNode(obj,tailNode.getPrev(),tailNode); 55 tailNode.getPrev().setNext(node); 56 tailNode.setPrev(node); 57 size++; 58 System.out.println(String.format("在尾结点插入%s",(String)obj)); 59 } 60 /* 61 以下方法当链表只有一个元素时同样适用,不用做特殊处理。 62 */ 63 public void removeAtTail(){ 64 if(size>0){ 65 DNode removedNode=tailNode.getPrev(); 66 tailNode.setPrev(removedNode.getPrev()); 67 removedNode.getPrev().setNext(tailNode); 68 size--; 69 System.out.println(String.format("在尾结点删除%s", (String)removedNode.getEle())); 70 71 } 72 else { 73 System.out.println("链表为空,无元素可删除!"); 74 } 75 } 76 public int getSize(){ 77 return size; 78 } 79 //test 80 public static void main(String[] args){ 81 DList doubleList=new DList(); 82 doubleList.addAtHeader("A1"); 83 doubleList.addAtHeader("A2"); 84 doubleList.addAtHeader("A3"); 85 doubleList.addAtHeader("A4"); 86 doubleList.addAtHeader("A5"); 87 doubleList.addAtHeader("A6"); 88 doubleList.removeAtHeader(); 89 doubleList.removeAtHeader(); 90 doubleList.removeAtHeader(); 91 doubleList.removeAtHeader(); 92 doubleList.removeAtHeader(); 93 doubleList.removeAtHeader(); 94 doubleList.removeAtHeader(); 95 doubleList.addAtTail("B1"); 96 doubleList.addAtTail("B2"); 97 doubleList.addAtTail("B3"); 98 doubleList.addAtTail("B4"); 99 doubleList.addAtTail("B5"); 100 doubleList.addAtTail("B6"); 101 doubleList.removeAtTail(); 102 doubleList.removeAtTail(); 103 doubleList.removeAtTail(); 104 doubleList.removeAtTail(); 105 doubleList.removeAtTail(); 106 doubleList.removeAtTail(); 107 doubleList.removeAtTail(); 108 doubleList.addAtHeader("C1"); 109 doubleList.addAtHeader("C2"); 110 doubleList.addAtTail("B2"); 111 doubleList.addAtTail("B3"); 112 doubleList.addAtTail("B4"); 113 doubleList.addAtTail("B5"); 114 doubleList.addAtHeader("A3"); 115 doubleList.addAtHeader("A4"); 116 doubleList.addAtHeader("A5"); 117 doubleList.addAtHeader("A6"); 118 doubleList.removeAtHeader(); 119 doubleList.removeAtHeader(); 120 doubleList.removeAtHeader(); 121 doubleList.removeAtTail(); 122 doubleList.removeAtTail(); 123 } 124 } 125 /* 126 单链表中每个节点只有一个指向后继节点的指针,而双链表中,每个节点还多了一个指向前驱结点的指针 127 */ 128 129 class DNode{ 130 private Object ele; 131 private DNode prev; 132 private DNode next; 133 public DNode(){ 134 this(null,null,null); 135 } 136 public DNode(Object ele,DNode prev,DNode next){ 137 this.ele=ele; 138 this.prev=prev; 139 this.next=next; 140 } 141 public Object getEle(){ 142 return ele; 143 } 144 public void setEle(Object obj){ 145 ele=obj; 146 } 147 148 public DNode getPrev(){ 149 return prev; 150 } 151 152 public void setPrev(DNode node){ 153 prev=node; 154 } 155 156 public DNode getNext(){ 157 return next; 158 } 159 public void setNext(DNode node){ 160 next=node; 161 } 162 163 }
2)双端队列,就是前端和后端都支持插入和删除的队列。可以参考基于单链表的队列实现,来实现基于双链表的双端队列的实现。基于双链表的双端队列,各方法时间复杂度如下图所示: