Chương 2: Các ADTs
1
Chương 2
Các kiểu dữ liệu trừu tượng cơ bả n
(Basic Abstract Data Types)
Chương 2: Các ADTs
2
Nội dung
• Danh sách (List)
– Cài đặt bằng mảng
– Cài đặt bằng con trỏ
– Cài đặt bằng con nháy (tham khảo)
• Ngăn xếp (Stack)
• Hàng đợi (Queue)
• Danh sách liên kết kép (Double Linked List) (tham khảo)
Chương 2: Các ADTs
3
• Khái niệm
• Các phép toán
• Cài đặt danh sách (CĐ DS)
– bằng mảng danh sách đặc
– bằng con trỏ danh sách liên kết (Single Linked List)
Danh sách (List)
Chương 2: Các ADTs
4
Khái niệm DS
• Là tập hợp hữu hạn các phần tử có cùng kiểu
• Kiểu chung được gọi là kiểu phần tử (Element Type)
• Thường biểu diễn dưới dạng: a
1
, a
2
, , a
n
• Nếu
– n=0: danh sách rỗng
– n>0: phần tử đầu tiên là a
1
, phần tử cuối cùng là a
n
• Độ dài của DS: số phần tử của DS
• Các phần tử trong DS có thứ tự tuyến tính theo vị trí xuất
hiện: a
i
đứng trước a
i+1
(i=1 n-1)
Chương 2: Các ADTs
5
Các phép toán trên DS (1)
Trả về vị trí trước phần tử p trong LPrevious(p, L)
Kiểm tra xem L có đầy hay khôngFull_List(L)
Trả về vị trí sau phần tử p trong LNext(p, L)
Trả về vị trí sau phần tử cuối trong LEnd_List(L)
Trả về vị trí phần tử đầu tiên trong LFirst_List(L)
Kiểm tra xem L có rỗng hay khôngEmpty_List(L)
Khởi tạo danh sách L rỗngMakeNull_List(L)
Chức năngPhép toán
Chương 2: Các ADTs
6
Các phép toán trên DS (2)
Nhập giá trị các phần tử trong LRead_List(L)
Truy xuất giá trị phần tử thứ p trong danh
sách L
Retrieve(p, L)
Trả về vị trí của phần tử có nội dung x trong
L, nếu không tìm thấy trả về End_List(L)
Locate(x, L)
Xóa phần tử tại vị trí p trong LDelete_List(p, L)
Hiển thị các phần tử trong L theo thứ tự
xuất hiện
Print_List(L)
Chèn phần tử có nội dung x vào L tại vị trí pInsert_List(x, p, L)
Chức năngPhép toán
Chương 2: Các ADTs
7
Áp dụng
• Thêm phần tử x vào đầu/ cuối L?
• Xóa phần tử ở đầu/ cuối L?
• Truy xuất phần tử ở đầu/ cuối L?
Insert_List(x, First_List(L), L)
Delete_List(First_List(L), L)
Retrieve(First_List(L), L)
Chương 2: Các ADTs
8
Ví dụ
Dùng các phép toán trừu tượng trên danh sách, viết hàm sắp
xếp danh sách theo thứ tự tăng dần
void Sort(List L)
{ Position p,q; //kiểu vị trí của các phần tử
p= First_List(L); // vị trí phần tử ñầu tiên
while (p->Next != End_List(L)) {
q = Next(p,L); // vị trí phần tử sau phần tử p
while (q != End_List(L)) {
if (Retrieve(p, L) > Retrieve(q, L))
Swap(p, q); // hoán ñổi nội dung 2 phần tử
q = Next(q, L);
}
p = Next(p, L);
}
}
Chương 2: Các ADTs
9
CĐ DS bằng mảng (1)
• Vị trí của phần tử trong danh sách:“chỉ số mảng tại vị trí
lưu trữ phần tử + 1”
Vị trí
1
2
3
…
Last
MaxLength
Chương 2: Các ADTs
10
CĐ DS bằng mảng (2)
• Dùng 1 mảng để lưu trữ liên tiếp các phần tử (Elements)
• Có kiểu phần tử (ElementType) và kiểu vị trí (Position)
xác định
• Phải ước lượng số phần tử tối đa của danh sách
(MaxLength)
• Phải lưu trữ độ dài hiện tại của danh sách (Last)
Chương 2: Các ADTs
11
CĐ DS bằng mảng (3)_Khai báo
#define MaxLength
typedef ElementType;
typedef int Position;
typedef struct {
ElementType Elements[MaxLength];
Position Last;
} List;
Khai báo khi sử dụng
List L;
Chương 2: Các ADTs
12
CĐ DS bằng mảng (4)_Khởi tạo L rỗng
• Cho độ dài danh sách bằng 0
void MakeNull_List(List *L){
L->Last = 0;
}
Chương 2: Các ADTs
13
CĐ DS bằng mảng (5)_Kiểm tra L rỗng?
• Độ dài danh sách có bằng 0 hay không?
int Empty_List(List L){
return (L.Last == 0);
}
Chương 2: Các ADTs
14
CĐ DS bằng mảng (6)_Kiểm tra L đầy?
• Độ dài danh sách có bằng MaxLength hay không?
int Full_List(List L){
return (L.Last == MaxLength);
}
Chương 2: Các ADTs
15
CĐ DS bằng mảng (7)_Vị trí phần tử đầu tiên
• Vị trí 1
Position First_List(List L){
return 1;
}
Chương 2: Các ADTs
16
CĐ DS bằng mảng (8)_Vị trí sau phần tử cuối
• Vị trí Last + 1
Position End_List(List L){
return (L.Last + 1);
}
Chương 2: Các ADTs
17
CĐ DS bằng mảng (9)_Vị trí phần tử kế tiếp p
• Vị trí p + 1
Position Next(Position p, List L){
return (p + 1);
}
Chương 2: Các ADTs
18
CĐ DS bằng mảng (10)_Vị trí phần tử trước p
• Vị trí p - 1
Position Previous(Position p, List L){
return (p - 1);
}
Chương 2: Các ADTs
19
CĐ DS bằng mảng (11)_Truy xuất phần tử thứ p
• Giá trị tại chỉ số p - 1
ElementType Retrieve(Position p, List L){
return (L.Elements[p-1]);
}
Chương 2: Các ADTs
20
CĐ DS bằng mảng (12)_Chèn x vào vị trí p
Nếu mảng đầy in thông báo …
Nếu vị trí p không hợp lệ ( p < 1 hoặc
p > End_List(L) ) in thông báo …
Ngược lại
• Dời các phần tử từ vị trí p đến cuối ra sau một vị trí
• Đưa phần tử x vào vị trí p
• Tăng độ dài lên 1
Chương 2: Các ADTs
21
CĐ DS bằng mảng (13)_Chèn x vào vị trí p
Chèn phần tử x=’k’ vào vị trí p=3 trong danh sách L (chỉ số 2
trong mảng)
Chương 2: Các ADTs
22
CĐ DS bằng mảng (14)_Chèn x vào vị trí p
void Insert_List(ElementType x,Position p, List *L){
if (Full_List(*L))
printf("Danh sach day \n");
else if ((p < 1) || (p > End_List(*L)))
printf("Vi tri khong hop le \n");
else {
Position i;
for(i = L->Last; i > p-1; i )
L->Elements[i] = L->Elements[i-1];
L->Elements[p-1] = x;
L->Last++;
}
}
Chương 2: Các ADTs
23
CĐ DS bằng mảng (15)_Xóa phần tử ở vị trí p
Nếu mảng rỗng in thông báo …
Nếu vị trí p không hợp lệ ( p < 1 hoặc p > L->Last )
in thông báo …
Ngược lại
• Dời các phần tử từ vị trí p+1 đến cuối ra trước một vị trí
• Giảm độ dài bớt 1
Chương 2: Các ADTs
24
Xóa phần tử vị trí p=4 của L
CĐ DS bằng mảng (16)_Xóa phần tử ở vị trí p
Chương 2: Các ADTs
25
void Delete_List(Position p, List *L){
if (Empty_List(*L))
printf("Danh sach rong \n");
else if ((p < 1) || (p > L->Last))
printf("Vi tri khong hop le \n");
else {
Position i;
for(i = p; i < L->Last; i++)
L->Elements[i-1] = L->Elements[i];
L->Last ;
}
}
CĐ DS bằng mảng (17)_Xóa phần tử ở vị trí p