zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Go语言标准库flag基本使用
    GO学习-(12) Go语言基础之函数
    GO学习-(11) Go语言基础之map
    GO学习-(10) Go语言基础之指针
    Spring AOP
    JDK动态代理
    版本控制
    版本控制
    浅析Java反射机制
    Spring Batch学习
  • 原文地址:https://www.cnblogs.com/Laughing-Lz/p/5360286.html
Copyright © 2011-2022 走看看