Professional Documents
Culture Documents
A/. Mô tả, tính chất của danh sách liên kết đơn
- Bên trên chính là hình ảnh mô tả một danh sách liên kết đơn. Trong hình, mỗi một ô
hình chữ nhật được gọi là một "Node". Trong một "Node" chứa 2 thuộc tính:
Data (dữ liệu): có thể là số nguyên, số thực hay là sinh viên, nhân viên...
Next: là một con trỏ để lưu địa chỉ của "Node" tiếp theo. Nói đơn giản là nó trỏ
đến phần tử kế tiếp như trong hình. Cũng có thể hiểu nó như một sợi dây buộc
vào Node tiếp theo
- Tính chất danh sách liên kết đơn:
Là một danh sách sử dụng con trỏ và động.
Danh sách liên kết có thể thêm phần tử vào thoải mái đến khi nào hết bộ nhớ
máy tính thì thôi.
Đối với mảng các phần tử trong mảng phải liên tiếp nhau, còn với Danh Sách
Liên Kết thì khác, các "Node" có thể nằm ở bất kì đâu trong bộ nhớ. Chỉ cần
chúng ta liên kết chúng lại với nhau thì sẽ tạo thành một danh sách.
Danh Sách Liên Kết đơn chỉ được đi tiến chứ không được đi lùi.
Ví dụ: Ta cần truy xuất phần tử thứ 2 trong Danh Sách Liên Kết Đơn, ta phải duyệt
từ đầu đến phần tử thứ 2 chứ không thể duyệt ngược lại từ cuối.
B/. Cài đặt và các phép toán trên Danh Sách Liên Kết Đơn
1/. Dạng cài đặt
Tạo một cấu trúc struct Node gồm 2 thuộc tính: Data (dữ liệu) và con trỏ Next
kiểu dữ liệu là Node luôn, vì con trỏ Next trỏ đến một Node khác.
Ví dụ: bạn khai báo một con trỏ P trỏ đến một bến kiểu nguyên (int) thì là: int P. Thì
tương tự như vậy Next trỏ đến "Node" thì phải là kiểu Node.
Khai báo thêm một kiểu cấu trúc struct LinkList để tượng trưng cho cả một
danh sách (gồm nhiều Node).
2
5/. Thêm Node vào Danh sách
Thêm vào Đầu danh sách (AddHead)
Vì L chính là Node đầu tiên vì thế ta chỉ cần cập nhật lại L là xong.
Cho Next của P (như là sợi dây) trỏ hay buộc vào L. Lúc này P chính là Node
đầu tiên thì cập nhật lại L chính là P.
3
5 if (IsEmpty(L) == true)
6 L = P; // nếu danh sách rỗng thì P chính là L luôn
7 else
8 {
9 Node* M; // khai báo node M
10 M = L; // gán M bằng L đầu danh sách
while (M->Next != NULL) // M tăng dần khi M->Next = NULL thì dừng
11 {
12 M = M->Next;
13 }
14 M->Next = P; // xác định được node cuối rồi thì nối vào P
15
P->Next = NULL; // P là node cuối cùng nên Next trỏ đến NULL
16
}
17
}
18
Đếm số lượng Node hay phần tử trong danh sách (Quantity)
Tạo node M cho nó chạy từ đầu danh sách, mỗi lần tăng lên thì số lượng tăng
thêm 1 đơn vị.
1 int Quantity(LinkList L)
2 {
3 int temp = 0; // khởi tạo ban đầu bằng 0
4 for (Node* M = L; M != NULL; M = M->Next) // M tăng lên bằng NULL thì dừng
5 {
6 temp++; // mỗi lần lặp temp tăng lên
7 }
8 return temp; // trả về temp
9 }
Thêm vào vị trí k bất kỳ (AddAny)
Kiểm tra vị trí k có thỏa mãn hay không? Nếu thỏa mãn thì xác định Node M
trước vị trí k. Sau đó cho Next của P trỏ vào Node mà Next của M đang trỏ (P->Next
= M->Next). Nối M với P (M->Next = P)
1 void AddAny(LinkList& L, int k, int x)
2 {
3 if (k < 1 || k > Quantity(L)) // kiểm tra vị trí k có thỏa mãn hay không?
4 cout << "Not Add. " << endl;
5 else
6 {
7 if (k == 1) // nếu k = 1 thì chính là thêm vào phần tử đầu tiên
8 AddHead(L, x);
9 else
10 {
11 Node* P;
12 P = AddNode(x); // tạo node P với giá trị x
13 Node* M = L; // tạo node M bằng L
14 int temp = 1; // biến temp để biết điều kiện dừng
15 while (temp != k - 1 && M != NULL)
16 {
17 temp++;
18 M = M->Next; // M tăng dần lên
4
19 }
20 P->Next = M->Next; // P->Next bằng chính là Node mà M->Next trỏ đến
21 M->Next = P; // M->Next là P;
22 }
23 }
24 }
5
C/. Danh sách số nguyên toàn bộ chức năng trên
1 #include <iostream>
2 using namespace std;
3
4 typedef struct Node
5 {
6 int Data;
7 Node* Next;
8 };
9
10 typedef struct Node* LinkList;
11
12 void Init(LinkList& L)
13 {
14 L = NULL;
15 }
16
17 bool IsEmpty(LinkList L)
18 {
19 if (L == NULL) return true;
20 return false;
21 }
22
23 int Quantity(LinkList L)
24 {
25 int temp = 0;
26 for (Node* M = L; M != NULL; M = M->Next)
27 {
28 temp++;
29 }
30 return temp;
31 }
32
33 Node* AddNode(int x)
34 {
35 Node* P;
36 P = new Node;
37 P->Data = x;
38 P->Next = NULL;
39 return P;
40 }
41
42 void AddTail(LinkList& L, int x)
43 {
44 Node* P;
45 P = AddNode(x);
46 if (IsEmpty(L) == true)
47 L = P;
48 else
49 {
50 Node* M;
51 M = L;
6
52 while (M->Next != NULL)
53 {
54 M = M->Next;
55 }
56 M->Next = P;
57 P->Next = NULL;
58 }
59 }
60
61 void AddHead(LinkList& L, int x)
62 {
63 Node* P;
64 P = AddNode(x);
65 if (IsEmpty(L) == true)
66 L = P;
67 else
68 {
69 P->Next = L;
70 L = P;
71 }
72 }
73
74 void AddAny(LinkList& L, int k, int x)
75 {
76 if (k < 1 || k > Quantity(L))
77 cout << "Not Add. " << endl;
78 else
79 {
80 if (k == 1)
81 AddHead(L, x);
82 else
83 {
84 Node* P;
85 P = AddNode(x);
86 Node* M = L;
87 int temp = 1;
88 while (temp != k - 1 && M != NULL)
89 {
90 temp++;
91 M = M->Next;
92 }
93 P->Next = M->Next;
94 M->Next = P;
95 }
96 }
97 }
98
99 void DeleteHead(LinkList& L)
100 {
101 L = L->Next;
102 }
103
104 void DeleteTail(LinkList& L)
7
105 {
106 Node* M = L;
107 while(M->Next->Next != NULL)
108 {
109 M = M->Next;
110 }
111 M->Next = NULL;
112 }
113
114 void DeleteAny(LinkList& L, int k)
115 {
116 if (k < 1 || k> Quantity(L))
117 cout << "Not Delete." << endl;
118 else
119 {
120 if (k == 1)
121 DeleteHead(L);
122 else
123 {
124 Node* M = L;
125 int temp = 1;
126 while (temp != k - 1 && M != NULL)
127 {
128 temp++;
129 M = M->Next;
130 }
131 M->Next = M->Next->Next;
132 }
133 }
134 }
135
136 void InPut(LinkList& L, int n)
137 {
138 Init(L);
139 int x;
140 for (int i = 0; i < n; i++)
141 {
142 cout << "Value " << i << " : ";
143 cin >> x;
144 AddTail(L, x);
145 }
146 }
147
148 void OutPut(LinkList L)
149 {
150 for (Node* M = L; M != NULL; M = M->Next)
151 {
152 cout << M->Data << " ";
153 }
154 }
155
156 int main()
157 {
8
158 LinkList L;
159 int n, select;
160 cout << "Quantity: ";
161 cin >> n;
162 InPut(L, n);
163 do
164 {
165 cout << endl;
166 cout << "1. Add Head. " << endl;
167 cout << "2. Add Tail. " << endl;
168 cout << "3. Add Any. " << endl;
169 cout << "4. Delete Head. " << endl;
170 cout << "5. Delete Tail. " << endl;
171 cout << "6. Delete Any. " << endl;
172 cout << "9. OutPut. " << endl;
173 cout << "0. Exit." << endl;
174 cin >> select;
175 switch (select)
176 {
177 case 1:
178 {
179 int x;
180 cout << "Value: ";
181 cin >> x;
182 AddHead(L, x);
183 break;
184 }
185 case 2:
186 {
187 int x;
188 cout << "Value: ";
189 cin >> x;
190 AddTail(L, x);
191 break;
192 }
193 case 3:
194 {
195 int x, k;
196 cout << "Possity: ";
197 cin >> k;
198 cout << "Value: ";
199 cin >> x;
200 AddAny(L,k, x);
201 break;
202 }
203 case 4:
204 {
205 DeleteHead(L);
206 break;
207 }
208 case 5:
209 {
210 DeleteTail(L);
9
211 break;
212 }
213 case 6:
214 {
215 int k;
216 cout << "Possity Delete: ";
217 cin >> k;
218 DeleteAny(L, k);
219 break;
220 }
221 case 9:
222 {
223 OutPut(L);
224 break;
225 }
226 }
227 } while (select != 0);
228 }
10