Danh sách liên kết (Linked List)... Lê Mậu Long 6.[r]
Trang 1Lê Mậu Long 1
•Xin vui lòng yên lặng!
Trang 2Lê Mậu Long 2
Danh sách liên kết
(Linked List)
Trang 3Lê Mậu Long 3
Giới thiệu
• Định nghĩa: Là danh sách bao gồm các
phần tử kết nối với nhau bằng 1 hay nhiều mối liên kết
Trang 4Lê Mậu Long 4
Các thao tác trên danh sách
• Khởi tạo danh sách rỗng
• Kiểm tra danh sách rỗng?
• Chèn phần tử vào danh sách
• Xóa phần tử trong danh sách
• Tìm kiếm phần tử trong danh sách
• Khởi đầu từ đầu danh sách
• Lấy dữ liệu 1 phần tư
• Chuyển sang phần tử kế tiếp
• Hết danh sách
• …
Trang 5Lê Mậu Long 5
Danh sách liên kết đơn
• Là danh sách mà mỗi phần tử có 1 mối liên kết để kết nối với phần tử kế tiếp
• Cài đặt: dựa trên con trỏ, bao gồm:
• 3 con trỏ: head (đầu ds), pos (phần tử hiện hành), và rear (cuối ds)
• biến count: số phần tử của danh sách
Trang 6Lê Mậu Long 6
Mô tả kiểu dữ liệu
typedef struct nodet {
Trang 7Lê Mậu Long 7
Trang 8Lê Mậu Long 8
Khởi tạo danh sách rỗng
Gán
– head, pos và rear = NULL
– count = 0
// Hàm khởi tạo
void createlist(list &l)
{
l.head = l.pos = l.rear = NULL;
l.count = 0;
}
Trang 9Lê Mậu Long 9
Kiểm tra danh sách rỗng?
• Kiểm tra số phần tử = 0
int emptylist(list l)
{
return l.count == 0;
}
Trang 10Lê Mậu Long 10
Chèn phần tử x vào danh sách – cục bộ
(local)
• Cấp phát bộ nhớ cho newp và gán dữ liệu
• Chèn ở đầu ds (p==NULL)
newp->next = head;
head = newp;
newp
Trang 11Lê Mậu Long 11
• Chèn sau phần tử p (p!=NULL)
newp->next = p->next;
p->next = newp;
newp
Trang 12Lê Mậu Long 12
• Trường hợp chèn cuối (newpnext == NULL)
• Thay đổi rear
rear = newp;
newp
Trang 13Lê Mậu Long 13
void insertlist(list &l, elem &x, nodeptr p)
{
nodeptr newp = new node;
memcpy(&newp->data, &x, sizeof(elem));
Trang 14Lê Mậu Long 14
Các hàm chèn phần tử – toàn cục (global)
• Chèn đầu danh sách
void inserthead(list &l, elem &x)
{
insertlist(l, x, NULL);
}
• Chèn vị trí hiện hành
void insertpos(list &l, elem &x)
{
insertlist(l, x, l.pos);
}
• Chèn cuối danh sách
void insertrear(list &l, elem &x)
{
insertlist(l, x, l.rear);
}
Trang 15Lê Mậu Long 15
Xoá phần tử trong danh sách – cục bộ
• Xoá phần tử đầu danh sách (p=NULL)
Trang 16Lê Mậu Long 16
void deletelist(list &l, nodeptr p)
{ nodeptr t;
if (p==NULL) {
t = l.head;
l.head = t->next;
} else {
Trang 17Lê Mậu Long 17
Các hàm xóa phần tử – toàn cục
• Xóa phần tử đầu danh sách
void deletehead(list &l)
{
deletelist(l, NULL);
}
• Xóa phần tử tại vị trí hiện hành
void deletepos(list &l)
{
deletelist(l, l.pos);
}
Trang 18Lê Mậu Long 18
Tìm kiếm trên DS
X=5
1 Khởi đầu từ đầu danh sách (pos = NULL; c = head)
2 Khi chưa hết ds và chưa tìm thấy
Chuyển sang phần tử kế tiếp (pos = c; c = cnext)
Trang 19Lê Mậu Long 19
Tìm kiếm trên DS – bản nháp
int searchlist(list &l, elem x)
}
Trang 20Lê Mậu Long 20
Tìm kiếm trên DS – viết lại
int searchlist(list &l, elem x, int (*comp)(elem, elem))
}
Trang 21Lê Mậu Long 21
Tìm kiếm trên DS có thứ tư
int searchorderlist(list &l, elem x, int (*comp)(elem, elem)) {
Trang 22Lê Mậu Long 22
// Hàm so sánh trên khoá
int ss(int x, int y) {
return x-y;
} //Đoạn chương trinh nhập dãy createlist(l);
cout<<" \nNhap day:" ;
do {
cin>>x;
if (x>0) {
searchorderlist(l, x, ss); insertpos(l, x);
} } while (x>0);
Trang 23Lê Mậu Long 23
• Khởi đầu từ đầu danh sách
void start(list &l)
{
l.pos = l.head;
}
• Chuyển sang phần tử kế tiếp
void skip(list &l)
Trang 24Lê Mậu Long 24
• Kiểm tra hết danh sách
int eol(list l)
{
return l.pos == NULL;
}
• Lấy dữ liệu 1 phần tử
void getdata(list l, elem &x)
Trang 25Lê Mậu Long 25
Ngăn xếp (Stack)
• Là cấu trúc bao gồm các phần tử được truy xuất theo nguyên tắc “vào sau, ra trước” (Last In, First Out – LIFO)
Ví dụ: Chồng đĩa, đổi số ra nhị phân
19 9 4 2 1
1 1 0 0 1
1 1 0 0 1
Trang 26Lê Mậu Long 26
Các thao tác trên Stack
4 thao tác cơ bản trên stack
Trang 27Lê Mậu Long 27
Cài đặt trên cơ sở mảng
• Sử dụng
– Mảng e[Max] phần tử kiểu elem
(elementtype)
– Chỉ số top để chỉ đỉnh stack (nơi
đưa vào, lấy ra)
• Tạo tập tin Stack.cpp:
top
e
Max-1
Trang 28Lê Mậu Long 28
Các thao tác trên Stack
• Khởi tạo stack s rỗng
void createstack(stack &s)
Trang 29Lê Mậu Long 29
• Đưa phần tử x vào stack s
void push(stack &s, elem &x)
{
if (s.top==Max-1) exit(0);
memcpy(&s.e[++s.top], &x, sizeof(elem));
}
• Lấy phần tử x ra khỏi stack s
void pop(stack &s, elem &x)
{
if (s.top==-1) exit(0);
memcpy(&x, &s.e[s.top ], sizeof(elem));
}
Trang 30Lê Mậu Long 30
Trang 31Lê Mậu Long 31
Đệ qui và tổ chức đệ qui
Trang 32Lê Mậu Long 32
Định nghĩa
• Một định nghĩa được gọi là đệ qui nếu nó được định nghĩa trên chính nó một cách trực tiếp hay gián tiếp
• Đệ qui luôn gồm 2 phần
– Phần dừng
– Phần đệ qui
Trang 33Lê Mậu Long 33
Ví du
0
0 )!
1 (
n n
0
0
x
0
0 )
% ,
(
) ,
a b US
a b
a
US
Trang 34Lê Mậu Long 34
Trang 35Lê Mậu Long 35
Khử bỏ đệ qui
• Sử dung Stack
• Đệ qui được thay bằng:
– Hàm đệ qui: Vòng lặp
– Lời gọi đệ qui: Push các giá trị cuc bộ
– Thực hiện đệ qui: Pop các giá trị cuc bộ
• Lưu ý: Stack là cấu trúc LIFO
Trang 36Lê Mậu Long 36
Bài toán Tháp Hanoi
Trang 37Lê Mậu Long 37
Bài toán Tháp Hanoi không đệ qui
1 Khởi tạo stack s rỗng
2 Push 1 bộ (3, ‘A’, ‘B’, ‘C’) vào s
Trang 38Lê Mậu Long 38
Cài đặt trên cơ sở con trỏ
• Cài đặt tương tư như danh sách liên kết đơn với 2 thao tác
– Chèn đầu danh sách
– Lấy ra ở đầu danh sách
s
pop
push
Trang 39Lê Mậu Long 39
• Tạo tập tin Stack.cpp:
typedef struct nodet {
elem data;
struct nodet *next;
} node;
typedef node *stack;
void createstack(stack &s)
{
s = NULL;
}
Trang 40Lê Mậu Long 40
stack newp = new node;
memcpy(&newp->data, &x, sizeof(elem));
Trang 41Lê Mậu Long 41
void pop(stack &s, elem &x)
Trang 42Lê Mậu Long 42
Hàng đợi (Queue)
• Là cấu trúc bao gồm các phần tử được truy xuất
theo nguyên tắc “vào trước, ra trước” (First In, First Out – FIFO)
Ví dụ: Các vùng đệm giao tiếp giữa máy tính và các thiết bị
Trang 43Lê Mậu Long 43
Các thao tác trên Queue
4 thao tác cơ bản trên queue
• Khởi tạo queue rỗng: CreateQueue(q)
• Kiểm tra queue rỗng: EmptyQueue(q)
• Đưa phần tủ vào queue : AddQueue(q, x)
• Lấy phần tủ ra khỏi queue : RemoveQueue(q, x)
Trang 44Lê Mậu Long 44
Cài đặt trên cơ sở mảng
Hai chỉ số front và rear tăng xoay vòng
• Tạo tập tin Queue.cpp:
typedef struct {
elem e[Max];
int front, rear;
} queue;
Trang 45Lê Mậu Long 45
Các thao tác trên Queue
• Khởi tạo queue q rỗng
void createqueue(queue &q)
Trang 46Lê Mậu Long 46
• Đưa phần tử x vào queue q
void addqueue(queue &q, elem &x)
• Lấy phần tử x ra khỏi queue q
void removequeue(queue &q, elem &x)
{
if (q.front == q.rear) exit(0);
memcpy(&x, &q.e[q.front], sizeof(elem));
q.front = (q.front + 1) % Max;
}
Trang 47Lê Mậu Long 47
Ví du: Radix sort
• Sắp xếp dãy số nguyên dương tăng dần
19
Trang 48Lê Mậu Long 48
Cài đặt trên cơ sở con trỏ
• Cài đặt tương tư như danh sách liên kết đơn với 2 thao tác
– Chèn cuối danh sách
– Lấy ra ở đầu danh sách
front
rear
Trang 49Lê Mậu Long 49
• Tạo tập tin Queue.cpp:
typedef struct nodet {
Trang 50Lê Mậu Long 50
nodeptr newp = new node;
memcpy(&newp->data, &x, sizeof(elem));
Trang 51Lê Mậu Long 51
void removequeue(queue &q, elem &x)
Trang 52Lê Mậu Long 52
• Viết hàm tách danh sách liên kết đơn
chứa các số nguyên thành 2 danh sách
chẵn/lẻ