You are on page 1of 16

u trúc d li u và gi i thu t

Ch ng 5. u trúc d li u ng

5.1. Gi i thi u
V i các c u trúc d li u c xây d ng t các ki u c s nh : ki u th c, ki u
nguyên, ki u ký t ,… ho c t c u trúc n gi n nh m u tin, t p h p, m ng,… l p trình
viên có th gi i quy t h u h t các bài toán t ra. Các i t ng c xác nh thu c
ki u d li u này có c m chung là không thay i c kích th c, c u trúc trong
quá trình s ng, do v y th ng c ng ng t, gò bó khi n ôi khi khó di n t c th c t
v n sinh ng, phong phú. Các ki u d li u trên c g i là ki u d li u t nh.
Do v y, nh m áp ng nhu c u th hi n sát th c b n ch t c a d li u c ng nh xây
d ng các thao tác hi u qu trên d li u c n ph i tìm cách t ch c k t h p d li u v i
nh ng hình th c linh ng h n, có th thay i kích th c, c u trúc trong su t th i gian
s ng. Các hình th c t ch c d li u nh v y c g i là c u trúc d li u ng.
5.2. Bi u di n danh sách trong máy tính
Danh sách là m t t p s p th t các ph n t cùng m t ki u. Tính tuy n tính c a
danh sách th hi n s ràng bu c gi a các ph n t trong danh sách v i nhau, ví d nh
t v trí c a ph n t ai ta s tìm c giá tr c a ph n t ai+1.
i v i danh sách, ng i ta có m t s thao tác: Tìm m t ph n t trong danh sách,
chèn m t ph n t vào danh sách, xoá m t ph n t kh i danh sách, s p x p l i các ph n t
trong danh sách theo m t tr t t nào ó v.v...
Vi c cài t m t danh sách trong máy tính t c là tìm m t c u trúc d li u c th mà
máy tính hi u c l u các ph n t c a danh sách ng th i vi t các n ch ng
trình con mô t các thao tác c n thi t i v i danh sách.
5.2.1. u tr k ti p v i danh sách tuy n tính
Khi cài t danh sách b ng m t m ng, thì có m t bi n nguyên n l u s ph n t hi n
có trong danh sách. N u m ng c ánh s b t u t 1 thì các ph n t trong danh sách
c c t gi trong m ng b ng các ph n t c ánh s t 1 t i n (ho c t 0 t i n-1).
v c m c a danh sách:
− Kích th c c a danh sách s c c p phát theo khai báo.
− Các ph n t c a danh sách n m liên t c nhau trong b nh , gi a các ph n t
này không có kho ng tr ng.
v Khai báo:
# define MAXLIST 100
struct list {
int n; // s nút c a danh sách
DATA nodes[MAXLIST]; // danh sách là m ng 1 chi u
};
typedef struct list LIST;
v Các phép toán c b n:

Ch ng 5. C u trúc d li u ng Trang 46
u trúc d li u và gi i thu t
n gi n, các phép toán sau ây s c thao tác trên danh sách các s nguyên
v i khai báo nh sau:
# define MAXLIST 100
struct list {
int n; // s nút c a danh sách
int nodes[MAXLIST]; // danh sách là m ng 1 chi u
};
typedef struct list LIST;
1. Phép toán empty: ki m tra xem danh sách có r ng hay không ?
int empty(LIST list) {
return (list.n==0 ? TRUE : FALSE);
}
2. Phép toán full: ki m tra xem danh sách ã y ch a ?
int full(LIST list)
{
return (list.n==MAXLIST ? TRUE : FALSE);
}
3. Phép thêm vào : Thêm m t ph n t có n i dung là info vào v trí th i c a danh
sách.
o N u i =0 : thêm ph n t vào u danh sách
o N u i = list.n+1 : thêm ph n t vào cu i danh sách.
L u ý: Khi thêm m t ph n t vào danh sách, ta ph i ki m tra xem danh sách ã
y hay ch a ?
void insert_item(LIST &list, int i, int info) {
if (i < 0 || i > list.n)
printf("Vi tri chen khong phu hop.");
else if (Full(list))
printf("Danh sach bi day.");
else {
for (int j = list.n -1; j >= i; j--)
list.nodes[j+1] = list.nodes[j];
list.nodes[i] = info;
list.n ++;
}
}

Ch ng 5. C u trúc d li u ng Trang 47
u trúc d li u và gi i thu t
4. Phép lo i b : Lo i b ph n t th i kh i danh sách tuy n tính. Khi lo i b 1
ph n t thì danh sách ph i có ít nh t m t ph n t .
void delete_item (LIST &list, int i) {
if(i < 0 || i > list.n)
printf("Vi tri xoa khong phu hop.");
else if(Empty(list))
printf("Danh sach khong co phan tu.");
else {
for(int j = i; j< list.n -1; j++)
list.nodes[j] = list.nodes[j+1];
list.n--;
}
}
u ý: Mu n lo i b t t c các ph n t trong danh sách, ta ch c n cho list.n=0
5. Duy t danh sách: duy t t u cho n cu i danh sách, m i ph n t c
duy t qua 1 l n. Gi s ta duy t danh sách in giá tr các ph n t .
void traverse(LIST list) {
if(list.n == 0) {
printf("\n Danh sach khong co phan tu");
}
for(int i = 0; i < list.n; i++)
printf("%5d", list.nodes[i]);
}
6. Tìm ki m: tìm v trí u tiên c a ph n t có giá tr info trong danh sách list.
N u không có info trong list thì hà m Search_info s tr v giá tr -1.
int search_info(LIST list, int info) {
int vitri = 0;
while( vitri < list.n && list.nodes[vitri] != info )
vitri++;
return(vitri==list.n ? -1 : vitri+1);
}
7. Nh p danh sách: ta có th dùng gi i thu t sau:
void create_list(LIST &list) {
printf("\nSo phan tu cua danh sach :"); scanf("%d", &list.n);
for (int i=0; i< list.n; i++) {
printf("List[%d] =", i); scanf("%d",&list.nodes[i]);
Ch ng 5. C u trúc d li u ng Trang 48
u trúc d li u và gi i thu t
}
}
v Nh n xét: Danh sách c dùng ph ng pháp truy xu t tr c ti p nên th i gian
truy xu t nhanh, nh ng hi u qu s d ng b nh th p. Danh sách c không phù
h p v i phép thêm vào và lo i b vì m i l n thêm vào và lo i b thì chúng ta
ph i i ch nhi u l n. c bi t tr ng h p x u nh t là khi thêm vào và lo i b
u danh sách
v K t lu n : Danh sách c nên s d ng cho các danh sách ít b bi n ng v s
ng các ph n t . Còn i v i nh ng danh sách th ng b bi n ng thì ng i
ta ch n c u trúc là danh sách liên k t.
5.2.2. u tr móc n i v i danh sách tuy n tính (danh sách liên k t)
C u trúc danh sách liên k t là c u trúc ng, vi c c p phát nút và gi i phóng nút
trên danh sách x y ra khi ch ng trình ang ch y. Ta th ng c p phát nút cho danh sách
liên k t b ng bi n ng. Các ph n t trong danh sách liên k t s c c p phát vùng nh
trong quá trình th c thi ch ng trình, do ó chúng có th n m r i rác nhi u n i khác
nhau trong b nh (không liên t c).
Danh sách liên k t có nhi u lo i nh danh sách liên k t n, danh sách liên k t kép,
danh sách liên k t a và danh sách liên k t vòng.
v c m c a danh sách:
M t ph n t trong danh sách là m t c u trúc ch a 2 thông tin:
- Thành ph n d li u: l u tr các thông tin v ph n t .
- Thành ph n k t n i: l u tr a ch c a ph n t k ti p trong danh sách, ho c
u tr giá tr NULL n u là ph n t cu i c a danh sách.
v Khai báo:
struct node {
DATA info; // Thành ph n d li u ã nh ngh a tr c
struct node *pNext; // Thành ph n k t n i ch n c u trúc node
};
typedef struct node NODE;
M t ph n t trong danh sách n là m t bi n ng s c yêu c u c p phát khi
c n. Và danh sách n chính là s liên k t các bi n ng này v i nhau do v y t c
s linh ng khi thay i s l ng các ph n t .
N u bi t c a ch c a ph n t u trong danh sách thì có th d a vào thông tin
pNext c a nó truy xu t n ph n t th 2, và d a vào thông tin pNext c a ph n t th
2 truy xu t n ph n t th 3,… Ngh a là qu n lý m t danh sách liên k t ta ch c n
bi t a ch u danh sách. Ta th ng dùng m t con tr Head l u tr a ch u danh
sách:
NODE* pHead;
V nguyên t c ta ch c n qu n lý danh sách thông qua pHead, nh ng trong nhi u
tr ng h p c n làm vi c v i ph n t cu i danh sách, khi ó, m i l n mu n xác nh ph n

Ch ng 5. C u trúc d li u ng Trang 49
u trúc d li u và gi i thu t
t cu i ta ph i duy t l i u danh sách. ti n l i, ta có th dùng thêm m t con tr pTail
gi a ch ph n t cu i danh sách.
NODE* pTail;
C u trúc danh sách liên k t là c u trúc ng, các nút c c p phát ho c b gi i
phóng khi ch ng trình ang ch y.
Danh sách liên k t r t thích h p khi th c hi n các phép toán trên danh sách th ng
b bi n ng. Trong tr ng h p xóa hay thêm ph n t trong danh sách liên k t thì ta
không d i các ph n t i nh trong danh sách tuy n tính (m ng) mà ch vi c hi u ch nh
l i tr ng next t i các nút ang thao tác. Th i gian th c hi n các phép toán thêm vào và
lo i b không ph thu c vào s ph n t c a danh sách liên k t.
Tuy nhiên, danh sách liên k t c ng có các m h n ch sau:
Vì m i nút c a danh sách liên k t ph i ch a thêm tr ng next nên danh sách liên
k t ph i t n thêm b nh .
Tìm ki m trên danh sách liên k t không nhanh vì ta ch c truy xu t tu n t t
u danh sách.
5.2.3. Các phép toán trên danh sách liên k t
Gi s ta có các nh ngh a:
- Ki u m t ph n t trong danh sách:
struct node {
DATA info;
struct node *pNext;
};
typedef struct node NODE;
- Ki u danh sách liên k t:
struct list {
NODE* pHead;
NODE* pTail;
};
typedef struct list LIST;
1. Kh i t o danh sách liên k t:
void init (LIST &list) {
list.pHead = NULL;
list.pTail = NULL;
}
2. T o m i m t ph n t :
NODE* getNode (DATA x){
NODE* p = new NODE;

Ch ng 5. C u trúc d li u ng Trang 50
u trúc d li u và gi i thu t
if (p==NULL) return NULL;
p->info = x;
p->pNext = NULL;
return p;
}
3. Thêm m t ph n t vào u danh sách:
- Thu t toán:
N u danh sách r ng thì:
o c 1.1: Head = new_element;
o c 1.2: Tail = Head;
Ng c l i:
o c 2.1: new_element -> Next = Head;
o c 2.2: Head = new_element;
- Cài t:
void addHead(LIST &list, NODE* new_ele){
if (list.pHead==NULL) {
list.pHead = new_ele;
list.pTail = list.pHead;
}
else {
new_ele -> pNext = list.pHead;
list.pHead = new_ele;
}
}
NODE* insertHead(LIST &list, DATA x){
NODE* new_ele = getNode(x);
if (new_ele==NULL) return NULL;
if (list.pHead==NULL) {
list.pHead = new_ele;
list.pTail = list.pHead;
}
else {
new_ele -> pNext = list.pHead;
list.pHead = new_ele;
}

Ch ng 5. C u trúc d li u ng Trang 51
u trúc d li u và gi i thu t
return new_ele;
}
4. Thêm m t ph n t vào cu i danh sách:
- Thu t toán:
N u danh sách r ng thì:
o c 1.1: Head = new_element;
o c 1.2: Tail = Head;
Ng c l i:
o c 2.1: Tail-> pNext = new_element;
o c 2.2: Tail = new_element;
- Cài t:
void addTail(LIST &list, NODE* new_ele){
if (list.pHead==NULL) {
list.pHead = new_ele;
list.pTail = list.pHead;
}
else {
list.pTail -> pNext = new_ele;
list.pTail = new_ele;
}
}
NODE* insertTail(LIST &list, DATA x){
NODE* new_ele = getNode(x);
if (new_ele==NULL) return NULL;
if (list.pHead==NULL) {
list.pHead = new_ele;
list.pTail = list.pHead;
}
else {
list.pTail -> pNext = new_ele;
list.pTail = new_ele;
}
return new_ele;
}
5. Thêm m t ph n t vào sau m t ph n t q:

Ch ng 5. C u trúc d li u ng Trang 52
u trúc d li u và gi i thu t
- Thu t toán:
N uq NULL thì:
o c 1: new_element -> Next = q->Next;
o c 2: q->Next = new_element;
- Cài t:
void addAfter(LIST &list,NODE* q, NODE* new_ele){
if (q!=NULL) {
new_ele->pNext=q->pNext;
q->pNext = new_ele;
if (q==list.pTail)
list.pTail = new_ele;
}
else addHead(list,new_ele);
}
NODE* insertAfter(LIST &list,NODE* q, DATA x){
NODE* new_ele = getNode(x);
if (new_ele==NULL) return NULL;
if (q!=NULL) {
new_ele->pNext=q->pNext;
q->pNext = new_ele;
if (q==list.pTail)
list.pTail = new_ele;
return new_ele;
}
else
return insertHead(list,x);
}
6. Tìm m t ph n t trong danh sách:
Danh sách liên k t òi h i ph i truy su t tu n t , do ó ch áp d ng thu t toán tìm
tuyên tính xác nh ph n t trong danh sách có khoá k.
- Thu t toán:
o c 1: p = Head; // Con tr p tr n u danh sách
o c 2: trong khi (p!=NULL) và (p->info != k) th c hiên: p = p->Next;
o c 3: n u p!=NULL thì p tr n ph n t c n tìm.
Ng c l i: không có ph n t c n tìm.

Ch ng 5. C u trúc d li u ng Trang 53
u trúc d li u và gi i thu t
- Cài t:
NODE* search(LIST list, DATA k){
NODE* p;
p = list.pHead;
while ((p!=NULL)&&(p->info!=k))
p = p->pNext;
return p;
}
7. Xóa ph n t u danh sách:
- Thu t toán:
N u (Head!=NULL) thì
o c 1: p = Head; // Con tr p tr n u danh sách
o c 2:
§ Head = Head->Next;
§ free(p); // hu bi n ng p
o c 3: n u Head =NULL thì Tail = NULL.
- Cài t:
DATA removeHead(LIST &list){
NODE* p;
DATA x = NULLDATA;
if (list.pHead!=NULL){
p=list.pHead;
x=p->info;
list.pHead = list.pHead->pNext;
delete p;
if (list.pHead==NULL)
list.pTail=NULL;
}
return x;
}
8. Xóa ph n t ng sau ph n t q:
- Thu t toán:
N u (q!=NULL) thì
o c 1: p = q->Next; // p là ph n t c n xóa
o c 2: n u (p!=NULL) thì; // q không ph i cu i danh sách

Ch ng 5. C u trúc d li u ng Trang 54
u trúc d li u và gi i thu t
§ q->Next = p->Next;
§ free(p); // hu bi n ng p
o c 3: n u Head =NULL thì Tail = NULL.
- Cài t:
void removeAfter(LIST &list, NODE* q){
NODE* p;
if (q!=NULL){
p=q->pNext;
if (p!=NULL){
if (p==list.pTail)
list.pTail=q;
q->pNext = p->pNext;
delete p;
}
}
else
removeHead(list);
}
9. Xóa ph n t có khóa k:
- Thu t toán:
o c 1: tìm ph n t p có khóa k và ph n t q ng tr c nó
o c 2: N u (p!=NULL) thì; // thìm th y k
Xoá p ra kh i danh sách (xóa ph n t p ng sau q)
Ng c l i: Báo không có k
- Cài t:
int removeNode(LIST &list, DATA k){
NODE* p=list.pHead;
NODE* q=NULL;
while ((p!=NULL)&&(p->info!=k)){
q=p;
p = p->pNext;
}
if (p==NULL) return 0;
if (q==NULL) {
list.pHead = p->pNext;

Ch ng 5. C u trúc d li u ng Trang 55
u trúc d li u và gi i thu t
if (list.pHead==NULL)
list.pTail=NULL;
}
else {
if (p==list.pTail)
list.pTail=q;
q->pNext = p->pNext;
delete p;
}
return 1;
}
10. Duy t danh sách:
- Thu t toán:
o c 1: p = Head; // Con tr p tr n u danh sách
o c 2: trong khi (p!=NULL) th c hiên:
§ X lý ph n t p
§ p = p->Next;
- Cài t:
void ProcessList(LIST list){
NODE* p;
p = list.pHead;
while (p!=NULL){
ProcessNode(p);
p=p->pNext;
}
}
trong ó: ProcessNode(NODE* p) là hàm x lý m t ph n t trong danh sách.
11. Xóa danh sách:
- Thu t toán:
o c 1: Trong khi danh sách ch a h t th c hiênh
§ p = Head; // Con tr p tr n u danh sách
§ Head=Head->Next
§ Hu p
o c 2: Tail=NULL
- Cài t:

Ch ng 5. C u trúc d li u ng Trang 56
u trúc d li u và gi i thu t
void removeList(LIST &list){
NODE* p;
while (list.pHead !=NULL){
p= list.pHead;
list.pHead = p->pNext;
delete p;
}
list.pTail =NULL;
}
12. Ki m tra danh sách r ng:
int empty(LIST list) {
return (list.pHead==NULL ? 1 : 0);
}

5.3. S p x p danh sách liên k t


1. S p x p Ch n tr c ti p trên danh sách:
void ListSelectionSort (LIST & list) {
NODE *min; // ch n ph n t có giá tr nh nh t trong danh sách
NODE *p,*q;
p = list.pHead;
while(p != list.pTail) {
min = p;
q = p->pNext;
while(q != NULL) {
if (q->info < min->info)
min = q; // ghi nh n v trí ph n t min hi n hành q
q= q -> pNext;
}
Hoanvi(min->info, p->info); // Hoán v n i dung 2 ph n t
p = p->pNext;
}
}

Ch ng 5. C u trúc d li u ng Trang 57
u trúc d li u và gi i thu t
2. S p x p i ch tr c ti p trên danh sách:
void ListInterChangeSort (LIST & list) {
NODE *p,*q;
p = list.pHead;
while(p != list.pTail) {
q = p->pNext;
while(q != NULL) {
if (q->info < p->info )
Hoanvi(q->info, p->info);
q= q -> pNext;
}
p = p->pNext;
}
}
3. S p x p nhanh trên danh sách:
Trong s các thu t toán s p x p, có l n i ti ng nh t v hi u qu là thu t toán Quick
Sort. Các cài t c a thu t toán này th ng th y trên c u trúc d li u m ng. Trong
ch ng 2 chúng ta ã kh o sát thu t toán này. Tuy nhiên ít ai ý r ng nó c ng là m t
trong nh ng thu t toán s p x p hi u qu nh t trên danh sách. H n n a, khi cài t trên
danh sách, b n ch t c a thu t toán này th hi n m t cách rõ ràng h n bao gi h t:
- Thu t toán Quick Sort:
o c 1:
§ Ch n X là ph n t u danh sách làm ph n t c m canh.
§ Lo i X ra kh i danh sách.
o c 2: Tách danh sách ra làm 2 danh sách list1 (g m các ph n t nh
n hay b ng X) và list2 (g m các ph n t l n h n X).
o c 3:
§ N u list1 != NULL thì QuickSort (list1)
§ N u list2 != NULL thì QuickSort (list2)
o c 4: N i list1, X, và list2 l i theo trình t ta có danh sách ã cs p
x p.

Ch ng 5. C u trúc d li u ng Trang 58
u trúc d li u và gi i thu t
void ListQuickSort (LIST & list) {
NODE *p, *X; // X ch n ph n t c m canh
LIST list1, list2;
if (list.pHead == list.pTail) return; // danh sách ã có th t
list1.pHead == list1.pTail = NULL; // kh i t o danh sách list1
list2.pHead == list2.pTail = NULL; // kh i t o danh sách list2
X = list.pHead;
list.pHead = X->pNext;
while (list.pHead != NULL) { //Tách l thành list1, list2;
p = list.pHead;
list.pHead = p->pNext;
p->pNext = NULL;
if (p->Info <= X->Info)
AddTail(list1, p);
else
AddTail(list2, p);
}
ListQSort(list1); //G i qui sort list1
ListQSort(list2); //G i qui sort list2
// N i list1, X và list2 l i thành l ã s p x p.
if (list1.pHead != NULL) {
list.pHead = list1.pHead;
list1.pTail->pNext = X;
}
else
list.pHead = X;
X->pNext = list2;
if (list2.pHead != NULL)
list.pTail = list2.pTail;
else
list.pTail = X;
}

5.4. Các d ng khác c a danh sách liên k t


5.4.1. Danh sách liên k t kép - double linked list

Ch ng 5. C u trúc d li u ng Trang 59
u trúc d li u và gi i thu t
Danh sách liên k t kép là danh sách mà m i ph n t trong danh sách có k t n i v i
1 ph n t ng tr c và 1 ph n t ng sau nó.
Ta dùng hai con tr : pPrev liên k t v i ph n t ng tr c và pNext liên k t v i
ph n t ng sau:
- Ki u m t ph n t trong danh sách:
struct dnode {
DATA info;
struct node *pPrev;
struct node *pNext;
};
typedef struct dnode DNODE;
- Ki u danh sách liên k t:
struct dlist {
DNODE* pHead;
DNODE* pTail;
};
typedef struct dlist DLIST;
ng t danh sách liên k t n, ta có th xây d ng các thao tác c b n trên danh
sách liên k t kép, các thao tác không khác gì trên danh sách liên k t n.
5.4.2. Danh sách liên k t vòng - circular linked list
Danh sách liên k t vòng là m t danh sách n (ho c kép) mà ph n t cu i danh
sách thay vì mang giá tr NULL thì l i tr t i ph n t u danh sách. Ð bi u di n, ta có
th x d ng các k thu t bi u di n nh danh sách n (ho c kép).
5.4.3. Danh sách có nhi u m i liên k t
Danh sách có nhi u m i liên k t là danh sách mà m i ph n t có nhi u khoá và
chúng c liên k t v i nhau theo t ng lo i khoá.
Danh sách có nhi u m i liên k t th ng c x d ng trong các ng d ng qu n lý
m t c s d li u l n v i nh ng nhu c u tìm ki m d li u theo nh ng khoá khác nhau.
5.4.4. Danh sách t ng quát
Danh sách t ng quát là m t danh sách mà m i ph n t c a nó có th l i là m t danh
sách khác.
v K t lu n:
1. Danh sách liên k t là các c u trúc d li u r t gi ng v i các m ng.
2. Các thao tác chính th ng c s d ng i v i m t danh sách liên k t là thêm,
xóa và tìm ki m trên danh sách.
3. Thao tác chèn và xóa có th th c hi n v i th i gian h ng s .
4. Vi c tìm m t ph n t trong danh sách liên k t th ng m t th i gian tuy n tính
(x p x dài danh sách) và tr ng h p x u nh t là úng b ng dài c a danh
Ch ng 5. C u trúc d li u ng Trang 60
u trúc d li u và gi i thu t
sách. ây c ng chính là m t trong nh ng nh c m l n nh t c a danh sách
liên k t.

Bài t p
1. Phân tích u, khuy t m c a danh sách liên k t so v i m ng. T ng quát hóa
các tr ng h p nên dùng danh sách liên k t.
2. Xây d ng m t c u trúc d li u thích h p bi u di n a th c P(x) có d ng :
P(x) = c1xn1 + c2xn2 +...+ckxnk
3. Cài t thu t toán s p x p Chèn tr c ti p trên danh sách kép. Có phát huy u th
c a thu t toán h n trên m ng hay không ?
4. Cài t thu t toán QuickSort theo ki u không qui.
5. Cài t l i ch ng trình qu n lý nhân viên theo bài t p 5 ch ng 1, nh ng s
d ng c u trúc d li u danh sách liên k t. Bi t r ng s nhân viên không h n ch .

Ch ng 5. C u trúc d li u ng Trang 61

You might also like