Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 51 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
51
Dung lượng
208,5 KB
Nội dung
CHƯƠNG 5 CẤU TRÚC DỮ LIỆU CÂY (TREE) 5.1- Định nghĩa và khỏi niệm Cõy là một tập hợp hữu hạn cỏc node cú cựng chung một kiểu dữ liệu, trong đú cú một node đặc biệt gọi là node gốc (root). Giữa cỏc node cú một quan hệ phõn cấp gọi là “quan hệ cha con”. Cú thể định nghĩa một cỏch đệ qui về cõy như sau: • Một node là một cõy. Node đú cũng là gốc (root) của cõy ấy. • Nếu n là một node và T 1 , T 2 , . , T k là cỏc cõy với n 1 , n 2 , . . , n k lần lượt là gốc thỡ một cõy mới T sẽ được tạo lập bằng cỏch cho node n trở thành cha của cỏc node n 1 , n 2 , . . , n k hay node n trở thành gốc và T 1 , T 2 , . ., T k là cỏc cõy con (subtree) của gốc. Vớ dụ: cấu trỳc tổ chức thư mục (directory) của dos là một cấu trỳc cõy. Hỡnh 5.1- Vớ dụ về một cõy thư mục Một cõy được gọi là rỗng nếu nú khụng cú bất kỳ một node nào. Số cỏc node con của một node được gọi là cấp (degree) của node đú. Vớ dụ: trong cõy 5.2 sau, cấp của node A là 3, cấp của node B là 2, cấp của node D là 3, cấp của node H là 2. 193 5 5. 1 5. 2 5. 3 5. 4 5.1.1 5.1.2 5.3.1 5.3.2 5.4.1 5.4.2 A B C D E F G H I J K Node cú cấp bằng 0 được gọi là lỏ (leaf) hay node tận cựng (terminal node). Vớ dụ: cỏc node E, F, C, G, I, J, K được gọi là lỏ. Node khụng là lỏ được gọi là node trung gian hay node nhỏnh (branch node). Vớ dụ node B, D, H là cỏc node nhỏnh. Cấp cao nhất của node trờn cõy gọi là cấp của cõy, trong trường hợp cõy trong hỡnh 5.2 cấp của cõy là 3. Gốc của cõy cú số mức là 1. Nếu node cha cú số mức là i thỡ node con cú số mức là i+1. Vớ dụ gốc A cú số mức là 1, D cú số mức là 2, G cú số mức là 3, j cú số mức là 4. Chiều cao (height) hay chiều sõu (depth) của một cõy là số mức lớn nhất của node trờn cõy đú. Cõy 5.2 cú chiều cao là 4. Đường đi từ node n 1 đến n k là dóy cỏc node n 1 , n 2 , . ., n k sao cho n i là node cha của node n i+1 (1<=i<k), độ dài của đường đi (path length) được tớnh bằng số cỏc node trờn đường đi trừ đi 1 vỡ nú phải tớnh từ node bắt đầu và node kết thỳc. Vớ dụ: trong cõy 5.2 đường đi từ node A tới node G là 2, đường đi từ node A đến node K là 3. Một cõy được gọi là cú thứ tự nếu chỳng ta xột đến thứ tự cỏc cõy con trong cõy (ordered tree), ngược lại là cõy khụng cú thứ tự (unordered tree). Thụng thường cỏc cõy con được tớnh theo thứ tự từ trỏi sang phải. 5.2- Cõy nhị phõn Cõy nhị phõn là một dạng quan trọng của cấu trỳc cõy cú đặc điểm là mọi node trờn cõy chỉ cú tối đa là hai node con. Cõy con bờn trỏi của cõy nhị phõn được gọi là left subtree, cõy con bờn phải của cõy được gọi là right subtree. Đối với cõy nhị phõn, bao giờ cũng được phõn biệt cõy con bờn trỏi và cõy con bờn phải. Như vậy, cõy nhị phõn là một cõy cú thứ tự. Vớ dụ trong hỡnh 5.3 đều là cỏc cõy nhị phõn: 194 Hỡnh 5.3 cỏc cõy nhị phõn Cỏc cõy nhị phõn cú dạng đặc biệt bao gồm: • Cõy nhị phõn lệch trỏi (hỡnh 5.4a): là cõy nhị phõn chỉ cú cỏc node bờn trỏi. • Cõy nhị phõn lệnh phải (hỡnh 5.4b): là cõy chỉ bao gồm cỏc node phải. • Cõy nhị phõn zic zắc (hỡnh 5.4 c, 5.4d): node trỏi và node phải của cõy đan xen nhau thành một hỡnh zic zắc. • Cõy nhị phõn hoàn chỉnh ( strictly binary tree: hỡnh 5.4e) : Một cõy nhị phõn được gọi là hoàn chỉnh nếu như node gốc và tất cả cỏc node trung gian đều cú hai con. • Cõy nhị phõn đầy đủ (complete binary tree : hỡnh 5.4f): Một cõy nhị phõn được gọi là đầy đủ với chiều sõu d thỡ nú phải là cõy nhị phõn hoàn chỉnh và tất cả cỏc node lỏ đều cú chiều sõu là d. 195 A B C D E A B C D E A B C D E Hỡnh 5.4a Hỡnh 5.4b Hỡnh 5.4c Hỡnh 5.4d Hỡnh 5.4 e Hỡnh 5.4f • Cõy nhị phõn hoàn toàn cõn bằng (hỡnh 5.5): là cõy nhị phõn mà ở tất cả cỏc node của nú số node trờn nhỏnh cõy con bờn trỏi và số node trờn nhỏnh cõy con bờn phải chờnh lệnh nhau khụng quỏ 1. Nếu ta gọi N l là số node của nhỏnh cõy con bờn trỏi và N r là số node của nhỏnh cõy con bờn phải, khi đú cõy nhị phõn hoàn toàn cõn bằng chỉ cú thể ở một trong 3 trường hợp: • Số node nhỏnh cõy con bờn trỏi bằng số node nhỏnh cõy con bờn phải bằng N l = N r (hỡnh 5.5a). • Số node nhỏnh cõy con bờn trỏi bằng số node nhỏnh cõy con bờn phải cộng 1 N l = N r+1 (hỡnh 5.5b) • Số node nhỏnh cõy con bờn trỏi bằng số node nhỏnh cõy con bờn phải trừ 1 N l = N r-1 (hỡnh 5.5c). 196 A B C D E A B C D E A B C D E A B C D E A B C D E F G H I A B C D E F G Hỡnh 5.5a Bỡnh 5.5b Hỡnh 5.5c • Cõy nhị phõn tỡm kiếm: là một cõy nhị phõn hoặc bị rỗng hoặc tất cả cỏc node trờn cõy thỏa món điều kiện sau: • Nội dung của tất cả cỏc node thuộc nhỏnh cõy con bờn trỏi đều nhỏ hơn nội dung của node gốc. • Nội dung của tất cả cỏc node thuộc nhỏnh cõy con bờn phải đều lớn hơn nội dung của node gốc. • Cõy con bờn trỏi và cõy con bờn phải cũng tự nhiờn hỡnh thành hai cõy nhị phõn tỡm kiếm. Hỡnh 5.6- vớ dụ về cõy nhị phõn tỡm kiếm 5.3- Biểu diễn cõy nhị phõn 5.3.1- Biểu diễn cõy nhị phõn bằng danh sỏch tuyến tớnh Trong trường hợp cõy nhị phõn đầy đủ, ta cú thể dễ dàng biểu diễn cõy nhị phõn bằng một mảng lưu trữ kế tiếp. Trong đú node gốc là phần tử đầu tiờn của mảng (phần tử 197 A B C D E A B C D E F A B C D E F 2 0 1 2 3 0 8 1 5 2 5 3 7 6 1 0 2 2 2 8 4 0 1 0 9 8 6 1 0 1 9 2 9 3 9 thứ 1), node con thứ i>=1 của cõy nhị phõn là phần tử thứ 2i, 2i + 1 hay cha của node thứ j là [j/2]. Với qui tắc đú, cõy nhị phõn cú thể biểu diễn bằng một vector V sao cho nội dung của node thứ i được lưu trữ trong thành phần V[i] của vector V. Ngược lại, nếu biết địa chỉ của phần tử thứ i trong vector V chỳng ta cũng hoàn toàn xỏc định được ngược lại địa chỉ của node cha, địa chỉ node gốc trong cõy nhị phõn. Vớ dụ: cõy nhị phõn trong hỡnh 5.7 sẽ được lưu trữ kế tiếp như sau: V[0] V[1] V[2] V[3] V[4] V[5] V[6] Hỡnh 5.7- Lưu trữ kế tiếp của cõy nhị phõn Đối với cõy nhị phõn khụng đầy đủ, việc lưu trữ bằng mảng tỏ ra khụng hiệu quả vỡ chỳng ta phải bỏ trống quỏ nhiều phần tử gõy lóng phớ bộ nhớ như trong vớ dụ sau: Hỡnh 5.8- Lưu trữ kế tiếp của cõy nhị phõn khụng đầy đủ V[0] V[1] V[2] V[3] V[4] V[5] V[6] 5.3.2- Biểu diễn cõy nhị phõn bằng danh sỏch múc nối Trong cỏch lưu trữ cõy nhị phõn bằng danh sỏch múc nối, mỗi node được mụ tả bằng ba loại thụng tin chớnh : left là một con trỏ trỏ tới node bờn trỏi của cõy nhị phõn; infor : là thụng tin về node, infor cú thể là một biến đơn hoặc một cấu trỳc; right là một con trỏ trỏ tới node bờn phải của cõy nhị phõn. Trong trường hợp node là node lỏ thỡ con trỏ left và con trỏ right được trỏ tới con trỏ NULL. Đối với node lệch trỏi, con trỏ right sẽ trỏ tới con trỏ NULL, ngược 198 3 0 2 5 3 7 2 2 2 8 4 0 3 5 30 25 37 22 28 35 40 3 0 2 5 3 7 2 2 3 5 30 25 37 22 φ 35 φ lại đối với node lệch phải, con trỏ left cũng sẽ trỏ tới con trỏ NULL. Cấu trỳc của một node được mụ tả trong hỡnh 5.9. Hỡnh 5.9 mụ tả một node của cõy nhị phõn. Vớ dụ: cõy nhị phõn trong hỡnh 5.10 sẽ được biểu diễn bằng danh sỏch liờn kết như sau: Hỡnh 5.10: biểu diễn cõy nhị phõn bằng danh sỏch múc nối . 5.4- Cỏc thao tỏc trờn cõy nhị phõn 5.4.1- Định nghĩa cõy nhị phõn bằng danh sỏch tuyến tớnh Mỗi node trong cõy được khai bỏo như một cấu trỳc gồm 3 trường: infor, left, right. Toàn bộ cõy cú thể coi như một mảng mà mỗi phần tử của nú là một node. Trường infor tổng quỏt cú thể là một đối tượng dữ liệu kiểu cơ bản hoặc một cấu trỳc. Vớ dụ: định nghĩa một cõy nhị phõn lưu trữ danh sỏch cỏc số nguyờn: #define MAX 100 #define TRUE 1 #define FALSE 0 struct node { int infor; int left; int right; }; typedef structnode node[MAX]; 199 Left Infor Right 3 0 2 5 3 7 2 2 3 5 Left 30 Right Left 25 NULL Left 37 NULL NULL 22 NULL NULL 35 NULL 5.4.2- Định nghĩa cõy nhị phõn theo danh sỏch liờn kết: struct node { int infor; struct node *left; struct node *right; } typedef struct node *NODEPTR 5.4.3- Cỏc thao tỏc trờn cõy nhị phõn Cấp phỏt bộ nhớ cho một node mới của cõy nhị phõn: NODEPTR Getnode(void) { NODEPTR p; p= (NODEPTR) malloc(sizeof(struct node)); return(p); } Giải phúng node đó được cấp phỏt void Freenode( NODEPTR p){ free(p); } Khởi động cõy nhị phõn void Initialize(NODEPTR *ptree){ *ptree=NULL; } Kiểm tra tớnh rỗng của cõy nhị phõn: int Empty(NODEPTR *ptree){ if (*ptree==NULL) 200 return(TRUE); return(FALSE); } Tạo một node lỏ cho cõy nhị phõn: • Cấp phỏt bộ nhớ cho node; • Gỏn giỏ trị thụng tin thớch hợp cho node; • Tạo liờn kết cho node lỏ; NODEPTR Makenode(int x){ NODEPTR p; p= Getnode();// cấp phỏt bộ nhớ cho node p ->infor = x; // gỏn giỏ trị thụng tin thớch hợp p ->left = NULL; // tạo liờn kết trỏi của node lỏ p ->right = NULL;// tạo liờn kết phải của node lỏ return(p); } Tạo node con bờn trỏi của cõy nhị phõn: Để tạo được node con bờn trỏi là node lỏ của node p, chỳng ta thực hiện như sau: • Nếu node p khụng cú thực (p==NULL), ta khụng thể tạo được node con bờn trỏi của node p; • Nếu node p đó cú node con bờn trỏi (p->left!=NULL), thỡ chỳng ta cũng khụng thể tạo được node con bờn trỏi node p; • Nếu node p chưa cú node con bờn trỏi, thỡ việc tạo node con bờn trỏi chớnh là thao tỏc make node đó được xõy dựng như trờn; Hỡnh 5.11 sẽ minh họa cho thao tỏc tạo node con X phớa bờn trỏi của node D. void Setleft(NODEPTR p, int x ){ if (p==NULL){ // nếu node p khụng cú thực thỡ khụng thể thực hiện được printf(“\n Node p khụng cú thực”); 201 delay(2000); return; } // nếu node p cú thực và tồn tại lỏ con bờn trỏi thỡ cũng khụng thực hiện được else if ( p ->left !=NULL){ printf(“\n Node p đó cú node con bờn trỏi”); delay(2000); return; } // nếu node cú thực và chưa cú node trỏi else p ->left = Makenode(x); } Hỡnh 5.11 mụ tả thao tỏc thờm node con bờn trỏi cõy nhị phõn Tạo node con bờn phải của cõy nhị phõn: Để tạo được node con bờn phải là node lỏ của node p, chỳng ta làm như sau: • Nếu node p khụng cú thực (p==NULL), thỡ ta khụng thể thực hiện được thao tỏc thờm node lỏ vào node phải node p; • Nếu node p cú thực (p!=NULL) và đó cú node con bờn phải thỡ thao tỏc cũng khụng thể thực hiện được; • Nếu node p cú thực và chưa cú node con bờn phải thỡ việc tạo node con bờn phải node p được thực hiện thụng qua thao tỏc Makenode(); 202 A B C E FD H IG A B C E FD H IG X [...]... khong la node la"); delay(2000); return(-1); } } node[p].left=-1;// Dua node con ben trai cua node p ve dang NULL Freenode(q);return(x);// Giai phong gia tri cua node con q }*/ delay(2000); break; case 5: 219 printf("\n Noi dung node cha:"); scanf("%d",&noidung); p=Search(ptree, noidung); if(p==-1) printf("\n Khong thay node cha"); else Delright(p); /* int Delright (int p){ int q, x; if (p ==-1){ printf("\n... while(p->sonut!=1 && p->sonut!=2){ if(p->sonut%2==1){ p->sonut++; p=p->left; } else { p->sonut++; p= p->right; } } 223 if (p->sonut==1){ p->sonut++; Setleft(p,x); } else { p->sonut++; Setright(p,x); } } Chương trỡnh cài đặt cõy nhị phõn hoàn toàn cõn bằng được thể hiện như sau: #include #include #include #include #include #include #define TRUE . CHƯƠNG 5 CẤU TRÚC DỮ LIỆU CÂY (TREE) 5.1- Định nghĩa và khỏi niệm Cõy là một tập hợp hữu hạn cỏc node cú cựng chung một kiểu dữ liệu, trong đú cú một node đặc. cấu trỳc gồm 3 trường: infor, left, right. Toàn bộ cõy cú thể coi như một mảng mà mỗi phần tử của nú là một node. Trường infor tổng quỏt cú thể là một đối tượng dữ liệu kiểu cơ bản hoặc một cấu. gốc và T 1 , T 2 , . ., T k là cỏc cõy con (subtree) của gốc. Vớ dụ: cấu trỳc tổ chức thư mục (directory) của dos là một cấu trỳc cõy. Hỡnh 5.1- Vớ dụ về một cõy thư mục Một cõy được gọi là rỗng