Căi đặt bằng danh sâch liín kết

Một phần của tài liệu Lập trình C (Trang 107 - 111)

V. CĐY TÌM KIẾM NHỊ PHĐN (BINARY SEARCH TREES)

2. Căi đặt bằng danh sâch liín kết

Tập hợp cũng có thể căi đặt bằng danh sâch liín kết, trong đó mỗi phần tử của danh sâch lă một thănh viín của tập hợp. Không như biểu diễn bằng vectơ bít, sự biểu diễn năy dùng kích thước bộ nhớ tỉ lệ với số phần tử của tập hợp chứ không phải lă kích thước đủ lớn cho toăn thể câc tập hợp đang xĩt. Hơn nữa, ta có thể biểu diễn một tập hợp bất kỳ. Mặc dù thứ tự của câc phần tử trong tập hợp lă không quan trọng nhưng nếu một danh sâch liín kết có thứ tự nó có thể trợ giúp tốt cho câc phĩp duyệt danh sâch. Chẳng hạn nếu tập hợp A được biểu diễn bằng một danh sâch có thứ tự tăng thì hăm MEMBER(x,A) có thể thực hiện việc so sânh x một câch tuần tự từ đầu danh sâch cho đến khi gặp một phần tử y ≥ x chứ không cần so sânh với tất cả câc phần tử trong tập hợp.

Một ví dụ khâc, chẳng hạn ta muốn tìm giao của hai tập hợp A vă B có n phần tử. Nếu A,B biểu diễn bằng câc danh sâch liín kết chưa có thứ tự thì để tìm giao của A vă B ta phải tiến hănh như sau:

for (mỗi x thuộc A )

{ Duyệt danh sâch B xem x có thuộc B không. Nếu có thì x thuộc giao của hai tập hợp A vă B; }

Rõ răng quâ trình năy có thể phải cần đến n x m phĩp kiểm tra (với n,m lă độ dăi của A vă B).

Nếu A,B được biểu diễn bằng danh sâch có thứ tự tăng thì đối với một phần tử e∈A ta chỉ tìm kiếm trong B cho đến khi gặp phần tử x ≥ e. Quan trọng hơn nếu f đứng ngay sau e trong A thì để tìm kiếm f trong B ta chỉ cần tìm từ phần tử x trở đi chứ không phải từ đầu danh sâch lưu trữ tập hợp B.

Khai bâo

typedef int ElementType; typedef struct Node

{

ElementType Data; Node * Next;

};

typedef Position SET;

Thủ tục UNION

//C= hop cua hai tap hop A,B

void UnionSET(SET A, SET B, SET *C) { Position p; MakeNullSET(C); p=First(A); while (p!=EndSET(A)) { InsertSET (Retrieve(p,A),*C); p=Next(p,A); } p=First(B); while (p!=EndSET (B)) { if (Member(Retrieve(p,B),*C)==0) InsertSET (Retrieve(p,B),*C); p=Next(p,B); } } Thủ tục INTERSECTION

// C=giao cua hai tap hop A,B

void IntersectionSET(SET A, SET B, SET *C) {

Position p; MakeNullSET(C);

p=First(A); while (p!=EndSET(A)) { if (Member(Retrieve(p,A),B)==1) InsertSET (Retrieve(p,A),*C); p=Next(p,A); } }

Phĩp toân hiệu có thể viết tương tự (xem như băi tập). Phĩp ASSIGN(A,B) chĩp câc câc phần tử của tập A sang tập B, chú ý rằng ta không được lăm bằng lệnh gân đơn giản B:=A vì nếu lăm như vậy hai danh sâch biểu diễn cho hai tập hợp A,B chỉ lă một nín sự thay đổi trín tập năy kĩo theo sự thay đổi ngoăi ý muốn trín tập hợp kia. Toân tử MIN(A) chỉ cần trả ra phần tử đầu danh sâch (tức lă A->Next->Data). Toân tử DELETESET lă hoăn toăn giống như DELETE_LIST. Phĩp INSERTSET(x,A) cũng tương tự INSERT_LIST tuy nhiín ta phải chú ý rằng khi xen x văo A phải đảm bảo thứ tự của danh sâch.

Thím phần tử văo tập hợp

// Them phan tu vao tap hop co thu tu void InsertSET(ElementType X, SET L) { Position T,P; int finish=0; P=L; while ((P->Next!=NULL)&&(finish==0)) if (P->Next->Data<=X) P=P->Next; else finish=1;

// P dang luu tru vi tri de xen phan tu X vao T=(Node*)malloc(sizeof(Node));

T->Data=X;

P->Next=T; }

Xoâ phần tử ra khỏi tập hợp:

void DeleteSET(ElementType X, SET L) {

Position T,P=L; int finish=0;

while ((P->Next!=NULL)&& (finish==0)) if (P->Next->Data<X) P=P->Next; else finish=1; if (finish==1) if(P->Next->Data==X) { T=P->Next; P->Next=T->Next; free(T); } } Kiểm tra sự hiện diện của phần tử trong tập hợp:

Hăm kiểm tra xem phần tử X có thuộc tập hợp hay không. Hăm trả về giâ trị 1 nếu phần tử X đó thuộc tập hợp vă ngược lại, hăm trả về giâ trị 0.

int Member(ElementType X, SET L) {

Position P; int Found = 0; P = First(L);

while ((P != EndSET(L)) && (Found == 0)) if (Retrieve(P,L) == X) Found = 1;

else P = Next(P, L); return Found;

}

Một phần của tài liệu Lập trình C (Trang 107 - 111)

Tải bản đầy đủ (PDF)

(151 trang)