Cây nhị phân

Một phần của tài liệu Baigiang dung chung kythuatlaptrinh (Trang 65 - 73)

4.2.1. Khái niệm

Cây nhị phân là cấu trúc cây quan trọng, đặc điểm là mọi node trên cây có tối đa 2 node con. Đối với cây nhị phân bao giờ cũng phân biệt cây con bên trái và cây con bên phải. Như vậy cây nhị phân là cây có thứ tự.

Hình 4.2. Cây nhị phân Một số dạng đặc biệt của cây nhị phân:

 Cây nhị phân lệch trái: là cây nhị phân chỉ có các nút bên trái  Cây nhị phân lệch phải: là cây nhị phân chỉ có các nút bên phải

 Cây nhị phân hoàn chỉnh: nếu nút gốc và nút trung gian đều có hai con.

 Cây nhị phân đầy đủ: một cây nhị phân đầy đủ với chiều sâu d nếu nó là cây nhị phân hoàn chỉnh và tất cả các nút lá đều có chiều sâu là d

Hình 4.3. a Cây nhị phân đầy đủ

Hình 4.3. b Cây nhị phân hoàn chỉnh

Cây nhị phân tìm kiếm là cây nhị phân hoặc là rỗng hoặc là tất cả các nút trên cây thỏa mãn các điều kiện sau:

 Nội dung của tất cả các nhánh bên trái đều nhỏ hơn nội dung của nút gốc  Nội dung của tất cả các nhánh bên phải đều lớn hơn nội dung nút gốc

 Các cây con bên trái và bên phải cũng tự nhiên hình thành cây nhị phân tìm kiếm

Hình 4.4. Cây nhị phân tìm kiếm 4.2.2 Biểu diễn cây nhị phân

Trong trường hợp cây nhị phân đầy đủ, ta dễ dàng biểu diễn bằng mảng lưu trữ kế tiếp. Node gốc là phần tử đầu tiên của mảng, node con thứ i>=1 của cây nhị phân là phần tử thứ 2i và 2i+1 hay cha của node thứ j là [j/2].

Hình 4.5. Biểu diễn cây nhị phân bằng mảng

Với cây nhị phân không đầy đủ, phương pháp biểu diễn cây nhị phân bằng mảng không hiệu quả vì để trống quá nhiều phần tử gây lãng phí bộ nhớ.

Biểu diễn cây nhị phân bằng danh sách móc nối

Trong phương pháp này, mỗi node được mô tả bằng 3 thông tin như sau:  Left là con trỏ trỏ tới nút bên trái của nút

 Infor là thông tin về nút

 Right là con trỏ trỏ tới nút bên phải phải của nút

Ví dụ biểu diễn bằng danh sách móc nối với cây nhị phân sau:

Hình 4.6. Biểu diễn cây nhị phân bằng danh sách móc nối 4.2.3. Các phép duyệt cây nhị phân

Phép duyệt cây là phương pháp thăm cây một cách hệ thống sao cho mỗi node được thăm đúng một lần.

Có 3 phép duyệt cây phổ biến:

 Duyệt theo thứ tự trước  Duyệt theo thứ tự giữa  Duyệt theo thứ tự sau

Hình 4.7. Duyệt cây

Duyệt theo thứ tự trước

Thăm nút gốc n

Thăm cây con T1 theo thứ tự trước. Thăm cây con T2 theo thứ tự trước. Thăm cây con Tk theo thứ tự trước.

Hình 4.8. Thứ tự duyệt cây

Với cây trên, trình tự thăm các nút là:

Duyệt cây con trái theo thứ tự giữa (adsbygoogle = window.adsbygoogle || []).push({});

Thăm gốc

Thăm cây con T2 theo thứ tự giữa Thăm cây con Tk theo thứ tự giữa

Với cây con hình 4.8. như trên, thứ tự thăm các như sau: 4->3->5->2->1->6->8->7->9

Duyệt theo thứ tự sau

Thăm cây con T1 theo thứ tự sau Thăm cây con T2 theo thứ tự sau Thăm cây con Tk theo thứ tự sau Thăm gốc n

Với cây hình 4.8. như trên, thứ tự thăm như sau: 4->5->3->2->6->8->9->7->1

4.2.4. Thao tác với cây nhị phân

Cài đặt cây nhị phân tìm kiếm bằng danh sách móc nối: #include<stdlib.h>

#include<stdio.h>

typedef int item; //kieu item la kieu nguyen struct Node

{

item key; //truong key cua du lieu

Node *Left, *Right; //con trai va con phai };

typedef Node *Tree; //cay

int insertNode(Tree &T, item x) // chen 1 Node vao cay {

if (T != NULL) {

if (T->key == x) return -1; // Node nay da co

if (T->key > x) return insertNode(T->Left, x); // chen vao Node trai

else if (T->key < x) return insertNode(T->Right, x); // chen vao Node phai }

if (T == NULL) return 0; // khong du bo nho T->key = x;

T->Left = T->Right = NULL; return 1; // ok

}

void CreateTree(Tree &T) // nhap cay {

int x; while (1) {

printf("Nhap vao Node: "); scanf("%d", &x);

if (x == 0) break; // x = 0 thi thoat int check = insertNode(T, x);

if (check == -1) printf("Node da ton tai!"); else if (check == 0) printf("Khong du bo nho"); } } // Duyet theo LNR void LNR(Tree T) { if(T!=NULL) { LNR(T->Left); printf("%d ",T->key); LNR(T->Right); } }

Node* searchKey(Tree T, item x) // tim nut co key x {

if (T!=NULL) {

if (T->key == x) { Node *P = T; return P;} if (T->key > x) return searchKey(T->Left, x); if (T->key < x) return searchKey(T->Right, x); } (adsbygoogle = window.adsbygoogle || []).push({});

return NULL; }

int delKey(Tree &T, item x) // xoa nut co key x {

if (T==NULL) return 0;

else if (T->key > x) return delKey(T->Left, x); else if (T->key < x) return delKey(T->Right, x); else // T->key == x

{

Node *P = T;

if (T->Left == NULL) T = T->Right; // Node chi co cay con phai else if (T->Right == NULL) T = T->Left; // Node chi co cay con trai else // Node co ca 2 con

{

Node *S = T, *Q = S->Left;

// S la cha cua Q, Q la Node phai nhat cua cay con trai cua P while (Q->Right != NULL)

{ S = Q; Q = Q->Right; } P->key = Q->key; S->Right = Q->Left; delete Q; } } return 1; } int main() { Tree T;

T=NULL; //Tao cay rong

CreateTree(T); //Nhap cay //duyet cay

printf("Duyet cay theo LNR: n"); LNR(T);

printf("n");

Node *P; item x;

printf("Nhap vao key can tim: "); scanf("%d", &x);

if (P != NULL) printf("Tim thay key %dn", P->key); else printf("Key %d khong co trong cayn", x);

if (delKey(T, x)) printf("Xoa thanh congn"); else printf("Khong tim thay key %d can xoan", x); printf("Duyet cay theo LNR: n");

LNR(T); printf("n"); return 0; }

Một phần của tài liệu Baigiang dung chung kythuatlaptrinh (Trang 65 - 73)