1. Trang chủ
  2. » Luận Văn - Báo Cáo

Đồ Án Hai cây nhị phân tìm kiếm tương tự

20 917 8

Đ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

Thông tin cơ bản

Định dạng
Số trang 20
Dung lượng 215 KB

Nội dung

ĐẠI HỌC ĐÀ NẴNG TRƯỜNG ĐẠI HỌC BÁCH KHOA KHOA CÔNG NGHỆ THÔNG TIN ---*---BÁO CÁO ĐỒ ÁN CẤU TRÚC DỮ LIỆU VÀ THUẬT TOÁN Đề số 10: Hai cây nhị phân tìm kiếm tương tự NGUYỄN TIẾN THÀNH LÊ

Trang 1

ĐẠI HỌC ĐÀ NẴNG TRƯỜNG ĐẠI HỌC BÁCH KHOA KHOA CÔNG NGHỆ THÔNG TIN

-* -BÁO CÁO ĐỒ ÁN CẤU TRÚC DỮ LIỆU VÀ THUẬT TOÁN

Đề số 10: Hai cây nhị phân tìm kiếm tương tự

NGUYỄN TIẾN THÀNH

LÊ NGUYỄN OANH VŨ NGUYỄN DƯƠNG VŨ

Đà Nẵng, tháng 12 năm 2009

Trang 2

I LỜI NÓI ĐẦU

Ngày nay công nghệ thông tin đóng vai trò cực kỳ quan trọng và trở thành một phần không thể thiếu trong đời sống Việc ứng dụng một cách rộng rãi vào mọi lĩnh vực đã đem lại hiệu quả, năng suất công việc khá cao Điều đó đòi hỏi ngày càng cải tiến công nghệ, tối ưu hóa thuật toán để phát triển nhiều tính năng hơn nữa Có rất nhiều công cụ, môn học để giải quyết vấn đề này Một trong những môn học nền tảng

quan trọng ảnh hưởng trực tiếp đến thuật toán đó là “Cấu trúc dữ liệu và thuật

toán”.

Để nghiên cứu kỹ hơn và xây dựng hợp lý cấu trúc dữ liệu và thuật toán, nhóm

chúng em đã chọn đề tài về “hai cây nhị phân tìm kiếm tương tự”

Trong quá trình thực hiện, mặc dù đã có nhiều cố gắng song không tránh khỏi những thiếu sót, chúng em rất mong nhận được sự chỉ dẫn, đóng góp của quý thầy cô

để đề tài của chúng em ngày càng hoàn thiện hơn

Đồng thời, chúng em cũng gửi lời cảm ơn chân thành đến thầy Phan Thanh

Tao đã giúp đỡ chúng em hoàn thành đề tài này.

Nhóm sinh viên thực hiện đề tài

Trang 3

II GIỚI THIỆU ĐỀ TÀI:

Cây là khái niệm quan trọng trong lý thuyết đồ thị, cấu trúc dữ liệu và giải

thuật Cây là một đồ thị thỏa mãn các tính chất sau:

· Có một đỉnh đặc biệt gọi là gốc.

· Mỗi đỉnh B bất kỳ không phải là gốc, tồn tại duy nhất một đỉnh A có

cung đi từ A đến B Đỉnh A được gọi là đỉnh cha của B, đỉnh B được gọi là đỉnh con của A

· Có đường đi duy nhất từ gốc đến mỗi đỉnh của cây.

Một ví dụ quen thuộc về cây đó là cây thư mục hay trong thực tế, tập hợp các thành viên trong một dòng họ với quan hệ cha – con Trừ ông tổ của dòng họ này, mỗi một người trong dòng họ là con của một người cha nào đó trong dòng họ Biểu diễn dòng họ dưới dạng đồ thị hướng: quan hệ cha – con được biểu diễn bởi các cung của

đồ thị, nếu A là cha của B, thì trong đồ thị có cung đi từ đỉnh A tới đỉnh B

Cây được sử dụng rộng rãi trong rất nhiều vấn đề khác nhau Chẳng hạn nó được áp dụng để tổ chức thông tin trong các hệ cơ sở dữ liệu, để mô tả cấu trúc cú pháp của các chương trình nguồn khi xây dựng các chương trình dịch Rất nhiều các bài toán mà ta gặp trong các lĩnh vực khác nhau được quy về việc thực hiện các phép toán trên cây

Trong thực tế thường hay gặp các bài toán liên quan cây nhị phân Cây nhị

phân là cây mà mỗi đỉnh có tối đa 2 nút con

Trong nội dung đề tài này, chúng ta sẽ tìm hiểu về cây nhị phân tìm kiếm Cây

nhị phân tìm kiếm là cây nhị phân mà mỗi nút đều được gán một khóa, sao cho với mỗi nút k thì:

· Mọi khóa trên cây con trái đều nhỏ hơn khóa trên nút k.

· Mọi khóa trên cây con phải đều lớn hơn khóa trên nút k.

Ví dụ cây nhị phân tìm kiếm:

YÊU CẦU BÀI TOÁN CẦN GIẢI QUYẾT LÀ: nhập 2 cây nhị phân tìm kiếm và xét xem chúng có tương tự hay không, tức là xét xem chúng có giống hệt nhau về hình dạng hay không.

Trang 4

III MÔ TẢ BÀI TOÁN:

1 Input:

- Nhập 2 cây nhị phân tìm kiếm

2 Output:

- Thông báo ra màn hình là CÓ nếu 2 cây nhị phân tương tự nhau

- Ngược lại, nếu 2 cây nhị phân không tương tự nhau thì thông báo KHÔNG

IV XÂY DỰNG CẤU TRÚC DỮ LIỆU CHO BÀI TOÁN:

Biểu diễn nút:

typedef int KeyType;

struct Node

Node *Left;

Node *Right;

};

Trong đó key là khóa của nút (ở đây ta dùng kiểu số nguyên) Left và Right là 2 con trỏ kiểu Node dùng để liên kết đến 2 nút con của nó (nếu có)

typedef Node *BTree;

BTree Root1, Root2;

Trong đó Root1, Root2 là 2 nút gốc của 2 cây nhị phân tìm kiếm

V THUẬT TOÁN:

1 Tạo cây nhị phân tìm kiếm:

Lần lượt đọc các khóa nhập từ bàn phím hoặc từ file Dùng hàm void

InsertNode(KeyType x, BTree &Root) để nhập từng nút vào cây nhị phân tìm kiếm

Tại mỗi thời điểm, khi xét đến nút có khóa là x

- Nếu Root=NULL thì tạo một nút mới với khóa x bằng hàm CreateNode(x)

- Ngược lại nếu Root!=NULL, tức là tại Root đã là 1 nút với khóa là (*Root).key

- Nếu (x<(*Root).key) ta sẽ gọi hàm InsertNode(x, (*Root).Left);

- Ngược lại, nếu (x>(*Root).key) ta sẽ gọi hàm InsertNode(x,(*Root).Right); Lặp lại quá trình cho đến khi nhập xong tất cả các nút

Trong đó hàm Node *CreateNode(KeyType x) có chức năng tạo 1 nút mới với khóa là x; 2 biến con trỏ Left và Right của nút này đều là NULL (vì tại thời điểm đó

nó chưa có nút con nào)

Hàm tạo cây nhị phân tìm kiếm:

Node *CreateNode(KeyType x)

{

Node *p;

p=new Node;

if(p==NULL) Error(1);

Trang 5

else

{

(*p).key=x;

(*p).Left=NULL;

(*p).Right=NULL;

}

return p;

}

/* -*/

void InsertNode(KeyType x, BTree &Root)

{

if(Root==NULL) Root=CreateNode(x);

else

{

if(x<(*Root).key) InsertNode(x,(*Root).Left);

if(x>(*Root).key) InsertNode(x,(*Root).Right);

}

}

2 Thuật toán hiển thị cây nhị phân tìm kiếm:

Dùng hàm Copy tạo ra cây nhị phân T1 có dữ liệu giống T nhưng có thêm tọa

độ hiển thị của các node trên màn hình Ý tưởng ở đây là 2 node cách nhau k (đơn vị) Duyệt từ Trái-Gốc-Phải, qua mỗi lần thấy 1 node thì tăng cột(c) lên k (đơn vị), r = r +

k và r = r - k Mục đích là để tăng số dòng(r) khi ta xét một dòng mới và sau đó quay lui

void Copy(BTree1 &T1,BTree T,int &r,int &c,int k)

{

if(T!=NULL)

{

T1=new Node1;

(*T1).key=(*T).key;

r+=k;

Copy((*T1).Left,(*T).Left,r,c,k);

(*T1).column=c;

(*T1).row=r;

c+=k;

Copy((*T1).Right,(*T).Right,r,c,k);

r-=k;

}

else T1=NULL;

}

Dùng hàm Line để vẽ đường nối giữa các node

void Line(int column1,int row1,int column2,int row2,int k)

Trang 6

int n;

n=(column2-column1)/k;

for(int i=1;i<=k;i++)

{

gotoxy(column1+i*n,row1+i);

printf("*");

}

}

Duyệt theo Gốc-Trái-Phải Kiểm tra node con bên trái, nếu tồn tại thì vẽ đường dẫn đến node đó và in giá trị của node con trái đó Tương tự cho node con phải

void Display(BTree1 T,int k)

{

BTree1 p;

gotoxy((*T).column,(*T).row);

printf("%d",(*T).key);

if((*T).Left!=NULL)

{

p=(*T).Left;

Line((*T).column,(*T).row,(*p).column,(*p).row,k);

Display((*T).Left,k);

}

if((*T).Right!=NULL)

{

p=(*T).Right;

Line((*T).column,(*T).row,(*p).column,(*p).row,k);

Display((*T).Right,k);

}

}

/* -*/

void DisplayBTree(BTree T,int x,int y,int k)

{

BTree1 T1;

Copy(T1,T,x,y,k);

if(T!=NULL) Display(T1,k);

DestroyBTree1(T1);

}

3 Kiểm tra tính tương tự của 2 cây nhị phân tìm kiếm:

Dùng thuật toán đệ quy Phương thức kiểm tra: Xét từng cặp node ở cùng vị trí trên 2 cây NPTK, bắt đầu từ node gốc

Điều kiện dừng: đến khi cả 2 node đang xét có giá trị NULL Trong khi chưa thỏa điều

kiện dừng, nếu giá trị 2 node đang xét của 2 cây là khác nhau (tức (Root1=NULL và

Trang 7

Root2!=NULL) hoặc (Root1!=NULL và Root2=NULL)) thì thông báo KHÔNG,

ngược lại gọi đệ quy xét tiếp cho 2 nút trái và phải

char TuongTu(BTree Root1,BTree Root2)

{

int t;

if (!Empty(Root1)||!Empty(Root2))

{

if (Empty(Root1) ^ Empty(Root2)) t=0;

else if (!Empty(Root1) && !Empty(Root2))

{

if( (TuongTu((*Root1).Left,(*Root2).Left)) &&

(TuongTu((*Root1).Right,(*Root2).Right))) t=1;

else t=0;

}

}

else t=1;

return t;

}

VI CHƯƠNG TRÌNH:

1 Minh họa:

a Giao diện ban đầu:

b Hiển thị cây NPTK:

Trang 8

c Ví dụ 2 cây nhị phân tìm kiếm tương tự:

Trang 9

d Ví dụ 2 cây nhị phân tìm kiếm không tương tự:

2 Code hoàn chỉnh:

#include<stdio.h>

#include<conio.h>

#include<stdlib.h>

typedef int KeyType;

struct Node

{

KeyType key;

Node *Left;

Node *Right;

};

Trang 10

typedef Node *BTree;

struct Node1

{

KeyType key,column,row;

Node1 *Left,*Right;

};

typedef Node1 *BTree1;

/* -*/

void Error(int i)

{

switch(i)

{

case 1: printf("\n Khong du bo nho.");

break;

case 2: printf("\n Khong co chuc nang nay.Moi ban thu lai.");

break;

case 3: printf("\n Du lieu nhap ko dung");

break;

case 4: printf("\n So nay da duoc nhap.Moi ban chon so khac.");

break;

case 5: printf("\n Hai cay hien dang rong.Khong the thuc hien thao tac.");

break;

case 6: printf("\n Khong mo duoc file.Please try

again");

getch();

break;

}

printf("\n\t********\n");

}

/* -*/

void MakeNullBTree(BTree &Root)

{

Root=NULL;

}

/* -*/

char Empty(BTree Root)

{

return (Root==NULL);

}

/* -*/

Trang 11

Node *SearchNode(BTree Root,KeyType x)

{

if (Empty(Root)) return NULL;

else

{

if ((*Root).key==x) return Root;

if ((*Root).key<x) return SearchNode((*Root).Right,x); else return SearchNode((*Root).Left,x);

}

}

/* -*/

Node *CreateNode(KeyType x)

{

Node *p;

p=new Node;

if(p==NULL) Error(1);

else

{

(*p).key=x;

(*p).Left=NULL;

(*p).Right=NULL;

}

return p;

}

/* -*/

void InsertNode(KeyType x,BTree &Root)

{

if(Root==NULL) // Neu cay nay dang rong

{

Root=CreateNode(x);

}

else

{

if (x<(*Root).key) InsertNode(x,(*Root).Left);

if (x>(*Root).key) InsertNode(x,(*Root).Right);

}

}

/* -*/

void InputBTree(BTree &Root)

{

Node *p;

KeyType key;

int n,i;

Trang 12

printf("\n Ban muon nhap bao nhieu node:");

scanf("%d",&n);

for(i=1;i<=n;i++)

{

printf("\n Moi ban nhap 1 so nguyen cho node thu

%d :",i);

scanf("%d",&key);

p=SearchNode(Root,key);

if(p==NULL) InsertNode(key,Root);

else

{

Error(4);

i ;

}

}

}

/* -*/

void InputBTreeFromFile(BTree &Root,const char *ten)

{

int n;

KeyType key;

Node *p;

FILE *fp;

fp=fopen(ten,"rt");

if (fp==NULL)

{

Error(6);

exit(1);

}

else

{

fscanf(fp,"%d",&n);

for(int i=1;i<=n;i++)

{

fscanf(fp,"%d",&key);

p=SearchNode(Root,key);

if (p==NULL) InsertNode(key,Root);

else

{

Error(3);

Root=NULL;

break;

}

Trang 13

}

fclose(fp);

}

/* -*/

void PreOrder(BTree Root)

{

if(Root!=NULL)

{

printf("\n %d ",(*Root).key);

PreOrder((*Root).Left);

PreOrder((*Root).Right);

}

}

/* -*/

char TuongTu(BTree Root1,BTree Root2)

{

int t;

if (!Empty(Root1)||!Empty(Root2)) // co it nhat 1 nut ko rong thi co the goi de quy

{

if (Empty(Root1) ^ Empty(Root2)) t=0; // ko tuong tu tai nut dang xet

else if (!Empty(Root1) && !Empty(Root2)) // nut dang xet tuong tu nhau

{ //xet tiep 2 nhanh phai va trai

if( (TuongTu((*Root1).Left,

(*Root2).Left))&&(TuongTu((*Root1).Right,(*Root2).Right))) t=1;

else t=0; //co it nhat mot nhanh khac nhau

}

}

else t=1; // ca 2 nut deu rong

return t;

}

/* -*/

void OutputBTree(BTree Root,int i,int muc)

{

if(Root)

{

if(i==muc)

{

Trang 14

OutputBTree((*Root).Left,i+1,muc);

OutputBTree((*Root).Right,i++,muc);

}

}

/* -*/

void DestroyBTree(BTree &Root)

{

if(Root)

{

DestroyBTree((*Root).Left);

DestroyBTree((*Root).Right);

delete Root;

}

Root=NULL;

}

/* -*/

void DestroyBTree1(BTree1 &Root)

{

if(Root)

{

DestroyBTree1((*Root).Left);

DestroyBTree1((*Root).Right);

delete Root;

}

Root=NULL;

}

/* -*/

int Max(int a,int b)

{

if(a>b) return a;

else return b;

}

/* -*/

int IsLeaf(Node *p)

{

if((*p).Left==NULL && (*p).Right==NULL) return 1;

else return 0;

}

/* -*/

int HightBTree(BTree Root)

{

if((Root==NULL) || (IsLeaf(Root))) return 0;

Trang 15

else return (1 +

Max(HightBTree((*Root).Left),HightBTree((*Root).Right)));

}

/* -*/

/* Ham copy tao ra cay nhi phan T1 co du lieu giong T

nhung co them toa do tren man hinh cua moi node

Y tuong o day la 2 node co column cach nhau k(don vi),

Duyet tu trai-goc-phai, qua moi lan thay 1 phan tu

thi tang column(c) len k(don vi), r+=k va r-=k

Muc dich de tang so dong(r) khi ta xet mot lop moi va sau do quay lui */

void Copy(BTree1 &T1,BTree T,int &r,int &c,int k)

{

if(T!=NULL)

{

T1=new Node1;

(*T1).key=(*T).key;

r+=k;

Copy((*T1).Left,(*T).Left,r,c,k);

(*T1).column=c;

(*T1).row=r;

c+=k;

Copy((*T1).Right,(*T).Right,r,c,k);

r-=k;

}

else T1=NULL;

}

/* -*/

//ham Line dung de ve duong noi giua 2 diem

void Line(int column1,int row1,int column2,int row2,int k) {

int n;

n=(column2-column1)/k;

for(int i=1;i<=k;i++)

{

gotoxy(column1+i*n,row1+i);

printf("*");

}

}

/* -*/

/* Duyet theo goc-trai-phai Chuong trinh kiem tra node con ben trai,

Trang 16

neu ton tai thi ve duong dan den node do va in gia tri cua node con trai do*/

void Display(BTree1 T,int k)

{

BTree1 p;

gotoxy((*T).column,(*T).row);

printf("%d",(*T).key);

if((*T).Left!=NULL)

{

p=(*T).Left;

Line((*T).column,(*T).row,(*p).column,(*p).row,k);

Display((*T).Left,k);

}

if((*T).Right!=NULL)

{

p=(*T).Right;

Line((*T).column,(*T).row,(*p).column,(*p).row,k);

Display((*T).Right,k);

}

}

/* -*/

void DisplayBTree(BTree T,int x,int y,int k)

{

BTree1 T1;

Copy(T1,T,x,y,k);

if(T!=NULL) Display(T1,k);

DestroyBTree1(T1);

}

/* -*/

int Menu()

{

int Router;

printf("\n\n

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»");

º");

printf("\n

ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹");

Trang 17

printf("\n º 0 THOAT KHOI CHUONG TRINH

º ");

printf("\n

ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ");

º");

printf("\n

ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ");

THU TU TRUOC º");

printf("\n

ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ");

º");

printf("\n

ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ");

KHONG º");

printf("\n

ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ");

scanf("%d",&Router);

return Router;

}

/* -*/

void Printout(BTree Root1,BTree Root2) //in ra 2 cay

{

int k;

clrscr();

if ( HightBTree(Root1)+HightBTree(Root2) < 7 ) k=3; //tinh tong chieu cao de xac dinh k

else k=2;

printf("Cay thu nhat\n");

DisplayBTree(Root1,-1,30,k);

if (Root1==NULL) printf("\n Cay nay rong");

printf("\n\nCay thu hai\n");

DisplayBTree(Root2, HightBTree(Root1)*k + 2, 30,k);

if (Root2==NULL) printf("\n Cay nay rong !");

}

Trang 18

int main()

{

BTree Root1,Root2;

Node *p;

int Router,Key;

MakeNullBTree(Root1);

MakeNullBTree(Root2);

clrscr();

do

{

Router=Menu();

switch(Router)

{

t -");

printf("\n\

tÚÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔ¿");

printf("\n\t³ Ban muon nhap theo phuong phap

tÊÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔ´");

³");

printf("\n\t³

³") ;

³");

printf("\n\

tĂÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔÔỖ");

printf("\n\n\tNhap theo phuong phap : ");

scanf("%d",&Key);

printf("\

n -");

switch(Key) {

case 1: printf("\n Nhap cay thu nhat \n");

InputBTree(Root1);

printf("\n -");

printf("\n Nhap cay thu hai \n");

InputBTree(Root2);

printf("\n -");

break;

Ngày đăng: 10/04/2015, 16:32

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w