Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 17 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
17
Dung lượng
188 KB
Nội dung
Trương Hải Bằng – CấutrúcliệuCHƯƠNG - CÂY ĐỎ ĐEN Trong chương tìm hiểu phần sau đây: 1.Giới thiệu 2.Định nghĩa đỏ đen 3.Phép quay 4.Thêm node 5.Loại bỏ node 6.Tính hiệu đỏ đen 7.Cài đặt Thảo luận cân Tóm tắt GIỚI THIỆU Cây tìm kiếm nhị phân thơng thường có thuận lợi lớn mặt lưu trữ truy xuất liệu phép tốn tìm kiếm thêm vào hay loại bỏ phần tử Do đó, tìm kiếm nhị phân xem cấutrúc lưu trữ liệu tốt Tuy nhiên số trường hợp tìm kiếm nhị phân có số hạn chế Nó hoạt động tốt liệu chèn vào theo thứ tự ngẫu nhiên Tuy nhiên, liệu chèn vào theo thứ tự đuợc xếp không hiệu Khi trị số cần chèn đuợc xếp nhị phân trở nên không cân Khi không cân bằng, khả tìm kiếm nhanh (hoặc chèn xóa) phần tử cho Chúng ta khảo sát cách giải vấn đề không cân bằng: đỏ đen, tìm kiếm nhị phân có thêm vài đặc điểm Có nhiều cách tiếp cận khác để bảo đảm cho cân bằng: chẳng hạn 2-3-4 Tuy vậy, phần lớn trường hợp, đỏ đen cân hiệu nhất, liệu lưu trữ nhớ tập tin Trước khảo sát đỏ đen, xem lại không cân tạo Chương 3: Cây đỏ đen Trang Trương Hải Bằng – Cấutrúcliệu Hình 3.1 Các node chèn theo thứ tự tăng dần Những node tự xếp thành đường không phân nhánh Bởi node lớn node chèn vào trước đố, node phải Khi ấy, bị cân hoàn toàn Nếu ta chèn mục (item) theo thứ tự giảm dần, node trái node cha chúng - bị cân phía bên Độ phức tạp: Khi nhánh, trở thành danh sách liên kết, liệu chiều thay hai chiều Trong trường hợp này, thời gian truy xuất giảm O(N), thay O(logN) cân Để bảo đảm thời gian truy xuất nhanh O(logN) cây, cần phải bảo đảm ln ln cân (ít gần cân bằng) Điều có nghĩa node phải có xấp xỉ số node bên phải số node bên trái Một cách tiếp cận giải vấn đề cân lại cây: đỏ đen-là tìm kiếm nhị phân bổ sung số đắc điểm Trong đỏ đen, việc cân thực thi chèn, xóa Khi thêm phần tử thủ tục chèn kiểm tra xem tính chất cân có bị vi phạm hay khơng Nếu có, xây dựng lại cấutrúc Bằng cách này, luôn giữ cân ĐỊNH NGHĨA CÂY ĐỎ ĐEN Cây đỏ đen nhị phân tìm kiếm( BST) tuân thủ quy tắc sau: (hình 3.2) Mọi node phải đỏ đen Node gốc node phải luôn đen Nếu node đỏ, node phải đen Mọi đường dẫn từ gốc đến phải có số lượng node đen Khi chèn (hay xóa) node mới, cần phải tuân thủ quy tắc -gọi quy tắc đỏ đen Nếu tuân thủ, cân Hình 3.2 Một ví dụ đỏ đen Số lượng node đen đường dẫn từ gốc đến gọi chiều cao đen (black height) Ta phát biểu quy tắc theo cách khác đường dẫn từ gốc đến phải có chiều cao đen Bổ đề: Một đỏ đen n-node Chương 3: Cây đỏ đen Trang Trương Hải Bằng – Cấutrúcliệu Có: height right */ x->right = y->left; if (y->left != NIL) y->left->parent = x; /* Thiết lập liên kết y->parent */ if (y != NIL) y->parent = x->parent; if (x->parent) { if (x == x->parent->left) x->parent->left = y; else x->parent->right = y; } else { root = y; } /* link x and y */ y->left = x; if (x != NIL) x->parent = y; } static void rotateRight(NodeType *x) { /**************************** * Xoay node x bên phải * ****************************/ NodeType *y = x->left; /* Thiết lập liên kết x->left */ x->left = y->right; if (y->right != NIL) y->right->parent = x; /* Thiết lập liên kết y->parent */ if (y != NIL) y->parent = x->parent; if (x->parent) { if (x == x->parent->right) x->parent->right = y; else x->parent->left = y; } else { root = y; } /* liên kết x y */ y->right = x; if (x != NIL) x->parent = y; } Chương 3: Cây đỏ đen Trang 10 Trương Hải Bằng – Cấutrúcliệu /************************************* * Chương trình thêm node x vào đỏ đen* *************************************/ static void insertFixup(NodeType *x) { /* Kiểm tra thuộc tính đỏ đen */ while (x != root && x->parent->color == RED) { /* we have a violation */ if (x->parent == x->parent->parent->left) { NodeType *y = x->parent->parent->right; if (y->color == RED) { /* bác RED */ x->parent->color = BLACK; y->color = BLACK; x->parent->parent->color = RED; x = x->parent->parent; } else { /* bác BLACK */ if (x == x->parent->right) { /* tạo x trái*/ x = x->parent; rotateLeft(x); } /* đổi màu xoay */ x->parent->color = BLACK; x->parent->parent->color = RED; rotateRight(x->parent->parent); } } else { /* Tương tự */ NodeType *y = x->parent->parent->left; if (y->color == RED) { /* bác is RED */ x->parent->color = BLACK; y->color = BLACK; x->parent->parent->color = RED; x = x->parent->parent; } else { /* bác BLACK */ if (x == x->parent->left) { x = x->parent; rotateRight(x); } } x->parent->color = BLACK; x->parent->parent->color = RED; rotateLeft(x->parent->parent); } } root->color = BLACK; } /*********************************************** * Cấp phát thêm vào * ***********************************************/ StatusEnum insert(KeyType key, RecType *rec) { NodeType *current, *parent, *x; /Tìm cha mới*/ current = root; parent = 0; Chương 3: Cây đỏ đen Trang 11 Trương Hải Bằng – Cấutrúcliệu while (current != NIL) { if (compEQ(key, current->key)) return STATUS_DUPLICATE_KEY; parent = current; current = compLT(key, current->key) ? current->left : current->right; } /* Thiết lập node */ if ((x = malloc (sizeof(*x))) == 0) return STATUS_MEM_EXHAUSTED; x->parent = parent; x->left = NIL; x->right = NIL; x->color = RED; x->key = key; x->rec = *rec; /* Thêm node */ if(parent) { if(compLT(key, parent->key)) parent->left = x; else parent->right = x; } else { root = x; } insertFixup(x); return STATUS_OK; } /************************************* * Chương trình loại bỏ node x * *************************************/ void deleteFixup(NodeType *x) { while (x != root && x->color == BLACK) { if (x == x->parent->left) { NodeType *w = x->parent->right; if (w->color == RED) { w->color = BLACK; x->parent->color = RED; rotateLeft (x->parent); w = x->parent->right; } if (w->left->color == BLACK && w->right->color == BLACK) { w->color = RED; x = x->parent; } else { if (w->right->color == BLACK) { w->left->color = BLACK; w->color = RED; rotateRight (w); w = x->parent->right; } w->color = x->parent->color; x->parent->color = BLACK; w->right->color = BLACK; rotateLeft (x->parent); x = root; } } else { Chương 3: Cây đỏ đen Trang 12 Trương Hải Bằng – Cấutrúcliệu NodeType *w = x->parent->left; if (w->color == RED) { w->color = BLACK; x->parent->color = RED; rotateRight (x->parent); w = x->parent->left; } if (w->right->color == BLACK && w->left->color == BLACK) { w->color = RED; x = x->parent; } else { if (w->left->color == BLACK) { w->right->color = BLACK; w->color = RED; rotateLeft (w); w = x->parent->left; } w->color = x->parent->color; x->parent->color = BLACK; w->left->color = BLACK; rotateRight (x->parent); x = root; } } } x->color = BLACK; } StatusEnum erase(iterator z) { NodeType *x, *y; if (z->left == NIL || z->right == NIL) { /* y có node NIL */ y = z; } else { /* Tìm thay với node NIL */ y = z->right; while (y->left != NIL) y = y->left; } /* y có */ if (y->left != NIL) x = y->left; else x = y->right; /* Xoá y */ x->parent = y->parent; if (y->parent) if (y == y->parent->left) y->parent->left = x; else y->parent->right = x; else root = x; if (y != z) { z->key = y->key; z->rec = y->rec; } if (y->color == BLACK) deleteFixup (x); free (y); Chương 3: Cây đỏ đen Trang 13 Trương Hải Bằng – Cấutrúcliệu return STATUS_OK; } StatusEnum eraseKey(KeyType key) { NodeType *z; /* Tìm node */ z = root; while(z != NIL) { if(compEQ(key, z->key)) break; else z = compLT(key, z->key) ? z->left : z->right; } if (z == NIL) return STATUS_KEY_NOT_FOUND; return erase(z); } iterator next(iterator i) { if (i->right != NIL) { for (i = i->right; i->left != NIL; i = i->left); } else { iterator p = i->parent; while (p && i == p->right) { i = p; p = p->parent; } /* trả node "inorder" */ i = p; } return i; } iterator begin() { /* Trả trỏ đến giá trị */ iterator i; for (i = root; i->left != NIL; i = i->left); return i; } iterator end() { /* Trả trỏ đến giá trị cuối */ return NULL; } RecType value(iterator i) { return i->rec; } StatusEnum find(KeyType key, iterator *iter) { NodeType *current; current = root; while(current != NIL) { if(compEQ(key, current->key)) { *iter = current; return STATUS_OK; } else { current = compLT (key, current->key) ? current->left : current->right; } } return STATUS_KEY_NOT_FOUND; } int main(int argc, char **argv) { Chương 3: Cây đỏ đen Trang 14 Trương Hải Bằng – Cấutrúcliệu int maxnum, ct, n; RecType rec; KeyType key; StatusEnum status; /* Chạy dòng lệnh: * * rbt maxnum * * rbt 2000 * Xữ lý 2000 records * */ iterator iter; maxnum = atoi(argv[1]); printf("maxnum = %d\n", maxnum); for (ct = maxnum; ct; ct ) { key = rand() % 90 + 1; if ((status = find(key, &iter)) == STATUS_OK) { rec = value(iter); if (rec.stuf != key) printf("fail rec\n"); status = erase(iter); if (status) printf("fail: status = %d\n", status); } else { rec.stuf = key; status = insert(key, &rec); if (status) printf("fail: status = %d\n", status); } /* Hiễn thị node */ { iterator i; for (i = begin(); i != end(); i = next(i)) { RecType rec; rec = value(i); printf("%d\n", rec.stuf); } } return 0; } Chương 3: Cây đỏ đen Trang 15 Trương Hải Bằng – Cấutrúcliệu THẢO LUẬN VỀ CÂY CÂN BẰNG Cây AVL cân xuất sớm Nó đặt tên theo nhà phát minh Adelson Velskii Landis Trong AVL node lưu trữ mẫu liệu phụ: khác biệt chiều cao bên trái bên phải Sự khác biệt khơng thể lớn Có nghĩa chiều cao bên trái node mức khác với chiều cao bên phải Lần theo việc chèn, cần kiểm tra node gốc thấp mà node cần chèn vào Nếu chiều cao nhũng node khác 1, cần phải tiến hành phép quay đơn hay quay kép để cân chiều cao chúng Thuật tốn lúc di chuyển lên kiểm tra node trên, cân chiều cao cần Điều tiếp tục tiến hành thụt lùi đến node gốc Thời gian tìm kiếm AVL O(logN) bảo đảm cân Tuy nhiên phải qua hai lần để chèn hay xóa nút, lần xuống để tìm điểm chèn lần lên để tái cân cây, AVL đỏ đen không hiệu không thường sử dụng Một loại cân quan trọng khác nhiều nhánh (Multiway Tree), node có hai node Chúng ta xét phiên nhiều nhánh, 2-3-4 phần Một vấn đề cho nhiều nhánh node phải lớn so với nhị phân, chúng cần tham khảo node TĨM TẮT Cây tìm kiếm nhị phân cân giảm thời gian tìm kiếm Thao tác chèn liệu xếp trước tạo nên hoàn toàn cân bằng, nầy có thời gian tìm kiếm O(N) Trong đỏ đen, node gán cho đặc tính mới: màu đỏ hay đen Quy tắc đỏ-đen, cách xếp node khác màu Một phép lật màu đổi node đen với hai node đỏ thành node đỏ với hai node đen Trong phép quay, node định node đỉnh Một phép quay phải di chuyển node đỉnh vào vị trí node phải nó, node trái node đỉnh vào vị trí node đỉnh Một phép quay trái di chuyển node đỉnh vào vị trí node trái node phải node đỉnh vào vị trí node đỉnh Các phép lật màu, đơi phép quay, sử dụng xuống để tìm nơi chèn node Những phép lật màu phục hồi tính đỏ-đen sau chèn nút Sau chèn node mới, cần phải rà sốt lại xem có xung khắc đỏ-đỏ khơng Nếu có, phải tiến hành phép quay để làm cho quy tắc đỏ-đen Những điều chỉnh làm cho cân hay gần cân Chương 3: Cây đỏ đen Trang 16 Trương Hải Bằng – Cấutrúcliệu Việc bổ sung tính cân cho nhị phân tác động lên hiệu suất trung bình, tránh hiệu suất trường hợp xấu (worst-case performance) liệu xếp Chương 3: Cây đỏ đen Trang 17