1. Trang chủ
  2. » Công Nghệ Thông Tin

Chương 6 Cấu trúc cây ( tree) pot

15 381 1
Tài liệu đã được kiểm tra trùng lặp

Đ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

Tiêu đề Cấu trúc cây
Trường học Đại Học Lạc Hồng
Thể loại Bài giảng
Năm xuất bản 2010
Thành phố Đồng Nai
Định dạng
Số trang 15
Dung lượng 4,54 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Cấu trúc cây TreeCấu trúc cây Tree Chương 6 Cây nhiều nhánh 4 Các khái niệm cơ bản 1 Cây nhị phân tìm kiếm 2 Cây nhị phân cân bằng 3 Nội dung  Có một bức thư cần chuyển đến địa chỉ “Ngu

Trang 1

Cấu trúc cây (Tree)

Cấu trúc cây (Tree)

Chương 6

Cây nhiều nhánh

4

Các khái niệm cơ bản

1

Cây nhị phân tìm kiếm

2

Cây nhị phân cân bằng

3

Nội dung

 Có một bức thư cần chuyển đến địa chỉ

“Nguyễn Văn A, 10 Huỳnh Văn Nghệ, Biên hoà, Đồng Nai, Việt nam”

 Trên thế giới hiện có khoảng 8 tỷ người

 Làm thế nào để tìm ra người A nhanh nhất?

 Dùng cấu trúc mảng ??

 Dùng danh sách liên kết ??

Các khái niệm cơ bản

Các khái niệm cơ bản

Các khái niệm cơ bản

Trang 2

3/11/2010 www.lhu.edu.vn

Các khái niệm cơ bản

Các khái niệm cơ bản

Nhiệt độ

Có Đau đầu

Bình thường

Đau đầu không

không Có không

có {e2} không{e5} {e3}có

không {e6}

 Một cây <T> (Tree) là:

 Một tập các phần tử, gọi là các nút (Node):

p1,p2,…,pN

 Nếu N=0, cây <T> gọi là cây rỗng (NULL)

 Nếu N>0:

• Tồn tại duy nhất 1 nút pk gọi là gốc của cây

• Các nút còn lại được chia thành m tập không giao nhau: T1,

T2, …, Tm

• Mỗi <Ti> là 1 cây con của cây <T>

Các khái niệm cơ bản

Các khái niệm cơ bản

Trang 3

3/11/2010 www.lhu.edu.vn

Nút (Node): là 1 phần tử trong cây Mỗi nút có

thể chứa 1 dữ liệu bất kỳ

Nhánh (Branch): là đoạn nối giữa 2 nút

Nút cha (Parent node)

Nút con (Child node)

Nút anh em (Sibling nodes): là những nút có

cùng nút cha

Các khái niệm cơ bản

Bậc của 1 nút pi: là số nút con của pi

Bậc (k) = 1; Bậc (c) = 0

Nút gốc (Root node): nút không có nút cha

Nút lá (Leaf node, hay nút ngoài – External

node): là nút có bậc = 0 (không có nút con)

Nút nội (Internal node): là nút có nút cha và có

nút con

Cây con (Subtree)

Các khái niệm cơ bản

Bậc của cây: là bậc lớn nhất của các nút trong

cây

 Bậc (<T>) = max {bậc (pi) / pi Î <T>}

 Bậc của cây <T> ?

Đường đi (Path) giữa nút pi đến nút pj: là dãy

các nút liên tiếp từ pi đến pj sao cho giữa hai nút

kề nhau đều có nhánh

 Path(a, d) ?

Các khái niệm cơ bản

Mức (Level):

 Mức (p) = 0 nếu p = root

 Mức (p) = 1 + Mức (Cha (p)) nếu p!=root

Chiều cao của cây (Height - hT): đường đi dài

nhất từ nút gốc đến nút lá

 hT = max {Path(root, pi) / pi là nút lá Î <T>}

Các khái niệm cơ bản

Trang 4

3/11/2010 www.lhu.edu.vn

Các khái niệm cơ bản

Các khái niệm cơ bản

Cây đầy đủ (Full tree): là 1 cây thoả

• Tất cả các nút lá đều nằm trên cùng 1 mức

• Tất cả những nút khác có cùng bậc với cây

• Mức h của cây đầy đủ bậc d có dh nút

VD mức h=2 của cây bậc 3 có bao nhiêu nút ?

• h mức đầu tiên của cây đầy đủ bậc d có số nút là:

1 + d + d 2 + d 3 + … + d h-1 = (d h - 1)/(d – 1)

3 mức đầu tiên của cây đầy đủ bậc 3 có bao nhiêu nút ?

Các khái niệm cơ bản

Cây hoàn chỉnh (Complete tree) với h mức:

là 1 cây thoả các điều kiện

trái sang phải

Cây nhị phân là cây có bậc = 2

Độ cao của cây nhị phân có N nút:

• hT(max) = N

• hT(min) = [logN] + 1

Trang 5

3/11/2010 www.lhu.edu.vn

Cấu trúc lưu trữ dùng mảng

Định nghĩa các cấu trúc dữ liệu

typedef struct NODE

{

int Data;

int Left; // ch ỉ s nút con trái

int Right; // ch ỉ s nút con ph ả

} NODETYPE; // c ấ u trúc 1 node

// cây nh ị phân có N nút

NODETYPE tree[N];

Cấu trúc lưu trữ dùng con trỏ Định nghĩa các cấu trúc dữ liệu

typedef struct NODE { int Data;

NODE *pLeft; // con tr ỏ đế n nút con trái NODE *pRight; // con tr ỏ đế n nút con ph ả } NODETYPE; // binary tree node

typedef struct BIN_TREE { int Count; // S ố nút trong cây NODETYPE *pRoot; // con tr ỏ đế n nút g ố }; // binary tree

Cấu trúc lưu trữ dùng con trỏ

Có 3 cách duyệt cây:

Trang 6

3/11/2010 www.lhu.edu.vn

Duyệt gốc trước (Pre-Order) NLR

void NLR(const NODETYPE *pCurr)

{

if (pCurr==NULL) return;

“ ử lý nút g ố c pCurr ”

NLR(pCurr->pLeft);

NLR(pCurr->pRight);

}

Duyệt gốc giữa (In-Order) LNR

void LNR(const NODETYPE *pCurr) {

if (pCurr==NULL) return;

LNR(pCurr->pLeft);

“ ử lý nút g ố c pCurr ”

LNR(pCurr->pRight);

}

Duyệt gốc sau (Post-Order) LRN

void LRN(const NODETYPE *pCurr)

{

if (pCurr==NULL) return;

LRN(pCurr->pLeft);

LRN(pCurr->pRight);

“ ử lý nút g ố c pCurr ”

}

Cây nhị phân tìm kiếm là:

 Tất cả các nút thuộc cây con trái (p->pLeft) đều có giá trị nhỏ hơn giá trị của p:

q  p->pLeft: q->Data < p->Data

 Tất cả các nút thuộc cây con phải (p->pRight) đều

có giá trị lớn hơn giá trị của p :

q  p->pRight: q->Data > p->Data

Trang 7

3/11/2010 www.lhu.edu.vn

Khởi tạo cây rỗng

void BSTCreate(BIN_TREE &t) {

t.Count = 0; // S ố nút trong cây t.pRoot = NULL; // Con tr ỏ đế n nút g ố

}

Kiểm tra cây rỗng

int BSTIsEmpty(const BIN_TREE &t) {

if (t.pRoot==NULL) return 1;

return 0;

}

Tìm kiếm một phần tử

NODETYPE *BSTSearch(const NODETYPE *pCurr, int Key)

{

if (pCurr==NULL) return NULL; // Không tìm th ấ

if (pCurr->Data==Key) return pCurr; // Tìm th ấ

else if (pCurr->Data > Key) // Tìm trên cây con trái

return BSTSearch(pCurr->pLeft, Key);

else // Tìm trong cây con ph ả

return BSTSearch(pCurr->pRight, Key);

}

Trang 8

3/11/2010 www.lhu.edu.vn

Xoá một phần tử

 Áp dụng giải thuật tìm kiếm để xác định nút chứa phần tử cần xóa

 Nếu tìm thấy, xóa phần tử đó khỏi cây

 Xóa 1 nút không có nút con

 Xóa 1 nút có 1 nút con

 Xóa 1 nút có 2 nút con

Xoá một nút không có nút con

Xoá một nút có một nút con

Trang 9

3/11/2010 www.lhu.edu.vn

Xoá một nút có một nút con

Xoá một nút có hai nút con

Xoá một nút có hai nút con

Thao tác

tử thay thế p,

hoặc

Trang 10

3/11/2010 www.lhu.edu.vn

int BSTDelete(NODETYPE *&pCurr, int Key)

{

if (pCurr==NULL) return 0; // Không tìm th ấ

if (pCurr->Data > Key) // Xóa trên cây con trái

return BSTDelete(pCurr->pLeft, Key);

else if (pCurr->Data < Key) //Xóa trên cây ph ả

return BSTDelete(pCurr->pRight, Key);

// Tìm th ấ y nút c ầ n xóa pCurr  Xóa !

_Delete(pCurr);

return 1;

}

void _Delete(NODETYPE *&pCurr) {

NODETYPE *pTemp = pCurr;

if (pCurr->pRight==NULL) //có 1 nút con trái pCurr = pCurr->pLeft; // Lưu lạ i nhánh con trái else if (pCurr->pLeft==NULL)

pCurr = pCurr->pRight; // Lưu lạ i nhánh ph ả

else // Có 2 nhánh con pTemp = _SearchStandFor(pCurr->pLeft, pCurr); delete pTemp;

}

// Tìm ph ầ n t ử thay th ế “ Ph ầ n t ử l n nh ấ t trong cây

//con bên trái ”

NODETYPE * _SearchStandFor(NODETYPE *&p, NODETYPE *pCurr)

{

if (p->pRight != NULL)

return _SearchStandFor(p->pRight, pCurr);

// Tìm th ấ y ph ầ n t ử thay th ế…

pCurr->Data = p->Data; // Copy d ữ li ệ

NODETYPE *pTemp = p;

p = p ->pLeft; // Lưu lạ i nhánh con trái

return pTemp; // Xóa ph ầ n t ử thay th ế

}

nó có chiều cao thấp nhất (cây đạt trạng thái cân

 Tuy nhiên khi thực hiện các thao tác thêm hoặc xoá các nút sẽ làm cho cây mất trạng thái cân

tìm kiếm giảm

đa thì phải giữ cho cây luôn trong trạng thái cân

Trang 11

3/11/2010 www.lhu.edu.vn

C:\MyData\Downloads\books\GiaoTrinh\CauTrucDuLieu1\Htm\images\hinh13.2.gif

20

5

30 10

15 13

5

30

20

15 10

30

5 10

20 15

Cây mất cân bằng

Cây bị suy biến

AVL), được các tác giả người Nga

Adelson-Velskii và Landis đưa ra năm 1962

mà tại mỗi nút của nó chiều cao của cây con trái

và cây con phải lệch nhau không quá 1 đơn vị

trên cây

Ta định nghĩa các hằng số chỉ trạng thái cân bằng của nút //Cây con trái cao hơn

#define LH -1 //Hai cây con bằng nhau

#define EH -0 //Cây con phải cao hơn

#define RH 1

Trang 12

3/11/2010 www.lhu.edu.vn

typedef struct Node

{

int Key;//Du lieu trong nut

struct Node *pLeft;//Con tro den cay con trai

struct Node *pRight;//Con tro den cay con phai

char Balance;//Trang thai can bang

int Count;//So nut trong cac cay con

}AVL_Node;

typedef AVL_Node *AVLTree;

Cân bằng lại cây

• Nút P bị mất cân bằng về bên trái

• Nhánh con trái P1 của P bị lệch trái

void RotateRight(AVLTree &P) //Xoay nút P sang bên ph ả

{

if(P!=NULL)

{

AVL_Node *P1;

P1 = P->pLeft; //Q la con trai' cua P

P->pLeft = P1->pRight; //Lien ket pLeft cua P tro

//toi con phai cua P1 P1->pRight = P;//Lien ket pRight cua Q tro toi P

P = P1; //ghi nhan dia chi moi cua P

}

}

Xoay đơn sang phải

Cân bằng lại cây

• Nút P bị mất cân bằng về bên trái

• Nhánh con trái P1 của P bị lệch phải

Trang 13

3/11/2010 www.lhu.edu.vn

void DLRR(AVLTree &p)

{

if(p!=NULL)

{

AVL_Node *p1;

p1 = p->pLeft;

RotateLeft(p1);

p->pLeft = p1;

RotateRight(p);

}

}

Xoay kép Left-Right

Cân bằng lại cây

• Nút P bị mất cân bằng về bên phải

• Nhánh con trái P1 của P bị lệch phải

P

P 1

C

h + 1 RL

Áp dụng xoay đơn phải – trái (Right-Left)

void RotateLeft(AVLTree &P) //Xoay nut P sang ben trai

{

if(P!=NULL)

{

AVL_Node *P1;

P1 =P->pRight; //q tro vao con trai' cua p

P->pRight = P1->pLeft; //lien ket Right cua p tro

//toi con trai' cua q P1>pLeft = P; //lien ket Left cua Q tro toi P

-//dua P xuong ben trai

P = P1; //xac nhan lai dia chi moi cua P

}

Xoay đơn sang trái

Cân bằng lại cây

• Nút P bị mất cân bằng về bên phải

• Nhánh con trái P1 của P bị lệch trái

P2 P1 P

P P1 P2 A

D

h

h 1

Trang 14

3/11/2010 www.lhu.edu.vn

void DRLR(AVLTree &p)

{

if(p!=NULL)

{

AVL_Node *p1;

P1 = p->pRight;

RotateRight(p1);

p->pRight = p1;

RotateLeft(p);

}

}

Xoay kép Right-Left

Thêm phần tử mới vào cây

Việc thêm một phần tử vào cây AVL diễn ra tương tự như trên CNPTK Tuy nhiên, sau khi thêm xong, nếu chiều cao của cây thay đổi, từ

vị trí thêm vào, ta phải lần ngược lên gốc để kiểm tra xem có nút nào bị mất cân bằng không Nếu có, ta phải cân bằng lại ở nút này

int insertNode(AVLTree &T, DataType X)

{ int res;

if(T) {

if(T->key == X) return 0; // đ ã có

if(T->key > X)

{

res = insertNode(T->pLeft, X);

if(res < 2) return res;

switch(T->Balance)

{

case RH: T->Balance = EH;

return 1;

case EH: T->Balance = LH;

return 2;

case LH: balanceLeft (T);

return 1;

}

}

else { res = insertNode(T-> pRight, X);

if(res < 2) return res;

switch(T->Balance) {

case LH: T->Balance = EH;

return 1;

case EH: T->Balance = RH;

return 2;

case RH: balanceRight(T); return 1;

} } }

T = new AVL_Node;

if(T == NULL) return -1; //thi ế u b ộ nh ớ T->key = X; T->Balance = EH;

T->pLeft = T->pRight = NULL;

return 2; // thành công, chi ều cao tăng

Huỷ phần tử trên cây

Cũng giống như thao tác thêm một nút, việc hủy một phần tử X ra khỏi cây AVL thực hiện giống như trên CNPTK

Chỉ sau khi hủy, ta phải lần ngược lên gốc để kiểm tra xem có nút nào bị mất cân bằng không, nếu có ta sẽ thực hiện việc cân bằng lại

Trang 15

3/11/2010 www.lhu.edu.vn

int delNode(AVLTree &T, DataType X)

{ int res;

if(T==NULL) return 0;

if(T->key > X) {

res = delNode (T->pLeft, X);

if(res < 2) return res;

switch(T->Balance) {

case LH: T->Balance = EH;

return 2;

case EH: T->Balance = RH;

return 1;

case RH: return balanceRight(T);

}

if(T->key < X) {

res = delNode (T->pRight, X);

if(res < 2) return res;

switch(T->Balance) {

case RH: T->Balance = EH;

return 2;

case EH: T->Balance = LH;

return 1;

case LH: return balanceLeft(T);

}

}else { //T->key == X

AVLNode* p = T;

if(T->pLeft == NULL) {

T = T->pRight; res = 2;

}else if(T->pRight == NULL) {

T = T->pLeft; res = 2;

}else { //T có c ả 2 con

res=searchStandFor(p,T->pRight);

if(res < 2) return res;

switch(T->Balance) { case RH: T->Balance = EH;

return 2;

case EH: T->Balance = LH;

return 1;

case LH: return balanceLeft(T);

} delete p;

return res;

}

//Tìm ph ầ n t ử th ế m ng

int searchStandFor(AVLTree &p, AVLTree &q)

if(q->pLeft) { res = searchStandFor(p, q->pLeft);

if(res < 2) return res;

switch(q->Balance) { case LH: q->Balance = EH;return 2;

case EH: q->Balance = RH;return 1;

case RH: return balanceRight(T);

} }else { p->key = q->key;

p = q;

q = q->pRight;

return 2;

} }

void BalanceRight(Tree &P)

{

AVL_Node *Q, *R;

Q = P->pRight; //q tro vao cay con

phai

switch(Q->Balance)

{

case 1: //Single Rotation

P->Balance = 0;

RotateLeft(P);

break;

case -1:

//cay lech trai >Double Rotation

R = Q->pLeft;

switch(R->Balance) { case 0:

P->Balance = 0;

Q->Balance = 0;

break;

case -1:

P->Balance = 0;

Q->Balance = 1;

break;

case 1:

P->Balance = -1;

Q->Balance = 0;

break;

} R->Balance = 0;

/*Double Right-Left Rotation*/

DRLR(P);

break;

Cân bằng lại cây con bên phải của node P trong trường hợp P lệch phải

void BalanceLeft(Tree &P) {

AVL_Node *Q, *R;

Q = P->pLeft; //q tro vao cay con trai

switch(Q->Balance) {

case -1: //Single Rotation P->Balance = 0;

RotateRight(P);

break;

case 1: //Double Rotation

R = Q->pRight;

switch(R->Balance) { case 0:

P->Balance = 0;

Q->Balance = 0;

break;

case -1:

P->Balance = -1;

Q->Balance = 0;

break;

case 1:

P->Balance = 0;

Q->Balance = -1;

break;

} R->Balance = 0;

/*Double pLeft-pRight Rotation*/ DLRR(P);

break;

Cân bằng lại cây con bên trái của node P trong trường hợp P lệch trái

Ngày đăng: 24/03/2014, 02:21

TỪ KHÓA LIÊN QUAN

w