1. Trang chủ
  2. » Giáo án - Bài giảng

Danh sách Cây nhị phân

97 537 0

Đ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 97
Dung lượng 369,11 KB

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

Nội dung

Tài liệu rất hay và dễ hiểu về Danh sách Cây nhị phân

Trang 1

Bai 3

DANH SÁCH

Trang 2

Ôn kiểu dữ liệu struct

đối t−ợng có nhiều thành phần Các thành phần có thể thuộc các kiểu dữ liệu khác nhau.

• Đ Định ịnh ịnh ngh ngh nghĩĩĩĩaaaa ki ki kiểểểểuuuu hocvien hocvien hocvien ::::

Trang 3

Kiểu dữ liệu struct (tt)

• Khai báo kết hợp với định nghĩa kiểu :

Trang 4

Ví dụ về kiểu dữ liệu struct

10 } ;

11 struct hocvien hv;

Trang 5

Truy xuất thành biến kiểu struct

• Truy xuÊt thµnh phÇn cña biÕn struct

BiÕn.thµnhphÇn[.thanhphan]*

Truy xuÊt tíi hä cña häc viªn hv : hv.ho

Truy xuÊt tíi th¸ng sinh cña häc viªn hv:

hv.ngsinh.thang

hv.ngsinh.thang

Trang 7

Con trỏ và biến struct

Khai báo con trỏ và mảng struct

• struct hocvien hv, *p, ds[100];

p trỏ dến địa chỉ biến hv : p = &hv;

Truy nhập đến thành phần của biến struct bằng con trỏ Cách 1 : p->thanhphan

ví dụ : p->ho

Cách 2 : (*p).thanhphan

ví dụ : (*p).ho

Trang 8

Ví dụ về mảng và con trỏ struct

1 #define MAX_SOSV 100 // số sinh viên tối đa trong danh sách

2 typedef struct sinhvien // định nghĩa kiểu sinhvien

Trang 9

VÝ dô vÒ m¶ng vµ con trá struct

Trang 10

VÝ dô vÒ m¶ng vµ con trá struct

1 int Timkiem(struct danhsach_sv *psv, char maso[])

Trang 11

VÝ dô vÒ m¶ng vµ con trá struct

11 printf("Ho ten cua sinh vien la %s",ds.sv[vitri].hoten);

12 else printf(" Khong co sinh vien voi ma ban nhap vao");

13 getch();

14.}

Trang 12

Danh sỏch tuyến tớnh

• Định nghĩa

Danh sách tuyến tính là 1 dãy các phần tử có cùng

kiểu dữ liệu được sắp xếp liên tiếp nhau trong bộ nhớ.

- Kích thước của danh sách sẽ được cấp phát theo khai báo.

- Các phần tử của danh sách nằm liên tục nhau trong bộ nhớ, giữa các phần tử này không có khoảng trống.

- Tiêu biểu cho danh sách đặc là dãy (array) Để cài đặt danh sách tuyến tính, ta dùng mảng 1 chiều.

Trang 13

Định nghĩa và khai báo danh sách

1 #define MAXLIST 100

2 typedef struct list

5 };

6 struct list ds; // biÕn ds thuéc kiÓu struct list

Trang 14

Phộp toỏn trờn danh sỏch

Phép

Phép to to toáááánnnn Empty Empty Empty: kiểm tra xem danh sách có rỗng hay không?

1 int Empty(struct list plist)

2 {

3 return (plist.n==0 ? TRUE : FALSE);

4 }

Phép

Phép to to toáááánnnn Full Full Full: kiểm tra xem danh sách đã đầy ch−a?

1 int Full(struct list plist)

2 {

3 return (plist.n==MAXLIST ? TRUE : FALSE);

4 }

Trang 16

Phộp toỏn trờn danh sỏch

Phép

Phép th th thêêêêm m m vvvvààààoooo : Thêm một phần tử có nội dung

là info vào vị trí thứ i của danh sách

• Nếu i ==0 : thêm phần tử vào đầu danh sách

• Nếu i ==ds.n+1 : thêm phần tử vào cuối danh

sách.

L

L−−−−u ý u ý u ý: : : :

• Khi thêm một phần tử vào danh sách, ta phải

kiểm tra xem danh sách đã đầy hay ch−a?

Trang 17

Thêm phần tử vào danh sách

1 void Insert_item(struct list &plist, int i, int info)

Trang 18

Loại bỏ phần tử i khỏi danh sách

1 void Delete_item (struct list &plist, int i)

Trang 20

Tìm kiếm phần tử trong danh sách

s¸ch plist NÕu kh«ng cã x trong plist th× hµm

Trang 21

Khái niệm danh sách liên kết

• Cấu trúc danh sách liên kết là cấu trúc động, việc cấp phát và giải phóng nút động trên danh sách xảy ra khi chương trình đang chạy

Trang 22

Khái niệm về DSLK (tt)

• First là con trỏ chỉ đến phần tử đầu của danh sách liên kết

• Phần tử cuối của danh sách liên kết với vùng liên kết có giá trị NULL

• Mỗi nút của danh sách có trường info chứa nội dung của nút và trường next là con trỏ chỉ đến nút kế tiếp trong danh sách

Nil

Trang 23

Ưu nhược điểm của DSLK

Ư

Ưu u u đđđđiiiiểểểểm : m :

Danh sách liên kết rất thích hợp khi thực hiện các phép toán trên danh sách thường bị biến động

Trong trường hợp xóa hay thêm phần tử trong danh sách liên kết thì ta

không dời các phần tử đi như trong mảng mà chỉ việc hiệu chỉnh lại trường next tại các nút đang thao tác

Thời gian thực hiện các phép toán thêm vào và loại bỏ không phụ thuộc vào

số phần tử của danh sách liên kết

Trang 24

§ Þnh nghÜa vµ khai b¸o danh s¸ch

§Þnh nghÜa nót cña danh s¸ch

Khai b¸o biÕn First qu¶n lý d¸nh s¸ch

NODEPTR First;

Khëi t¹o danh s¸ch liªn kÕt :

First = NULL;

Trang 25

§ Þnh nghÜa vµ khai b¸o danh s¸ch (2)

kiÓu d÷ liÖu kh¸c nhau.

6 typedef struct node *NODEPTR

s¸ch ®a liªn kÕt hoÆc danh s¸ch liªn kÕt kÐp.

1 struct node

2 { int info;

3 struct node *next ;

4 struct node *previous;

5 };

6 typedef struct node *NODEPTR

Trang 26

Định nghĩa struct con trỏ

kÕt, nã cã thÓ lµ kiÓu con trá (nh− khai b¸o trªn), vµ còng cã thÓ lµ mét struct cã hai thµnh phÇn:

Trang 27

Các phép toán trên danh sách

1 Tạo danh sách

2 Cập nhật danh sách

3 Duyệt danh sách

4 Sắp xếp danh sách

Trang 28

Tạo danh sách

1 void Initialize(NODEPTR &First)

Trang 29

Tạo danh sách : thêm nút

dung x vµo ®Çu danh s¸ch liªn kÕt.

1 void Insert_First (NODEPTR &First, int x)

Trang 30

Tạo danh sỏch : thờm nỳt

• Thêm nút mới vào sau nút có địa chỉ p (Insert_After): thêm một nút có nộidung x vào sau nút có địa chỉ p trong danh sách liên kết First

1 void Insert_After(NODEPTR p, int x)

Trang 31

Cập nhật dỏnh sỏch

Gi

Giảảảảiiii phóngphóngphóng vvvvùùùùngngng nhnhnhớớớớ(Free_Node(Free_Node(Free_Node): Hàm này dùng để hủy nút đã cấp

phát, và trả vùng nhớ về lại cho memory heap

Trang 32

Cập nhật dánh sách : xóa nút

Xãa phXãa phphÇÇÇÇnnnn ttttöööö ®®®®ÇÇÇÇuuuu ccccññññaaaa danhdanhdanh ssss¸¸¸¸chchch ((((Delete_FirstDelete_FirstDelete_First):):): muèn xãa 1 phÇn tö khái danhs¸ch liªn kÕt th× ta ph¶i kiÓm tra xem danh s¸ch cã rçng hay kh«ng NÕudanh s¸ch cã phÇn tö th× míi xãa ®−îc

1 int Delete_First (NODEPTR &First)

Trang 33

Cập nhật dỏnh sỏch : xúa nỳt

Xóa phần tử đứng sau nút có địa chỉ p (Delete_After):

1 int Delete_After(NODEPTR First, NODEPTR &Last, NODEPTR p)

2 { NODEPTR q;

3 // nếu p là NULL hoặc sau p không có nút

4 if((p == NULL) || (p->next == NULL))

Trang 34

Cập nhật danh sách : xóa danh sách

1 void Delete_All (NODEPTR &First)

Trang 36

Tìm kiếm phần tử chứa nội dung x

Trang 37

Sắp xếp danh sỏch

• Nội dung: Ta so sánh tất cả các phần tử của

danh sách để chọn ra một phần tử nhỏ nhất đ−a

về đầu danh sách; sau đó, tiếp tục chọn phần tử nhỏ nhất trong các phần tử còn lại để đ−a về

phần tử thứ hai trong danh sách Quá trình này lặp lại cho đến khi chọn ra đ−ợc phần tử nhỏ

thứ (n-1).

Trang 38

Sắp xếp danh sách : selection sort

1 void Selection_Sort(NODEPTR First)

Trang 39

Stack (Ngăn xếp) và ứng dụng

• Stack lµ mét danh s¸ch mµ viÖc thªm vµo vµ lo¹i bá chØ diÔn

ra cïng mét ®Çu cña danh s¸ch, tøc lµ theo c¬ chÕ LIFO

(Last In First Out) Stack gåm nhiÒu phÇn tö cã cïng kiÓu

d÷ liÖu, phÇn tö trªn cïng Stack lu«n lu«n cã mét con trá

chØ tíi ta gäi lµ Stack Pointer (ký hiÖu: sp)

10 5 Stack Sp

Trang 40

Phép toán trên stack

• Stack cã 2 phÐp to¸n chÝnh :

* Push : thªm mét phÇn tö vµo ®Çu Stack

* Pop : xãa mét phÇn tö khái Stack, tr¶ cho ch−¬ng tr×nh gäi gi¸ trÞ cña phÇn tö võa xãa.

2 0

1 5

1 0 5

0 1 2

0 1 2 3

s p

2 0 4

1 5

1 0 5

1 2 3

s p

2 0 4

1 5

1 0 5

1 2 3

2 0 4

0 1 2

0 1 2 3

s p

2 0 4

1 5

1 0 5

1 2 3

s p

2 0 4

1 5

1 0 5

1 2 3

2 0 4

1

s p

5

Trang 41

0 1 1

0 0 1 1

1 0 0 1 1

Trang 42

Ví dụ về stack

• TÝnh trÞ mét biÓu thøc d¹ng hËu tè (PostFix), biÕt r»ng mçi sè h¹ng lµ 1 ký sè vµ c¸c to¸n tö trong biÓu thøc

gåm cã: céng(+), trõ (-), nh©n (*), chia (/), lòy thõa (^).

• D¹ng hËu tè cña biÓu thøc cã d¹ng nh− sau:

Trang 43

Stack bằng danh sách tuyến tính

Trang 44

Phép toán trên stack (dstt)

PhÐp

PhÐp to to to¸¸¸¸nnnn push push push : thªm mét phÇn tö cã gi¸ trÞ x vµo ®Çu stack

1 void push (struct stack &st, int x)

Trang 45

Phép toán trên stack (dstt)

• PhÐp PhÐp to to to¸¸¸¸nnnn pop pop pop : lo¹i bá phÇn tö khái Stack vµ tr¶ vÒ gi¸ trÞ cña

phÇn tö võa xãa; tr−íc khi xãa, ta ph¶i kiÓm tra Stack cã kh¸c rçng hay kh«ng.

1 int pop(struct stack &st)

Trang 46

Chương trình đổi số thập phân không âm

5 long int so;

6 st.sp =- 1; // khoi dong stack

7 printf("\n\nNhap vao mot so thap phan: ");

Trang 48

Hàng đợi và ứng dụng

• Queue lµ mét danh s¸ch h¹n chÕ mµ viÖc thªm vµo

®−îc thùc hiÖn ë ®Çu danh s¸ch, vµ viÖc lo¹i bá ®−îc thùc hiÖn ë ®Çu cßn l¹i (FIFO - First In First Out) Queue chøa c¸c phÇn tö cã cïng kiÓu d÷ liÖu Queue còng cã thÓ ®−îc tæ chøc theo danh s¸ch tuyÕn tÝnh hoÆc danh s¸ch liªn kÕt

Trang 49

• Vị trí để loại bỏ phần tử được gọi là Front

• Vị trí để thêm vào được gọi là Rear

• Queue có hai phép toán chính:

- Insert_queue : thêm một phần tử vào hàng đợi; khi

thêm ta phải lưu ý xem hàng đợi bị tràn hay bị đầy để

xử lý cho thích hợp.

trị của phần tử vừa xóa; trước khi xóa, ta phải kiểm tra Queue có khác rỗng hay không.

Trang 50

+ Hàng đợi bị tràn : là trường hợp khi Rear =

(trường hợp này Front luôn nhỏ hơn Rear)

- Di chuyển vòng : cho Rear = 0, Front giữ nguyên

(trường hợp này Front có lúc nhỏ hơn, có lúc lớn hơn

Rear )

Trang 51

Vớ dụ về hàng đợi bị tràn

C B A

RearFront

C B

Rear

Front

Di chuyển vòng

0 1 2 3

n

C B A

RearFront

C B

Rear

Front

Di chuyển vòng

0 1 2 3

n

Hàng đợi bị tràn Rear ≥ Front Rear >< Front

Trang 52

VÍ dụ về hàng đợi bị đầy

• Hàng đợi bị đầy: hàng đợi không có phần tử nào

trống: Front = 0 và Rear = n hoặc Rear đứng ngay

trước Front; do đó nếu tiếp tục thêm vào sẽ bị mất dữ liệu.

Rear = QUEUESIZE-1

Front = -1 } Rear - Front + 1 = QUEUESIZE

hoặc hoặc

Rear đứng ngay trước Front: Rear - Front + 1 = 0

Rear

Front

0

Rear Front Rear

Front

0

Rear Front

Trang 53

Khởi tạo và phộp toỏn trờn hàng đợi

- Khởi tạo hàng đợi:

Trang 54

Định nghĩa hàng đợi

Ta khai báo biến q có kiểu cấu trúc Queue gồm 3 thành phần:

- front, rear : số nguyên chỉ đầu và cuối hàng đợi

- nodes: mảng 1 chiều, mỗi phần tử của mảng là 1 phần tử trong

Trang 55

Hàm thờm vào hàng đợi

• Phép thêêêêm v Phép th m v m vààààoooo : thêm một phần tử x vào hàng đợi; khi thêm ta phải lưu ý xem hàng

đợi bị tràn hay bị đầy để xử lý cho thích hợp.

Trang 56

Thờm vào hàng đợi

2 3 4

<- Front & Rear 0 01

1 02 2

3 4

Danh sách rỗng

Hàng đợi chỉ

có 1 phần tử

Trang 59

Trường hợp hàng đợi tràn, đầy

Hàng đợi đầy

Trang 60

Stack bằng danh sỏch liờn kết

Khai báo: Ta khai báo biến sp (Stack Pointer) là con trỏ

chỉ đến một danh sách là Stack, mỗi phần tử trong

Stack là 1 số nguyên nh− sau:

Trang 61

Thêm vào Stack DSLK

• a a PhÐp PhÐp PhÐp th th thªªªªm m m vvvvµµµµoooo (push) (push) (push) : Thªm mét phÇn tö cã gi¸

trÞ x vµo ®Çu Stack.

1 void push(Stack &sp, int x)

Trang 63

Hàng đợi danh sỏch liờn kết

• Khai báo: Ta khai báo biến q có kiểu cấu trúc Queue gồm 2 thành phần front, rear

là con trỏ chỉ đầu và cuối hàng đợi Mỗi phần tử của hàng đợi là một nút chứa một

Trang 64

Thờm vào hàng đợi DSLK

• PhépPhép thththêêêêmmm vvvvààààoooo : Thêm vào cuối danh sách liên kết nên sẽ thay đổi giá trịcủa Rear

1 void Insert_queue(Queue &q, int x)

Trang 66

Kiểm tra giữa kỳ Đ08VTA2

1 Viết hàm đệ qui F(x,n)

• F= 1 khi n=0

• F= x * F(x, n-1) khi n>0

2 Viết hàm tính điểm trung binh của học viên i trong

bảng điểm có n học viên sau :

Hệ số môn 2 có hệ số 2 còn các môn còn lại có hệ số 1.

Trang 67

Fn =  1 Fn-1 + Fn-2 ; n =0,1 ; n>1

Cho hàm Fibonacci như sau

1 Viết một hàm đệ qui tính hàm Fibonacci

2 Dùng một mảng để lưu trữ các phần tử của dãy Fibonnaci Viết một hàm tính các phần tử của dãy Fibonacci

Trang 69

Cõy nhị phõn tỡm kiếm

• (Binary Search Tree): Một cây nhị phân gọi là cây nhị phân tìm kiếm nếu và chỉ nếu đối với mọi nút của cây thì khóa của một nút bất kỳ phải lớn hơn khóa của tất cả các nút trong cây con bên trái của nó và phải nhỏ hơn khóa của tất cả các nút trong cây con bên phải

của nó.

Trang 70

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

1

5

k 1 <k 1 <k 1

Trang 71

Preorder cho cây con bên phải.

• Ví dụ: Theo cây nhị phân 5.4, ta có:

• ROOT 1 2 3 4 6 7 5 8 9

• Inorder - Trung tự (LNR) : qua cây con bên trái duyệt trước (theo thứ tự LNR), sau

đó thăm nút gốc Cuối cùng qua cây con bên phải (theo thứ tự LNR)

• Ví dụ: Theo cây nhị phân 5.4, ta có:

Trang 72

Định nghĩa cấu trúc cây nhị phân

1 struct nodetype

2 {

7 };

8 typedef struct nodetype *NODEPTR;

9 NODEPTR tree;

Trang 73

Phép toán trên cây nhị phân

Khëi t¹o c©y(Initialize):

1 void Initialize(NODEPTR &root)

Trang 74

Thờm nỳt vào cõy

1 void Insert(NODEPTR root, int x, int a)

9 // điều kiện dừng giải thuật đệ qui

10 if(x < root->key && root->left == NULL) {

19 //điều kiện dừng giải thuật đệ qui

20 if(x > root->key && root->right == NULL)

Trang 75

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

1 void Create_Tree(NODEPTR &root)

2 { int khoa, noidung;

Trang 76

• Lêi gäi hµm: Free_Node (p);

• KiÓm tra c©y nhÞ ph©n rçng hay kh«ng (Empty): hµm Empty tr¶ vÒ TRUE nÕu c©y nhÞ ph©n rçng, vµ ng−îc l¹i

1 int Empty(NODEPTR root)

2 return(root == NULL ? TRUE : FALSE);

3 }

• Lêi gäi hµm: Empty(tree)

Trang 77

Xóa nút

Trang 78

Trường hợp 1 : nút p cần xóa là nút lá Việc xóa nút p chỉ đơn giản là hủy nút p

Trang 79

Trường hợp 2 : Nút p cần xóa có 1 cây con, thì ta cho rp chỉ tới nút p Sau đó, ta tạo liên kết từ nút cha của p tới nút con của rp, cuối cùng hủy nút p.

2

10 5

20

Trang 80

Trường hợp 3 : Nút p cần xóa có 2 cây con Ta cho rp chỉ tới nút p

Do tính chất nút cực trái của cây con bên phải của p có khóa vừa lớn hơn khóa của p, nên để loại p thì ta sẽ cho r chỉ tới nút cực trái đó Sau đó, ta sao chép nội dung và khóa của nút r vào nút mà rp đang chỉ tới Ta tạo liên kết thích hợp để bứt nút rp

ra khỏi cây nhị phân và cuối cùng xóa nút rp.

Trang 81

11 if (rp->right == NULL) p = rp->left;

// p lµ nót l¸ hoac la nut chi co cay con ben trai

12 else if (rp->left == NULL)

13 p = rp->right; // p lµ nut co cay con ben phai

14 else remove_case_3 (rp->right);

Trang 82

9 rp->key = r->key; //Chep noi dung cua r sang rp ";

10 rp->info =r->info; // de lat nua free(rp)

11 rp = r;

12 r = r->right;

13 }

14 }

Trang 84

Duyệt cây

• C C¸¸¸¸cccc phÐp phÐp phÐp duy duy duyÖÖÖÖtttt cccc©©©©yyyy : : : : Cã 3 c¸ch duyÖt c¬ b¶n lµ NLR, LNR, LRN

a DuyÖt c©y theo thø tù NLR (Preorder):

void Preorder (NODEPTR root)

b DuyÖt c©y theo thø tù LNR (Inorder):

void Inorder(NODEPTR root) { if(root != NULL)

{ Inorder(root->left);

printf("%d ", root->info);

Inorder(root->right);

} }

c DuyÖt c©y theo thø tù LRN (Posorder):

void Posorder(NODEPTR root)

{ if(root != NULL)

{ Posorder(root->left);

Posorder(root->right);

printf("%d ", root->info);

Trang 85

C©©©©yyyy nhÞ nhÞ nhÞ ph ph ph©©©©nnnn tttt××××m m m kiÕm kiÕm kiÕm cccc©©©©nnnn bbbb»»»»ng ng

(AVL)

• AVL lµ c©y nhÞ ph©n t×m kiÕm mµ t¹i tÊt c¶ c¸c nót cña nã

chiÒu cao cña c©y con bªn tr¸i cña nã vµ chiÒu cao cña c©y con bªn ph¶i chªnh lÖch nhau kh«ng qu¸ mét.

10

20

6 8

Trang 86

AVL: balance factor

• Ch Ch ChØØØØ ssssèèèè cccc©©©©nnnn bbbb»»»»ng ng ng (balance factor) cña mét nót p trªn c©y AVL= = lh(p

lh(p) ) ) rh(p rh(p rh(p))))

lh (p) lµ chiÒu cao cña c©y con bªn tr¸i cña p

rh(p) lµ chiÒu cao cña c©y con bªn ph¶i cña p

-1 1

0

B

0 B

0

0 0

A

Trang 88

PhÐp to to to¸¸¸¸nnnn tr tr trªªªªnnnn cccc©©©©yyyy AVL: AVL: AVL: Th Th Thªªªªm m

- Néi dung: : : : Thªm 1 nót cã khãa x, néi dung a vµo c©y nhÞ ph©n t×m kiÕm c©nb»ng sao cho sau khi thªm th× c©y nhÞ ph©n vÉn lµ c©y nhÞ ph©n t×m kiÕmc©n b»ng

-Chó ý: Cã 2 tr−êng hîp khi thªm nót x vµo c©y AVL lµm c©y mÊt c©n b»ng,

- thªm c¸c nót vµo sau bªn tr¸i cña nót cã bf = 1,

- vµ thªm c¸c nót vµo sau bªn ph¶i cña nót cã bf = -1

Trang 89

• TrTrTr−−−−êng hêng hêng hỵỵỵỵp 1ap 1ap 1a: NÕu thªm nĩt míi x vµo vÞ trÝ nĩt sau bªn tr¸i cđa s (thuéc nh¸nh T1) ta xoay ph¶i quanh nĩt ya

• - Nĩt s sÏ lµ nĩt gèc míi cđa nh¸nh c©y nµy víi bfs = 0

• - Nĩt ya lµ nĩt con bªn ph¶i cđa s víi bf ya = 0

0

T1 chiều sâu n

0

T2 chiều sâu n

T3 chiều sâu n

T1 chiều sâu n

T2 chiều sâu n

S

ya

xoay phải quanh nút ya

0

T1 chiều sâu n

0

T2 chiều sâu n

T3 chiều sâu n

0

T2 chiều sâu n

T3 chiều sâu n

T1 chiều sâu n

T2 chiều sâu n

S

ya

xoay phải quanh nút ya xoay phải quanh nút ya

Ngày đăng: 11/04/2017, 09:31

TỪ KHÓA LIÊN QUAN

w