Professional Documents
Culture Documents
Danh Sach Lien Ket Don
Danh Sach Lien Ket Don
Contents
THUẬT TOÁN QUICK SORT..............................................................................................1
DANH SÁCH LIÊN KẾT......................................................................................................2
DANH SÁCH LIÊN KẾT ĐƠN............................................................................................2
1. PHẦN 1: VIẾT DANH SÁCH LIÊN KẾT ĐƠN CHỈ QUẢN LÝ BỞI ĐIỂM ĐẦU
TIÊN CỦA DANH SÁCH HEAD.....................................................................................2
2. Hình ảnh danh sách liên kết đơn...................................................................................2
3. Cấu trúc dữ liệu danh sách liên kết đơn........................................................................2
4. Khởi tạo danh sách liên kết đơn...................................................................................3
5. Kiểm tra danh sách liên kết đơn rỗng...........................................................................4
6. Tạo node cho danh sách liên kết đơn............................................................................4
7. Thêm 1 node vào đầu danh sách liên kết đơn...............................................................4
8. Nhập từ bàn phím danh sách liên kết đơn.....................................................................5
9. Duyệt tuần tự danh sách liên kết đơn............................................................................6
10. Chương trình đầu tiên danh sách liên kết đơn...........................................................6
DSLK Đơn: PHẦN 2: VIẾT HÀM CODE DANH SÁCH LIÊN KẾT ĐƠN ĐƯỢC QUẢN
LÝ BỞI ĐIỂM ĐẦU VÀ ĐIỂM CUỐI.................................................................................9
1. Hình ảnh danh sách liên kết đơn...................................................................................9
2. Cấu trúc dữ liệu danh sách liên kết đơn........................................................................9
3. Khởi tạo danh sách liên kết đơn.................................................................................10
4. Kiểm tra danh sách liên kết đơn rỗng.........................................................................10
5. Tạo một node và gán giá trị cho node.........................................................................11
6. Thêm một node vào đầu danh sách liên kết đơn.........................................................12
Thêm một node vào cuối danh sách liên kết đơn..........................................................12
Thêm một node vào vị trí bất kỳ danh sách liên kết đơn..............................................13
7. Nhập từ bàn phím danh sách liên kết đơn...................................................................13
8. Duyệt tuần tự danh sách liên kết đơn..........................................................................15
9. Chương trình đầu tiên danh sách liên kết đơn............................................................16
10. Tìm kiếm một phần tử có khóa x............................................................................18
11. Hủy toàn bộ danh sách............................................................................................18
12. Sắp xếp các node trong danh sách...........................................................................19
13. BÀI TẬP................................................................................................................. 19
14. Bài tập chuẩn..........................................................................................................20
1
Bài tập chuẩn 1: Định nghĩa hàm thêm một node vào cuối danh sách liên kết đơn......20
Bài tập chuẩn 2: Định nghĩa hàm đếm số lượng node trong danh sách liên kết đơn.....20
Bài tập chuẩn 3: Tìm một node có thành phần dữ liệu bằng X trong danh sách liên kết
đơn các số nguyên........................................................................................................20
Bài tập chuẩn 4: Định nghĩa hàm tách node đầu danh sách đơn ra khỏi danh sách......20
Bài tập chuẩn 5: Định nghĩa hàm tính tổng các giá trị chẵn có trong danh sách liên kết
đơn các số nguyên........................................................................................................20
Bài tập chuẩn 6: Định nghĩa hàm tìm node lớn nhất trong danh sách đơn các số thực. 20
Bài tập chuẩn 7: Định nghĩa hàm tìm địa chỉ node kế cuối trong danh sách liên kết đơn
...................................................................................................................................... 20
Bài tập chuẩn 8: Định nghĩa hàm tách node cuối danh sách liên kết đơn ra khỏi danh
sách............................................................................................................................... 20
Bài tập chuẩn 9: Định nghĩa hàm kiểm tra node q có trong danh sách liên kết đơn hay
không............................................................................................................................ 20
Bài tập C10: Định nghĩa hàm tìm địa chỉ của node nằm trước node q có trong danh
sách liên kết đơn...........................................................................................................20
Bài tập C11: Định nghĩa hàm tách node p trong danh sách liên kết đơn ra khỏi danh
sách............................................................................................................................... 20
Bài tập C12: Bài tập chuẩn 12: Định nghĩa hàm thu hồi bộ nhớ đã cấp phát cho toàn bộ
danh sách liên kết đơn..................................................................................................21
Bài tập chuẩn 13:..........................................................................................................21
Bài tập 14:.................................................................................................................... 21
DANH SÁCH LIÊN KẾT ĐƠN VÒNG..............................................................................23
1. Hình ảnh..................................................................................................................... 23
2. Cấu trúc dữ liệu danh sách liên kết đơn vòng.............................................................23
3. Khởi tạo danh sách liên kết đơn vòng........................................................................23
4. Kiểm tra danh sách liên kết đơn vòng rỗng................................................................23
5. Tạo node cho danh sách liên kết đơn vòng.................................................................23
6. Thêm một node vào đầu danh sách liên kết đơn vòng................................................24
7. Nhập từ bàn phím danh sách liên kết đơn vòng..........................................................24
8. Duyệt tuần tự.............................................................................................................. 25
9. Chương trình đầu tiên trên danh sách liên kết đơn vòng............................................26
10. Bài tập..................................................................................................................... 28
DANH SÁCH LIÊN KẾT KÉP............................................................................................29
1. Hình ảnh danh sách liên kết kép.................................................................................29
2. Cấu trúc dữ liệu..........................................................................................................29
2
3. Khởi tạo danh sách liên kết kép..................................................................................29
4. Kiểm tra danh sách liên kết kép rỗng.........................................................................29
5. Tạo node cho danh sách liên kết kép..........................................................................29
6. Thêm 1 node vào danh sách liên kết kép....................................................................30
7. Nhập từ bàn phím danh sách liên kết kép...................................................................30
8. Duyệt tuần tự danh sách liên kết kép..........................................................................31
9. Bài tập đơn giản.........................................................................................................32
10. Bài tập chuẩn..........................................................................................................34
NGĂN XẾP - STACK.........................................................................................................36
1. Nguyên lý hoạt động..................................................................................................36
2. Cấu trúc dữ liệu của ngăn xếp....................................................................................36
3. Khởi tạo ngăn xếp......................................................................................................36
4. Kiểm tra ngăn xếp rỗng..............................................................................................36
5. Kiểm tra ngăn xếp đầy................................................................................................36
6. Thêm một đối tượng vào trong ngăn xếp....................................................................37
7. Lấy một đối tượng ra khỏi ngăn xếp...........................................................................37
8. Ứng dụng.................................................................................................................... 37
Bài toán 1:.................................................................................................................... 37
9. Bài tập........................................................................................................................ 39
Bài 881: Đếm số lượng nút có đúng hai con mà thông tin tại nút đó là số chính phương
...................................................................................................................................... 39
Bài 885: Tính tổng các nút trong cây............................................................................39
HÀNG ĐỢI – QUEUE.........................................................................................................40
1. Nguyên lý hoạt động..................................................................................................40
2. Cấu trúc dữ liệu của hàng đợi.....................................................................................40
3. Khởi tạo hàng đợi.......................................................................................................40
4. Kiểm tra hàng đợi rỗng...............................................................................................40
5. Kiểm tra hàng đợi đầy................................................................................................40
6. Thêm một đối tượng vào trong hàng đợi....................................................................41
7. Lấy một đối tượng ra khỏi hàng đợi...........................................................................41
8. Ứng dụng.................................................................................................................... 41
CÂY NHỊ PHÂN.................................................................................................................42
1. Hình ảnh cây nhị phân................................................................................................42
2. Khái niệm cây nhị phân..............................................................................................42
3. Cấu trúc dữ liệu của cây nhị phân..............................................................................42
3
4. Khởi tạo cây nhị phân.................................................................................................42
5. Tạo node cho cây nhị phân.........................................................................................42
6. Duyệt cây nhị phân.....................................................................................................42
7. Hàm cài đặt duyệt cây................................................................................................43
8. Bài tập........................................................................................................................ 43
CÂY NHỊ PHÂN TÌM KIẾM – BINARY SEARCH TREE – BST.....................................45
1. Hình vẽ....................................................................................................................... 45
2. Khái niệm................................................................................................................... 45
3. Khởi tạo cây nhị phân tìm kiếm.................................................................................45
4. Kiểm tra cây nhị phân tìm kiếm rỗng.........................................................................46
5. Tạo node cho cây nhị phân tìm kiếm..........................................................................46
6. Thêm giá trị vào cây nhị phân tìm kiếm.....................................................................46
7. Nhập cây nhị phân tìm kiếm.......................................................................................48
8. Duyệt cây nhị phân tìm kiếm......................................................................................49
9. Một chương trình đơn giản về cây BST.....................................................................50
10. Bài tập..................................................................................................................... 52
B – Cây................................................................................................................................. 53
4
ĐỀ CƯƠNG CẤU TRÚC DỮ LIỆU – GIẢI THUẬT
5
DANH SÁCH LIÊN KẾT
Khái niệm
Danh sách liên kết là tập hợp các phần tử mà giữa chúng có một sự nối kết với nhau thông
qua vùng liên kết của chúng
Các loại danh sách liên kết:
Danh sách liên kết đơn
Danh sách liên kết đôi/kép
Danh sách liên kết đơn vòng
Danh sách liên kết kép vòng
struct node
{
6
KDL info;
struct node* pNext;
};
typedef struct node NODE;
typedef NODE*NODEPTR;
Ví dụ 1: Khai báo cấu trúc dữ liệu cho danh sách liên kết đơn các số nguyên
struct node
{
int info;
struct node* pNext;
};
typedef struct node NODE;
typedef NODE*NODEPTR;
Ví dụ 2: Khai báo cấu trúc dữ liệu cho danh sách liên kết đơn các phân số
struct phanso
{
int tu;
int mau;
};
typedef struct phanso PHANSO;
struct node
{
PHANSO info;
struct node* pNext;
};
typedef struct node NODE;
typedef NODE*NODEPTR;
4. Khởi tạo danh sách liên kết đơn
void Init(NODEPTR &ptr)
{
7
ptr = NULL;
}
5. Kiểm tra danh sách liên kết đơn rỗng
int IsEmpty (NODEPTR ptr)
{
if(ptr == NULL)
return 1;
return 0;
}
6. Tạo node cho danh sách liên kết đơn
NODE * GetNode (KDL x)
{
NODE * p = new NODE;
if(p == NULL)
return NULL;
p->info = x;
p->pNext = NULL;
return p;
}
7. Thêm 1 node vào đầu danh sách liên kết đơn
Hình vẽ ptr
p
8
8. Nhập từ bàn phím danh sách liên kết đơn
Hàm tổng quát:
void Input (NODEPTR &ptr)
{
NhapN();
Init(ptr);
for (int i=1; i<=n; i++)
{
NhapX();
NODE* p = GetNode(x);
if(p!=NULL)
AddHead(ptr, p);
}
}
Ví dụ: Nhập danh sách liên kết đơn các số nguyên
void Input (NODEPTR &ptr)
{
int n;
printf (“Nhap n:”);
scanf(“%d”, &n);
Init(ptr);
for (int i=1; i<=n; i++)
{
int x;
printf(“Nhap x”);
scanf(“%d”, &x);
NODE* p = GetNode(x);
if(p!=NULL)
AddHead(ptr, p);
}
9
}
9. Duyệt tuần tự danh sách liên kết đơn
Định nghĩa hàm trừu tượng
KDL <Tên hàm> (NODEPTR ptr)
{
….
NODE * p = ptr;
while (p!= NULL)
{
….
p = p -> pNext
}
…
}
Ví dụ: Định nghĩa hàm tính tổng các số lẻ trong danh sách liên kết đơn các số nguyên
int Tong(NODEPTR ptr)
{
int s = 0;
NODE *p = ptr;
while (p!=NULL)
{
s = s + p->info;
p = p->pNext;
}
return s;
}
10
}
//Tạo node
NODE * GetNode(int x)
{
NODE * p = new NODE;
if (p == NULL)
return NULL;
p->info = x;
p->pNext = NULL;
return p;
}
//Thêm node vào đầu danh sách
void AddHead(NODEPTR &ptr, NODE*p)
{
p->pNext = ptr;
ptr = p;
}
//NHập danh sách liên kết
void Input(NODEPTR &ptr)
{
int n;
printf("Nhap n : ");
scanf_s("%d", &n);
Init(ptr);
for (int i = 1; i <= n; i++)
{
int x;
printf("Nhap x: ");
scanf_s("%d", &x);
NODE* p = GetNode(x);
if (p != NULL)
AddHead(ptr, p);
}
}
//Xuất danh sách liên kết đơn
void Output(NODEPTR ptr)
{
NODE *p = ptr;
while (p != NULL)
{
printf("%4d", p->info);
p = p->pNext;
}
}
//Tính tổng danh sách liên kết đơn các số nguyên
int Tong(NODEPTR ptr)
{
int s = 0;
NODE *p = ptr;
while (p!=NULL)
{
11
s = s + p->info;
p = p->pNext;
}
return s;
}
void main()
{
NODEPTR ds;
Init(ds);
printf("\n==Tao 1 danh sach lien ket==");
Input(ds);
printf("\n==Xuat danh sach lien ket==");
Output(ds);
int s = Tong(ds);
printf("\n==Ket qua ham tinh tong: %d ",s);
_getch();
}
12
DSLK Đơn: PHẦN 2: VIẾT HÀM CODE DANH SÁCH LIÊN KẾT
ĐƠN ĐƯỢC QUẢN LÝ BỞI ĐIỂM ĐẦU VÀ ĐIỂM CUỐI
1. Hình ảnh danh sách liên kết đơn
pHead pTail
13
{
NODE *pHead;
NODE *pTail;
};
typedef struct list LIST;
Ví dụ 4: Hãy khai báo CTDL cho DSLK đơn tọa độ các điểm trong mặt phẳng Oxy
struct diem
{
float x;
float y;
};
typedef struct diem DIEM;
struct node{
DIEM info;
struct node *pNext;
};
typedef struct node NODE;
struct list
{
NODE *pHead;
NODE *pTail;
};
typedef struct list LIST;
14
{
if(l.pHead == NULL)
return 1;
return 0;
}
5. Tạo một node và gán giá trị cho node
Khái niệm: Tạo node cho danh sách liên kết đơn là xin cấp phát bộ nhớ có kích thước
bằng với kích thước của kiểu dữ liệu node để chứa thông tin đã được biết trước.
Định nghĩa hàm trừu tượng:
NODE* GetNode (KDL x)
{
NODE *p = new NODE;
if(p==NULL)
{
printf("Khong du bo nho!");
return NULL;
}
p->info = x;
p->pNext = NULL;
return p;
}
Ví dụ 1: Định nghĩa hàm tạo node cho danh sách liên kết đơn các số thực
NODE* GetNode(float x)
{
NODE *p = new NODE;
if (p == NULL)
{
printf("Khong du bo nho!");
return NULL;
}
p->info = x;
p->pNext = NULL;
return p;
}
Ví dụ 2: Định nghĩa hàm tạo node cho danh sách liên kết đơn các phân số
NODE* GetNode(PHANSO x)
{
NODE *p = new NODE;
if (p == NULL)
{
printf("Khong du bo nho!");
return NULL;
}
p->info = x;
15
p->pNext = NULL;
return p;
}
Ví dụ 3: Định nghĩa hàm tạo node cho danh sách liên kết đơn các số nguyên
NODE* GetNode(int x)
{
NODE *p = new NODE;
if (p == NULL)
{
printf("Khong du bo nho!");
return NULL;
}
p->info = x;
p->pNext = NULL;
return p;
}
Ví dụ 4: Định nghĩa hàm tạo node cho danh sách liên kết đơn tọa độ các điểm trong mặt
phẳng Oxy
NODE* GetNode(DIEM x)
{
NODE *p = new NODE;
if (p == NULL)
{
printf("Khong du bo nho!");
return NULL;
}
p->info = x;
p->pNext = NULL;
return p;
}
6. Thêm một node vào đầu danh sách liên kết đơn
Khái niệm: Thêm một node vào đầu danh sách liên kết đơn là gắn node đó vào đầu danh
sách.
Hình vẽ
pHead pTail
16
ls.pHead = ls.pTail = p;
}
else
{
p->pNext = ls.pHead;
ls.pHead = p;
}
}
Thêm một node vào cuối danh sách liên kết đơn
Trường hợp 1: Nếu danh sách liên kết đơn rỗng thì node mới được xem là node đầu
tiên và cũng là node cuối cùng.
Trường hợp 2: Nếu danh sách liên kết đơn không rỗng thì:
+ Cho con trỏ liên kết (next) của node cuối danh sách hiện tại trỏ đến node mới.
+ Cho con trỏ cuối của danh sách liên kết đơn (*tail) trỏ vào node mới.
void AddTail(LIST &ls, NODE*p)
{
if (ls.pHead == NULL)//DS rỗng
{
ls.pHead = ls.pTail = p;
}
else
{
ls.pTail->pNext = p;
ls.pTail = p;
}
}
Thêm một node vào vị trí bất kỳ danh sách liên kết đơn
Thêm vào sau nút q trong danh sách
Thêm một node p vào sau một node q trong danh sách
+ Cho con trỏ liên kết (next) của node p chỉ vào node sau của q.
+ Cho con trỏ liên kết của q chỉ vào node p.
+ Nếu q là nút cuối thì gán lại p là nút cuối.
17
if (q == l.pTail)
{
l.pTail = new_node;
}
}
}
18
l.pHead = NULL;
l.pTail = NULL;
}
NODE* GetNode(int x)
{
NODE *p = new NODE;
if (p == NULL)
{
printf("Khong du bo nho!");
return NULL;
}
p->info = x;
p->pNext = NULL;
return p;
}
void AddHead(LIST &ls, NODE*p)
{
if (ls.pHead == NULL)//DS rỗng
{
ls.pHead = ls.pTail = p;
}
else
{
p->pNext = ls.pHead;
ls.pHead = p;
}
}
void Input(LIST &l)
{
int n;
printf("Nhap n:");
scanf_s("%d", &n);
Init(l);
for (int i = 1; i <= n; i++)
{
int x;
printf("Nhap so nguyen:");
scanf_s("%d", &x);
NODE *p = GetNode(x);
if (p != NULL)
AddHead(l, p);
}
19
{
……
NODE *p = l.pHead;
while (p!=NULL)
{
……
p = p -> pNext;
}
……
}
Ví dụ 1: Định nghĩa hàm tính tổng các số lẻ trong danh sách liên kết đơn các số nguyên
struct node{
int info;
struct node *pNext;
};
typedef struct node NODE;
struct list
{
NODE *pHead;
NODE *pTail;
};
typedef struct list LIST;
int TongLe(LIST l)
{
int s = 0;
NODE *p = l.pHead;
while (p!=NULL)
{
if (p->info % 2 != 0)
s = s + p->info;
p = p->pNext;
}
return s;
}
Ví dụ 2: Định nghĩa hàm xuất danh sách liên kết đơn các số nguyên
void Xuat(LIST l)
{
NODE *p = l.pHead;
while (p != NULL)
{
printf("%4d", p->info);
p = p->pNext;
}
}
20
9. Chương trình đầu tiên danh sách liên kết đơn
Bài toán:
Viết chương trình thực hiện các yêu cầu sau:
+ Nhập danh sách liên kết đơn các số nguyên
+ Tính tổng các giá trị trong danh sách liên kết đơn
+ Xuất danh sách liên kết đơn
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <string.h>
struct node{
int info;
struct node *pNext;
};
typedef struct node NODE;
struct list
{
NODE *pHead;
NODE *pTail;
};
typedef struct list LIST;
void Init(LIST &l)
{
l.pHead = NULL;
l.pTail = NULL;
}
NODE* GetNode(int x)
{
NODE *p = new NODE;
if (p == NULL)
{
printf("Khong du bo nho!");
return NULL;
}
p->info = x;
p->pNext = NULL;
return p;
}
void AddHead(LIST &ls, NODE*p)
{
if (ls.pHead == NULL)//DS rỗng
{
ls.pHead = ls.pTail = p;
}
else
{
p->pNext = ls.pHead;
ls.pHead = p;
}
}
void Input(LIST &l)
{
int n;
21
printf("Nhap n:");
scanf_s("%d", &n);
Init(l);
for (int i = 1; i <= n; i++)
{
int x;
printf("Nhap so nguyen:");
scanf_s("%d", &x);
NODE *p = GetNode(x);
if (p != NULL)
AddHead(l, p);
}
}
void Output(LIST l)
{
NODE *p = l.pHead;
while (p != NULL)
{
printf("%4d", p->info);
p = p->pNext;
}
}
int Tong(LIST l)
{
int s = 0;
NODE *p = l.pHead;
while (p != NULL)
{
s = s + p->info;
p = p->pNext;
}
return s;
}
void main()
{
LIST l;
Input(l);
Output(l);
int kq = Tong(l);
printf("\n Tong : %4d", kq);
_getch();
}
22
}
24
{
lc = lc->pNext;
}
return lc;
}
Bài tập C11: Định nghĩa hàm tách node p trong danh sách liên kết đơn ra khỏi danh sách
Bài tập C12: Bài tập chuẩn 12: Định nghĩa hàm thu hồi bộ nhớ đã cấp phát cho toàn bộ danh
sách liên kết đơn
struct node{
int info;
struct node *pNext;
};
typedef struct node NODE;
struct list
{
NODE *pHead;
NODE *pTail;
};
typedef struct list LIST;
NODE *GetHead(LIST &l)
{
if (l.pHead == NULL)
return NULL;
if (l.pHead == l.pTail)
{
NODE*p = l.pHead;
l.pHead = l.pTail = NULL;
return p;
}
NODE *p = l.pHead;
l.pHead = l.pHead->pNext;
p->pNext = NULL;
return p;
}
void RemoveAll(LIST &l)
{
while (l.pHead)
{
NODE*p = GetHead(l);
delete p;
}
}
25
Bài tập 14:
Hãy viết chương trình với C/C++ để thao tác với danh sách liên kết đơn ở trên:
a. Tạo danh sách liên kết đơn như hình minh họa.
b. Thêm một node có giá trị là 9 vào đầu danh sách.
c. Xuất giá trị và địa chỉ của các node trong danh sách lên màn hình.
d. Sắp xếp danh sách theo thứ tự tăng dần các giá trị của các node.
e. Giải phóng bộ nhớ cho toàn bộ danh sách.
26
DANH SÁCH LIÊN KẾT ĐƠN VÒNG
1. Hình ảnh
pHead pTail
27
return 1;
return 0;
}
5. Tạo node cho danh sách liên kết đơn vòng
NODE * GetNode(KDL x)
{
NODE * p = new NODE;
if (p == NULL)
return NULL;
p->info = x;
p->pNext = p;
return p;
}
Ví dụ 1: Định nghĩa hàm tạo node cho danh sách liên kết đơn vòng các số thực
NODE * GetNode(floaf x)
{
NODE * p = new NODE;
if (p == NULL)
return NULL;
p->info = x;
p->pNext = p;
return p;
}
Ví dụ 2: Định nghĩa hàm tạo node cho danh sách liên kết đơn vòng các phân số
NODE * GetNode(PHANSO x)
{
NODE * p = new NODE;
if (p == NULL)
return NULL;
p->info = x;
p->pNext = p;
return p;
}
6. Thêm một node vào đầu danh sách liên kết đơn vòng
void AddHead(LIST &l, NODE*p)
{
if (l.pHead == NULL)
l.pHead = l.pTail = p;
else
{
p->pNext = l.pHead;
l.pTail->pNext = p;
l.pHead = p;
}
}
28
7. Nhập từ bàn phím danh sách liên kết đơn vòng
void Input(LIST &l)
{
int n;
printf("Nhap n:");
scanf("%d", &n);
Init(l);
for (int i = 1; i <= n; i++)
{
KDL x;
Nhap(x);
NODE *p = GetNode(x);
if (p != NULL)
AddHead(l, p);
}
}
29
8. Duyệt tuần tự
KDL <Tên hàm> (LIST l)
{
if(l.pHead==NULL)
return…;
….
NODE *p= l.pHead;
do{
….
p = p ->pNext;
}while (p != l.pHead)
…
}
Định nghĩa hàm tính tổng các số lẻ trong danh sách liên kết đơn vòng các số thực
float TongLe(LIST l)
{
if (l.pHead == NULL)
return 0;
float s = 0;
NODE *p = l.pHead;
do{
if (p->info % 2 != 0)
s = s + p->info;
p = p->pNext;
} while (p != l.pHead);
return s;
}
Định nghĩa hàm xuất danh sách liên kết đơn vòng các số nguyên.
void Output(LIST l)
{
if (l.pHead == NULL)
return;
NODE *p = l.pHead;
do{
printf("%4d", p->info);
p = p->pNext;
} while (p != l.pHead);
}
9. Chương trình đầu tiên trên danh sách liên kết đơn vòng
Bài toán: Viết chương trình thực hiện các yêu cầu sau:
30
+ Nhập danh sách liên kết đơn vòng các số nguyên
+ Tính tổng lẻ các giá trị trong danh sách liên kết đơn vòng
+ Xuất danh sách liên kết đơn vòng
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <string.h>
struct node
{
int info;
struct node *pNext;
};
typedef struct node NODE;
struct list
{
NODE *pHead;
NODE *pTail;
};
typedef struct list LIST;
void Init(LIST &l)
{
l.pHead = NULL;
l.pTail = NULL;
}
NODE *GetNode(int x)
{
NODE *p = new NODE;
if (p == NULL)
return NULL;
p->info = x;
p->pNext = p;
return p;
}
void AddHead(LIST &l, NODE*p)
{
if (l.pHead == NULL)
l.pHead = l.pTail = p;
else
{
p->pNext = l.pHead;
l.pTail->pNext = p;
l.pHead = p;
}
}
void Input(LIST &l)
{
int n;
printf("Nhap n:");
scanf_s("%d", &n);
Init(l);
for (int i = 1; i <= n; i++)
{
int x;
printf("Nhap x:");
scanf_s("%d", &x);
31
NODE *p = GetNode(x);
if (p != NULL)
AddHead(l, p);
}
}
void Output(LIST l)
{
if (l.pHead == NULL)
return;
NODE *p = l.pHead;
do{
printf("%4d", p->info);
p = p->pNext;
} while (p != l.pHead);
}
int TongLe(LIST l)
{
if (l.pHead == NULL)
return 0;
int s = 0;
NODE *p = l.pHead;
do{
if (p->info % 2 != 0)
s = s + p->info;
p = p->pNext;
} while (p != l.pHead);
return s;
}
void main()
{
LIST l;
Init(l);
Input(l);
Output(l);
int kq = TongLe(l);
printf("\n Tong : %4d", kq);
_getch();
}
32
DANH SÁCH LIÊN KẾT KÉP
1. Hình ảnh danh sách liên kết kép
LIST
pHead pTail
NODE
struct node
{
KDL info;
struct node*pNext;
struct node *pPrev;
};
typedef struct node NODE;
struct list
{
NODE*pHead;
NODE*pTail;
};
typedef struct list LIST;
Ví dụ: Hãy khai báo cấu trúc dữ liệu cho danh sách liên kết kép các số nguyên
struct node
{
int info;
struct node*pNext;
struct node *pPrev;
};
typedef struct node NODE;
struct list
{
NODE*pHead;
NODE*pTail;
};
typedef struct list LIST;
Ví dụ: Hãy khai báo cấu trúc dữ liệu cho danh sách liên kết kép các số thực
struct node
{
float info;
struct node*pNext;
struct node *pPrev;
33
};
typedef struct node NODE;
struct list
{
NODE*pHead;
NODE*pTail;
};
typedef struct list LIST;
Ví dụ: Hãy khai báo cấu trúc dữ liệu cho danh sách liên kết kép các số phân số
struct phanso
{
int tu;
int mau;
};
typedef struct phanso PHANSO;
struct node
{
PHANSO info;
struct node*pNext;
struct node *pPrev;
};
typedef struct node NODE;
struct list
{
NODE*pHead;
NODE*pTail;
};
typedef struct list LIST;
Ví dụ: Hãy khai báo cấu trúc dữ liệu cho danh sách liên kết kép tọa độ các điểm trong mặt
phẳng Oxy
struct diem
{
float x;
float y;
};
typedef struct diem DIEM;
struct node
{
DIEM info;
struct node*pNext;
struct node *pPrev;
};
typedef struct node NODE;
struct list
{
NODE*pHead;
NODE*pTail;
};
typedef struct list LIST;
34
3. Khởi tạo danh sách liên kết kép
void Init(LIST &l)
{
l.pHead = NULL;
l.pTail = NULL;
}
Ví dụ: Hãy định nghĩa hàm tạo 1 node cho danh sách liên kết kép các số thực
NODE*GetNode(float x)
{
NODE*p = new NODE;
if (p == NULL)
return NULL;
p->info = x;
p->pNext = NULL;
p->pPrev = NULL;
return p;
}
Ví dụ: Hãy định nghĩa hàm tạo 1 node cho danh sách liên kết kép các phân số
NODE*GetNode(PHANSO x)
{
NODE*p = new NODE;
if (p == NULL)
return NULL;
p->info = x;
p->pNext = NULL;
p->pPrev = NULL;
return p;
}
35
6. Thêm 1 node vào danh sách liên kết kép
l
pHead pTail
p
36
if (p != NULL)
AddHead(l, p);
}
}
37
}
Ví dụ 1: Tính tổng các số lẻ trong danh sách liên kết kép các số nguyên
int TongLe(LIST l)
{
int s = 0;
NODE *p = l.pHead;
while (p!=NULL)
{
if (p->info % 2 != 0)
s = s + p->info;
p = p->pNext;
}
return s;
}
Ví dụ 2: Định nghĩa hàm xuất danh sách liên kết kép các số nguyên ra màn hình
void Xuat(LIST l)
{
NODE *p = l.pHead;
while (p != NULL)
{
printf("%4d", p->info);
p = p->pNext;
}
}
38
{
l.pHead = NULL;
l.pTail = NULL;
}
int IsEmpty(LIST l)
{
if (l.pHead == NULL)
return 1;
return 0;
}
NODE*GetNode(int x)
{
NODE*p = new NODE;
if (p == NULL)
return NULL;
p->info = x;
p->pNext = NULL;
p->pPrev = NULL;
return p;
}
void AddHead(LIST &l, NODE*p)
{
if (l.pHead == NULL)
l.pHead = l.pTail = p;
else
{
p->pNext = l.pHead;
l.pHead->pPrev = p;
l.pHead = p;
}
}
void Input(LIST &l)
{
int n;
printf("Nhap n:");
scanf_s("%d", &n);
Init(l);
for (int i = 1; i <= n; i++)
{
int x;
printf("Nhap x:");
scanf_s("%d", &x);
NODE*p = GetNode(x);
if (p != NULL)
AddHead(l, p);
}
}
void Output(LIST l)
{
NODE*p = l.pHead;
while (p!=NULL)
{
printf("%4d", p->info);
p = p->pNext;
}
}
39
int Tong(LIST l)
{
int s = 0;
NODE *p = l.pHead;
while (p!=NULL)
{
s = s + p->info;
p = p->pNext;
}
return s;
}
void main()
{
LIST ls;
Init(ls);
Input(ls);
Output(ls);
int s1 = Tong(ls);
printf("\nTong gia tri danh sach %4d", s1);
_getch();
}
40
41
NGĂN XẾP - STACK
1. Nguyên lý hoạt động
Cấu trúc dữ liệu ngăn xếp hoạt động theo nguyên lý vào sau, ra trước (LIFO – Last In –
First Out)
2. Cấu trúc dữ liệu của ngăn xếp
struct stack
{
int n;
KDL a[100];
};
typedef struct stack STACK;
KDL là kiểu dữ liệu của đối tượng được lưu trong stack.
3. Khởi tạo ngăn xếp
void Init(STACK &st)
{
st.n=0;
}
4. Kiểm tra ngăn xếp rỗng
int IsEmpty (STACK st)
{
if(st.n==0)
return 1;
return 0;
}
5. Kiểm tra ngăn xếp đầy
int IsFull (STACK st)
{
if(st.n==100)
return 1;
return 0;
42
}
6. Thêm một đối tượng vào trong ngăn xếp
Hình vẽ minh họa
0 1 …. st.n-1
st.a
st.n
Định nghĩa hàm
void Push (STACK &st, KDL x)
{
st.a[st.n]=x;
st.n++;
}
7. Lấy một đối tượng ra khỏi ngăn xếp
Hình vẽ minh họa
43
struct node
{
float info;
struct node *pLeft;
struct node *pRight;
};
typedef struct node NODE;
typedef NODE *TREE;
float Tong(TREE t)
{
if(!t)
return 0;
float a=Tong(t->pLeft);
floatb=Tong(t->pRight);
return (a + b + t->info);
}
Cách 2: Khử đệ quy
struct node
{
float info;
struct node *pLeft;
struct node *pRight;
};
typedef struct node NODE;
typedef NODE *TREE;
struct stack
{
int n;
NODE *a[100];
};
44
typedef struct stack STACK;
9. Bài tập
Bài 881: Đếm số lượng nút có đúng hai con mà thông tin tại nút đó là số chính phương
Bài 885: Tính tổng các nút trong cây
45
HÀNG ĐỢI – QUEUE
1. Nguyên lý hoạt động
Cấu trúc dữ liệu hàng đợi hoạt động theo nguyên lý vào trước, ra trước (FIFO – First In –
First Out)
46
return 1;
return 0;
}
6. Thêm một đối tượng vào trong hàng đợi
Hình vẽ minh họa
47
CÂY NHỊ PHÂN
1. Hình ảnh cây nhị phân
Ví dụ 1: Hãy khai báo cấu trúc dữ liệu cho cây nhị phân các số nguyên
Ví dụ 2: Hãy khai báo cấu trúc dữ liệu cho cây nhị phân các phân số.
4. Khởi tạo cây nhị phân
void Init(TREE &t)
{
t = NULL;
}
Ví dụ 1: Định nghĩa hàm tạo node cho cây nhị phân các số nguyên
Ví dụ 2: Định nghĩa hàm tạo node cho cây nhị phân các phân số
48
6. Duyệt cây nhị phân
Khái niệm: Duyệt cây nhị phân là thăm qua tất cả các node trong cây, mỗi node một
lần.
Các phương pháp duyệt cây:
+ Phương pháp LNR
+ Phương pháp RNL
+ Phương pháp NLR
+ Phương pháp NRL
+ Phương pháp LRN
+ Phương pháp RLN
Duyệt cây theo phương pháp LNR là duyệt cây con trái trước, sau đó duyệt đến nút
gốc và cuối cùng duyệt cây con phải.
Cách thức duyệt cây con trái và duyệt cây con phải cũng giống như cách thức duyệt
cha.
7. Hàm cài đặt duyệt cây
Bài toán: Hãy định nghĩa tất cả các hàm duyệt và xuất cây nhị phân các số nguyên bằng
6 phương pháp.
struct node
{
KDL info;
struct node *pLeft;
struct node *pRight;
};
typedef struct node NODE;
typedef NODE * TREE;
Định nghĩa hàm duyệt và xuất cây theo phương pháp LNR
Định nghĩa hàm duyệt và xuất cây theo phương pháp LNR
Định nghĩa hàm duyệt và xuất cây theo phương pháp LNR
Định nghĩa hàm duyệt và xuất cây theo phương pháp LNR
Định nghĩa hàm duyệt và xuất cây theo phương pháp LNR
Định nghĩa hàm duyệt và xuất cây theo phương pháp LNR
8. Bài tập
Viết hàm xuất các giá trị trong cây nhị phân các số nguyên.
Viết hàm xuất các giá trị chẵn trong cây.
Viết hàm xuất địa chỉ các nút trên cây có giá trị (khóa) > x và < y.
Viết hàm xuất các số hoàn thiện trong cây.
Đếm số lượng nút có đúng 1 con.
Đếm số lượng nút có đúng 2 con.
49
Đếm số lượng nút chẵn.
Đếm số lượng nút lá mà thông tin tại nút đó là giá trị chẵn.
Đếm số lượng nút có đúng 1 con mà thông tin tại nút đó là số nguyên tố.
Viết hàm đếm số lượng nút có đúng 2 con mà thông tin tại nút đó là số chính phương.
Tính tổng các nút trong cây.
Tính tổng các nút lá trong cây.
Tính tổng các nút có đúng 1 con.
Tính tổng các nút có đúng 2 con.
Tính tổng các nút lẻ.
Tính tổng các nút lá mà thông tin tại đó là giá trị chẵn.
Tính tổng các nút có đúng 1 con mà thông tin tại đó là số nguyên tố.
Tính tổng các nút có đúng 2 con mà thông tin tại đó là số chính phương.
Tính chiều cao của cây nhị phân các số nguyên.
Tìm giá trị lớn nhất trong cây.
Tìm giá trị nhỏ nhất trong cây.
Tìm địa chỉ của nút trong cây mà giá trị tại nút đó bằng giá trị x. Nếu không tìm thấy
hàm trả về giá trị null.
Viết hàm độ lệch lớn nhất trong cây.
50
CÂY NHỊ PHÂN TÌM KIẾM – BINARY SEARCH TREE – BST
1. Hình vẽ
64
37 78
10 57 69 82
6 67 96
2. Khái niệm
Cây nhị phân tìm kiếm là cây nhị phân thỏa điều kiện sau: Mọi node trong cây đều
có khóa lớn hơn tất cả các khóa thuộc cây con trái và nhỏ hơn tất cả các khóa thuộc
cây con phải
Cây nhị phân tìm kiếm là cây nhị phân hỗ trợ việc tìm kiếm dựa trên khóa của từng
node trong cây.
struct node
{
KDL info;
struct node *pLeft;
struct node *pRight;
};
typedef struct node NODE;
typedef NODE *TREE;
3. Khởi tạo cây nhị phân tìm kiếm
void Init (TREE &t)
{
t=NULL;
51
}
4. Kiểm tra cây nhị phân tìm kiếm rỗng
int IsEmpty (TREE t)
{
if(t==NULL)
return 1;
return 0;
}
5. Tạo node cho cây nhị phân tìm kiếm
NODE *GetNode (KDL x)
{
NODE *p=new NODE;
if(p==NULL)
return NULL;
p->info=x;
p->pLeft=NULL;
p->pRight=NULL;
}
6. Thêm giá trị vào cây nhị phân tìm kiếm
Khái niệm: Thêm 1 giá trị vào trong cây nhị phân tìm kiếm là thêm thông tin vào cây
sao cho tính chất của cây nhị phân tìm kiếm không vi phạm
Giá trị trả về: Hàm thêm một giá trị vào trong cây nhị phân tìm kiếm trả về một trong
3 giá trị -1, 0, 1 với ý nghĩa như sau:
+ Giá trị 1: thêm thành công
+ Giá trị 0: trùng với khóa 1 node có sẵn trong cây
+ Giá trị -1: không đủ bộ nhớ
64
37 78
10 57 69 82
52
6 67 96
Vấn đề 1: Hãy định nghĩa hàm thêm một node (thông tin) vào cây nhị phân tìm kiếm các số
nguyên
struct node
{
int info;
struct node *pLeft;
struct node *pRight;
};
typedef struct node NODE;
typedef NODE *TREE;
NODE *GetNode(int x)
{
NODE*p = new NODE;
if (p == NULL)
return NULL;
p->info = x;
p->pLeft = NULL;
p->pRight = NULL;
return p;
}
int InsertNode(TREE &t, int x)
{
if (t != NULL)
{
if (t->info < x)
return InsertNode(t->pRight, x);
if (t->info>x)
return InsertNode(t->pLeft, x);
return 0;
}
t = GetNode(x);
if (t == NULL)
return -1;
return 1;
}
Vấn đề 2: Thêm 1 node vào cây nhị phân tìm kiếm các số thực
struct node
{
float info;
struct node *pLeft;
struct node *pRight;
53
};
typedef struct node NODE;
typedef NODE *TREE;
NODE *GetNode(float x)
{
NODE*p = new NODE;
if (p == NULL)
return NULL;
p->info = x;
p->pLeft = NULL;
p->pRight = NULL;
return p;
}
int InsertNode(TREE &t, float x)
{
if (t != NULL)
{
if (t->info < x)
return InsertNode(t->pRight, x);
if (t->info>x)
return InsertNode(t->pLeft, x);
return 0;
}
t = GetNode(x);
if (t == NULL)
return -1;
return 1;
}
Vấn đề 2: Định nghĩa hàm nhập cây nhị phân tìm kiếm các số nguyên
void Input(TREE &t)
{
int n;
printf("Nhap n:");
54
scanf_s("%d", &n);
Init(t);
for (int i = 1; i <= n; i++)
{
int x;
printf("Nhap x:");
scanf_s("%d", &x);
InsertNode(t, x);
}
}
Vấn đề 3: Định nghĩa hàm nhập cây nhị phân tìm kiếm các số thực
void Input(TREE &t)
{
int n;
printf("Nhap n:");
scanf_s("%d", &n);
Init(t);
for (int i = 1; i <= n; i++)
{
float x;
printf("Nhap x:");
scanf_s("%f", &x);
InsertNode(t, x);
}
}
Ví dụ 2: Định nghĩa hàm đếm số lượng số chính phương trong cây nhị phân tìm kiếm các số
nguyên
//Đếm số chính phương
int DemCP(TREE t)
{
if (t == NULL)
return 0;
int a = DemCP(t->pLeft);
int b = DemCP(t->pRight);
if (ktcp(t->info) == 1)
return (a + b + 1);
return (a + b);
}
//kiểm tra số chính phương
int ktcp(int x)
{
int lc = 0;
for (int i = 0; i <= x;i++)
if (i*i == x)
lc = 1;
return lc;
}
56
void Output(TREE);
float TongDuong(TREE);
int ktcp(float);
int DemCP(TREE );
void main()
{
TREE t;
Input(t);
Output(t);
float kq = TongDuong(t);
printf("\n Tong cac gia tri duong la: %8.3f", kq);
int cp = DemCP(t);
printf("\n So luong so chinh phuong la: %4d", cp);
_getch();
}
NODE *GetNode(float x)
{
NODE*p = new NODE;
if (p == NULL)
return NULL;
p->info = x;
p->pLeft = NULL;
p->pRight = NULL;
return p;
}
int InsertNode(TREE &t, float x)
{
if (t != NULL)
{
if (t->info < x)
return InsertNode(t->pRight, x);
if (t->info > x)
return InsertNode(t->pLeft, x);
return 0;
}
t = GetNode(x);
if (t == NULL)
return -1;
return 1;
}
void Init(TREE &t)
{
t = NULL;
}
void Input(TREE &t)
{
int n;
printf("Nhap n:");
scanf_s("%d", &n);
Init(t);
for (int i = 1; i <= n; i++)
57
{
float x;
printf("Nhap x:");
scanf_s("%f", &x);
InsertNode(t, x);
}
}
void Output(TREE t)
{
if (t == NULL)
return;
Output(t->pLeft);
printf("%8.3f", t->info);
Output(t->pRight);
return;
}
float TongDuong(TREE t)
{
if (t == NULL)
return 0;
float a = TongDuong(t->pLeft);
float b = TongDuong(t->pRight);
if (t->info > 0)
return (a + b + t->info);
return (a + b);
}
//Đếm số chính phương
int DemCP(TREE t)
{
if (t == NULL)
return 0;
int a = DemCP(t->pLeft);
int b = DemCP(t->pRight);
if (ktcp(t->info) == 1)
return (a + b + 1);
return (a + b);
}
//kiểm tra số chính phương
int ktcp(float x)
{
int lc = 0;
for (int i = 0; i <= x;i++)
if (i*i == x)
lc = 1;
return lc;
}
10.Bài tập
58
B – Cây
59