1. 1
Danh Sách Liên Kết
Nguyễn Thanh Hiên
Danh Sách Liên Kết (Linked List)
• Gồm nhiều phần tử (gọi mỗi phần tử là
một node)
• Các phần tử nối kết với nhau thông qua
vùng liên kết
• Các phần tử được try xuất tuần tự và bao
gồm: vùng dữ liệu và các vùng liên kết
Ai
A node in a
linked list
A header node
A tail node
2. 2
Các loại danh sách liên kết
• DSLK đơn
• DSLK kép
• DSLK vòng
A2 A3 ANA1
A1
A2 A3 AN
A1
A2 A3 AN
Các Tác Vụ
• Khởi tạo (init)
• Kiểm tra DSLK rỗng (IsEmpty)
• Xác định kích thước (Size)
• Chèn (Insert)
• Xóa (Remove)
• Tìm kiếm (Retrieve)
• Thay thế (Replace)
• Duyệt (Traverse)
3. 3
DSLK Đơn- Cấu trúc dữ liệu
• typedef struct node{
T info; // T là kiểu đã định nghĩa trước
struct node* link; // con trỏ chỉ đến cấu trúc node
}NODE;
• T là kiểu dữ liệu cơ bản hoặc kiểu dữ liệu
tự định nghĩa
DSLK Đơn- Cấu trúc dữ liệu
• typedef struct node
{
int info;
struct node* link;
}NODE;
CTDL cho một
phần tử của DS
các số nguyên
4. 4
DSLK Đơn- Cấu trúc dữ liệu
• typedef struct SinhVien
{
char Ten[30];
int MaSV;
}SV;
• typedef struct svNode
{
SV info;
struct svNode* link;
}SVNODE;
CTDL cho một
phần tử của DS
các sinh viên
DSLK Đơn- Cấu trúc dữ liệu
• typedef struct phanso
{
int tu;
int mau;
}PS;
• typedef struct psNode
{
PS info;
struct psNode* link;
}PSNODE;
CTDL cho một
phần tử của DS
các phân số
5. 5
DSLK Đơn- Cấu trúc dữ liệu
• typedef struct
{
NODE* pHead;
NODE* pTail;
} LIST;
pHead
pTail
A1
A2 A3 AN
DSLK Đơn- Các Tác Vụ
• Khởi tạo DS
void init (LIST &list){
list.pHead=NULL;
list.pTail=NULL;
}
6. 6
DSLK Đơn- Các Tác Vụ
• Tạo một Node mới cho DS
NODE* getNode(T x){
NODE* p;
p=new NODE;
if (p==NULL)
return NULL;
p-> info = x;
p-> link=NULL;
return p;
}
x
DSLK Đơn- Các Tác Vụ
• Chèn một phần tử vào DS
– Chèn vào đầu (insertHead)
– Chèn vào cuối (insertTail)
– Chèn sau phần tử q (insertMid)
7. 7
DSLK Đơn- Các Tác Vụ
• Chèn vào đầu (insertHead)
A1
A2 A3 AN
pTail
pHead
x
newNode
(1)(2)
DSLK Đơn- Các Tác Vụ
• Chèn vào đầu (insertHead)
void insertHead(LIST &ds, NODE* newNode)
{
if (ds.pHead==NULL) //ds rỗng
{
ds.pHead = newNode; ds.pTail = ds.pHead;
}
else
{
newNode ->link = ds.pHead;
ds.pHead = newNode;
}
}
8. 8
DSLK Đơn- Các Tác Vụ
• Chèn vào cuối (insertTail)
pHead
pTail
A1
A2 A3 AN
x
(1)
(2)
DSLK Đơn- Các Tác Vụ
• Chèn vào cuối (insertTail)
void insertTail(LIST &ds, NODE *newNode)
{
if (ds.pHead==NULL)
{
ds.pHead = newNode; ds.pTail = ds.pHead;
}
else
{
ds.pTail->link = newNode;
ds.pTail = newNode;
}
}
9. 9
DSLK Đơn- Các Tác Vụ
• Chèn sau phần tử q (insertMid)
pHead
pTail
A1
A2 A3 AN
x
(1)(2)
q
DSLK Đơn- Các Tác Vụ
• Chèn sau phần tử q (insertMid)
void insertMid(LIST &ds,NODE *q, NODE* newNode)
{
if ( q!=NULL)
{
newNode ->link = q-> link;
q-> link = newNode;
if(q == ds.pTail)
ds.pTail = newNode;
}
else //chèn vào đầu danh sách
insertHead(ds, newNode);
}
10. 10
DSLK Đơn- Các Tác Vụ
• Tìm một phần tử trong DS
NODE * Retrieve(LIST ds, Data k)
{
NODE *p;
p = ds.pHead;
while((p!= NULL)&&(p->info != x))
p = p->link;
return p;
}
DSLK Đơn- Các Tác Vụ
• Duyệt DS
void * Traverse(LIST ds)
{
NODE *p;
p = ds.pHead;
while(p!= NULL){
process(p);
p = p->link;
}
}
11. 11
DSLK Đơn- Các Tác Vụ
• Xoá một phần tử
– Xoá phần tử đầu
– Xoá phân ftử sau phần tử q
– Xoá phần tử có khoá k
DSLK Đơn- Các Tác Vụ
• Xoá phần tử đầu
A1
A2 A3 AN
pTail
pHead
12. 12
DSLK Đơn- Các Tác Vụ
• Xoá phần tử đầu
Data RemoveHead(LIST &ds)
{
NODE *p;
Data x = NULLDATA;
if ( ds.pHead != NULL)
{
p = ds.pHead; x = p->info;
ds.pHead = ds.pHead->link;
delete p;
if(ds.pHead == NULL) ds.pTail = NULL;
}
return x;
}
DSLK Đơn- Các Tác Vụ
• Xoá phân ftử sau phần tử q
A1
A2 A3 AN
pTail
pHead
q p
13. 13
DSLK Đơn- Các Tác Vụ
• Xoá phần tử sau phần tử q
void RemoveAfter (LIST &ds, NODE *q)
{ NODE *p;
if ( q != NULL)
{
p = q ->link ;
if ( p != NULL)
{
if(p == ds.pTail) ds.pTail = q;
q->link = p->link;
delete p;
}
}
else
RemoveHead(ds);
}
DSLK Đơn- Các Tác Vụ
• Xoá phần tử có khoá k
int RemoveNode(LIST &ds, Data k)
{
NODE *p = ds.pHead;
NODE *q = NULL;
while( p != NULL)
{
if(p->info == k) break;
q = p; p = p->link;
}
if(p == NULL) return 0;
//Không tìm thấy k
if(q != NULL)
{
if(p == ds.pTail)
ds.pTail = q;
q->link = p->link;
delete p;
}
else //p là phần tử đầu ds
{
ds.pHead = p->link;
if(ds.pHead == NULL)
ds.pTail = NULL;
}
return 1;
}
17. 17
DSLK Kép- Remove
• Xóa đầu
• Xóa cuối
• Xóa sau phần tử q
• Xóa trước phần tử q
• Xóa có khóa k
DSLK Kép- Remove sau q
void Remove(DLIST &ds, DNODE *q)
{ DNODE *p;
if ( q != NULL)
{
p = q ->pNext ;
if ( p != NULL)
{
q->pNext = p->pNext;
if(p == ds.pTail) ds.pTail = q;
else p->pNext->pPrev = q;
delete p;
}
}
else
RemoveHead(ds);
}
18. 18
STACK
56
31
29
179
52
21 Bottom_of_stack
(this is where the
stack started)
top
Empty/unfilled
portion of stack
Direction
in which
stack grows
•Danh sách hạn chế
•Các phần tử được
thêm vào và lấy ra ở
đỉnh stack
• Hiện thực dùng dslk
hoặc array
Stack – Tác vụ
• Init()
• Push()
• Pop()
• IsEmpty()
• IsFull()
typedef struct {
T *theArray;
int top;
int size;
}STACK;
void init (STACK &s, int size) {
s.size = size;
s.theArray = new T[size];
s.top = -1;
}
21. 21
Queue-Tác vụ
• EnQueue()
Input: element to be enqueued
Algorithm:
increment back by 1
add element to the empty location pointed to by back
Return: void
• DeQueue()
Input: void
Algorithm:
return the element pointed to by front
increment front by 1
Return: the element dequeued
Queue – Ví dụ
front back
12 31 79 5 63
front back
12 31 79 5 63 17
front back
31 79 5 63 17
front back
5231 79 5 63 17
front back
5279 5 63 17
enqueue(17)
dequeue
enqueue(52)
dequque
22. 22
Queue – Ví dụ
front back
79 5 63 17
front back
5279 5 63 17 enqueue(23)
dequeue
52 23
back
5 63 17 52 23
front
back
63 17 52 23
front
17 52 23
front back
dequeue
dequeue
enqueue(44):
QUEUE_FULL
Circular Queue
23. 23
Circular Queue
• In enqueue:
back = (back +1) mod ARRAY_SIZE
• In dequeue:
front = (front + 1) mod ARRAY_SIZE
Circular Queue
back front
1171 57 81 122 39
back
front
8
EnQueue -> Queue full: (back+1)%size == front
DeQueue-> Queue empty: back == front
24. 24
Circular Queue
typedef struct {
int size;
int front;
int back;
T* values;
} QUEUE;
Circular Queue
void init(QUEUE &q, int size) {
q.size = size;
q.values = new T[size];
q.front = 0;
q.back = 0;
}
26. 26
CÂY
A
B C D E F
G H I J K L
T1 T3
T5leaf
root
T2 T4
edge
• Cây N node sẽ có N-1 cạnh
subtree
Path: n1->nk là một chuỗi các nút n1 ->nk sao cho ni là cha ni+1, 1 <= i <=k
depth
CÂY
A
B C D E F
G H I J K L
T1 T3
T5leaf
root
T2 T4
depth
Cây nhị phân là cây
mà mỗi nút có tối
đa hai nút con
27. 27
CÂY NHỊ PHÂN
CÁC PHÉP DUYỆT
• PreOrder
– Duyệt gốc
– Duyệt các cây con bên trái
– Duyệt cây con bên phải
• InOrder
– Duyệt cây con bên trái
– Duyệt gốc
– Duyệt cây con bên phải
• PostOrder
– Duyệt cây con bên trái
– Duyệt cây con bên phải
– Duyệt gốc
29. 29
VÍ DỤ
• Cho cây nhị phân, mỗi nút có info (không trùng
nhau) là một số nguyên
– Đếm số nút trên cây
– Tính tổng các info trên cây
– Cho biết tổ tiên của nút có info là x
– Cho biết info các nút ở mức 3
– Cho biết tổng info trên cây
– Cho biết các nút có tổng info các conlà bội số của info
của cha nó
– Cho biết tổng số nút lá
– Cho biết tổng số nút bậc một
– Cho biết cây có bị suy biến không
LAN TRUYỀN THÔNG TIN
• Tham số
– Tham biến
– Tham trị
• Hỏi-đáp
Hỏi
a
Hỏi
b
a, b
30. 30
CÂY NHỊ PHÂN TÌM KIẾM (BST)
BST-Retrieval
TNODE* Retrieval(TNODE* root, T x){
if (root != NULL) {
If (root->info==x) return root;
if (x < root->info)
return Retrieveal (root->left, x);
else
return Retrieveal (root->right, x);
}
return NULL;
}