Mô phỏng cây cân bằng AVL Mô phỏng cây cân bằng AVL Mô phỏng cây cân bằng AVL Mô phỏng cây cân bằng AVL Mô phỏng cây cân bằng AVL Mô phỏng cây cân bằng AVL Mô phỏng cây cân bằng AVL Mô phỏng cây cân bằng AVL
MỤC LỤC LỜI CẢM ƠN PHẦN 1: GIỚI THIỆU CÂY CÂN BẰNG CHIỀU CAO AVL .6 Định nghĩa Chỉ số cân việc cân lại AVL Các trường hợp cân PHẦN 2: CÁC THUẬT TOÁN Cân lại trường hợp a .9 Cân lại trường hợp b .10 Cài đặt thao tác cân lại 12 Chèn phần tử vào AVL 13 Xóa phần tử khỏi AVL 15 PHẦN 3: MÔ PHỎNG CÂY AVL .19 Giao diện 19 PHÂN CÔNG NHIỆM VỤ 21 MỤC LỤC HÌNH ẢNH Hình 1: Ví dụ AVL .6 Hình 2: Cây T1 lệch trái Hình 3: Cây T1 lệch phải Hình 4: Cây T1 không lệch .8 Hình 5: Minh họa phép quay Left-Left Hình 6: Minh họa phép quay Left-Right 10 Hình 7: Giao diện 19 Hình 8: Thiết lập đầu vào .19 Hình 9: Tốc độ 20 Hình 10: Thêm xóa node .20 Hình 11: Thiết lập thuật toán 20 LỜI CẢM ƠN “Đặc biệt, chúng em xin gửi lời cảm ơn sâu sắc đến giảng viên môn – Thầy quan tâm hướng dẫn, truyền đạt kiến thức quý báu cho chúng em suốt thời gian học tập vừa qua Trong thời gian tham gia lớp học thầy, thầy cung cấp cho chúng em nói riêng lớp nói chung kiến thức bổ ích, hướng dẫn cách tự học, tự tìm hiểu kiến thức Đây chắn kiến thức quý báu, hành trang để chúng em vững bước sau Tuy nhiên, vốn kiến thức nhiều hạn chế khả tiếp thu thực tế nhiều bỡ ngỡ Mặc dù, chúng em cố gắng chắn khó tránh khỏi thiếu sót nhiều chỗ cịn chưa xác, kính mong thầy xem xét góp ý để đồ án chúng em hồn thiện Nhóm chúng em xin chân thành cảm ơn!” TP.HCM, tháng năm 2021 PHẦN 1: GIỚI THIỆU CÂY CÂN BẰNG CHIỀU CAO AVL Định nghĩa Cây cân chiều cao AVL mà nút độ cao trái phải chênh lệch khơng q Hình 1: Ví dụ AVL Cây cân hoàn toàn AVL, AVL chưa cân hoàn toàn Tính cân đối AVL nhẹ so với tính cân đối nhị phân cân hồn tồn Cây nhị phân tìm kiếm mà ln có dạng cân đối AVL, chi phí tìm kiếm trường hợp xấu O(log2n) Từ giới thiệu, AVL nhanh chóng tìm thấy ứng dụng nhiều tốn khác Vì vậy, mau chóng trở nên thịnh hành thu hút nhiều nghiên cứu Từ AVL, người ta phát triển thêm nhiều loại CTDL hữu dụng khác đỏ-đen (Red-Black Tree), B-Tree, … Chỉ số cân việc cân lại AVL Định nghĩa: số cân (CSCB) nút p hiệu chiều cao phải trái Kí hiệu: hl(p) hay hl chiều cao trái p hr(p) hay hr chiều cao phải p EH = 0, RH = 1, LH = -1 CSCB(p) = EH => hR(p) = hL(p) :2 cao CSCB(p) = RH => hR(p) > hL(p) : lệch phải CSCB(p) = LH => hR(p) < hL(p) : lệch trái Với nút AVL, ngồi thuộc tính thơng thường nhị phân, ta cần lưu ý thêm thông tin số cân cấu trúc nút Việc thêm hay hủy nút AVL làm tăng hay giảm chiều cao, ta cần phải cân lại Để giảm tối đa chi phí cân lại cây, ta cân lại AVL phạm vi cục Các trường hợp cân Ngoài thao tác thêm hủy cân bằng, ta cịn có thêm thao tác cân lại AVL trường hợp thêm hủy nút Khi độ lệch chiều cao phải trái Do trường hợp lệch trái phải tương ứng đối xứng nhau, nên ta xét trường hợp AVL lệch trái Trường hợp a: T1 lệch trái Hình 2: Cây T1 lệch trái Trường hợp b: T1 lệch phải Hình 3: Cây T1 lệch phải Trường hợp c: T1 không lệch Hình 4: Cây T1 khơng lệch PHẦN 2: CÁC THUẬT TOÁN Cân lại trường hợp a Ta cân lại phép quay đơn Left – Left, ta được: Hình 5: Minh họa phép quay Left-Left //Phép quay đơn Left – Left void RotateLL(AVLTree &T) { AVLTree T1 = T->Lchild; T->Lchild = T1->Rchild; T1->Rchild = T; switch (T1->Balfactor) { case LH: T->Balfactor = EH; T1->Balfactor = EH; break; case EH: T->Balfactor = LH; T1->Balfactor = RH; break; } T = T1; return ; } // Phép quay đơn Right – Right void RotateRR (AVLTree &T) { AVLTree T1 = T->Rchild; T->Rchild = T1->Lchild; T1->Lchild = T; switch (T1->Balfactor) { case RH: T->Balfactor = EH; T1->Balfactor = EH; break; case EH: T->Balfactor = RH; T1->Balfactor = LH; break; } T = T1; return ; } Cân lại trường hợp b Cân lại phép quay kép left-right, ta có kết sau: Hình 6: Minh họa phép quay Left-Right //Phép quay kép Left – Right void RotateLR(AVLTree &T) 10 { AVLTree T1 = T->Lchild, T2 = T1->Rchild; T->Lchild = T2->Rchild; T2->Rchild = T; T1->Rchild = T2->Lchild; T2->Lchild = T1; switch (T2->Balfactor) { case LH: T->Balfactor = RH; T1->Balfactor = EH; break; case EH: T->Balfactor = EH; T1->Balfactor = EH; break; case RH: T->Balfactor = EH; T1->Balfactor = LH; break; } T2->Balfactor = EH; T = T2; return ; } //Phép quay kép Right-Left void RotateRL(AVLTree &T) { AVLTree T1 = T->RLchild, T2 = T1->Lchild; 26 T->Rchild = T2->Lchild; T2->Lchild = T; T1->Lchild = T2->Rchild; T2->Rchild = T1; switch (T2->Balfactor) { case LH: T->Balfactor = EH; T1->Balfactor = RH; break; case EH: T->Balfactor = EH; T1->Balfactor = EH; break; case RH: T->Balfactor = LH; 11 T1->Balfactor = EH; break; } T2->Balfactor = EH; T = T2; return ; } Cài đặt thao tác cân lại //Cân lại bị lệch trái int LeftBalance(AVLTree &T) { AVLTree T1 = T->Lchild; switch (T1->Balfactor) { case LH : RotateLL(T); return 2; //cây T không bị lệch case EH : RotateLL(T); return 1;//cây T bị lệch phải case RH : RotateLR(T); return 2; } return 0; } //Cân lại bị lệch phải int RightBalance(AVLTree &T) { AVLTree T1 = T->Rchild; switch (T1->Balfactor) { case LH : RotateRL(T); return 2; //cây T không lệch case EH : RotateRR(T); 12 return 1; //cây T lệch trái case RH : RotateRR(T); return 2; } return 0; } Chèn phần tử vào AVL Việc chèn phần tử vào AVL xảy tương tự nhị phân tìm kiếm Tuy nhiên sau chèn xong, chiều cao thay đổi vị trí thêm vào, ta cần phải ngược lên gốc để kiểm tra xem có nút bị cân hay khơng Nếu có, ta cần phải cân lại nút AVLTree CreateAVL() { AVLTree Tam= new AVLTreeNode; if (Tam == NULL) cout Data==x) return 0; //Đã có nút if (T-> Data > x) { //chèn nút vào trái Kqua = InsertNodeAVL(T->Lchild,x); if (Kqua < 2) return Kqua; switch (T->Balfactor) 13 { case LH: LeftBalance(T); return 1;//T lệch trái case EH: T->Balfactor=LH; return 2;//T không lệch caseRH:T->Balfactor=EH; return 1;//T lệch phải } } else // T-> Data < x { Kqua= InsertNodeAVL(T->Rchild,x); if (Kqua < 2) return Kqua; switch (T->Balfactor) { case LH: T->Balfactor = EH; return 1; case EH:T->Balfactor=RH; return 2; case RH : RightBalance(T); return 1; } } else //T==NULL { if ((T = CreateAVL()) == NULL) return –1; T->Data = x; T->Balfactor = EH; T->Lchild = T->Rchild = NULL; 14 return 2; } } Xóa phần tử khỏi AVL Việc xóa phần tử khỏi AVL diễn tương tự nhị phân tìm kiếm, khác sau hủy, AVL bị cân bằng, ta phải cân lại Việc cân lại xảy phản ứng dây chuyền int DeleteAVL(AVLTree &T, ElementType x) { int Kqua; if (T== NULL) return 0; // khơng có x if (T-> Data > x) { Kqua = DeleteAVL(T->Lchild,x);// tìm xóa x trái T if (Kqua < 2) return Kqua; switch (T->Balfactor) { case LH : T->Balfactor = EH; return 2;//trước xóa T lệch trái case EH : T->Balfactor = RH; return 1;//trước xóa T khơng lệch case RH : return RightBalance(T); // trước xóa T lệch phải } } else if (T-> Data < x) { Kqua = DeleteAVL(T->Rchild,x);// tìm xóa x trái T if (Kqua < 2) return Kqua; 15 switch (T->Balfactor) { case LH : return LeftBalance(T);//trước xóa T lệch trái case EH : T->Balfactor = LH; return 1; //trước xóa T không lệch case RH : T->Balfactor = EH; return 2;//trước xóa T lệch phải } } else //T->Data== x { AVLTree p = T; if (T->Lchild == NULL) { T = T->Rchild; Kqua = 2; } else if (T->Rchild == NULL) { T = T->Lchild; Kqua = 2; } else // T có hai { Kqua = TimPhanTuThayThe(p,T->Rchild); //Tìm phần tử thay P để xóa nhánh phải cuả T if (Kqua < 2) return Kqua; switch (T->Balfactor) { case LH : return LeftBalnce(T); case EH : T->Balfactor = LH; return 2; 16 case RH : T->Balfactor = EH; return 2; } } delete p; return Kqua; } } // Tìm phần tử thay int TimPhanTuThayThe(AVLTree &p, AVLTree &q) { int Kqua; if (q->Lchild) { Kqua = TimPhanTuThayThe(p, q->Lchild); if (Kqua < 2) return Kqua; switch (q->Balfactor) { case LH : q->Balfactor = EH; return 2; case EH : q->Balfactor = RH; return 1; case RH : return RightBalance(q); } } else { p->Data = q->Data; p = q; q = q->Rchild; 17 return 2; } } 18 PHẦN 3: MÔ PHỎNG CÂY AVL Giao diện Hình 7: Giao diện Hướng dẫn sử dụng: Bước 1: Chọn thiết lập đầu vào, có cách: tự động (nhập số phần tử, hệ thống xuất ngẫu nhiên) tay (nhập vào phần tử) Bước 2: Chọn tốc độ chạy chương trình từ thấp đến cao, có mức độ từ đến Hình 8: Thiết lập đầu vào Hình 9: Tốc độ Bước 3: Nhập giá trị phần tử để thêm xóa node Bước 4: Chọn trình tự duyệt Hình 10: Thêm xóa node Hình 11: Thiết lập thuật tốn 20 ... THIỆU CÂY CÂN BẰNG CHIỀU CAO AVL Định nghĩa Cây cân chiều cao AVL mà nút độ cao trái phải chênh lệch khơng q Hình 1: Ví dụ AVL Cây cân hoàn toàn AVL, AVL chưa cân hồn tồn Tính cân đối AVL nhẹ... cân lại Để giảm tối đa chi phí cân lại cây, ta cân lại AVL phạm vi cục Các trường hợp cân Ngoài thao tác thêm hủy cân bằng, ta cịn có thêm thao tác cân lại AVL trường hợp thêm hủy nút Khi độ lệch... xem có nút bị cân hay khơng Nếu có, ta cần phải cân lại nút AVLTree CreateAVL() { AVLTree Tam= new AVLTreeNode; if (Tam == NULL) cout