Tải bản đầy đủ (.pdf) (8 trang)

Các thuật toán trên cấu trúc, danh sách liên kết

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (152.55 KB, 8 trang )

Kỹ thuật lập trì nh
97
CHƯƠNG 5 CáC THUậT TOáN TRÊN CấU TRúC
DANH SáCH LIÊN KếT (LINKED LIST)

I. Khái niệm:
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ử 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) .


























3
























First
1

2






















4























Cá c phầ n tử trong danh sá ch đ ược kế t nối với nhau theo chùm liê n kế t như
hì nh trê n:
- First là con trỏ chỉ đế n phầ n tử đầ u của danh sá ch liê n kế t
- Phầ n tử cuối của danh sá ch liê n kế t với vùng liê n kế t có giá trị NULL
-Mỗi nút của danh sá ch có trường info chứa nội dung của nút và trường
next là con trỏ chỉ đế n nút kế tiế p trong danh sá ch.
* Lưu ý
:
- 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 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.
Nil
First

Kỹ thuật lập trì nh
98
- Tuy nhiê n, danh sá ch liê n kế t cũng có cá c điể 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.
& Khai bá o
: Một phầ n tử của danh sá ch liê n kế t í t nhấ t phả i có hai thà nh
phầ n : nội dung của phầ n tử (info) và thà nh phầ n next liê n kế t phầ n tử nà y với
phầ n tử khá c.
Giả sử ta khai bá o kiể u NODEPTR là kiể u con trỏ chỉ đế n nút trong 1 danh
sá ch liê n kế t, mỗi phầ n tử có 2 thà nh phầ n : info (int) và next .
struct node
{ int info ;
struct node *next ;
};
typedef struct node *NODEPTR;
- Để khai bá o biế n First quả n lý danh sá ch liê n kế t ta viế t như sau:
NODEPTR First;
- Khởi tạ o danh sá ch liê n kế t : First = NULL;
- Ghi chú
:

' Thà nh phầ n chứa nội dung có thể gồm nhiề u vùng với các kiể u dữ liệ u
khá c nhau.
' Thà nh phầ n liê n kế t cũng có thể nhiề u hơn một nế u là danh sá ch đa liê n
kế t hoặ c danh sá ch liê n kế t kép.
' First là con trỏ trỏ đế n phầ n tử đầ u tiê n của danh sá ch liê n kế t, nó có thể
là kiể u con trỏ (như khai bá o trê n), và cũng có thể là một struct có hai
thà nh phầ n: First trỏ đế n phầ n tử đầ u tiê n của danh sá ch liê n kế t, và Last
trỏ đế n phầ n tử cuối của danh sá ch liê n kế t.
struct Linked_List;
{ First NODEPTR;
Last NODEPTR;
};
II. Các phép toán trên danh sách liên kết
:
II.1. Tạo danh sách
:
a. Khởi tạ o danh sá ch
(Initialize): dùng để khởi động một danh sá ch liê n
kế t, cho chương trì nh hiể u là hiệ n tạ i danh sá ch liê n kế t chưa có phầ n tử.
void Initialize(NODEPTR &First)
{
Kỹ thuật lập trì nh
99
First = NULL;
}
b. Cấ p phá t vùng nhớ
(New_Node): cấ p phá t một nút cho danh sá ch liê n
kế t. Hà m New_Node nà y trả về địa chỉ của nút vừa cấ p phá t.
Trong chương trì nh có sử dụng hà m malloc (trong <alloc.h>) , hà m nà y cấ p
phá t một khối nhớ tí nh theo byte từ bộ nhớ heap. Nế u cấ p phá t thà nh công, hà m

malloc trả về địa chỉ của vùng nhớ vừa cấ p phá t, ngược lạ i nó sẽ trả về NULL.
NODEPTR New_Node()
{
NODEPTR p;
p = (NODEPTR)malloc(sizeof(struct node));
return (p);
}
c. Thê m và o đầ u danh sá ch
(Insert_First): thê m một nút có nội dung x và o
đầ u danh sá ch liê n kế t.
void Insert_First (NODEPTR &First, int x)
{
NODEPTR p;
p = New_Node();
p->info = x;
p->next = First;
First = p;
}
d. Thê m nút mới và o sau nút có địa chỉ p
(Insert_After): thê m một nút có
nội dung x và o sau nút có địa chỉ p trong danh sá ch liê n kế t First.
void Insert_After(NODEPTR p, int x)
{
NODEPTR q;
if(p == NULL)
printf("khong them nut moi vao danh sach duoc");
else
{
q = New_Node();
q->info = x;

q->next = p->next;
p->next = q;
}
}
Kỹ thuật lập trì nh
100
II.2. Cập nhật danh sách:
a. Giả i phóng vùng nhớ
(Free_Node): Hà m nà y dùng để hủy nút đ cấ p
phá t, và trả vùng nhớ về lạ i cho memory heap.
void Free_Node(NODEPTR p)
{
free(p);
}
b. Kiể m tra danh sá ch liê n kế t rỗng hay không
(Empty): hà m Empty trả về
TRUE nế u danh sá ch liê n kế t rỗng, và ngược lạ i.
int Empty(NODEPTR First)
{
return(First == NULL ? TRUE : FALSE);
}
c. Xóa phầ n tử đầ u của danh sá ch
(Delete_First): muốn xóa 1 phầ n tử khỏi
danh sá ch liê n kế t thì ta phả i kiể m tra xem danh sá ch có rỗng hay không. Nế u
danh sá ch có phầ n tử thì mới xóa đ ược.
void Delete_First (NODEPTR First)
{ NODEPTR p;
if (Empty(First))
printf("Danh sach rong nen khong the xoa");
else

{
p = First; // nut can xoa la nut dau
First = p->next;
Free_Node(p);
}
}
d. Xóa phầ n tử đứng sau nút có địa chỉ p
(Delete_After):
void Delete_After(NODEPTR p)
{ NODEPTR q;
// nế u p là NULL hoặ c sau p không có nút
if((p == NULL) || (p->next == NULL))
printf("khong xoa duoc");
else
{
q = p->next; // q chi nut can xoa
p->next = q->next;
Kỹ thuật lập trì nh
101
Free_Node(q);
}
}
e. Xóa toà n bộ danh sá ch
(Delete_All): ta có thể sử dụng lệ nh *First =
NULL để xóa toà n bộ danh sá ch, nhưng trong bộ nhớ, cá c vùng nhớ đ cấ p phá t
cho cá c nút không giả i phóng về lạ i cho memory heap, nê n sẽ l ng phí vùng nhớ.
Do đó, ta sử dụng giả i thuậ t sau:
void Delete_All (NODEPTR &First)
{ NODEPTR p;
while (First != NULL)

{ p=First;
First = First->next; // hoặ c First = p->next
Free_Node(p);
}
}
II.3. Duyệ t danh sách
: Thông thường ta hay duyệ t danh sá ch liê n kế t để thực
hiệ n một công việ c gì đó, như liệ t kê dữ liệ u trong danh sá ch hay đế m số nút
trong danh sá ch...
void Traverse(NODEPTR First)
{ NODEPTR p;
int stt = 0;
p = First;
if(p == NULL)
printf("\n (Khong co sinh vien trong danh sach)");
while(p != NULL)
{
printf("\n %5d%8d", stt++, p->info);
p = p->next;
}
}
II.4. Tì m kiế m
(Search): Tì m nút đầ u tiê n trong danh sá ch có info bằ ng với x.
Do đâ y là danh sá ch liê n kế t nê n ta phả i tì m từ đầ u danh sá ch.
Hà m Search nế u tì m thấ y x trong danh sá ch thì trả về địa chỉ của nút có trị
bằ ng x trong danh sá ch, nế u không có thì trả về trị NULL.
NODEPTR Search(NODEPTR First, int x)
{
NODEPTR p;

×