1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Bài giảng cấu trúc dữ liệu và giải thuật cây AVL nguyễn mạnh hiển

27 2 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Cây AVL Nguyễn Mạnh Hiển hiennm@tlu.edu.vn Mở đầu • Khi xây dựng nhị phân tìm kiếm, ta muốn có kiểu hơn? • Ví dụ: dựng từ dãy {3, 5, 8, 20, 18, 13, 22} 13 20 13 18 20 22 18 22 Mở đầu (tiếp) • Ta muốn nhị phân tìm kiếm cân đối: − có độ sâu = log n, − cho phép chèn xóa với thời gian chạy O(log n) trường hợp • Cây AVL kiểu vậy! Cây AVL (Adelson-Velskii & Landis) • Cây AVL nhị phân tìm kiếm thỏa mãn điều kiện cân bằng: − Với nút X, chiều cao hai trái phải X sai khác không − Quy ước rỗng có chiều cao -1 18 13 20 22 Cây AVL ? Chèn xóa AVL • Thực chèn/xóa nhị phân tìm kiếm thơng thường • Sau chèn/xóa, điều kiện cân bị vi phạm: − Sửa phép xoay − Sau phép xoay, trở lại cân Ví dụ phép chèn Chèn làm điều kiện cân bị vi phạm nút Sửa phép xoay quanh nút Vi phạm điều kiện cân • Nếu điều kiện cân bị vi phạm, nút cần xoay? − Chỉ nút đường từ điểm chèn ngược gốc bị ảnh hưởng • Chỉ cần tái cân dùng phép xoay nút sâu có điều kiện cân bị vi phạm − Toàn tái cân Các trường hợp vi phạm • Giả sử nút k nơi xảy vi phạm Có trường hợp: trái-trái: chèn vào trái trái k trái-phải: chèn vào phải trái k phải-trái: chèn vào trái phải k phải-phải: chèn vào phải phải k • Hai trường hợp (chèn ngoài) tương tự nhau: − Phép xoay đơn để tái cân • Hai trường hợp (chèn trong) tương tự nhau: − Phép xoay kép để tái cân Kiểu liệu nút struct AvlNode { T elem; AvlNode * left; AvlNode * right; int height; // Chiều cao nút AvlNode(T e, AvlNode * l, AvlNode * r, int h) { elem = e; left = l; right = r; height = h; } }; // Hàm trả chiều cao nút int height(AvlNode * t) { return t == NULL ? -1 : t->height; } Phép xoay đơn (trường hợp 1) void rotateWithLeftChild(AvlNode * & k2) { AvlNode * k1 = k2->left; k2->left = k1->right; k1->right = k2; k2->height = max(height(k2->left), height(k2->right)) + 1; // Hàm max trả giá trị lớn k1->height = max(height(k1->left), k2->height) + 1; k2 = k1; } Ví dụ phép xoay đơn (1) • Chèn 3, 2, sau 4, 5, 6, vào AVL rỗng Ví dụ phép xoay đơn (2) • Chèn 4, 5: Ví dụ phép xoay đơn (3) • Chèn 6: Ví dụ phép xoay đơn (4) • Chèn 7: Phép xoay đơn không giải trường hợp khác • Đối với trường hợp 2: − Sau phép xoay đơn, nút k1 khơng cân • Ta cần dùng phép xoay kép cho hai trường hợp Phép xoay kép (trường hợp 2) • Phép xoay kép trái-phải để sửa trường hợp 2: − Đầu tiên xoay nút k1 nút k2 − Sau xoay nút k2 nút k3 • Với trường hợp 3, cách làm tương tự (xoay theo chiều ngược lại) Ví dụ phép xoay kép (1) • Chèn 16, 15 14 vào AVL sau đây: Ví dụ phép xoay kép (2) • Chèn 16, 15: Ví dụ phép xoay kép (3) • Chèn 14: Phép xoay kép (trường hợp 2) void doubleWithLeftChild(AvlNode * & k3) { rotateWithRightChild(k3->left); rotateWithLeftChild(k3); } Chèn vào AVL // Hàm private chèn x vào có gốc trỏ t void insert(T x, AvlNode * & t ) { if (t == NULL) t = new AvlNode(x, NULL, NULL, 0); else if (x < t->elem) insert(x, t->left); else if (x > t->elem) insert(x, t->right); balance(t); // Cân sau chèn } Xóa khỏi AVL // Hàm private xóa phần tử x khỏi có gốc trỏ t void remove(T x, AvlNode * & t) { if (t == NULL) return; // Thoát rỗng if (x < t->elem) remove(x, t->left); else if (x > t->elem) remove(x, t->right); else if (t->left != NULL && t->right != NULL) { // Nút t->elem = findMin(t->right)->elem; remove(t->elem, t->right); } else { // Nút AvlNode * old = t; t = (t->left != NULL) ? t->left : t->right; delete old; } balance(t); // Cân sau xóa } Cân AVL sau chèn/xóa void balance(AvlNode * & t) { if (t == NULL) return; if (height(t->left) - height(t->right) > 1) if (height(t->left->left) >= height(t->left->right)) rotateWithLeftChild(t); else doubleWithLeftChild(t); else if (height(t->right) - height(t->left) > 1) if (height(t->right->right) >= height(t->right->left)) rotateWithRightChild(t); else doubleWithRightChild(t); t->height = max(height(t->left), height(t->right)) + 1; } Bài tập Vẽ hình mơ tả q trình biến đổi AVL rỗng chèn vào giá trị sau vào cây: { 2, 1, 4, 5, 9, 3, 6, } ... nhau: − Phép xoay kép để tái cân Kiểu liệu nút struct AvlNode { T elem; AvlNode * left; AvlNode * right; int height; // Chiều cao nút AvlNode(T e, AvlNode * l, AvlNode * r, int h) { elem = e; left... log n, − cho phép chèn xóa với thời gian chạy O(log n) trường hợp • Cây AVL kiểu vậy! Cây AVL (Adelson-Velskii & Landis) • Cây AVL nhị phân tìm kiếm thỏa mãn điều kiện cân bằng: − Với nút X, chiều... rotateWithRightChild(k3->left); rotateWithLeftChild(k3); } Chèn vào AVL // Hàm private chèn x vào có gốc trỏ t void insert(T x, AvlNode * & t ) { if (t == NULL) t = new AvlNode(x, NULL, NULL, 0); else if (x < t->elem)

Ngày đăng: 26/12/2021, 17:20

Xem thêm: