激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java中雙向鏈表詳解及實例

Java中雙向鏈表詳解及實例

2020-09-21 17:11Dylansuns Java教程

這篇文章主要介紹了Java中雙向鏈表詳解及實例的相關資料,需要的朋友可以參考下

Java雙向鏈表詳解及實例

寫在前面:

  雙向鏈表是一種對稱結構,它克服了單鏈表上指針單向性的缺點,其中每一個節點即可向前引用,也可向后引用,這樣可以更方便的插入、刪除數據元素。

  由于雙向鏈表需要同時維護兩個方向的指針,因此添加節點、刪除節點時指針維護成本更大;但雙向鏈表具有兩個方向的指針,因此可以向兩個方向搜索節點,因此雙向鏈表在搜索節點、刪除指定索引處節點時具有較好的性能。

Java語言實現雙向鏈表:

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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
package com.ietree.basic.datastructure.dublinklist;
 
/**
 * 雙向鏈表
 *
 * @author Dylan
 */
public class DuLinkList<T> {
 
  // 定義一個內部類Node,Node實例代表鏈表的節點
  private class Node {
 
    // 保存節點的數據
    private T data;
    // 保存上個節點的引用
    private Node prev;
    // 指向下一個節點的引用
    private Node next;
 
    // 無參構造器
    public Node() {
    }
 
    // 初始化全部屬性的構造器
    public Node(T data, Node prev, Node next) {
 
      this.data = data;
      this.prev = prev;
      this.next = next;
 
    }
 
  }
 
  // 保存該鏈表的頭節點
  private Node header;
  // 保存該鏈表的尾節點
  private Node tail;
  // 保存該鏈表中已包含的節點數
  private int size;
 
  // 創建空鏈表
  public DuLinkList() {
 
    // 空鏈表,header和tail都是null
    header = null;
    tail = null;
 
  }
 
  // 以指定數據元素來創建鏈表,該鏈表只有一個元素
  public DuLinkList(T element) {
 
    header = new Node(element, null, null);
    // 只有一個節點,header、tail都指向該節點
    tail = header;
    size++;
 
  }
 
  // 返回鏈表的長度
  public int length() {
 
    return size;
 
  }
 
  // 獲取鏈式線性表中索引為index處的元素
  public T get(int index) {
 
    return getNodeByIndex(index).data;
 
  }
 
  // 根據索引index獲取指定位置的節點
  public Node getNodeByIndex(int index) {
 
    if (index < 0 || index > size - 1) {
 
      throw new IndexOutOfBoundsException("線性表索引越界");
 
    }
    if (index <= size / 2) {
 
      // 從header節點開始
      Node current = header;
      for (int i = 0; i <= size / 2 && current != null; i++, current = current.next) {
        if (i == index) {
 
          return current;
 
        }
      }
 
    } else {
 
      // 從tail節點開始搜索
      Node current = tail;
      for (int i = size - 1; i > size / 2 && current != null; i++, current = current.prev) {
        if (i == index) {
 
          return current;
 
        }
      }
 
    }
 
    return null;
  }
 
  // 查找鏈式線性表中指定元素的索引
  public int locate(T element) {
 
    // 從頭結點開始搜索
    Node current = header;
    for (int i = 0; i < size && current != null; i++, current = current.next) {
 
      if (current.data.equals(element)) {
        return i;
      }
 
    }
    return -1;
 
  }
 
  // 向線性鏈表的指定位置插入一個元素
  public void insert(T element, int index) {
 
    if (index < 0 || index > size) {
      throw new IndexOutOfBoundsException("線性表索引越界");
    }
 
    // 如果還是空鏈表
    if (header == null) {
 
      add(element);
 
    } else {
 
      // 當index為0時,也就是在鏈表頭處插入
      if (index == 0) {
 
        addAtHeader(element);
 
      } else {
 
        // 獲取插入點的前一個節點
        Node prev = getNodeByIndex(index - 1);
        // 獲取插入點的節點
        Node next = prev.next;
        // 讓新節點的next引用指向next節點,prev引用指向prev節點
        Node newNode = new Node(element, prev, next);
        // 讓prev的next節點指向新節點
        prev.next = newNode;
        // 讓prev的下一個節點的prev指向新節點
        next.prev = newNode;
        size++;
      }
 
    }
 
  }
 
  // 采用尾插法為鏈表添加新節點
  public void add(T element) {
 
    // 如果該鏈表還是空鏈表
    if (header == null) {
 
      header = new Node(element, null, null);
      // 只有一個節點,header、tail都指向該節點
      tail = header;
 
    } else {
 
      // 創建新節點,新節點的pre指向原tail節點
      Node newNode = new Node(element, tail, null);
      // 讓尾節點的next指向新增的節點
      tail.next = newNode;
      // 以新節點作為新的尾節點
      tail = newNode;
 
    }
    size++;
  }
 
  // 采用頭插法為鏈表添加新節點
  public void addAtHeader(T element) {
    // 創建新節點,讓新節點的next指向原來的header
    // 并以新節點作為新的header
    header = new Node(element, null, header);
    // 如果插入之前是空鏈表
    if (tail == null) {
 
      tail = header;
 
    }
    size++;
  }
 
  // 刪除鏈式線性表中指定索引處的元素
  public T delete(int index) {
 
    if (index < 0 || index > size - 1) {
 
      throw new IndexOutOfBoundsException("線性表索引越界");
 
    }
    Node del = null;
    // 如果被刪除的是header節點
    if (index == 0) {
 
      del = header;
      header = header.next;
      // 釋放新的header節點的prev引用
      header.prev = null;
 
    } else {
 
      // 獲取刪除節點的前一個節點
      Node prev = getNodeByIndex(index - 1);
      // 獲取將要被刪除的節點
      del = prev.next;
      // 讓被刪除節點的next指向被刪除節點的下一個節點
      prev.next = del.next;
      // 讓被刪除節點的下一個節點的prev指向prev節點
      if (del.next != null) {
 
        del.next.prev = prev;
 
      }
 
      // 將被刪除節點的prev、next引用賦為null
      del.prev = null;
      del.next = null;
 
    }
    size--;
    return del.data;
  }
 
  // 刪除鏈式線性表中最后一個元素
  public T remove() {
 
    return delete(size - 1);
 
  }
 
  // 判斷鏈式線性表是否為空表
  public boolean empty() {
 
    return size == 0;
 
  }
 
  // 清空線性表
  public void clear() {
 
    // 將底層數組所有元素賦為null
    header = null;
    tail = null;
    size = 0;
 
  }
 
  public String toString() {
 
    // 鏈表為空鏈表
    if (empty()) {
 
      return "[]";
 
    } else {
 
      StringBuilder sb = new StringBuilder("[");
      for (Node current = header; current != null; current = current.next) {
 
        sb.append(current.data.toString() + ", ");
 
      }
      int len = sb.length();
      return sb.delete(len - 2, len).append("]").toString();
 
    }
 
  }
 
  // 倒序toString
  public String reverseToString() {
 
    if (empty()) {
 
      return "[]";
 
    } else {
 
      StringBuilder sb = new StringBuilder("[");
      for (Node current = tail; current != null; current = current.prev) {
 
        sb.append(current.data.toString() + ", ");
 
      }
      int len = sb.length();
      return sb.delete(len - 2, len).append("]").toString();
 
    }
 
  }
 
}
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
package com.ietree.basic.datastructure.dublinklist;
 
/**
 * 測試類
 *
 * @author Dylan
 */
public class DuLinkListTest {
 
  public static void main(String[] args) {
 
    DuLinkList<String> list = new DuLinkList<String>();
    list.insert("aaaa", 0);
    list.add("bbbb");
    list.insert("cccc", 0);
    // 在索引為1處插入一個新元素
    list.insert("dddd", 1);
    // 輸出順序線性表的元素
    System.out.println(list);
    // 刪除索引為2處的元素
    list.delete(2);
    System.out.println(list);
    System.out.println(list.reverseToString());
    // 獲取cccc字符串在順序線性表中的位置
    System.out.println("cccc在順序線性表中的位置:" + list.locate("cccc"));
    System.out.println("鏈表中索引1處的元素:" + list.get(1));
    list.remove();
    System.out.println("調用remove方法后的鏈表:" + list);
    list.delete(0);
    System.out.println("調用delete(0)后的鏈表:" + list);
 
  }
 
}
1
2
3
4
5
6
7
[cccc, dddd, aaaa, bbbb]
[cccc, dddd, bbbb]
[bbbb, dddd, cccc]
cccc在順序線性表中的位置:0
鏈表中索引1處的元素:dddd
調用remove方法后的鏈表:[cccc, dddd]
調用delete(0)后的鏈表:[dddd]

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 大西瓜永久免费av在线 | 干少妇av| 免费观看高清视频网站 | 免费在线观看成年人视频 | 双性精h调教灌尿打屁股的文案 | 成人黄色网战 | 黄网站色成年大片免费高 | 黄视频 | 午夜视频在线在免费 | 欧美一级做一a做片性视频 黄色网址免费进入 | 成品片a免费直接观看 | 国产91丝袜在线熟 | 国产一级不卡毛片 | chengrenyingshi| 国产a级网站 | 草操影院 | 国产精品一区二区免费在线观看 | 欧美在线观看视频一区 | 成人不卡 | 免费国产视频在线观看 | 成人在线视频免费观看 | 91精品国产九九九久久久亚洲 | 日本精品网 | 成人午夜免费看 | 亚洲国产精品久久久久婷婷老年 | 日韩精品中文字幕在线观看 | 国产精品视频一区二区三区综合 | 在线播放亚洲 | 中文字幕在线网站 | 成熟女人特级毛片www免费 | 久久影院免费观看 | 在线成人av观看 | 免费一级片观看 | 色诱亚洲精品久久久久久 | 国产精品1区,2区,3区 | 性欧美videos另类极品 | 欧美一及| 一区二区三区欧美日韩 | 米奇电影网 | 精品一区二区电影 | 国产精品久久久久久久久久大牛 |