Bài giảng Cấu trúc dữ liệu và giải thuật - Chương 5: Cây nhị phân tìm kiếm cung cấp cho người học các kiến thức: Khái niệm, đặc điểm, định nghĩa cấu trúc dữ liệu, các lưu ý khi cài đặt, các thao tác xử lý. Mời các bạn cùng tham khảo nội dung chi tiết.
Chương Cây nhị phân tìm kiếm Trần Minh Thái Email: minhthai@huflit.edu.vn Website: www.minhthai.edu.vn Nội dung Khái niệm Đặc điểm Định nghĩa cấu trúc liệu Các lưu ý cài đặt Các thao tác xử lý Khái niệm Bậc nút: số nút Bậc cây: bậc lớn nút Cây có bậc n gọi n-phân 2 1 Nút gốc: nút khơng có nút cha Nút lá: nút có bậc Nút nhánh: nút có bậc khác khơng phải gốc 0 Khái niệm Chiều dài đường đến nút x: số nhánh cần qua kể từ gốc đến x Mức Chiều cao h cây: Mức lớn nút Mức Mức Mức xx Đặc điểm nhị phân Số nút mức I ≤ 2I-1 Số nút mức ≤ 2h-1, với h chiều cao Chiều cao h ≥ log2N, với N số nút Biểu diễn nhị phân Cây nhị phân cấu trúc bao gồm phần tử (node) kết nối với theo quan hệ “cha-con” với cha có tối đa Mỗi nút gồm thông tin: Dữ liệu lưu trữ: data Liên kết tới trái nút: pLeft Liên kết tới phải nút: pRight Định nghĩa kiểu liệu dùng C data Giá trị TNODE Nút Trỏ trái pLeft Trỏ phải typedef struct TNode { DataType data; TNode *pLeft, *pRight; } *Tree; pRight Ví dụ khai báo node chứa giá trị nguyên typedef struct TNode { int data; TNode *pLeft, *pRight; } *Tree; Cây nhị phân tìm kiếm Là nhị phân Giá trị node lớn giá trị node nhánh trái nhỏ giá trị node nhánh 77 phải Nút có giá trị nhỏ nằm nút trái 33 36 36 11 66 44 15 15 Nút có giá trị lớn nằm nút phải 40 40 23 23 Các lưu ý cài đặt Bước 1: Khai báo kiểu liệu biểu diễn Bước 2: Xây dựng hàm đưa liệu (nhập) vào Bước 3: Xây dựng thao tác duyệt, tìm kiếm, huỷ, … 10 Trường hợp 1.3: T1 lệch phải Quay kép Left - Right 56 void RotateLR(AVLTree &T) { AVLNode * T1 = T-> pLeft ; AVLNode * T2 = T1-> pRight ; T-> pLeft = T2-> pRight ; T2-> pRight = T; T1-> pRight = T2-> pLeft ; T2-> pLeft = T1; switch (T2-> bF) { case LH: T-> bF = RH; T1-> bF = EH; break ; case EH: T-> bF = EH; T1-> bF = EH; break ; case RH: T-> bF = EH; T1-> bF = LH; break ; } T2-> bF = EH; T = T2; } Trường hợp 2.1 2.2 void RotateRR(AVLTree &T) { AVLNode * T1 = T-> pRight ; T->pRight = T1-> pLeft ; T1-> pLeft = T; switch (T1-> bF) { case RH: T-> bF = EH; T1-> bF = EH; break ; case EH: T-> bF = RH; T1-> bF = LH; break ; } T = T1; } 58 void RotateRL ( AVLTree &T) { AVLNode * T1 = T-> pRight ; AVLNode * T2 = T1-> pLeft ; Trường hợp 2.3 T->pRight = T2-> pLeft ; T2->pLeft = T; T1->pLeft = T2-> pRight ; T2-> pRight = T1; switch (T2-> bF) { case RH: T-> bF = LH; T1-> bF = EH; break ; case EH: T-> bF = EH; T1-> bF = EH; break ; case LH: T-> bF = EH; T1-> bF = RH; break ; } T2-> bF = EH; T = T2; } 59 Thêm node vào AVL Tương tự NPTK Sau thêm xong, chiều cao thay đổi Nếu có cân cân lại nút Hàm insertNode trả giá trị -1: không đủ nhớ 0: trùng giá trị 1: thêm thành công 2: thêm thành công chiều cao tăng 60 int InsertNode(AVLTree &T, int X) { int kq; if (T != NULL ) { if(T->key == X) return 0; // tồn x else if (T->key > X) // thêm bên trái { kq = InsertNode(T->pLeft, X); if (kq < 2) return res; switch (T->bF) { case RH: T->bF= EH; return 1; case EH: T->bF = LH; return 2; case LH: BalanceLeft(T); return 1; } } 61 else //Trường hợp T->key pRight, X); if (res < 2) return res; switch (T->bF) { case LH: T->bF = EH; return 1; case EH: T->bF = RH; return 2; case RH: BalanceRight(T); return 1; } } } 62 //Tạo node T = new TNode; if (T == NULL) return -1; //thiếu nhớ T->key = X; T->bF = EH; T->pLeft = T->pRight = NULL; return 2; //Thêm thành công chiều cao tăng } 63 int BalanceLeft(AVLTree &T) { switch (T-> pLeft -> bF) { case LH: RotateLL (T); return 2; case EH: RotateLL (T); return 1; case RH: RotateLR (T); return 2; } return 0; } int BalanceRight(AVLTree &T) { switch (T-> pRight -> bF) { case LH: RotateRL (T); return 2; case EH: RotateRR (T); return 1; case RH: RotateRR (T); return 2; Hủy node Tương tự NPTK Sau hủy, cân cân lại Hàm deleteNode trả giá trị 1: hủy thành công 0: khơng có X 2: hủy thành cơng chiều cao giảm 65 int DeleteNode(AVLTree &T, int X) { int kq ; if (T==NULL) return 0; if (T->key > X) { kq = DeleteNode (T-> pLeft , X); if ( kq < 2) return kq ; switch ( T-> bF ) { case LH: T-> bF = EH; return 2; case EH: T-> bF = RH; return 1; case BalanceRight (T); } } 66 else if (T->key < X) { kq = DeleteNode (T-> pRight , X); if ( kq < 2) return kq ; switch (T-> bF ) { case RH: T-> bF = EH; return 2; case EH: T-> bF = LH; return 1; case LH: return BalanceLeft (T); } } 67 else // if (T->key == X) { AVLNode * p = T; if (T-> pLeft == NULL) { T = T->pRight ; kq = 2; } else if (T-> pRight == NULL) { T = T-> pLeft ; kq = 2; } 68 else // if (T-> pLeft != NULL && T-> pRight != NULL) { kq = SearchStandFor ( p, T -> pRight ); if( kq < 2) return kq; switch( T-> bF ) { case RH: T-> bF = EH; return 2; case EH: T-> bF = LH; return 1; case LH: return BalanceLeft (T); } } delete p; return kq ; } } 69 int SearchStandFor(AVLTree &p, AVLTree &q){ int kq; if (q->pLeft != NULLL) { kq = SearchStandFor(p, q->pLeft); if (kq < 2) return kq; switch (q->bF){ case LH: q->bF= EH; return 2; case EH: q->bF= RH; return 1; case RH: return BalanceRight(T); } } else { p->key = q->key; p = q; q = q->pRight; return 2; } } 70 ... 10 Cấu trúc chương trình Khai báo cấu trúc Khởi tạo rỗng Xây dựng Các thao tác Hủy 11 Các thao tác Tạo Duyệt Cho biết thơng tin Tìm kiếm Xố node 12 Tạo 36 7643136 15 40 3136 764 40 15 15 40... R7 L3 R3 R7 R3 R7 L6 R7 R7 R7 R7 L36 R36 36 R 15 15 R36 36 10 23 15 R36 36 15 R36 36 40 36 36 7 11 33 12 36 36 11 66 44 13 14 KQ 15 15 23 23 23 15 40 36 22 40 40 Hàm duyệt LRN Tại node t xét,... 36 11 66 44 15 15 40 40 Node Node có Node có 23 23 33 Xóa node 77 33 36 36 11 66 44 15 15 Xóa Xóa 23 40 40 23 23 34 Xóa node Node cha 77 33 36 36 11 66 44 15 15 Xóa 40 40 23 23 35 Xóa node 77