Bài giảng giới thiệu khái niệm cấu trúc cây; cấu trúc dữ liệu cây nhị phân tìm kiếm như cách tổ chức, các thuật toán, ứng dụng; giới thiệu cấu trúc dữ liệu cây nhị phân tìm kiếm,.. Mời các bạn cùng tham khảo.
12/1/2016 Kỹ thuật lập trình Tuần 13 – Cây (Tree) Giáo viên: Hà Đại Dương duonghd@mta.edu.vn 12/1/2016 Nội dung • Giới thiệu khái niệm cấu trúc • Cấu trúc liệu nhị phân tìm kiếm: tổ chức, thuật tốn, ứng dụng • Giới thiệu cấu trúc liệu nhị phân tìm kiếm 12/1/2016 Cấu trúc 12/1/2016 12/1/2016 Định nghĩa • Cây tập hợp T phần tử (gọi nút cây) đó: – Có nút đặc biệt gọi gốc, – Các nút lại chia thành tập rời T1, T2 , , Tn theo quan hệ phân cấp Ti – Mỗi nút cấp i quản lý số nút cấp i+1 Quan hệ người ta gọi quan hệ cha-con 12/1/2016 Một số khái niệm • Bậc nút : số nút • Bậc : bậc lớn nút (số tối đa nút thuộc ) Cây có bậc n gọi n-phân • Nút gốc : nút khơng có nút cha • Nút : nút có bậc • Nút nhánh : nút có bậc khác khơng phải gốc 12/1/2016 Một số khái niệm … • Mức nút : – Mức (gốc (T) ) = – Gọi T1, T2, T3, , Tn T0 – Mức (T1) = Mức (T2) = = Mức (Tn) = Mức (T0) + 12/1/2016 12/1/2016 Một số khái niệm … • Độ dài đường từ gốc đến nút x : số nhánh cần qua kể từ gốc đến x • Độ dài đường tổng : P P T X XT Px độ dài đường từ gốc đến X • Độ dài đường trung bình : PI = PT/n (n số nút T) • Rừng cây: tập hợp nhiều thứ tự quan trọng 12/1/2016 Ví dụ gốc J Cạnh nút Z B Q A R K D A F L Lá 12/1/2016 Cây nhị phân (Binary tree) 12/1/2016 12/1/2016 Định nghĩa • Cây nhị phân mà nút có tối đa • Trong thực tế thường gặp cấu trúc có dạng nhị phân • Một tổng qt biểu diễn thơng qua nhị phân 12/1/2016 10 Ví dụ Cây trái Cây phải Hình ảnh nhị phân 12/1/2016 11 Một số tính chất 2i • Số nút nằm mức i • Chiều cao h mức cao + Số nút 2h-1, với h chiều cao Chiều cao h log2(số nút cây) Số nút 2h-1 • • • • Đường (path) – Tên node trình từ node gốc theo đến node 12/1/2016 12 12/1/2016 Biểu diễn nhị phân T • Cây nhị phân cấu trúc bao gồm phần tử (nút) kết nối với theo quan hệ “cha-con” với cha có tối đa Để biểu diễn nhị phân ta chọn phương pháp cấp phát liên kết Ứng với nút, ta sử dụng biến động lưu trữ thông tin sau: – Thông tin lưu trữ nút – Địa nút gốc trái nhớ – Địa nút gốc phải nhớ 13 Cây nhị phân Để đơn giản, ta khai báo cấu trúc liệu sau : typedef struct NODE { int data; NODE* left; NODE* right; }; typedef struct NODE* TREE; TREE root; 14 Tạo nhị phân void CreateTree(TREE &root) { int x; printf(“\nGia tri node :”); x=toupper(getch()); if(isspace(x)==0) { root=(node*)malloc(sizeof(node)); root ->data=x; printf(“\nCon trai cua %c (ENTER NULL)”,x); CreateTree(root->left); printf(“\nCon phai cua %c (ENTER NULL)”,x); CreateTree(root->right); } else root=NULL; } 15 12/1/2016 Cây nhị phân Duyệt nhị phân • Có kiểu duyệt áp dụng nhị phân: – Duyệt theo thứ tự trước (NLR) – Duyệt theo thứ tự (LNR) – Duyệt theo thứ tựï sau (LRN) • Tên kiểu duyệt đặt dựa trình tự việc thăm nút gốc so với việc thăm 16 Cây nhị phân Duyệt theo thứ tự trước (Node-Left-Right) • Kiểu duyệt trước tiên thăm nút gốc sau thăm nút trái đến phải • Thủ tục duyệt trình bày đơn giản sau: void NLR(TREE root) { if (Root != NULL) { ;//Xử lý tương ứng theo nhu cầu NLR(root->left); NLR(root->right); } } 17 Cây nhị phân Duyệt theo thứ tự trước (Node-Left-Right) • Một ví dụ: đọc sách hay báo từ đầu đến cuối minh họa hình bên dưới: 18 12/1/2016 Duyệt theo thứ tự trước (Node(Node-Left Left Right) A B C D E H I J N F G K L O M P Kết quả: A B D H I N E J O K C F L P G M 19 Cây nhị phân Duyệt theo thứ tự (Left- Node-Right) • • Kiểu duyệt trước tiên thăm nút trái sau thăm nút gốc đến phải Thủ tục duyệt trình bày đơn giản sau: void LNR(TREE root) { if (root != NULL) { LNR(root->left); ; //Xử lý tương ứng theo nhu cầu LNR(root->right); } } 20 Duyệt theo thứ tự (Left- Node-Right) A B C D E H I N J F G K O L M P Kết quả: H D N I B J O E K A F P L C M G 21 12/1/2016 Cây nhị phân Duyệt theo thứ tự sau (Left-Right-Node) • • Kiểu duyệt trước tiên thăm nút trái sau thăm đến phải cuối thăm nút gốc Thủ tục duyệt trình bày đơn giản sau: void LRN(TREE root) { if (root != NULL) { LRN(root->left); LRN(root->right); ; //Xử lý tương ứng theo nhu cầu } } 22 Cây nhị phân Duyệt theo thứ tự sau (Left-Right-Node) • Một ví dụ quen thuộc tin học ứng dụng duyệt theo thứ tự sau việc xác định tồng kích thước thư mục đĩa 23 Duyệt theo thứ tự sau (Left-Right-Node) A B C D E H I N J F G K O L M P Kết quả: H N I D O J K E B P L F M G C A 24 12/1/2016 Cây nhị phân Duyệt theo thứ tự sau (Left-Right-Node) • Tính tốn giá trị biểu thức dựa biểu thức (3 + 1)3/(9 – + 2) – (3(7 – 4) + 6) = –13 25 Cây nhị phân Biểu diễn tổng quát nhị phân • Nhược điểm cấu trúc tổng quát: – Bậc nút dao động biên độ lớn việc biểu diễn gặp nhiều khó khăn lãng phí – Việc xây dựng thao tác tổng quát phức tạp nhị phân nhiều • Vì vậy, thường khơng q cần thiết phải sử dụng tổng quát, người ta chuyển tổng quát thành nhị phân 26 Cây nhị phân Biểu diễn tổng quát nhị phân • Ta biến đổi thành nhị phân theo qui tắc sau: – Giữ lại nút trái làm nút trái – Các nút lại chuyển thành nút phải – Như vậy, nhị phân mới, trái thể quan hệ cha phải thể quan hệ anh em tổng quát ban đầu 27 12/1/2016 Cây nhị phân Biểu diễn tổng quát nhị phân • Giả sử có tổng qt hình bên dưới: A B E F C G D H I J 28 Cây nhị phân Biểu diễn tổng quát nhị phân • Cây nhị phân tương ứng sau:A B E C H F G D I J 29 Cây nhị phân Một cách biểu diễn nhị phân khác • Đơi khi, định nghĩa nhị phân, người ta quan tâm đến quan hệ chiều cha không chiều định nghĩa phần • Lúc đó, cấu trúc nhị phân định nghĩa lại sau: typedef struct tagTNode { DataType Key; struct tagTNode* pParent; struct tagTNode* pLeft; struct tagTNode* pRight; }TNODE; typedef TNODE *TREE; 30 10 12/1/2016 Cây nhị phân Một cách biểu diễn nhị phân khác 31 Cây nhị phân tìm kiếm Cây nhị phân tìm kiếm • Trong chương 3, làm quen với số cấu trúc liệu động Các cấu trúc có mềm dẻo lại bị hạn chế việc tìm kiếm thơng tin chúng (chỉ tìm kiếm tuần tự) • Nhu cầu tìm kiếm quan trọng Vì lý này, người ta đưa cấu trúc để thỏa mãn nhu cầu • Tuy nhiên, với cấu trúc nhị phân định nghĩa trên, việc tìm kiếm cịn mơ hồ • Cần có thêm số ràng buộc để cấu trúc trở nên chặt chẽ, dễ dùng • Một cấu trúc nhị phân tìm kiếm 33 11 12/1/2016 Cây nhị phân tìm kiếm • Định nghĩa: nhị phân tìm kiếm (CNPTK) nhị phân nút, khóa nút xét lớn khóa tất nút thuộc trái nhỏ khóa tất nút thuộc phải • Nếu số nút N chi phí tìm kiếm trung bình khoảng log2N 34 Cây nhị phân tìm kiếm 44 18 88 13 59 37 15 23 40 55 108 71 35 Thêm nút vào int InsertTree(tree &root , int x) { if(root != NULL) { if(root->data==x) return 0; if(root->data>x) return InsertTree(root->letf,x); else return InsertTree(root->right,x); } else { root=(node*)malloc(sizeof(node); if(root !=NULL) return -1; root->data=x; root->left=root->right=NULL; return 1; } } 36 12 12/1/2016 Tạo nhị phân tìm kiếm • Ta tạo nhị phân tìm kiếm cách lặp lại trình thêm phần tử vào rỗng void CreateTree(tree &root) { int x,n; printf(“Nhap n = “); scanf(“%d”,&n); for(int i=1; idata == X) return root; if(root->data > X) return searchNode(root->left, X); return searchNode(root->right, X); } return NULL; } 40 Tìm phần tử x (khơng đệ quy) • Tìm phần tử x (không đệ quy): TNODE * searchNode(TREE root, Data x) { TNODE *p = root; while (p != NULL) { if(x == p->data) return p; else if(x < p->data) p = p->left; else p = p->right; } return NULL; } 41 Tìm phần tử x=13 25 10 37 18 12 29 20 13 50 35 41 32 Giốngnhau Node gốc nhỏ lớn Khác Tìm kiếm 13 Tìm thấy Số node duyệt: Số lần so sánh: 42 14 12/1/2016 Tìm phần tử x Nhận xét: – Số lần so sánh tối đa phải thực để tìm phần tử X h, với h chiều cao – Như thao tác tìm kiếm CNPTK có n nút tốn chi phí trung bình khoảng O(log2n) 43 Tìm phần tử x 44 Tìm X=55 44 < X 18 13 37 15 88 88 > X 23 59 59 > X 40 55 108 71 44 Thêm phần tử x vào • Thêm phần tử x vào cây: – Việc thêm phần tử X vào phải bảo đảm điều kiện ràng buộc CNPTK Ta thêm vào nhiều chỗ khác cây, thêm vào nút tiện lợi ta thực hiên q trình tương tự thao tác tìm kiếm Khi chấm dứt trình tìm kiếm lúc tìm chỗ cần thêm – Hàm insert trả giá trị –1, 0, không đủ nhớ, gặp nút cũ hay thành công: 45 15 12/1/2016 Thêm phần tử x vào int insertNode(TREE &root, Data X) { if (root) { if(root->data == X) return 0; // có if(root->data > X) return insertNode(root->left, X); else return insertNode(root->right, X); } root = new Node; if (root == NULL) return -1; // thiếu nhớ root->data = X; root->left = root->right = NULL; return 1; // thêm vào thành công } 46 Thêm phần tử x vào 44 Theâm X=50 44 < X 18 13 37 15 88 88 > X 23 59 59 > X 40 55 108 71 55 > X 50 47 Hủy phần tử có khóa x • Việc hủy phần tử X khỏi phải bảo đảm điều kiện ràng buộc CNPTK • Có trường hợp hủy nút X xảy ra: – X nút – X có (trái phải) – X có đủ 48 16 12/1/2016 Hủy phần tử có khóa x Trường hợp 1: X nút Xóa node Gán liên kết từ cha thành rỗng 49 Hủy phần tử có khóa x Trường hợp 1: X nút • Ví dụ : đơn giản hủy X khơng móc nối đến phần tử khác 44 T/h 1: huûy X=40 18 88 13 59 37 15 23 40 55 108 71 50 Hủy phần tử có khóa x Trường hợp 2: X có (trái phải) Gán liên kết từ cha xuống Xóa node u u x v v 51 17 12/1/2016 Hủy phần tử có khóa x Trường hợp 2: X có (trái phải) • Trường hợp thứ hai: trước hủy X ta móc nối cha X với 44 T/h 2: hủy X=37 18 88 13 59 37 15 23 55 108 71 52 Hủy phần tử có khóa x Trường hợp 3: X có đủ Tìm w node trước node x phép duyệt inorder (chính node cực phải bên trái x) Thay x w Xóa node w cũ (giống trường hợp xét) 53 Hủy phần tử có khóa x Trường hợp 3: X có đủ • Trường hợp cuối cùng: – Khơng thể hủy trực tiếp X có đủ – Hủy gián tiếp: • Thay hủy X, ta tìm phần tử mạng Y Phần tử có tối đa • Thơng tin lưu Y chuyển lên lưu X • Sau đó, nút bị hủy thật Y giống trường hợp đầu – Vấn đề: chọn Y cho lưu Y vào vị trí X, CNPTK 54 18 12/1/2016 Hủy phần tử có khóa x Trường hợp 3: X có đủ • Vấn đề phải chọn Y cho lưu Y vào vị trí X, CNPTK • Có phần tử thỏa mãn yêu cầu: – Phần tử nhỏ (trái nhất) phải – Phần tử lớn (phải nhất) trái • Việc chọn lựa phần tử phần tử mạng hoàn toàn phụ thuộc vào ý thích người lập trình • Ở đây, ta chọn phần tử phải trái làm phân tử mạng 55 Hủy phần tử có khóa x Trường hợp 3: X có đủ • Khi hủy phần tử X=18 khỏi cây, phần tử 23 phần tử mạng: 44 T/h 3: huûy X=18 18 88 13 59 37 15 23 40 55 108 71 30 56 Hủy phần tử có khóa x Trường hợp 3: X có đủ • Hàm delNode trả giá trị 1, hủy thành cơng khơng có X cây: int delNode(TREE &root, Data X) • Hàm searchStandFor tìm phần tử mạng cho nút p void searchStandFor(TREE &p, TREE &q) 57 19 12/1/2016 Hủy phần tử có khóa x int delNode(TREE &root, Data X) { if(root== NULL) return 0; if(root->data > X) return delNode(root->left, X); if(root->data < X) return delNode(root->right, X); //T->Key == X Node* p = root; if(root->left == NULL) root = root->right; else if(root->right == NULL) root = root->left; else // T cĩ dủ searchStandFor(p, root->right); delete p; } 58 Hủy phần tử có khóa x void searchStandFor(TREE &p, TREE &q) { if(q->left) searchStandFor(p, q->left); else { p->data = q->data; p = q; q = q->right; } } 59 Hủy toàn nhị phân tìm kiếm • Việc tồn thực thơng qua thao tác duyệt theo thứ tự sau Nghĩa ta hủy trái, phải hủy nút gốc void removeTree(TREE &root) { if(root) { removeTree(root->reft); removeTree(root->right); delete(root); } } 60 20 12/1/2016 Cây nhị phân tìm kiếm Nhận xét: – Tất thao tác searchNode, insertNode, delNode có độ phức tạp trung bình O(h), với h chiều cao – Trong trường hợp tốt nhất, CNPTK có n nút có độ cao h = log2(n) Chi phí tìm kiếm tương đương tìm kiếm nhị phân mảng có thứ tự – Trong trường hợp xấu nhất, bị suy biến thành danh sách liên kết (khi mà nút có trừ nút lá) Lúc thao tác có độ phức tạp O(n) – Vì cần có cải tiến cấu trúc CNPTK để đạt chi phí cho thao tác log2(n) 61 Bài tập 12/1/2016 62 Bài tập nhà Cài đặt thử nghiệm nhị phân tìm kiếm 12/1/2016 63 21 ... chuyển tổng quát thành nhị phân 26 Cây nhị phân Biểu diễn tổng qt nhị phân • Ta biến đổi thành nhị phân theo qui tắc sau: – Giữ lại nút trái làm nút trái – Các nút lại chuyển thành nút phải – Như... cây: – Việc thêm phần tử X vào phải bảo đảm điều kiện ràng buộc CNPTK Ta thêm vào nhiều chỗ khác cây, thêm vào nút ngồi tiện lợi ta thực hiên trình tương tự thao tác tìm kiếm Khi chấm dứt q trình. .. 56 Hủy phần tử có khóa x Trường hợp 3: X có đủ • Hàm delNode trả giá trị 1, hủy thành công khơng có X cây: int delNode(TREE &root, Data X) • Hàm searchStandFor tìm phần tử mạng cho nút p void