hoa cuong có thì sử dụng – thích thì lao vào

70 5 0
hoa cuong có thì sử dụng – thích thì lao vào

Đ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

Sinh viên cài đặt như bài tập.. CÂY CÂN BẰNG AVL.[r]

(1)(2)

2

Cây

• Định nghĩa:

• Rỡng là

• T1 , T2 , ……Tm là thi

là (m-phân)

• T1 , T2 , ……Tm gọi là của T T

Tm T2

(3)

• Ví dụ

– Cây thư mục hệ điều hành – Cây gia phả của dòng họ

– Cây biểu thức: a-b+c*d/e

+

- /

(4)

4

Mợt sớ khái niệm

• R là cha của U, O, P • U, O, P là của R

• Q, R là đỉnh trước của A • A là đỉnh sau của Q, R

• T, Y, U, O, A là các nút lá (khơng có con) • Q là nút gớc

Q

E R

w

Y

T U O P

A

mức

mức

mức

(5)

Phép duyệt

• Phép duyệt: Đưa tất cả các nút theo mợt thứ tự nào đó, mỡi nút lần

– Ví dụ: Tim kiếm một file hay mợt folder thư mục

• Phổ biến:

– Duyệt theo bề sâu (Depth First Search - DFS) – Duyệt theo bề rộng (Breadth First Search -

(6)

6

Cây nhị phân (Binary tree)

• Là bao gờm các nút, mỡi nút có tới đa con:

– Cây bên trái (Left) – Cây bên phải (Right) • Mô tả cấu trúc:

typedef struct nodet { elem data;

struct nodet *left, *right; } node;

(7)

Duyệt theo bề sâu (DFS)

• Duyệt tiền tự (Preorder Search – NLR)

– Thăm nút gốc (Node)

– Duyệt bên trái (Left)

– Duyệt bên phải (Right)

• Duyệt trung tự (Inorder Search – LNR) (tương tự)

(8)

8

Duyệt theo bề sâu (DFS)

• NLR: QWTYRUPA • LNR: TWYQURAP • LRN: TYWUAPRQ

Q

R w

Y

T U P

(9)

Ví dụ: Đếm số nút cây

int sonut(tree t) {

if (t==NULL) return 0;

(10)

10

Độ cao cây?

int h(tree t) {

if (t==NULL) return 0;

return + max(h(t->left), h(t->right)); }

(11)

Nhập số nguyên>0

void nhap(tree &t) {

int x; cin>>x; if (x>0) {

t = new node; t->data = x; nhap(t->left); nhap(t->right); }

else

t = NULL;

• Với dữ liệu nhập:

7 0 0 0 0

7

6

5

4

(12)

12

In (số nguyên)

void incay(tree t, int m=1) {

if (t!=NULL) {

incay(t->left, m+1);

cout<<endl<<setw(4*m)<<t->data; incay(t->right, m+1);

(13)

Xóa toàn bộ cây

void xoacay(tree &t) {

if (t!=NULL) {

xoacay(t->left); xoacay(t->right); delete t;

(14)

14

Đếm số nút lá cây

int sonutla(tree t) {

if (t==NULL) return 0;

if (t->left==NULL && t->right==NULL) return 1;

(15)

Đếm số nút có cây

int sonut1(tree t) {

if (t==NULL) return 0;

if ((t->left!=NULL) &&( t->right==NULL)) return 1+sonut1(t->left);

if ((t->left==NULL) &&( t->right!=NULL)) return 1+sonut1(t->right);

(16)

16

Đếm số nút có cây

int sonut1(tree t) {

if (t==NULL) return 0;

if ((t->left!=NULL && t->right==NULL)|| (t->left==NULL && t->right!=NULL)) return 1+sonut1(t->left) +sonut1(t->right); return sonut1(t->left)+sonut1(t->right);

(17)

Đếm số nút có cây

int sonut1(tree t) {

if (t==NULL) return 0;

if ((t->left==NULL) ^( t->right==NULL))

return 1+sonut1(t->left)+sonut1(t->right); return sonut1(t->left)+sonut1(t->right);

(18)

18

Đếm số nút (không phải là lá)

int sonuttrg(tree t) {

if (t==NULL) return 0;

if (t->left==NULL && t->right==NULL) return 0;

(19)

Tính trung binh cộng

void NLR(tree t, int &sn, int &tg) {

if (t!=NULL) {

tg+=t->data; sn++;

NLR(t->left, sn, tg); NLR(t->right, sn, tg); }

}

float tbc(tree t) {

int sn, tg; sn = tg = 0;

NLR(t, sn, tg);

(20)

20

Bài tập

• Đếm sớ nút mức thứ k • Đếm sớ nút mức >= k • Đếm sớ nút mức <= k

(21)

Đếm số nút mức lẻ của cây

int muccl(tree t, int m=1) {

if (t==NULL) return 0;

return m%2 +muccl(t->left, m+1) +

muccl(t->right, m+1); }

Gọi hàm:

cout<<“Số nút mức lẻ =“<<muccl(t);

(22)

22

Đếm số nút mức thứ k

int nutk(tree t, int k) {

if (t==NULL) return 0; if (k>1)

return nutk(t->left,k-1)+nutk(t->right, k-1); return 1;

(23)

void nlr(tree t, int k, int &sn, int &tg) { if (t!=NULL) { if (k>1) {

nlr(t->left, k-1, sn, tg); nlr(t->right, k-1, sn, tg); } else { sn++; tg +=t->data); } } }

float tbc(tree t, int k) {

int sn, tg; sn = tg = 0;

nlr(t, k, sn, tg);

(24)

24

void nlr(tree t, int k, int &sn, int &tg) { if (t!=NULL) { sn++; tg +=t->data); if (k>1) {

nlr(t->left, k-1, sn, tg); nlr(t->right, k-1, sn, tg); }

} }

float tbc(tree t, int k) {

int sn, tg; sn = tg = 0;

nlr(t, k, sn, tg);

if (sn == 0) return 0.;

(25)

void nlr(tree t, int k, int &sn, int &tg) { if (t!=NULL) { if (k<=1) { sn++; tg +=t->data); }

nlr(t->left, k-1, sn, tg);

nlr(t->right, k-1, sn, tg);

} }

float tbc(tree t, int k) {

int sn, tg; sn = tg = 0;

nlr(t, k, sn, tg);

if (sn == 0) return 0.;

(26)

26

Dụt theo bề rợng (BFS)

• Hay còn gọi là duyệt theo mức • Sử dụng hàng đợi: Tuần tự từ mức thấp đến cao, từ trái qua phải

• Với ta có thứ tự các nút được duyệt lần lượt:

Q W R T Y U P A SV cài đặt bài tập

Q

R w

Y

T U P

(27)

1 Khởi tạo hàng đợi q rỗng 2 M=0; p=NULL;

3 Nếu t!=NULLĐưa p vào q

Đưa t vào q

4 Khi q!=rỗng

Lấy p khỏi q

Nếu p==NULLNếu q!=rỗng

M = M+1;

Đưa p vào q

//Xử lý

Ngược lại

Xử lý p->data

(28)

28

Cây tim kiếm nhị phân

(Binary Search Tree – BST)

• Ý nghĩa: Phục vụ tim kiếm nhị phân cấu trúc đợng

• Định nghĩa: Là nhị phân thỏa điều kiện mọi nút đều có khóa

(29)

BST

7

11

5

1 15

(30)

30

Chèn phần tử vào BST

• Thêm 12

20

10

15

30

25 40

35 12<

12>

12<

12

(31)

Chèn phần tử vào BST

void inserttree(tree &t, elem x) {

if (t==NULL) {

t = new node; t->data = x;

(32)

32

Nhập (số nguyên >0)

t = NULL; do {

cin>>x; if (x>0)

(33)

Xóa phần tử BST

• Xóa 15

20

10

15

30

25 40

35 15<

15>

15=

(34)

34 • Xóa 20

20

10

15

30

25 40

(35)

void deletetree(tree &t, elem x) { if (t!=NULL) if (x<t->data) deletetree(t->left, x); else if (x>t->data) deletetree(t->right, x); else {

tree q = t;

if (t->right==NULL) t = t->left;

else

if (t->left==NULL) t = t->right; else

(36)

36 Tim phần tử thay (phần tử lớn nhất)

void del(tree &r, tree &q) {

if (r->right!=NULL) del(r->right, q);

else {

q->data = r->data; q = r;

(37)

Tim kiếm phần tử BST

(38)

38

Tim kiếm phần tử x

tree searchtree(tree t, elem x) {

if (t==NULL)

return NULL; if (x<t->data)

return searchtree(t->left, x); if (x>t->data)

return searchtree (t->right, x); return t;

(39)

Cắt có gớc x

tree cuttree(tree &t, elem x) {

if (t==NULL) return NULL; if (x<t->data)

return cuttree (t->left, x); if (x>t->data)

return cuttree (t->right, x); {

(40)

40

void ink(tree t, int &k) {

if (t!=NULL) {

if (k>0)

ink(t->right, k); if (k>0)

{

cout<<setw(4)<<t->data; k ;

}

if (k>0)

ink(t->left, k); }

(41)(42)

42 • Đưa vào cây:1, 2, 3, …, n

1

2

3

(43)

Định nghĩa

(44)

44

Định nghĩa

(45)

Biểu diễn cây

(46)

46

Tổ chức cấu trúc dữ liệu

• Tương tự BST, nhiên mỡi node cần bổ sung một vùng bal (balance), ghi nhận trạng thái cân bằng tại node đó:

(47)

Mô tả cấu trúc dữ liệu

typedef struct nodet { elem data;

struct nodet *left, *right; int bal;

} node;

(48)

48

Trạng thái cân bằng tại node

• Tại p có trường hợp:

p->bal = p->bal = p->bal = -1

(49)

a) Trường hợp p->bal = 1

• Thêm vào làm cho hR tăng

hoặc xóa làm cho hL giảm

Đặt p1 = p->right phép quay:

p->right=p1->left p1->left =p

p

p1 p

(50)

50

a1) Trường hợp p1->bal = 1

• Thêm vào làm cho hR tăng

hoặc xóa làm cho hL giảm

phép quay đơn: p->right=p1->left p1->left =p

p->bal =0 p1->bal=0 p = p1

p

p1 p

(51)

a2) Trường hợp p1->bal = 0

• Chỉ xảy xóa làm cho hL giảm

phép quay đơn:

p->right=p1->left p1->left =p

p->bal =1 p1->bal=-1

p

p1 p

(52)

52

a3) Trường hợp p1->bal = -1

• Khơng sử dụng phép quay đơn được vi sẽ cân bằng

phép quay đơn:

p->right=p1->left p1->left =p

p1 p

p

(53)

a3) Trường hợp p1->bal = -1

• Đặt p2 = p1->left

Sử dụng phép quay kép

p->right=p2->left p2->left=p

p1->left=p2->right p2->right=p1

p->bal=(p2->bal==1? -1: 0) p1->bal=(p2->bal==-1? 1: 0)

p

p1

p2

p2

(54)

54

b) Trường hợp p->bal = -1

• Trường hợp này đới xứng với trường hợp a), chính vi ta cần thay

– left thành right và ngược lại

(55)

Chèn phần tử vào AVL

• Tương tự BST, nhiên sau

chèn sẽ tăng độ cao, sử dụng biến h để ghi nhận có tăng đợ cao hay

(56)

56

Ví dụ minh họa

• Thêm lần lượt 3, và

3

5 7

3

5

0

5

7

Thêm

Mất cân bằng tại

Sử dụng quay đơn …và cân bằng

7

3

5

(57)

Ví dụ minh họa

Thêm 12, 10

5

7

12

10

Thêm 10

5

7

12 -1

10

(58)

58

Ví dụ minh họa

• Thêm 11

5

10 0/1

12 0/-1

7 11 -1 10 12

0 11

(59)

• Thêm 8, ?

-1

5

0 10

12

7

0 11

(60)

60

void insertAVL(AVLtree &p, elem x, int &h) {

if (p==NULL) {

p = new node; p->data = x;

p->left = p->right = NULL; p->bal=0; h=1; //true } else if (x<p->data) {

insertAVL(p->left, x, h);

if (h) Xem lại cân bằng trái tại p;

} else

if (x>p->data) {

insertAVL(p->right, x, h); if (h) Xem lại cân bằng

phải tại p;

} else

(61)

Xem lại cân bằng trái

switch (p->bal) {

case 1: p->bal = 0; h = 0; break; case 0: p->bal = -1; break;

case -1:

{ AVLtree p1 = p->left; if (p1->bal ==-1)

{

p->left = p1->right; p1->right = p;

p->bal = 0;

p = p1; //p->bal =0; h=0 }

else {

AVLtree p2 = p1->right; p->left = p2->right;

p2->right = p;

p1->right = p2->left; p2->left = p1;

p->bal = (p2->bal==-1?1:0); p1->bal = (p2->bal==1?-1:0); p = p2; //p->bal =0; h=0

}

p->bal = 0; h = 0;

(62)

62

Xem lại cân bằng phải

• Trường hợp này đối xứng với trường hợp xem lại cân bằng trái, chính vi ta cần thay

– left thành right và ngược lại

– thành -1 và ngược lại

(63)

Xóa phần tử Xóa 35 0 10 12

0 11

1 20 25 -1 30 23 35 27 0

0

-1

(64)

64

5

0 10

12

7

0 11

1

20

23

1 25

30

27

0

0

-1

(65)

Xóa phần tử Xóa 35 0 -1 10 12

0 11

1 20 25 -1 30 23 35 -1

0

-1

(66)

66 • Mất cân bằng tại 20

20

23

1 25

30

-1

5

-1 10

12

7

0 11

1

0

(67)

0 10

20

12

-1

0

5

7

0

0

23

0 25

30

(68)

68

Xóa phần tử AVL

void deleteAVL(AVLtree &p, elem x, int &h) {

if (p==NULL) h = 0; else

if (x<p->data) {

deleteAVL(p->left, x, h);

if (h) Xem lại thê cân bằng trái tại p

} else

if (x>p->data) {

deleteAVL(p->right, x, h); if (h)

Xem lại thê cân bằng phải tại p

}

else {

AVLtree q = p;

if (p->right==NULL) {

p = p->left; h = 1;

} else

if (p->left==NULL) {

p = p->right; h = 1;

} else {

del(p->left, q, h); if (h)

Xem lại thê cân bằng trái tại p

} delete q; }

(69)

Tim phần tử thay thế

void del(AVLtree &r, AVLtree &q, int &h) {

if (r->right!=NULL) {

del(r->right, q, h);

if (h) Xem lại thê cân bằng phải tại r

} else {

q->data = r->data; q = r;

r = r->left; h = 1;

(70)

70

Kiểm tra 10% (đến 11g30)

• Minh họa quá trinh hinh thành AVL thêm lần lượt các giá trị sau vào (chỉ rõ phép quay- có):

Ngày đăng: 20/04/2021, 01:36

Tài liệu cùng người dùng

Tài liệu liên quan