Các thuật toán trên cấu trúc danh sách liên kết (Linked list)

8 804 5
Các thuật toán trên cấu trúc danh sách liên kết (Linked list)

Đang tải... (xem toàn văn)

Thông tin tài liệu

Kỹ thuật lập trì nh 96 for (i=0; i<n-1;i++) for (j=i+1; j<n; j++) if ( strcmp(p[i],p[j]) >0) { tam = p[i]; p[i] = p[j]; p[j] = tam; } printf("\n Danh sach ho ten sau khi sap xep\n"); for (i=0; i<n;i++) printf("%s\n", p[i]); } Lưu ý : Chương trì nh trê n thực chấ t ta chỉ hoán đổi giá trị của mả ng con trỏ p chứ mả ng chuỗi ds vẫ n như cũ. Bà i tậ p: 1. Sắ p xế p lạ i danh sá ch học viê n theo thứ tự họ tă ng dầ n bằ ng con trỏ. 2. Sắ p xế p lạ i danh sá ch học viê n theo thứ tự tê n tă ng dầ n, nế u trùng tê n thì sắ p theo họ bằ ng con trỏ. 3. Sắ p xế p lạ i danh sá ch học viê n theo thứ tự tê n tă ng dầ n, nế u trùng tê n thì sắ p theo họ bằ ng mả ng chuỗi. 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; Kỹ thuật lập trì nh 102 p = First; while(p != NULL && p->info != x ) p = p->next; return (p); } II.5. Sắp xế p (Selection_Sort): sắ p xế p danh sá ch liê n kế t theo thứ tự info tă ng dầ n. - Nội dung : Ta so sá nh tấ t cả cá c phầ n tử của danh sá ch để chọn ra một phầ n tử nhỏ nhấ t đ ưa về đầ u danh sá ch; sau đ ó, tiế p tục chọn phầ n tử nhỏ nhấ t trong cá c phầ n tử còn lạ i để đ ưa về phầ n tử thứ hai trong danh sá ch. Quá trì nh nà y lặ p lạ i cho đế n khi chọn ra đ ược phầ n tử nhỏ thứ (n-1). - Giả i thuậ t: void Selection_Sort(NODEPTR First) { NODEPTR p, q, pmin; int min; for(p = First; p->next != NULL; p = p->next) { min = p->info; pmin = p; for(q = p->next; q != NULL; q = q->next) if(min > q->info) { min = q->info; pmin = q; } // hoan doi truong info cua hai nut p va pmin pmin->info = p->info; p->info = min; } } Kỹ thuật lập trì nh 103 Bài tập: 1. Viế t chương trì nh tạ o một menu thực hiệ n cá c công việ c sau: a. Nhậ p danh sá ch liê n kế t theo giả i thuậ t thê m về đầ u danh sá ch, mỗi phầ n tử gồm có cá c thông tin sau: mssv (int), và hoten ( char hoten[30] ). b. Liệ t kê danh sá ch ra mà n hì nh c. Cho biế t tổng số nút trong danh sá ch liê n kế t, đặ t tê n hà m là Reccount ( int Reccount(NODEPTR First) ) d. Thê m 1 phầ n tử có nội dung info (mssv, hoten) và o sau phầ n tử có thứ tự thứ i trong danh sá ch. Ghi chú : - Thứ tự theo qui ước bắt đầu là 1 - Nế u (i = 0) thê m và o đầ u danh sá ch Nế u i > Reccount(&First) thì thê m và o cuối danh sá ch. e. In ra họ tê n của sinh viê n có m do ta nhậ p và o. f. Loạ i bỏ nút có m do ta nhậ p và o, trước khi xóa hỏi lạ i "Bạ n thậ t sự muốn xóa (Y/N) ? " g. Sắ p xế p lạ i danh sá ch theo thứ tự m số giả m dầ n. h.Ghi toà n bộ danh sá ch và o file tê n 'DSSV.DAT' i. Nạ p danh sá ch từ file 'DSSV.DAT' và o danh sá ch liê n kế t. Nế u trong danh sá ch liê n kế t đ có nút thì xóa tấ t cả dữ liệ u hiệ n có trong danh sá ch liê n kế t trước khi đ ưa dữ liệ u từ file và o. 2. Viế t chương trì nh tạ o một danh sá ch liê n kế t theo giả i thuậ t thê m và o cuối danh sá ch, mỗi nút chứa một số nguyê n. 3. -Viế t hà m tê n Delete_Node để xóa nút có địa chỉ p. - Viế t một hà m loạ i bỏ tấ t cả cá c nút có nội dung x trong danh sá ch liê n kế t First. 4. Viế t hà m Copy_List trê n danh sá ch liê n kế t để tạ o ra một danh sá ch liê n kế t mới giống danh sá ch liê n kế t cũ. 5. Ghép một danh sá ch liê n kế t có địa chỉ đầ u là First2 và o một danh sá ch liê n kế t có địa chỉ đầ u là First1 ngay sau phầ n tử thứ i trong danh sá ch liê n kế t First1. 6. Viế t hà m lọc danh sá ch liê n kế t để trá nh trường hợp cá c nút trong danh sá ch liê n kế t bị trùng info. 7. Đả o ngược vùng liê n kế t của một danh sá ch liê n kế t sao cho: - First sẽ chỉ đế n phầ n tử cuối - Phầ n tử đầ u có liê n kế t là NULL. . 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. }; 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,

Ngày đăng: 05/10/2013, 11:20

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan