理論基礎:
在結點中設兩個引用域,一個保存直接前驅結點的地址,叫prev,一個直接後繼結點的地址,叫next,這樣的鏈表就是雙向鏈表(Doubly Linked List)。
雙向鏈表的結點結構示意圖如上,雙向鏈表結點的定義與單鏈表的結點的定義很相似,因此,雙向鏈表節點類的實現可以參考單鏈表的節點類。
C#實現:
1接口
引用線性表的接口IListDS<T>
2實現
(1)雙向鏈表節點類,參考單鏈表的節點類
Code
[copy to clipboard]
CODE:
1 public class DBNode<T>
2 {
3 private T data; //數據域
4 private DBNode<T> next; //後繼
5 private DBNode<T> prev; //前驅
6 public T Data
7 {
8 get { return data; }
9 set { data = value; }
10 }
11 public DBNode<T> Next
12 {
13 get { return next; }
14 set { next = value; }
15 }
16 public DBNode<T> Prev
17 {
18 get { return prev; }
19 set { prev = value; }
20 }
21 public DBNode()
22 {
23 data = default(T);
24 prev = null;
25 next = null;
26 }
27 public DBNode(T val)
28 {
29 data = val;
30 next = null;
31 prev = null;
32 }
33 }
(2) 雙向鏈表操作類實現
注意:由於雙向鏈表的結點有兩個引用,所以,在雙向鏈表中插入和刪除結點比單鏈表要復雜。雙向鏈表中結點的插入分為在結點之前插入和在結點之後插入,插入操作要對四個引用進行操作
同樣,刪除操作也需要多多注意,其他的操作和單鏈表類似,不再贅述.
Code
[copy to clipboard]
CODE:
1public class DBLinkList<T> : IListDS<T>
2 {
3 private DBNode<T> header;
4 public DBNode<T> Header
5 {
6 get
7 {
8 return header;
9 }
10 set
11 {
12 header = value;
13 }
14 }
15 public DBLinkList()
16 {
17 header = new DBNode<T>();
18 header.Next = null;
19 header.Prev = null;
20 }
21 /**//// <summary>
22 /// 獲取長度
23 /// </summary>
24 /// <returns></returns>
25 public int GetLength()
26 {
27 DBNode<T> p = header;
28 int len = 0;
29 while (p != null)
30 {
31 ++len;
32 p = p.Next;
33 }
34 return len;
35 }
36 /**//// <summary>
37 /// 清空操作
38 /// </summary>
39 public void Clear()
40 {
41 header = null;
42 }
43 /**//// <summary>
44 /// 判斷線性表是否為空
45 /// </summary>
46 /// <returns></returns>
47 public bool IsEmpty()
48 {
49 if (header.Data==null)
50 {
51 return true;
52 }
53 else
54 {
55 return false;
56 }
57 }
58 /**//// <summary>
59 /// 查找節點
60 /// </summary>
61 /// <param name="i"></param>
62 /// <returns></returns>
63 private DBNode<T> FindNode(int i)
64 {
65 if (IsEmpty())
66 {
67 Console.Write("list is empty");
68 return null;
69 }
70 if (i < 1)
71 {
72 Console.Write("Index is error");
73 return null;
74 }
75 DBNode<T> current = new DBNode<T>();
76 current = header;
77 int j = 1;
78 while (current.Next != null && j < i)
79 {
80 ++j;
81 current = current.Next;
82 }
83 return current;
84 }
85 /**//// <summary>
86 /// 插入操作,在第i個節點前面
87 /// </summary>
88 /// <param name="item"></param>
89 /// <param name="i"></param>
90 public void Insert(T item, int i)
91 {
92 DBNode<T> current = FindNode(i);
93 DBNode<T> newNode = new DBNode<T>(item);
94 if (current != null)
95 {
96 current.Prev.Next = newNode;
97 newNode.Next = current;
98 newNode.Prev = current.Prev;
99 current.Prev = newNode;
100 }
101 else
102 {
103 Console.Write("the node is not exist!");
104 }
105 }
106 /**//// <summary>
107 /// 插入操作,在第i個節點後面插入item
108 /// </summary>
109 /// <param name="item"></param>
110 /// <param name="i"></param>
111 public void InsertBack(T item, int i)
112 {
113 DBNode<T> current = FindNode(i);
114 DBNode<T> newNode = new DBNode<T>(item);
115 if (current != null)
116 {
117 current.Next.Prev = newNode;
118 newNode.Prev = current;
119 newNode.Next = current.Next;
120 current.Next = newNode;
121 }
122 else
123 {
124 Console.Write("the node is not exist!");
125 }
126 }
127 /**//// <summary>
128 /// 附加操作,線性表未滿,將值為item的新元素添加到末尾
129 /// </summary>
130 /// <param name="item"></param>
131 public void Append(T item)
132 {
133 DBNode<T> newNode = new DBNode<T>(item);
134 DBNode<T> p = new DBNode<T>();
135 if (header == null)
136 {
137 header = newNode;
138 return;
139 }
140 p = header;
141
142 while (p.Next != null)
143 {
144 p = p.Next;
145 }
146 p.Next = newNode;
147 }
148
149 /**//// <summary>
150 /// 刪除操作
151 /// </summary>
152 /// <param name="i"></param>
153 /// <returns></returns>
154 public T Delete(int i)
155 {
156 DBNode<T> current = FindNode(i);
157 if (current != null)
158 {
159 current.Prev.Next = current.Next;
160 current.Next.Prev = current.Prev;
161 current.Prev = null;
162 current.Next = null;
163 return current.Data;
164 }
165 else
166 {
167 Console.Write("the node is not exist!");
168 return default(T);
169 }
170 }
171 /**//// <summary>
172 /// 取表元
173 /// </summary>
174 /// <param name="i"></param>
175 /// <returns></returns>
176 public T GetElem(int i)
177 {
178 DBNode<T> current = FindNode(i);
179 if (current != null)
180 {
181 return current.Data;
182 }
183 else
184 {
185 Console.Write("the node is not exist!");
186 return default(T);
187 }
188 }
189
190 /**//// <summary>
191 /// 按值查找
192 /// </summary>
193 /// <param name="value"></param>
194 /// <returns>-1:鏈表或參數異常;0:節點不存在;1:值代表的位置</returns>
195 public int Locate(T value)
196 {
197 if (IsEmpty())
198 {
199 Console.Write("list is empty");
200 return -1;
201 }
202 if (value == null)
203 {
204 Console.Write("value is empty");
205 return -1;
206 }
207 DBNode<T> current = new DBNode<T>();
208 current = header;
209 int result = 0;
210
211 while (current.Next != null)
212 {
213 if (current.Data.Equals(value))
214 {
215 result=1;
217 }
218 }
219 return result;
220 }
221 }
此外,循環鏈表的基本操作與單鏈表大體相同,只是判斷鏈表結束的條件並不是判斷結點的引用域是否為空,
而是判斷結點的引用域是否為頭引用,其它沒有較大的變化,有興趣的朋友可以寫寫。