Tài liệu rất hay và dễ hiểu về Danh sách Cây nhị phân
Bai DANH SCH Ôn kiểu liệu struct Một biến có kiểu struct đợc dùng để lu trữ đối tợng có nhiều thành phần Các thành phần thuộc kiểu liệu khác Định nghĩ nghĩa kiể kiểu hocvien : struct hocvien { char ho[30]; char ten[7]; float toan, ly, hoa , dtb; char xeploai[10]; }; Khai bá báo biến kiể kiểu hocvien : struct hocvien hv; Kiu d liu struct (tt) Khai báo kết hợp với định nghĩa kiểu : struct hocvien { char ho[30]; char ten[7]; float toan, ly, hoa , dtb; char xeploai[10]; } hv1, hv2; Vớ d v kiu d liu struct struct ngaysinh { unsigned int ngay, thang, nam; }; struct hocvien { char ho[30]; char ten[7]; struct ngaysinh ngsinh; float toan, ly, hoa, dtb; char xeploai[10]; 10 } ; 11 struct hocvien hv; Truy xut thnh bin kiu struct Truy xuất thành phần biến struct Biến.thànhphần[.thanhphan]* Truy xuất tới họ học viên hv : hv.ho Truy xuất tới tháng sinh học viên hv: hv.ngsinh.thang hv.ngsinh.thang Phép gán biến cấu trúc Hai biến struct có kiểu gán cho : ví dụ struct hocvien hv1, hv2; hv1 = hv2 tơng đơng với dãy phép gán thành phần Con trỏ biến struct Khai báo trỏ mảng struct struct hocvien hv, *p, ds[100]; p trỏ dến địa biến hv : p = &hv; Truy nhập đến thành phần biến struct trỏ Cách : p->thanhphan ví dụ : p->ho Cách : (*p).thanhphan ví dụ : (*p).ho Ví dụ mảng trỏ struct #define MAX_SOSV 100 // số sinh viên tối đa danh sách typedef struct sinhvien // định nghĩa kiểu sinhvien { char maso[6]; char hoten[30]; }; typedef struct danhsach_sv // định nghĩa kiểu danhsach_sv { int tssv; sinhvien sv[MAX_SOSV]; } ; Bài toán : Tìm kiếm sinh viên theo mã số, có in tên sinh viên Ví dụ mảng trỏ struct void Nhap_ds (struct danhsach_sv *psv) { char sosv[4]; printf("So sinh vien muon nhap :"); gets(sosv); psv->tssv=atoi(sosv); for (int i=0; itssv; i++) { printf("Ma so :"); gets(psv->sv[i].maso); printf("Ho ten :"); 10 gets(psv->sv[i].hoten); 11 } 12 } void Lietke_ds (struct danhsach_sv *psv) { int i=0; clrscr(); printf (" Ma so Ho & ten \n"); while (i < psv->tssv) { printf ("%8s %-s\n", psv-sv[i].maso, psv->sv[i].hoten); i++; } getch(); 10 } Ví dụ mảng trỏ struct /* Hàm Timkiem tìm maso danhsach *psv */ int Timkiem(struct danhsach_sv *psv, char maso[]) { int i=0; while ((itssv) && (strcmp(psv->sv[i].maso, maso)!=0)) i++; return (i==psv->tssv ? -1 : i) ; } 10 Tỡm kim NODEPTR Search(NODEPTR root, int x) { NODEPTR p; p = root; while(p != NULL && x!=p->key) if(x < p->key) p = p->left; else p = p->right; 10 return(p); 11 } 12 Lời gọi hàm: p=Search(tree, x); 83 Duyt cõy Các phép duyệệt cây: Có cách duyệt NLR, LNR, LRN a Duyệt theo thứ tự NLR (Preorder): void Preorder (NODEPTR root) { if(root != NULL) { printf("%d ", root->info); Preorder(root->left); Preorder (root->right); } } c Duyệt theo thứ tự LRN (Posorder): void Posorder(NODEPTR root) { if(root != NULL) { Posorder(root->left); Posorder(root->right); printf("%d ", root->info); } } b Duyệt theo thứ tự LNR (Inorder): void Inorder(NODEPTR root) { if(root != NULL) { Inorder(root->left); printf("%d ", root->info); Inorder(root->right); } } 84 Cây nhị phâ phân tìm kiếm cân (AVL) AVL nhị phân tìm kiếm mà tất nút chiều cao bên trái chiều cao bên phải chênh lệch không 10 20 30 15 12 18 25 40 AVL: balance factor Chỉ = Chỉ số cân (balance factor) nút p AVL= lh(p) lh(p) - rh(p) rh(p) lh (p) chiều cao bên trái p rh(p) chiều cao bên phải p -1 A 0 U1 B U2 B 0 U3 B 0 U4 U5 U6 U7 B U8 C -1 0 BB B U9 U10 U11 U12 Định nghĩ nghĩa và khai bá báo AVL struct nodetype { int key; int info; int bf; struct nodetype *left, *right; }; typedef struct nodetype *NODEPTR; Phép toá toán trê AVL: Thê Thêm - Nội dung:: Thêm nút có khóa x, nội dung a vào nhị phân tìm kiếm cân cho sau thêm nhị phân nhị phân tìm kiếm cân - Giải thuật: Đ Thêm nút vào nh bình thờng, nghĩa nút vừa thêm nút Đ Tính lại số cân nút có bị ảnh hởng Đ Kiểm tra xem có bị cân hay không? Nếu bị cân ta cân lại -Chú ý: Có trờng hợp thêm nút x vào AVL làm cân bằng, - thêm nút vào sau bên trái nút có bf = 1, - thêm nút vào sau bên phải nút có bf = -1 Tr Trờng hợ hợp 1a: 1a Nếu thêm nút x vào vị trí nút sau bên trái s (thuộc nhánh T1) ta xoay phải quanh nút ya - Nút s nút gốc nhánh với bfs = - Nút ya nút bên phải s với bf ya = S T1 chieu saõu n x T2 chieu saõu n (a) S ya T3 xoay phaỷi chieu quanh nuựt ya saõu n T1 chieu saõu n x 0 ya T2 chieu saõu n (b) T3 chieu saõu n Tr Trờng hợp 1b: 1b Nếu thêm nút x vào vị trí nút sau bên phải s (thuộc nhánh T2) ta xoay lần (xoay kép): xoay trái quanh nút s xoay phải quanh nút ya - Nút p nút gốc nhánh với bfp = - Nút ya nút bên phải p với bfya = -1 - Nút s nút bên trái p với bfs = ya S -1 T1 chie u saõ u n T2-1 chie u saõ u n-1 x p T2-2 chie u saõ u n-1 T3 chie u saõ u n Cây AVL sau thêm nút x p xoay traự i S quanh nuự t S T1 chie u saõ u n T2-1 chie u saõ u n-1 x 2 T2-2 chie u saõ u n-1 ya T3 chie u saõ u n xoay phaỷ i quanh nuựt ya p S T1 chieu saõ u n -1 T2-1 T2-2 chieu chieu saõu saõu n-1 n-1 x ya T3 chieu saõu n Trớ Trớc ớc thê thêm nút x Sau thê thêm nút x Các phép xoay chỉ số cân bfya = bfs = bfya = bfs = Xoay phai quanh nút ya bfya = bfs = bfya = bfs = -1 Xoay kép bfya = -1 bfs = bfya = -2 bfs = -1 Xoay trái quanh nút ya bfya = -1 bfs = bfya = -2 bfs = Xoay kép Tr Trờng hợp 1.a 1.b 2.a 2.b bfs=0, bf ya = Xoay trái quanh nút s Xoay phai quanh nút ya bfs=0, bf ya = -1 bfs=0, bf ya = Xoay phai quanh nút s Xoay trái quanh nút ya bfs=0, bf ya = Phép xoay trá trái (Rotate_Left) Rotate_Left) Xoay trái nhị phân tìm kiếm có nút gốc root, yêu cầu root phải có nút bên phải (gọi nút p) Sau xoay trái nút p trở thành nút gốc, nút gốc cũ trở thành nút bên trái nút gốc Phép xoay trái trả trỏ nút gốc NODEPTR Rotate_Left(NODEPTR root) Rotate_Left { NODEPTR p; if(root == NULL) printf("Khong the xoay trai vi cay bi rong."); else if(root->right == NULL) printf("Khong the xoay trai vi khong co nut ben phai."); else { p = root->right; root->right = p->left; p->left = root; } return p; } Phép xoay phả phải (Rotate_Right) Rotate_Right) xoay phải nhị phân tìm kiếm có nút gốc root, yêu cầu root phải có nút bên trái (gọi nút p) Sau xoay phải nút p trở thành nút gốc, nút gốc cũ trở thành nút bên phải nút gốc Phép xoay phải trả trỏ nút gốc NODEPTR Rotate_Right(NODEPTR root) Rotate_Right { NODEPTR p; if(root == NULL) printf("Khong the xoay phai vi cay bi rong."); else if(root->left == NULL) printf("Khong the xoay phai vi khong co nut ben trai."); else { p = root->left; root->left = p->right; p->right = root; } return p; } Thê Thêm nút (Insert) Thêm nút có khóa x, nội dung a vào AVL: - Thêm nút theo giải thuật thêm nút vào nhị phân tìm kiếm - Cân lại cách xoay đơn hay xoay kép Thuật toán : link Tạo AVL 10 11 12 13 14 15 16 17 18 19 20 21 void Create_AVLTree(NODEPTR &root) Create_AVLTree { int khoa, noidung; char so[10]; NODEPTR p; { printf("Nhap khoa :"); gets(so) ; khoa = atoi(so); if (khoa !=0) { printf("Nhap noi dung :"); gets(so) ; noidung = atoi(so); if (root==NULL) { p = New_Node(); p->key = khoa; p->info = noidung; p->bf = ; p->left = NULL; p->right = NULL; root =p; } else Insert(root,khoa,noidung); } } while (khoa!=0); // khóa =0 dừng nhập } Xóa nút Nếu root == NULL Thôngbáo ("Không thể xóa đợc nút x cây") Nếu root != NULL Nếu x< root->info thì: + Gọi đệ qui để xóa nút x nhánh bên trái root : Remove(root->left, x) + Gọi balance_left để cân lại nút gốc root nhánh bên trái bị giảm độ cao Nếu x > root->info thì: + Gọi đệ qui để xóa nút x nhánh bên phải root : Remove(root->right, x) + Gọi balance_right để cân lại nút gốc root nhánh bên phải bị giảm độ cao Nếu x==root->info thì: Xóa nút root nh phép toán xóa nhị phân BST Tìm kiếm (Search) Tìm nút có khóa x nhị phân AVL có gốc root Nếu tìm thấy x trả địa nút có trị x trongcây, trả trị NULL Do AVL nhị phân BST nên ta tìm kiếm nhanh phơng pháp tìm kiếm nhị phân, tính chất lúc cân nên thời gian tìm kiếm nhanh nhiều ... đến phần tử đầu danh sách liên kết Phần tử cuối danh sách liên kết với vùng liên kết có giá trị NULL Mỗi nút danh sách có trờng info chứa nội dung nút trờng next trỏ đến nút danh sách 22 Ưu nhợc... thuộc vào số phần tử danh sách liên kết Nhợ Nhợc ợc điểm : - Vì nút 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 nhớ - Tìm kiếm danh sách liên kết không nhanh... First; NODEPTR Last ; }; 26 Cỏc phộp toỏn trờn danh sỏch To danh sỏch Cp nht danh sỏch Duyt danh sỏch Sp xp danh sỏch 27 To danh sỏch Khởi tạo danh sách (Initialize): void Initialize(NODEPTR &First)