3、链接表的实现:双向链表

链接表ADT:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package ren.laughing.datastructure.base;
import ren.laughing.datastructure.exception.InvalidNodeException;
import ren.laughing.datastructure.exception.OutOfBoundaryException;
/**
* 链接表ADT
* 单链表和双链表用顺序存储结构并不友好
* 链表方便插入,不方便查找
* SLNode和DLNode都实现了Node结点
* 因此采用Node结点作为参数、降低算法复杂度
* 链接表可以看作是一组结点序列以及基于结点进行操作的线性结构的抽象
* @author Laughing_Lz
* @time 2016年4月6日
*/
public interface LinkedList {
//查询链接表当前的规模
public int getSize();
//判断列表是否为空
public boolean isEmpty();
//返回第一个结点
public Node first() throws OutOfBoundaryException;
//返回最后一结点
public Node last() throws OutOfBoundaryException;
//返回 p 之后的结点
public Node getNext(Node p) throws InvalidNodeException, OutOfBoundaryException;
//返回 p 之前的结点
public Node getPre(Node p) throws InvalidNodeException, OutOfBoundaryException;
//将 e 作为第一个元素插入链接表,并返回 e 所在结点
public Node insertFirst(Object e);
//将 e 作为最后一个元素插入列表,并返回 e 所在结点
public Node insertLast(Object e);
//将 e 插入至 p 之后的位置,并返回 e 所在结点
public Node insertAfter(Node p, Object e) throws InvalidNodeException;
//将 e 插入至 p 之前的位置,并返回 e 所在结点
public Node insertBefore(Node p, Object e) throws InvalidNodeException;
//删除给定位置处的元素,并返回之
public Object remove(Node p) throws InvalidNodeException;
//删除首元素,并返回之
public Object removeFirst() throws OutOfBoundaryException;
//删除末元素,并返回之
public Object removeLast() throws OutOfBoundaryException;
//将处于给定位置的元素替换为新元素,并返回被替换的元素
public Object replace(Node p, Object e) throws InvalidNodeException;
//元素迭代器
public Iterator elements();
}

双向链表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package ren.laughing.datastructure.baseImpl;
 
import ren.laughing.datastructure.base.Iterator;
import ren.laughing.datastructure.base.LinkedList;
import ren.laughing.datastructure.base.Node;
import ren.laughing.datastructure.exception.InvalidNodeException;
import ren.laughing.datastructure.exception.OutOfBoundaryException;
/**
 * 链接表的实现:双向链表
 * @author Laughing_Lz
 * @time 2016年4月6日
 */
public class DLinkList implements LinkedList{
    private DLNode head;//头结点
    private DLNode tail;//尾结点
    private int size;//规模
 
    public DLinkList() {
        size=0;
        head = new DLNode();
        tail = new DLNode();
        head.setNext(tail);//初始化双链表时,首尾结点互指
        tail.setPre(head);
    }
    //辅助方法:检验结点p是否合法,如合法转换为DLNode
    public DLNode checkPosition(Node p) throws InvalidNodeException{
        if(p == null){
            throw new InvalidNodeException("错误:p为空");
        }else if(p==head){
            throw new InvalidNodeException("错误:p指向头结点,非法");
        }else if(p == tail){
            throw new InvalidNodeException("错误:p指向尾结点,非法");
        }else{
            DLNode node = (DLNode) p;
            return node;
        }
    }
 
    @Override
    public int getSize() {
        return this.size;
    }
 
    @Override
    public boolean isEmpty() {
        if(this.size==0){
            return true;
        }else{
            return false;
        }
    }
 
    @Override
    public Node first() throws OutOfBoundaryException {
        if(size==0){
            throw new OutOfBoundaryException("链接表为空");
        }else{
            return head.getNext();//返回DLNode(已实现Node)
        }
    }
 
    @Override
    public Node last() throws OutOfBoundaryException {
        if(size==0){
            throw new OutOfBoundaryException("链接表为空");
        }else{
            return tail.getPre();//返回DLNode(已实现Node)
        }
    }
 
    @Override
    public Node getNext(Node p) throws InvalidNodeException, OutOfBoundaryException {
        DLNode node = this.checkPosition(p);
        node  = node.getNext();
        if(node == tail){
            throw new OutOfBoundaryException("错误:已经是链表尾端");
        }
        return node;
    }
 
    @Override
    public Node getPre(Node p) throws InvalidNodeException, OutOfBoundaryException {
        DLNode node =this.checkPosition(p);
        node = node.getPre();
        if(node == head){
            throw new OutOfBoundaryException("错误:已经是链表首端");
        }
        return node;
    }
    //将 e 作为第一个元素插入链接表,并将含有该元素的结点返回
    @Override
    public Node insertFirst(Object e) {
        DLNode p = new DLNode(e, head, head.getNext());
        head.getNext().setPre(p);
        head.setNext(p);
        size++;
        return p;
    }
    //将 e 作为最后一个元素插入链接表,并将含有该元素的结点返回
    @Override
    public Node insertLast(Object e) {
        DLNode p = new DLNode(e, tail.getPre(), tail);
        tail.getPre().setNext(p);
        tail.setPre(p);
        size++;
        return p;
    }
 
    @Override
    public Node insertAfter(Node p, Object e) throws InvalidNodeException {
        DLNode node = checkPosition(p);
        DLNode newNode = new DLNode(e, node, node.getNext());
        node.getNext().setPre(newNode);
        node.setNext(newNode);
        size++;
        return newNode;
    }
 
    @Override
    public Node insertBefore(Node p, Object e) throws InvalidNodeException {
        DLNode node = checkPosition(p);
        DLNode newNode = new DLNode(e, node.getPre(), node);
        node.getPre().setNext(newNode);
        node.setPre(newNode);
        size++;
        return newNode;
    }
 
    @Override
    public Object remove(Node p) throws InvalidNodeException {
        DLNode node = checkPosition(p);
        node.getPre().setNext(node.getNext());
        node.getNext().setPre(node.getPre());
        size--;
        return node.getData();
    }
 
    @Override
    public Object removeFirst() throws OutOfBoundaryException {
        return remove(head.getNext());
    }
 
    @Override
    public Object removeLast() throws OutOfBoundaryException {
        return remove(tail.getPre());
    }
 
    @Override
    public Object replace(Node p, Object e) throws InvalidNodeException {
        DLNode node = checkPosition(p);
        Object obj = node.getData();
        node.setData(e);
        return obj;
    }
    //元素迭代器
    @Override
    public Iterator elements() {
        Iterator it = new LinkListIterator(this);
        return it;
    }
 
}

涉及到使用迭代器遍历链表,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package ren.laughing.datastructure.base;
/**
 * 迭代器,为了遍历链表中的数据元素
 * @author Laughing_Lz
 * @time 2016年4月6日
 */
public interface Iterator {
    // 移动到第一个元素
    public void first();
 
    // 移动到下一个元素
    public void next();
 
    // 检查迭代器中是否还有剩余的元素
    public boolean isDone();
 
    // 返回当前元素
    public Object currentItem();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package ren.laughing.datastructure.baseImpl;
 
import ren.laughing.datastructure.base.Iterator;
import ren.laughing.datastructure.base.LinkedList;
import ren.laughing.datastructure.base.Node;
import ren.laughing.datastructure.exception.OutOfBoundaryException;
/**
 * 对于链接表的迭代器的实现
 * @author Laughing_Lz
 * @time 2016年4月6日
 */
public class LinkListIterator implements Iterator{
    private LinkedList linkedList;//链接表
    private Node current;//当前结点
 
    public LinkListIterator(LinkedList linkedList) {
        this.linkedList = linkedList;
        if(linkedList.isEmpty()){//若当前链表为空
            current = null;//当前结点置空
        }else{
            current = linkedList.first();//否则从第一个数据元素开始
        }
    }
 
    @Override
    public void first() {
        if(linkedList.isEmpty()){
            current = null;
        }else{
            current = linkedList.first();
        }
    }
 
    @Override
    public void next() {
        if(isDone()){
            throw new OutOfBoundaryException("错误:已经没有未遍历的元素了");
        }else if(current == linkedList.last()){
            current = null;//已经到达最后一个数据元素
        }else{
            current= linkedList.getNext(current);
        }
    }
    //检查迭代器中是否还有剩余的元素
    @Override
    public boolean isDone() {
        if(current == null){
            return true;
        }else{
            return false;
        }
    }
    //返回当前元素
    @Override
    public Object currentItem() throws OutOfBoundaryException {
        if(isDone()){
            throw new OutOfBoundaryException("错误:已经没有未遍历的元素了");
        }
        return current.getData();
    }
 
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注