Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 23 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
23
Dung lượng
277,5 KB
Nội dung
Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 162 - Thuật toán: B1: IF (BinTree = NULL) B1.1: NN = 0 B1.2: Thực hiện Bkt B2: NNL = NN(BinTree->BinT_Left) B3: NNR = NN(BinTree->BinT_Right) B4: NN = NNL + NNR + 1 Bkt: Kết thúc Ví dụ: Số nút của cây nhò phân sau bằng 8. BinTree 40 36 55 12 18 45 21 NULL NULL NULL NULL NULL 8 NULL NULL 0 0 0 0 0 0 0 1(0+0+1) 1 (0+0+1) NULL NULL 1 (0+0+1) 3 (1+1+1) 0 0 1 (0+0+1) 2 (0+1+1) 4 (2+1+1) 8 (3+4+1) - Cài đặt thuật toán: Hàm BinT_Num_Node có prototype: int BinT_Num_Node(BinT_Type BTree); Hàm tính số nút của cây BTree theo thuật toán đệ quy. Hàm trả về số nút của cây cần tính. int BinT_Num_Node(BinT_Type BTree) { if (BTree == NULL) return (0); int NNL = BinT_Num_Node(BTree->BinT_Left); int NNR = BinT_Num_Node(BTree->BinT_Right); return (NNL + NNR + 1); } g. Hủy một nút trên cây nhò phân: Việc hủy một nút trong cây có thể làm cho cây trở thành rừng. Do vậy trong thao tác này nếu chúng ta tiến hành hủy một nút lá thì không có điều gì xảy ra, song nếu hủy Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 163 nút không phải là nút lá thì chúng ta phải tìm cách chuyển các nút gốc cây con là các nút con của nút cần hủy thành các nút gốc cây con của các nút khác rồi mới tiến hành hủy nút này. - Trường hợp nếu nút cần hủy chỉ có 01 nút gốc cây con thì chúng ta có thể chuyển nút gốc cây con này thành nút gốc cây con của nút cha của nút cần hủy. - Trường hợp nếu nút cần hủy có 2 nút gốc cây con thì chúng ta phải chuyển 02 nút gốc cây con này thành nút gốc cây con của các nút khác với nút cần hủy. Việc chọn các nút để làm nhiệm vụ nút cha của các nút gốc cây con này tùy vào từng trường hợp cụ thể của cây nhò phân mà chúng ta sẽ lựa chọn cho phù hợp. Do vậy, thao tác hủy một nút sẽ được trình bày cụ thể trong các loại cây cụ thể được trình bày ở các phần sau. 5.2.3. Cây nhò phân tìm kiếm (Binary Searching Tree) A. Khái niệm – Cấu trúc dữ liệu: Cây nhò phân tìm kiếm là cây nhò phân có thành phần khóa của mọi nút lớn hơn thành phần khóa của tất cả các nút trong cây con trái của nó và nhỏ hơn thành phần khóa của tất cả các nút trong cây con phải của nó. Ví dụ: Hình ảnh sau là hình ảnh của một cây nhò phân tìm kiếm BSTree 60 25 65 19 40 NULL NULL 10 NULL 30 44 NULL NULL NULL NULL 50 15 NULL NULL NULL NULL Từ khái niệm này chúng ta có một số nhận xét: - Cấu trúc dữ liệu của cây nhò phân tìm kiếm là cấu trúc dữ liệu để biểu diễn các cây nhò phân nói chung. typedef struct BST_Node { T Key; BST_Node * BST_Left; // Vùng liên kết quản lý đòa chỉ nút gốc cây con trái BST_Node * BST_Right; // Vùng liên kết quản lý đòa chỉ nút gốc cây con phải } BST_OneNode; Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 164 typedef BST_OneNode * BST_Type; Để quản lý các cây nhò phân tìm kiếm chúng ta cần quản lý đòa chỉ nút gốc của cây: BST_Type BSTree; - Khóa nhận diện (Key) của các nút trong cây nhò phân tìm kiếm đôi một khác nhau (không có hiện tượng trùng khóa). Tuy nhiên trong trường hợp cần quản lý các nút có khóa trùng nhau trong cây nhò phân tìm kiếm thì chúng ta có thể mở rộng cấu trúc dữ liệu của mỗi nút bằng cách thêm thành phần Count để ghi nhận số lượng các nút trùng khóa. Khi đó, cấu trúc dữ liệu để quản lý các cây nhò phân tìm kiếm được mở rộng như sau: typedef struct BSE_Node { T Key; int Count; BSE_Node * BSE_Left; // Vùng liên kết quản lý đòa chỉ nút gốc cây con trái BSE_Node * BSE_Right; // Vùng liên kết quản lý đòa chỉ nút gốc cây con phải } BSE_OneNode; typedef BSE_OneNode * BSE_Type; và chúng ta quản lý cây nhò phân tìm kiếm này bằng cách quản lý đòa chỉ nút gốc: BSE_Type BSETree; - Nút ở bên trái nhất là nút có giá trò khóa nhận diện nhỏ nhất và nút ở bên phải nhất là nút có giá trò khóa nhận diện lớn nhất trong cây nhò phân tìm kiếm. - Trong một cây nhò phân tìm kiếm thứ tự duyệt cây Left – Root – Right là thứ tự duyệt theo sự tăng dần các giá trò của Key trong các nút và thứ tự duyệt cây Right – Root – Left là thứ tự duyệt theo sự giảm dần các giá trò của Key trong các nút. B. Các thao tác trên cây nhò phân tìm kiếm: a. Tìm kiếm trên cây: Giả sử chúng ta cần tìm trên cây nhò phân tìm kiếm xem có tồn tại nút có khóa Key là SearchData hay không. Để thực hiện thao tác này chúng ta sẽ vận dụng thuật toán tìm kiếm nhò phân: Do đặc điểm của cây nhò phân tìm kiếm thì tại một nút, nếu Key của nút này khác với SearchData thì SearchData chỉ có thể tìm thấy hoặc trên cây con trái của nút này nếu SearchData nhỏ hơn Key của nút này hoặc trên cây con phải của nút này nếu SearchData lớn hơn Key của nút này. - Thuật toán tìm kiếm 1 nút trên cây nhò phân tìm kiếm: B1: CurNode = BSTree B2: IF (CurNode = NULL) or (CurNode->Key = SearchData) Thực hiện Bkt B3: IF (CurNode->Key > SearchData) // Tìm kiếm trên cây con trái CurNode = CurNode->BST_Left B4: ELSE // Tìm kiếm trên cây con phải CurNode = CurNode->BST_Right B5: Lặp lại B2 Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 165 Bkt: Kết thúc - Minh họa thuật toán: Giả sử chúng ta cần tìm kiếm nút có thành phần dữ liệu là 30 trên cây nhò phân tìm kiếm sau: SearchData = 30 CurNode BSTree 60 25 65 19 40 NULL NULL 10 NULL 30 44 NULL NULL NULL NULL 50 15 NULL NULL NULL NULL CurNode->Key > SearchData // Tìm kiếm trên cây con trái ⇒ CurNode = CurNode->BST_Left BSTree CurNode 60 25 65 19 40 NULL NULL 10 NULL 30 44 NULL NULL NULL NULL 50 15 NULL NULL NULL NULL Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 166 CurNode->Key < SearchData // Tìm kiếm trên cây con phải ⇒ CurNode = CurNode->BST_Right BSTree 60 25 CurNode 65 19 40 NULL NULL 10 NULL 30 44 NULL NULL NULL NULL 50 15 NULL NULL NULL NULL CurNode->Key > SearchData // Tìm kiếm trên cây con trái ⇒ CurNode = CurNode->BST_Left BSTree 60 25 65 19 CurNode 40 NULL NULL 10 NULL 30 44 NULL NULL NULL NULL 50 15 NULL NULL NULL NULL CurNode->Key = SearchData ⇒ Thuật toán kết thúc (Tìm thấy) Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 167 Bây giờ giả sử chúng ta cần tìm kiếm nút có thành phần dữ liệu là 35 trên cây nhò phân tìm kiếm trên: SearchData = 35 CurNode BSTree 60 25 65 19 40 NULL NULL 10 NULL 30 44 NULL NULL NULL NULL 50 15 NULL NULL NULL NULL CurNode->Key > SearchData // Tìm kiếm trên cây con trái ⇒ CurNode = CurNode->BST_Left BSTree CurNode 60 25 65 19 40 NULL NULL 10 NULL 30 44 NULL NULL NULL NULL 50 15 NULL NULL NULL NULL Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 168 CurNode->Key < SearchData // Tìm kiếm trên cây con phải ⇒ CurNode = CurNode->BST_Right BSTree 60 25 CurNode 65 19 40 NULL NULL 10 NULL 30 44 NULL NULL NULL NULL 50 15 NULL NULL NULL NULL CurNode->Key > SearchData // Tìm kiếm trên cây con trái ⇒ CurNode = CurNode->BST_Left BSTree 60 25 65 19 CurNode 40 NULL NULL 10 NULL 30 44 NULL NULL NULL NULL 50 15 NULL NULL NULL NULL CurNode->Key < SearchData // Tìm kiếm trên cây con phải ⇒ CurNode = CurNode->BST_Right Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 169 BSTree 60 25 65 19 40 NULL NULL 10 NULL 30 CurNode 44 NULL NULL NULL NULL 50 15 NULL NULL NULL NULL CurNode = NULL ⇒ Thuật toán kết thúc (Không tìm thấy) - Cài đặt thuật toán: Hàm BST_Searching có prototype: BST_Type BST_Searching(BST_Type BS_Tree, T SearchData); Hàm thực hiện thao tác tìm kiếm trên cây nhò phân tìm kiếm BS_Tree nút có thành phần Key là SearchData. Hàm trả về con trỏ trỏ tới đòa chỉ của nút có Key là SearchData nếu tìm thấy, trong trường hợp ngược lại hàm trả về con trỏ NULL. BST_Type BST_Searching(BST_Type BS_Tree, T SearchData) { BST_Type CurNode = BS_Tree; while (CurNode != NULL && CurNode->Key != SearchData) { if (CurNode->Key > SearchData) CurNode = CurNode->BST_Left; else CurNode = CurNode->BST_Right; } return (CurNode); } b. Thêm một nút vào trong cây: Giả sử chúng ta cần thêm một nút có thành phần dữ liệu (Key) là NewData vào trong cây nhò phân tìm kiếm sao cho sau khi thêm cây vẫn là một cây nhò phân tìm kiếm. Trong thao tác này trước hết chúng ta phải tìm kiếm vò trí thêm, sau đó mới tiến hành thêm nút mới vào cây (Do vậy thuật toán còn được gọi là thuật toán tìm kiếm và thêm vào cây). Quá trình tìm kiếm tuân thủ các bước trong thuật toán tìm kiếm đã trình bày ở trên. Trong thuật toán này chúng ta sẽ trình bày thao tác thêm vào cây nhò phân tìm kiếm trong trường hợp không có hiện tượng trùng lắp khóa. Do vậy, nếu NewData bò trùng Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 170 với Key của một trong các nút ở trong cây nhò phân tìm kiếm thì chúng ta sẽ không thực hiện thao tác thêm này. Tuy nhiên, nếu chúng ta sử dụng cấu trúc dữ liệu mở rộng thì việc trùng khóa sẽ giải quyết đơn giản vì không làm tăng số nút của cây nhò phân tìm kiếm mà chỉ làm tăng thành phần Count của nút bò trùng khóa thêm 1. - Thuật toán thêm 1 nút vào cây nhò phân tìm kiếm: B1: NewNode = BinT_Create_Node(NewData) B2: IF (NewNode = NULL) Thực hiện Bkt B3: IF (BSTree = NULL) // Cây rỗng B3.1: BSTree = NewNode B3.2: Thực hiện Bkt B4: CurNode = BSTree B5: IF (CurNode->Key = NewData) // Trùng khóa Thực hiện Bkt B6: IF (CurNode->Key > NewData) B6.1: AddLeft = True // Thêm vào cây con trái của CurNode B6.2: If (CurNode->BST_Left != NULL) CurNode = CurNode->BST_Left B7: IF (CurNode->Key < NewData) B7.1: AddLeft = False // Thêm vào cây con phải của CurNode B7.2: If (CurNode->BST_Right != NULL) CurNode = CurNode->BST_Right B8: Lặp lại B5 B9: IF (AddLeft = True) CurNode->BST_Left = NewNode B10: ELSE CurNode->BST_Right = NewNode Bkt: Kết thúc - Minh họa thuật toán: Giả sử chúng ta cần thêm vào trong cây nhò phân tìm kiếm 1 nút có thành phần dữ liệu là 55: NewData = 55 NewNode CurNode BSTree 55 60 NULL NULL 25 65 19 40 NULL NULL 10 NULL 30 44 NULL NULL NULL NULL NULL NULL Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 171 CurNode->Key > NewData // Thêm vào cây con trái ⇒ AddLeft = True CurNode->BST_Left != NULL // Chuyển sang cây con trái ⇒ CurNode = CurNode->BST_Left BSTree NewNode CurNode 60 55 25 65 NULL NULL 19 40 NULL NULL 10 NULL 30 44 NULL NULL NULL NULL NULL NULL CurNode->Key < NewData // Thêm vào cây con phải ⇒ AddLeft = False CurNode->BST_Right != NULL // Chuyển sang cây con phải ⇒ CurNode = CurNode->BST_Right BSTree 60 NewNode 25 CurNode 65 55 19 40 NULL NULL NULL NULL 10 NULL 30 44 NULL NULL NULL NULL NULL NULL CurNode->Key < NewData // Thêm vào cây con bên phải ⇒ AddLeft = False CurNode->BST_Right != NULL // Chuyển sang cây con bên phải ⇒ CurNode = CurNode->BST_Right [...]... phải tìm kiếm đòa chỉ của nút cần hủy là DelNode, sau đó mới tiến hành hủy nút có đòa chỉ là DelNode này nếu tìm thấy (Do vậy thuật toán này còn được gọi là thuật toán tìm kiếm và loại bỏ trên cây) Quá trình tìm kiếm đã trình bày ở trên, ở đây chúng ta chỉ trình bày thao Trang: 173 Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật tác hủy khi tìm thấy nút có đòa chỉ DelNode (DelNode->Key = DelData) và trong. .. sử cần hủy nút có Key = 25 (DelData = 25) Chúng ta sẽ chọn phần tử thế mạng MLNode là nút trái nhất trong cây con phải của DelNode (trái nhất trong DelNode->BST_Right) để hủy, Trang: 1 78 Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật BSTree DelNode 60 25 19 10 NULL PrMLNode MLNode NULL NULL 40 65 NULL 30 NULL NULL 44 NULL NULL NULL Chuyển dữ liệu trong MLNode về cho DelNode: DelNode->Key = MLNode->Key BSTree... Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Kết quả sau khi hủy: BSTree DelNode 60 30 19 10 NULL 40 NULL NULL PrMLNode 65 NULL NULL NULL 44 NULL NULL - Thuật toán hủy 1 nút trong cây nhò phân tìm kiếm bằng phương pháp chuyển cây con phải của nút cần hủy về thành cây con phải của cây con có nút gốc là nút phải nhất trong cây con trái của nút cần hủy (nếu nút cần hủy có đủ 02 cây con): // Tìm nút cần... DelNode B8.4.1: MRNode = DelNode->BST_Left B8.4.2: if (MRNode->BST_Right = NULL) Thực hiện B8.4.5 B8.4.3: MRNode = MRNode->BST_Right B8.4.4: Lặp lại B8.4.2 // Chuyển cây con phải của DelNode về cây con phải của MRNode B8.4.5: MRNode->BST_Right = DelNode->BST_Right B8.4.6: DelNode->BST_Right = NULL // Chuyển cây con trái còn lại của DelNode về cho BSTree B8.4.7: BSTree = BSTree->BST_Left B8.4 .8: DelNode->BST_Left... mối quan hệ của DelNode cho các nút khác B8: IF (PrDelNode = NULL) // DelNode là nút gốc // Nếu DelNode là nút lá B8.1: If (DelNode->BST_Left = NULL) and (DelNode->BST_Right = NULL) B8.1.1: BSTree = NULL B8.1.2: Thực hiện B10 // Nếu DelNode có một cây con phải B8.2: If (DelNode->BST_Left = NULL) and (DelNode->BST_Right != NULL) B8.2.1: BSTree = BSTree->BST_Right Trang: 180 Giáo trình: Cấu Trúc Dữ Liệu. .. Giải Thuật B8.2.2: DelNode->BST_Right = NULL B8.2.3: Thực hiện B10 // Nếu DelNode có một cây con trái B8.3: If (DelNode->BST_Left != NULL) and (DelNode->BST_Right = NULL) B8.3.1: BSTree = BSTree->BST_Left B8.3.2: DelNode->BST_Left = NULL B8.3.3: Thực hiện B10 // Nếu DelNode có hai cây con B8.4: If (DelNode->BST_Left != NULL) and (DelNode->BST_Right != NULL) // Tìm nút phải nhất trong cây con trái của. .. con trái của cây con có nút gốc là nút trái nhất trong cây con phải của DelNode (trái nhất trong Trang: 176 Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật DelNode->BST_Right) Sau khi chuyển thì DelNode sẽ trở thành nút lá hoặc nút chỉ có 01 cây con và chúng ta hủy DelNode như đối với trường hợp c1) và c2) ở trên Ví dụ: Giả sử cần hủy nút có Key = 25 (DelData = 25) Chúng ta sẽ chuyển cây con phải của DelNode... NULL NULL NewNode 55 NULL NULL - Cài đặt thuật toán: Hàm BST_Add_Node có prototype: BST_Type BST_Add_Node(BST_Type &BS_Tree, T NewData); Trang: 172 Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Hàm thực hiện việc thêm vào cây nhò phân tìm kiếm BS_Tree một nút có thành phần Key là NewData Hàm trả về con trỏ trỏ tới đòa chỉ của nút mới thêm nếu việc thêm thành công, trong trường hợp ngược lại hàm trả về con... Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Kết quả sau khi hủy: BSTree 60 25 PrDelNode 19 10 NULL 40 NULL 65 NULL NULL NULL 44 NULL NULL NULL c2) DelNode là nút chỉ có 01 nút gốc cây con: Trong trường hợp này cũng khá đơn giản chúng ta chỉ cần chuyển mối quan hệ chacon giữa PrDelNode và DelNode thành mối quan hệ cha-con giữa PrDelNode và nút gốc cây con của DelNode rồi tiến hành cắt bỏ mối quan hệ cha-con... True) PrDelNode->BST_Left = DelNode->BST_Left Trang: 181 Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật B9.3.2: else PrDelNode->BST_Right = DelNode->BST_Left B9.3.3: DelNode->BST_Left = NULL B9.3.4: Thực hiện B10 // Nếu DelNode có hai cây con B9.4: If (DelNode->BST_Left != NULL) and (DelNode->BST_Right != NULL) // Tìm nút phải nhất trong cây con trái của DelNode B9.4.1: MRNode = DelNode->BST_Left B9.4.2: . SearchData ⇒ Thuật toán kết thúc (Tìm thấy) Giáo trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 167 Bây giờ giả sử chúng ta cần tìm kiếm nút có thành phần dữ liệu là 35 trên cây nhò phân tìm kiếm. ta có thể mở rộng cấu trúc dữ liệu của mỗi nút bằng cách thêm thành phần Count để ghi nhận số lượng các nút trùng khóa. Khi đó, cấu trúc dữ liệu để quản lý các cây nhò phân tìm kiếm được mở. trình: Cấu Trúc Dữ Liệu và Giải Thuật Trang: 170 với Key của một trong các nút ở trong cây nhò phân tìm kiếm thì chúng ta sẽ không thực hiện thao tác thêm này. Tuy nhiên, nếu chúng ta sử dụng cấu