You are on page 1of 34

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 A header node
linked list A tail node

1
Các loại danh sách liên kết
• DSLK đơn
A1 A2 A3 AN

• DSLK kép
A1 A2 A3 AN

• DSLK vòng

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)

2
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;
CTDL cho một
}NODE; phần tử của DS
các số nguyên

3
DSLK Đơn- Cấu trúc dữ liệu
• typedef struct SinhVien
{
char Ten[30];
int MaSV;
}SV;
• typedef struct svNode CTDL cho một
{ phần tử của DS
SV info; các sinh viên
struct svNode* link;
}SVNODE;

DSLK Đơn- Cấu trúc dữ liệu


• typedef struct phanso
{
int tu;
int mau;
}PS;
• typedef struct psNode CTDL cho một
{ phần tử của DS
PS info; các phân số
struct psNode* link;
}PSNODE;

4
DSLK Đơn- Cấu trúc dữ liệu
pTail

A1 A2 A3 AN

pHead

• typedef struct
{
NODE* pHead;
NODE* pTail;
} LIST;

DSLK Đơn- Các Tác Vụ

• Khởi tạo DS
void init (LIST &list){
list.pHead=NULL;
list.pTail=NULL;
}

5
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; x
if (p==NULL)
return NULL;
p-> info = x;
p-> link=NULL;
return p;
}

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)

6
DSLK Đơn- Các Tác Vụ
• Chèn vào đầu (insertHead)

pTail

pHead

A1 A2 A3 AN

(2) (1)

newNode

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;
}
}

7
DSLK Đơn- Các Tác Vụ
• Chèn vào cuối (insertTail)
(2)
pTail x
(1)

A1 A2 A3 AN
pHead

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;
}
}

8
DSLK Đơn- Các Tác Vụ
• Chèn sau phần tử q (insertMid)

q pTail

A1 A2 A3 AN
pHead
(2) (1)

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);
}

9
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;
}
}

10
DSLK Đơn- Các Tác Vụ
• Xoá một phần tử
– Xoá phần tử đầu

– Xoá phần tử sau phần tử q

– Xoá phần tử có khoá k

DSLK Đơn- Các Tác Vụ


• Xoá phần tử đầu
pTail

pHead

A1 A2 A3 AN

11
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
q p pTail

pHead

A1 A2 A3 AN

12
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 if(q != NULL)
int RemoveNode(LIST &ds, Data k) {
{ if(p == ds.pTail)
NODE *p = ds.pHead; ds.pTail = q;
NODE *q = NULL; q->link = p->link;
while( p != NULL) delete p;
{ }
if(p->info == k) break; else //p là phần tử đầu ds
q = p; p = p->link; {
} ds.pHead = p->link;
if(p == NULL) return 0; if(ds.pHead == NULL)
//Không tìm thấy k ds.pTail = NULL;
}
return 1;
}

13
DSLK Đơn- Hủy danh sách
void ReamoveList(LIST &ds)
{ NODE *p;
while (ds.pHead!= NULL)
{
p = ds.pHead;
ds.pHead = p->link;
delete p;
}
ds.pTail = NULL;
}

DSLK Kép- Cấu trúc dữ liệu

typedef struct DNode


{
T info;
struct DNode* pPre;
struct DNode* pNext;
}DNODE;

14
DSLK Kép- Cấu trúc dữ liệu
DNODE* GetNode(T x)
{
DNODE *p;
p = new DNODE;
if ( p==NULL) return NULL
p ->Info = x;
p->pPrev = NULL;
p->pNext = NULL;
return p;
}

DSLK Kép- Insert


• Chèn đầu
• Chèn cuối
• Chèn sau phần tử q
• Chèn trước phần tử q

15
DSLK Kép- Insert

DSLK Kép- Insert


void Insert(DLIST &ds, DNODE* q, DNODE* newNode)
{ DNODE* p = q->pNext;
if ( q!=NULL) {
newNode->pNext = p; //(1)
newNode->pPrev = q; //(2)
q->pNext = newNode; //(3)
if(p != NULL)
p->pPrev = newNode; //(4)
if(q == ds.pTail)
ds.pTail = newNode;
}
else //chèn vào đầu danh sách
InsertHead(ds, newNode);
}

16
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);
}

17
STACK
21 Bottom_of_stack
•Danh sách hạn chế
56 (this is where the
31 stack started) •Các phần tử được
29
thêm vào và lấy ra ở
Direction đỉnh stack
179 in which
52 top • Hiện thực dùng dslk
stack grows
hoặc array

Empty/unfilled
portion of stack

Stack – Tác vụ
typedef struct {
• Init() T *theArray;
• Push() int top;
• Pop() int size;
}STACK;
• IsEmpty()
void init (STACK &s, int size) {
• IsFull()
s.size = size;
s.theArray = new T[size];
s.top = -1;
}

18
Stack- Push()
void push(STACK &s, T x){
if (!isFull(s)){
s.top++;
s.theArray[s.top]=x;
}
}
bool isFull(STACK s) {
if(s.top < s.size-1) return false;
else return true;
}

Stack- Pop(), Top()


T pop(STACK &s){
if (!isEmpty(s))
return s.theArray[s.top--];
}
T top(STACK s){
return s.theArray[s.top];
}
bool isEmpty(STACK s) {
if(s.top == -1) return true;
else return false;
}

19
Stack-Ví dụ
21 21 21 21
56 56 56 56
31 31 31 31
pop() push(2)
29 29 29 top() 29
179 179 179 179
52 top 2 2
top top

Return 52 Return 2

Queue
12 31 79 5 63

front back empty portion


of the queue

• Danh sách hạn chế


• Chèn vào một đầu, lấy ra ở đầu kia
• Hiện thực dùng dslk hoặc array
• Linear and Circular Queues

20
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ụ
12 31 79 5 63 enqueue(17)

front back
12 31 79 5 63 17
dequeue
front back

31 79 5 63 17 enqueue(52)
front back
dequque 31 79 5 63 17 52
front back

79 5 63 17 52
front back

21
Queue – Ví dụ
79 5 63 17 52 enqueue(23)
front back
79 5 63 17 52 23
dequeue
front back

5 63 17 52 23 dequeue
front back
dequeue 63 17 52 23
front back
17 52 23
enqueue(44):
front back
QUEUE_FULL

Circular Queue

22
Circular Queue
• In enqueue:
back = (back +1) mod ARRAY_SIZE
• In dequeue:
front = (front + 1) mod ARRAY_SIZE

Ghi chú: back giữ vị trí phần tử có


giữ liệu
front giữ vị trí phần tử không có giữ
liệu

Circular Queue – ĐK Rỗng

DeQueue-> Queue empty: back == front

23
Circular Queue – ĐK Đầy
EnQueue-> Queue full:
(back +1)%size == front

Circular Queue

typedef struct {
int size;
int front;
int back;
T* values;
} QUEUE;

24
Circular Queue
void init(QUEUE &q, int size) {
q.size = size;
q.values = new T[size];
q.front = 0;
q.back = 0;
}

Circular Queue
bool isFull(QUEUE q) {
if( (q.back+1) % q.size == q.front) return true;
else return false;
}
bool isEmpty(QUEUE q) {
if(q.back == q.front) return true;
else return false;
}

25
Circular Queue
void enqueue(QUEUE &q,T x) {
if(!isFull(q)) {
q.back = (q.back+1) % q.size;
q.values[q.back] = x;
}
}
T dequeue(QUEUE &q) {
if(!isEmpty(q)) {
q.front = (q.front+1) % q.size;
return values[q.front];
}
return NULLDATA;
}

CÂY
Path: n1->nk là một chuỗi các nút n1 ->nk sao cho ni là cha ni+1, 1 <= i <=k
root depth

subtree A edge

B C D E F
T2 T4

G H I J K L

T1 T3
leaf T5
• Cây N node sẽ có N-1 cạnh

26
CÂY
Cây nhị phân là cây
mà mỗi nút có tối root depth
đa hai nút con
A

B C D E F
T2 T4

G H I J K L

T1 T3
leaf T5

CÂY NHỊ PHÂN

27
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

CÂY NHỊ PHÂN- CTDL

typedef struc TNode{


T info;
TNode* left;
TNode* right;
}TNODE;

TNODE *root=NULL;

28
CÂY NHỊ PHÂN- Duyệt
void PreOrder(TNODE *root){ void PostOrder(TNODE *root){
if (root!=NULL){ if (root!=NULL){
process(root); PostOrder (root->left);
PreOrder(roo->left); PostOrder (root->right);
PreOrder(root->right); process(root);
} }
} }
void InOrder(TNODE *root){
if (root!=NULL){
InOrder (root->left);
process(root);
InOrder (root->right);
}
}

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

29
LAN TRUYỀN THÔNG TIN
• Tham số
– Tham biến a, b
– Tham trị
• Hỏi-đáp
Hỏi Hỏi
a b

CÂY NHỊ PHÂN TÌM KIẾM (BST)

30
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;
}

BST-Retrieval

31
BST-Insert
• Tạo BSTvới các info: 5 9 7 3 8 12 6 4 20

BST-Insert

32
BST-Insert

BST-Insert

33
BST-Insert
int Insert(TNODE*& root, T x)
{
if (root != NULL) {
if (root->info==x) return 0;
if (x < root ->info)
return Insert(root ->left, x);
else
return Insert(root ->right, x);
}
root = new TNODE;
If (root==NULL) return -1
root ->right = NULL;
root ->left = NULL:
root ->info = x;
return 1;
}

34

You might also like