3、链接表的实现:双向链表
链接表ADT:
1 package ren.laughing.datastructure.base; 2 3 4 import ren.laughing.datastructure.exception.InvalidNodeException; 5 import ren.laughing.datastructure.exception.OutOfBoundaryException; 6 /** 7 * 链接表ADT 8 * 单链表和双链表用顺序存储结构并不友好 9 * 链表方便插入,不方便查找 10 * SLNode和DLNode都实现了Node结点 11 * 因此采用Node结点作为参数、降低算法复杂度 12 * 链接表可以看作是一组结点序列以及基于结点进行操作的线性结构的抽象 13 * @author Laughing_Lz 14 * @time 2016年4月6日 15 */ 16 public interface LinkedList { 17 //查询链接表当前的规模 18 public int getSize(); 19 //判断列表是否为空 20 public boolean isEmpty(); 21 //返回第一个结点 22 public Node first() throws OutOfBoundaryException; 23 //返回最后一结点 24 public Node last() throws OutOfBoundaryException; 25 //返回 p 之后的结点 26 public Node getNext(Node p) throws InvalidNodeException, OutOfBoundaryException; 27 //返回 p 之前的结点 28 public Node getPre(Node p) throws InvalidNodeException, OutOfBoundaryException; 29 //将 e 作为第一个元素插入链接表,并返回 e 所在结点 30 public Node insertFirst(Object e); 31 //将 e 作为最后一个元素插入列表,并返回 e 所在结点 32 public Node insertLast(Object e); 33 //将 e 插入至 p 之后的位置,并返回 e 所在结点 34 public Node insertAfter(Node p, Object e) throws InvalidNodeException; 35 //将 e 插入至 p 之前的位置,并返回 e 所在结点 36 public Node insertBefore(Node p, Object e) throws InvalidNodeException; 37 //删除给定位置处的元素,并返回之 38 public Object remove(Node p) throws InvalidNodeException; 39 //删除首元素,并返回之 40 public Object removeFirst() throws OutOfBoundaryException; 41 //删除末元素,并返回之 42 public Object removeLast() throws OutOfBoundaryException; 43 //将处于给定位置的元素替换为新元素,并返回被替换的元素 44 public Object replace(Node p, Object e) throws InvalidNodeException; 45 //元素迭代器 46 public Iterator elements(); 47 }
双向链表:
1 package ren.laughing.datastructure.baseImpl; 2 3 import ren.laughing.datastructure.base.Iterator; 4 import ren.laughing.datastructure.base.LinkedList; 5 import ren.laughing.datastructure.base.Node; 6 import ren.laughing.datastructure.exception.InvalidNodeException; 7 import ren.laughing.datastructure.exception.OutOfBoundaryException; 8 /** 9 * 链接表的实现:双向链表 10 * @author Laughing_Lz 11 * @time 2016年4月6日 12 */ 13 public class DLinkList implements LinkedList{ 14 private DLNode head;//头结点 15 private DLNode tail;//尾结点 16 private int size;//规模 17 18 public DLinkList() { 19 size=0; 20 head = new DLNode(); 21 tail = new DLNode(); 22 head.setNext(tail);//初始化双链表时,首尾结点互指 23 tail.setPre(head); 24 } 25 //辅助方法:检验结点p是否合法,如合法转换为DLNode 26 public DLNode checkPosition(Node p) throws InvalidNodeException{ 27 if(p == null){ 28 throw new InvalidNodeException("错误:p为空"); 29 }else if(p==head){ 30 throw new InvalidNodeException("错误:p指向头结点,非法"); 31 }else if(p == tail){ 32 throw new InvalidNodeException("错误:p指向尾结点,非法"); 33 }else{ 34 DLNode node = (DLNode) p; 35 return node; 36 } 37 } 38 39 @Override 40 public int getSize() { 41 return this.size; 42 } 43 44 @Override 45 public boolean isEmpty() { 46 if(this.size==0){ 47 return true; 48 }else{ 49 return false; 50 } 51 } 52 53 @Override 54 public Node first() throws OutOfBoundaryException { 55 if(size==0){ 56 throw new OutOfBoundaryException("链接表为空"); 57 }else{ 58 return head.getNext();//返回DLNode(已实现Node) 59 } 60 } 61 62 @Override 63 public Node last() throws OutOfBoundaryException { 64 if(size==0){ 65 throw new OutOfBoundaryException("链接表为空"); 66 }else{ 67 return tail.getPre();//返回DLNode(已实现Node) 68 } 69 } 70 71 @Override 72 public Node getNext(Node p) throws InvalidNodeException, OutOfBoundaryException { 73 DLNode node = this.checkPosition(p); 74 node = node.getNext(); 75 if(node == tail){ 76 throw new OutOfBoundaryException("错误:已经是链表尾端"); 77 } 78 return node; 79 } 80 81 @Override 82 public Node getPre(Node p) throws InvalidNodeException, OutOfBoundaryException { 83 DLNode node =this.checkPosition(p); 84 node = node.getPre(); 85 if(node == head){ 86 throw new OutOfBoundaryException("错误:已经是链表首端"); 87 } 88 return node; 89 } 90 //将 e 作为第一个元素插入链接表,并将含有该元素的结点返回 91 @Override 92 public Node insertFirst(Object e) { 93 DLNode p = new DLNode(e, head, head.getNext()); 94 head.getNext().setPre(p); 95 head.setNext(p); 96 size++; 97 return p; 98 } 99 //将 e 作为最后一个元素插入链接表,并将含有该元素的结点返回 100 @Override 101 public Node insertLast(Object e) { 102 DLNode p = new DLNode(e, tail.getPre(), tail); 103 tail.getPre().setNext(p); 104 tail.setPre(p); 105 size++; 106 return p; 107 } 108 109 @Override 110 public Node insertAfter(Node p, Object e) throws InvalidNodeException { 111 DLNode node = checkPosition(p); 112 DLNode newNode = new DLNode(e, node, node.getNext()); 113 node.getNext().setPre(newNode); 114 node.setNext(newNode); 115 size++; 116 return newNode; 117 } 118 119 @Override 120 public Node insertBefore(Node p, Object e) throws InvalidNodeException { 121 DLNode node = checkPosition(p); 122 DLNode newNode = new DLNode(e, node.getPre(), node); 123 node.getPre().setNext(newNode); 124 node.setPre(newNode); 125 size++; 126 return newNode; 127 } 128 129 @Override 130 public Object remove(Node p) throws InvalidNodeException { 131 DLNode node = checkPosition(p); 132 node.getPre().setNext(node.getNext()); 133 node.getNext().setPre(node.getPre()); 134 size--; 135 return node.getData(); 136 } 137 138 @Override 139 public Object removeFirst() throws OutOfBoundaryException { 140 return remove(head.getNext()); 141 } 142 143 @Override 144 public Object removeLast() throws OutOfBoundaryException { 145 return remove(tail.getPre()); 146 } 147 148 @Override 149 public Object replace(Node p, Object e) throws InvalidNodeException { 150 DLNode node = checkPosition(p); 151 Object obj = node.getData(); 152 node.setData(e); 153 return obj; 154 } 155 //元素迭代器 156 @Override 157 public Iterator elements() { 158 Iterator it = new LinkListIterator(this); 159 return it; 160 } 161 162 }
涉及到使用迭代器遍历链表,代码如下:
1 package ren.laughing.datastructure.base; 2 /** 3 * 迭代器,为了遍历链表中的数据元素 4 * @author Laughing_Lz 5 * @time 2016年4月6日 6 */ 7 public interface Iterator { 8 // 移动到第一个元素 9 public void first(); 10 11 // 移动到下一个元素 12 public void next(); 13 14 // 检查迭代器中是否还有剩余的元素 15 public boolean isDone(); 16 17 // 返回当前元素 18 public Object currentItem(); 19 }
1 package ren.laughing.datastructure.baseImpl; 2 3 import ren.laughing.datastructure.base.Iterator; 4 import ren.laughing.datastructure.base.LinkedList; 5 import ren.laughing.datastructure.base.Node; 6 import ren.laughing.datastructure.exception.OutOfBoundaryException; 7 /** 8 * 对于链接表的迭代器的实现 9 * @author Laughing_Lz 10 * @time 2016年4月6日 11 */ 12 public class LinkListIterator implements Iterator{ 13 private LinkedList linkedList;//链接表 14 private Node current;//当前结点 15 16 public LinkListIterator(LinkedList linkedList) { 17 this.linkedList = linkedList; 18 if(linkedList.isEmpty()){//若当前链表为空 19 current = null;//当前结点置空 20 }else{ 21 current = linkedList.first();//否则从第一个数据元素开始 22 } 23 } 24 25 @Override 26 public void first() { 27 if(linkedList.isEmpty()){ 28 current = null; 29 }else{ 30 current = linkedList.first(); 31 } 32 } 33 34 @Override 35 public void next() { 36 if(isDone()){ 37 throw new OutOfBoundaryException("错误:已经没有未遍历的元素了"); 38 }else if(current == linkedList.last()){ 39 current = null;//已经到达最后一个数据元素 40 }else{ 41 current= linkedList.getNext(current); 42 } 43 } 44 //检查迭代器中是否还有剩余的元素 45 @Override 46 public boolean isDone() { 47 if(current == null){ 48 return true; 49 }else{ 50 return false; 51 } 52 } 53 //返回当前元素 54 @Override 55 public Object currentItem() throws OutOfBoundaryException { 56 if(isDone()){ 57 throw new OutOfBoundaryException("错误:已经没有未遍历的元素了"); 58 } 59 return current.getData(); 60 } 61 62 }
—————————————————————————————————————行走在人猿的并行线——Laughing_Lz