Вы находитесь на странице: 1из 198

CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng TRƢỜNG ĐH CÔNG NGHỆ THÔNG TIN

CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT

Giáo viên: Mai Xuân Hùng


Email: hungmx@uit.edu.vn
ĐT: 08.8533077

1
Bài Toán Tìm Kiếm

 Cho danh sách có n phần tử a0, a1, a2…, an-1.


 Để đơn giản trong việc trình bày giải thuật ta dùng
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

mảng 1 chiều a để lưu danh sách các phần tử nói


trên trong bộ nhớ chính.
 Tìm phần tử có khoá bằng X trong mảng
 Giải thuật tìm kiếm tuyến tính (tìm tuần tự)
 Giải thuật tìm kiếm nhị phân
 Lưu ý: Trong quá trình trình bày thuật giải ta
dùng ngôn ngữ lập trình C.
2
void nhap1c(int a[], int n)
{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

int i;
for(i=0;i<n;i++)
{
printf(“a[%d]=”,i);
scanf(“%d”,&a[i]);
}
}

3
Tìm Kiếm Tuyến Tính

 Ý tƣởng : So sánh X lần lượt với phần tử thứ 1, thứ


2,…của mảng a cho đến khi gặp được khóa cần
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

tìm, hoặc tìm hết mảng mà không thấy.


 Các bƣớc tiến hành
• Bước 1: Khởi gán i=0;
• Bước 2: So sánh a[i] với giá trị x cần tìm, có 2 khả năng
+ a[i] == x tìm thấy x. Dừng;
+ a[i] != x sang bước 3;
• Bước 3: i=i+1 // Xét tiếp phần tử kế tiếp trong mảng
Nếu i==N: Hết mảng. Dừng;
Ngược lại: Lặp lại bước 2;
4
Thuật Toán Tìm Kiếm Tuyến Tính

 Hàm trả về 1 nếu tìm thấy, ngược lại trả về 0


int LinearSearch(int a[],int n, int x)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

{
int i=0;
while((i<n)&&(a[i]!=x))
i++;
if(i==n)
return 0; //Tìm không thấy x
else
return 1; //Tìm thấy
}
5
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Minh Họa Thuật Toán Tìm Kiếm Tuyến Tính

X=6 Tìm thấy 6 tại vị trí 4


i

2 8 5 1 6 4 6

0 1 2 3 4 5 6

6
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Minh Họa Thuật Toán Tìm Kiếm Tuyến Tính (tt)

X=10 i=7, không tìm thấy


i

2 8 5 1 6 4 6

0 1 2 3 4 5 6

7
Thuật Toán Tìm Kiếm Nhị Phân

 Được áp dụng trên mảng đã có thứ tự.


 Ý tƣởng: .
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Giả xử ta xét mảng có thứ tự tăng, khi ấy ta có


ai-1<ai<ai+1
 Nếu X>ai thì X chỉ có thể xuất hiện trong đoạn [ai+1,
an-1]
 Nếu X<ai thì X chỉ có thể xuất hiện trong đoạn [a0,
ai-1]
 Ý tưởng của giải thuật là tại mỗi bước ta so sánh X
với phần tử đứng giữa trong dãy tìm kiếm hiện hành,
dựa vào kết quả so sánh này mà ta quyết định giới
hạn dãy tìm kiếm ở nữa dưới hay nữa trên của dãy
tìm kiếm hiện hành.
8
Các Bƣớc Thuật Toán Tìm Kiếm Nhị Phân

 Giả sử dãy tìm kiếm hiện hành bao gồm các phần tử
nằm trong aleft, aright, các bước của giải thuật như sau:
 Bước 1: left=0; right=N-1;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Bước 2:
 mid=(left+right)/2; //chỉ số phần tử giữa dãy hiện hành
 So sánh a[mid] với x. Có 3 khả năng
• a[mid]= x: tìm thấy. Dừng
• a[mid]>x : Right= mid-1;
• a[mid]<x : Left= mid+1;
 Bước 3: Nếu Left <=Right ; // còn phần tử trong dãy hiện
hành
+ Lặp lại bước 2
Ngược lại : Dừng
9
Cài Đặt Thuật Toán Tìm Nhị Phân

 Hàm trả về giá trị 1 nếu tìm thấy, ngược lại hàm
trả về giá trị 0
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

int BinarySearch(int a[],int n,int x)


{ int left, right, mid; left=0; right=n-1;
do{
mid=(left+right)/2;
if(a[mid]==x) return 1;
else if(a[mid]<x) left=mid+1;
else right=mid-1;
}while(left<=right);
return 0;
}
10
Minh Họa Thuật Toán Tìm Nhị Phân

Tìm thấy 2 tại vị trí 1


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

X=2

L M R

1 2 4 6 7 9 10

0 1 2 3 4 5 6

11
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Minh Họa Thuật Toán Tìm Nhị Phân (tt)

X=-1

L M R

1 2 4 6 7 9 10

0 1 2 3 4 5 6

L=0
R=-1 => không tìm thấy X=-1

12
BÀI TẬP ÁP DỤNG

3 5 6 8 12 17 19
0 1 2 3 4 5 6
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Ghi kết quả chạy từng bước khi tìm X=19

 B1: l=0, r=6, mid=(l+r)/2, A[mid] = 8, 8<19

 B2: l= mid+1=4, mid=(l+r)/2=5, A[mid] =17<19

 B3: l=mid+1=6, mid=(l+r)/2=6, A[mid]=19 =X dừng

13
Gọi hàm tìm tuyến tính và tìm nhị phân

void main()
{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

int a[100], n, tv,x;


nhập số phần tử n;
nhap1c(a,n);
nhập giá trị cần tìm x
tv=LinearSearch(a,n,x);
if(tv==1) printf(“tìm thấy”);
else printf(“không tìm thấy”);
Tương tự cho lời gọi hàm BinarySearch;
}
14
Các Thuật Toán Sắp Xếp

1. Đổi chỗ trực tiếp – Interchange Sort


2. Chọn trực tiếp – Selection Sort
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

3. Nổi bọt – Bubble Sort


4. Chèn trực tiếp – Insertion Sort
5. Quick sort

15
Đổi Chỗ Trực Tiếp – Interchange Sort

 Ý tƣởng: Xuất phát từ đầu dãy, tìm tất các


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

các nghịch thế chứa phần tử này, triệt tiêu


chúng bằng cách đổi chỗ 2 phần tử trong cặp
nghịch thế. Lặp lại xử lý trên với phần tử kế
trong dãy.

16
Các Bƣớc Tiến Hành

 Bước 1: i = 0; // bắt đầu từ đầu dãy


 Bước 2: j = i+1; //tìm các nghịch thế với a[i]
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Bước 3:
Trong khi j < N thực hiện
Nếu a[j]<a[i] //xét cặp a[i], a[j]
Swap(a[i],a[j]);
j = j+1;
 Bước 4: i = i+1;
Nếu i < N-1: Lặp lại Bước 2.
Ngược lại: Dừng.
17
Đổi Chỗ Trực Tiếp – Interchange Sort

 Cho dãy số a:
12 2 8 5 1 6 4 15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i=0 j=1

i=0 j=4

18
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Đổi Chỗ Trực Tiếp – Interchange Sort

i=1 j=2

i=1 j=3

i=1 19 j=4
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Đổi Chỗ Trực Tiếp – Interchange Sort

i=2 j=3

i=2 j=4

i=2 20 j=6
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Đổi Chỗ Trực Tiếp – Interchange Sort

i=3 j=4

i=3 j=5

i=3
21
j=6
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Đổi Chỗ Trực Tiếp – Interchange Sort

i=4 j=5

i=4 j=6

i=5 j=6
22
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

23
Đổi Chỗ Trực Tiếp – Interchange Sort

i=6
j=7
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i
1
0
12
2
j

1
8
2
Minh Họa Thuật Toán

24
5
3
1
4
6
5
4
6
7
15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i
1
0
2
1
12
j

8
2
Minh Họa Thuật Toán

25
5
3
2
4
6
5
4
6
7
15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

1
0 0

i
2
1 2
4
12
Minh Họa Thuật Toán

26
8
3
j

5
4
6
5
4
6
7
15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

1
0
2
1 0

i
4
2
Minh Họa Thuật Toán

27
5
3
12
j

8
4
6
5
5
6
7
15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

0
1
1
2
2
4
Minh Họa Thuật Toán

i
3
5

28
4
6
12
j

8
5
6
6
7
15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

0
1
1
2
4
2
Minh Họa Thuật Toán

5
3

29
0

i
6
4
8
12
5
8
j

6
15
7
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

0
1
1
2
2
4
Minh Họa Thuật Toán

5
3

30
6
4
8
0

i
5
12
6
j

15
7
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

1
1
2
2
4
3
Minh Họa Thuật Toán

31
5
4
6
5
8
6
7
12
8
15
Cài Đặt Đổi Chỗ Trực Tiếp

void Swap(int &x,int &y)


{ int tam;
tam=x;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

x=y;
y=tam;
}
void InterchangeSort(int a[], int N )
{ int i, j;
for (i = 0 ; i<N-1 ; i++)
for (j =i+1; j < N ; j++)
if(a[j ]< a[i]) // Thỏa 1 cặp nghịch thế
Swap(a[i], a[j]);
}
32
Bài tập áp dụng

9 7 4 5 8
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

7 9 4 5 8

4 9 7 5 8

4 9 7 5 8

4 7 9 5 8

4 5 933 7 8
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

4
4
4

5
5
5
Bài tập áp dụng

7
7
9

34
8
9
7

9
8
8
Chọn Trực Tiếp – Selection Sort

 Ý tƣởng:

 Chọn phần tử nhỏ nhất trong N phần tử trong


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

dãy hiện hành ban đầu.


 Đưa phần tử này về vị trí đầu dãy hiện hành
 Xem dãy hiện hành chỉ còn N-1 phần tử của
dãy hiện hành ban đầu
 Bắt đầu từ vị trí thứ 2;
 Lặp lại quá trình trên cho dãy hiện hành...
đến khi dãy hiện hành chỉ còn 1 phần tử

35
Các Bƣớc Của Thuật Toán Chọn Trực Tiếp

 Bước 1: i = 0;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Bước 2: Tìm phần tử a[min] nhỏ nhất trong


dãy hiện hành từ a[i] đến a[N]
 Bước 3 : Đổi chỗ a[min] và a[i]
 Bước 4 : Nếu i < N-1 thì
i = i+1; Lặp lại Bước 2;
Ngược lại: Dừng.

36
Chọn Trực Tiếp – Selection Sort

 Cho dãy số a:
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

12 2 8 5 1 6 4 15

37
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i=0

i=1

38
Chọn Trực Tiếp – Selection Sort
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i=2

i=3

39
i=4
Chọn Trực Tiếp – Selection Sort
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

40
Chọn Trực Tiếp – Selection Sort

i=5

i=6
Minh Họa Thuật Toán Chọn Trực Tiếp

Vị trí nhỏ nhất(0,7) Swap(a[0], a[4])


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

min

12 2 8 5 1 6 4 15
0 1 2 3 4 5 6 7
i

41
Minh Họa Thuật Toán Chọn Trực Tiếp

Vị trí nhỏ nhất(1,7) Swap(a[1], a[1])


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

min

1 2 8 5 12 6 4 15
0 1 2 3 4 5 6 7
i

42
Minh Họa Thuật Toán Chọn Trực Tiếp

Vị trí nhỏ nhất(2,7) Swap(a[2], a[6])


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

min

1 2 8 5 12 6 4 15
0 1 2 3 4 5 6 7
i

43
Minh Họa Thuật Toán Chọn Trực Tiếp

Vị trí nhỏ nhất(3, 7) Swap(a[3], a[3])


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

min

1 2 4 5 12 6 8 15
0 1 2 3 4 5 6 7
i

44
Minh Họa Thuật Toán Chọn Trực Tiếp

Vị trí nhỏ nhất(4, 7) Swap(a[4], a[5])


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

min

1 2 4 5 12 6 8 15
0 1 2 3 4 5 6 7
i

45
Minh Họa Thuật Toán Chọn Trực Tiếp

Vị trí nhỏ nhất(5,7) Swap(a[5], a[6])


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

min

1 2 4 5 6 12 8 15
0 1 2 3 4 5 6 7
i

46
Minh Họa Thuật Toán Chọn Trực Tiếp

Vị trí nhỏ nhất(6, 7)


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

min

1 2 4 5 6 8 12 15

0 1 2 3 4 5 6 7
i

47
Cài Đặt Thuật Toán Chọn Trực Tiếp

void SelectionSort(int a[],int n )


{
int vtmin,i,j; // chỉ số phần tử nhỏ nhất trong dãy hiện hành
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

for (i=0; i<n-1 ; i++) //chỉ số đầu tiên của dãy hiện hành
{
vtmin = i;
for(j = i+1; j <N ; j++)
if (a[j ] < a[vtmin])
vtmin = j; // lưu vtrí phần tử hiện nhỏ nhất
Swap(a[vtmin],a[i]);
}
}

48
Cho biết kết quả chạy từng bƣớc

9 7 4 4 8
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

4 7 9 4 8

4 4 9 7 8

4 4 7 9 8

4 4 7 8 9

49
Nổi Bọt – Bubble Sort

 Ý tƣởng:
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Xuất phát từ cuối dãy, đổi chỗ các cặp phần


tử kế cận để đưa phần tử nhỏ hơn trong cặp
phần tử đó về vị trí đúng đầu dãy hiện hành,
sau đó sẽ không xét đến nó ở bước tiếp theo,
do vậy ở lần xử lý thứ i sẽ có vị trí đầu dãy là
i.

 Lặp lại xử lý trên cho đến khi không còn cặp


phần tử nào để xét.
50
Nổi Bọt – Bubble Sort

 Bước 1 : i = 0; // lần xử lý đầu tiên


 Bước 2 : j = N-1;//Duyệt từ cuối dãy ngược về vị trí i
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

Trong khi (j > i) thực hiện:


Nếu a[j]<a[j-1]
Doicho(a[j],a[j-1]);
j = j-1;
 Bước 3 : i = i+1; // lần xử lý kế tiếp
Nếu i =N-1: Hết dãy. Dừng
Ngược lại : Lặp lại Bước 2.

51
Nổi Bọt – Bubble Sort

 Cho dãy số a:
2 12 8 5 1 6 4 15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i=0 j=6

i=0 i=4
52
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i=0
i=0
i=0

j=1
j=2

53
Nổi Bọt – Bubble Sort

j=3
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i=1
i=1

i=1

j=3

54
Nổi Bọt – Bubble Sort

j=4
j=5
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i=2
i=2

i=355
Nổi Bọt – Bubble Sort

j=4
j=5

j=6
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

56
Nổi Bọt – Bubble Sort

i=3

i=4

i=5
j=5

j=6
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i
0
1
12
2

1
8

57
5

3
Minh Họa Thuật Toán

4
6

5
4

6
j

7
15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i
1
0
2
1
12
2
2

58
8
3
Minh Họa Thuật Toán

5
4
4
5
6
6
j

7
15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

1
0
i
2
1
4
2
12

59
4
3
Minh Họa Thuật Toán

8
4
5
5
6
6
j

7
15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

1
0
2
1
i
4
2

60
3
Minh Họa Thuật Toán

5
12
8
4
5
5
6
6
j

7
15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

1
0
2
1
4
2
i

61
5
3
Minh Họa Thuật Toán

6
4
12
8
5
6
6
j

7
15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

1
0
2
1
4
2

62
5
3
Minh Họa Thuật Toán

i
6
4
8
5
12
8
6
j

7
15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

1
1
2
2
4
3

63
5
4
Minh Họa Thuật Toán

6
5

i
8
6
7
12
j
8
15
Cài Đặt Thuật Toán Nổi Bọt

void BubbleSort(int a[],int n)


{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

int i, j;
for (i = 0 ; i<n-1 ; i++)
for (j =n-1; j >i ; j --)
if(a[j]< a[j-1])// nếu sai vị trí thì đổi chỗ
Swap(a[j], a[j-1]);
}

64
Ghi kết quả chạy từng bƣớc

9 7 4 3 5
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

9 7 3 4 5

9 3 7 4 5

3 9 7 4 5

3 9 4 7 5

3 4 9 7 5

65
Ghi kết quả chạy từng bƣớc

3 4 9 7 5
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

3 4 9 5 7

3 4 5 9 7

3 4 5 7 9

66
Chèn Trực Tiếp – Insertion Sort

 Giả sử có một dãy a0 , a1 ,... ,an-1 trong đó i phần


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

tử đầu tiên a0 , a1 ,... ,ai-1 đã có thứ tự.

 Tìm cách chèn phần tử ai vào vị trí thích hợp của


đoạn đã được sắp để có dãy mới a0 , a1,... ,ai trở
nên có thứ tự. Vị trí này chính là vị trí giữa hai
phần tử ak-1 và ak thỏa ak-1 < ai < ak (1≤k≤i).

67
Chèn Trực Tiếp – Insertion Sort

 Bước 1: i = 1; //giả sử có đoạn a[1] đã được sắp


 Bước 2: x = a[i]; Tìm vị trí pos thích hợp trong
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

đoạn a[1] đến a[i-1] để chèn a[i]


vào
 Bước 3: Dời chỗ các phần tử từ a[pos] đến a[i-1]
sang phải 1 vị trí để dành chổ cho a[i]
 Bước 4: a[pos] = x; //có đoạn a[1]..a[i] đã được sắp

 Bước 5: i = i+1;
Nếu i < n : Lặp lại Bước 2
Ngược lại : Dừng
68
Chèn Trực Tiếp – Insertion Sort

 Cho dãy số :
12 2 8 5 1 6 4 15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i=1

i=2
69
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i=3

70
i=4
Chèn Trực Tiếp – Insertion Sort

i=5
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

71
Chèn Trực Tiếp – Insertion Sort

i=6

i=7
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Minh Họa Thuật Toán Insertion Sort

12 2 8 5 1 6 4 15
0 1 2 3 4 5 6 7

72
Minh Họa Thuật Toán Insertion Sort

Insert a[1] into (0,0)


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

pos

2
12 2 8 5 1 6 4 15
0 1 2 3 4 5 6 7
i

73
Minh Họa Thuật Toán Insertion Sort

Insert a[2] into (0, 1)


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

pos

2 8
12 8 5 1 6 4 15
0 1 2 3 4 5 6 7
i

74
Minh Họa Thuật Toán Insertion Sort

Insert a[3] into (0, 2)


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

pos

2 5
8 12 5 1 6 4 15
0 1 2 3 4 5 6 7
i

75
Minh Họa Thuật Toán Insertion Sort

Insert a[4] into (0, 3)


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

pos

2
1 5 8 12 1 6 4 15
0 1 2 3 4 5 6 7
i

76
Minh Họa Thuật Toán Insertion Sort

Insert a[5] into (0, 4)


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

pos

1 2 5 6
8 12 6 4 15
0 1 2 3 4 5 6 7
i

77
Minh Họa Thuật Toán Insertion Sort

Insert a[6] into (0, 5)


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

pos

1 2 4
5 6 8 12 4 15
0 1 2 3 4 5 6 7
i

78
Minh Họa Thuật Toán Insertion Sort

Insert a[8] into (0, 6)


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

pos

1 2 4 5 6 8 12 15
0 1 2 3 4 5 6 7
i

79
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Minh Họa Thuật Toán Insertion Sort

pos

1 2 4 5 6 8 12 15
0 1 2 3 4 5 6 7

80
Cài Đặt Thuật Toán Chèn Trực Tiếp

void InsertionSort(int d, int n )


{ int pos, i;
int x;//lưu giá trị a[i] tránh bị ghi đè khi dời chỗ các phần tử.
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

for(i=1 ; i<n ; i++) //đoạn a[0] đã sắp


{
x = a[i]; pos = i-1;
// tìm vị trí chèn x
while((pos >= 0)&&(a[pos] > x))
{//kết hợp dời chỗ các phần tử sẽ đứng sau x trong dãy mới
a[pos+1] = a[pos];
pos--;
}
a[pos+1] = x; // chèn x vào dãy
}
}
81
Kết quả chạy từng bƣớc

9 7 4 3 5
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

7 9 4 3 5

4 7 9 3 5

3 4 7 9 5

3 4 5 7 9

82
Quick Sort

 Ý tưởng:
 Giải thuật QuickSort sắp xếp dãy a1, a2 ..., aN
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

dựa trên việc phân hoạch dãy ban đầu thành 3


phần :
• Phần 1:Gồm các phần tử có giá trị bé hơn x
• Phần 2: Gồm các phần tử có giá trị bằng x
• Phần 3: Gồm các phần tử có giá trị lớn hơn x
với x là giá trị của một phần tử tùy ý trong dãy
ban đầu.

83
Quick Sort - Ý Tƣởng

 Sau khi thực hiện phân hoạch, dãy ban đầu được phân
thành 3 đoạn:
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

• 1. ak ≤ x , với k = 0 .. j
• 2. ak = x , với k = j+1 .. i-1
• 3. ak  x , với k = i..N-1

84
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Quick Sort – Ý Tƣởng

 Đoạn thứ 2 đã có thứ tự.


 Nếu các đoạn 1 và 3 chỉ có 1 phần tử : đã có
thứ tự
 khi đó dãy con ban đầu đã được sắp.

85
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Quick Sort – Ý Tƣởng

 Đoạn thứ 2 đã có thứ tự.


 Nếu các đoạn 1 và 3 có nhiều hơn 1 phần tử
thì dãy ban đầu chỉ có thứ tự khi các đoạn 1, 3
được sắp.
 Để sắp xếp các đoạn 1 và 3, ta lần lượt tiến
hành việc phân hoạch từng dãy con theo cùng
phương pháp phân hoạch dãy ban đầu vừa
trình bày …
86
Giải Thuật Quick Sort

 Bước 1: Nếu left ≥ right //dãy có ít hơn 2 phần tử


Kết thúc; //dãy đã được sắp xếp
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Bước 2: Phân hoạch dãy aleft … aright thành các đoạn:


aleft.. aj, aj+1.. ai-1, ai.. aright
Đoạn 1  x
Đoạn 2: aj+1.. ai-1 = x
Đoạn 3: ai.. aright  x
 Bước 3: Sắp xếp đoạn 1: aleft.. aj
 Bước 4: Sắp xếp đoạn 3: ai.. aright

87
Giải Thuật Quick Sort

 Bước 1 : Chọn tùy ý một phần tử a[k] trong dãy là


giá trị mốc ( l ≤ k ≤ r):
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

x = a[k]; i = l; j = r;
 Bước 2 : Phát hiện và hiệu chỉnh cặp phần tử
a[i], a[j] nằm sai chỗ :
 Bước 2a : Trong khi (a[i]<x) i++;
 Bước 2b : Trong khi (a[j]>x) j--;
 Bước 2c : Nếu i< j Đoicho(a[i],a[j]);
 Bước 3 : Nếu i < j: Lặp lại Bước 2.
Ngược lại: Dừng
88
Quick Sort – Ví Dụ

 Cho dãy số a:
12 2 8 5 1 6 4 15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

Phân hoạch đoạn l =0, r = 7: x = a[3] = 5

12 2 8 5 1 6 4 15

l=0 r=7

89
Quick Sort – Ví Dụ

4 2 8 5 1 6 12 15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i=0
j=6
l=0 r=7

4 2 8 5 1 6 12 15

i=1 i=2
l=0 j=4 j=5 j=6 r=7

90
Quick Sort – Ví Dụ

 Phân hoạch đoạn l = 0, r = 2:


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

4 2 1 5 8 6 12 15

l=0 r =2

i=0 j=2

91
Quick Sort – Ví Dụ
 Phân hoạch đoạn l =4, r = 7:
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

1 2 4 5 8 6 12 15

l=4 r =7
i=4 j=5 j=6 j=7

1 2 4 5 6
i=4 8 12 15

l=5 r =7

92
Quick Sort – Ví Dụ

 Phân hoạch đoạn l =6, r = 7:


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

1 2 4 5 6 8 12 15

93
Quick Sort – Ví Dụ
Phaân hoaïch daõy
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i j
0 1 2 3 4 5 6 7
12 2 8 5
5 1 6 4 15

left X right

STOP STOP
Không nhỏ hơnKh
X ông lớn hơn X

94
Quick Sort – Ví Dụ
Phaân hoaïch daõy
X 5
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i j
0 1 2 3 4 5 6 7
4 2 8 5 1 6 12 15

left right

STOP STOP
Không nhỏ hơn XKhông lớn hơn X

95
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Quick Sort – Ví Dụ

j i
0 1 2 3 4 5 6 7
4 2 1 5 8 6 12 15

left right

96
Quick Sort – Ví Dụ
Phaân hoaïch daõy
X 6
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

i j
0 1 2 3 4 5 6 7
1 2 4 5 8 6 12 15

left right

Saép xeáp ñoaïn 3 STOP STOP


Không nhỏ hơn X
Không lớn hơn X

97
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Quick Sort – Ví Dụ

j i
0 1 2 3 4 5 6 7
1 2 4 5 6 8 12 15

left right

Saép xeáp ñoaïn 3

98
Quick Sort

void QuickSort(int a[], int left, int right)


{ int i, j, x;
x = a[(left+right)/2];
i = left; j = right;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

do
{
while(a[i] < x) i++;
while(a[j] > x) j--;
if(i <= j)
{
Swap(a[i],a[j]);
i++ ; j--;
}
} while(i <= j);
if(left<j)
QuickSort(a, left, j);
if(i<right)
QuickSort(a, i, right);
}
99
Bài tập áp dụng

12 2 8 5 1 6 4 15
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

4 2 8 5 1 6 12 15

4 2 1 5 8 6 12 15

1 2 4 5 8 6 12 15

1 2 4 5 6 8 12 15

100
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng NỘI DUNG

101
CẤU TRÚC DỮ LIỆU ĐỘNG
Biến Tĩnh

 Được khai báo tường minh, có tên gọi


 Tồn tại trong phạm vi khai báo
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Được cấp phát trong stack


 Kích thước không đổi => không tận dụng hiệu
quả bộ nhớ
 Ví dụ : int x,y;
char c;
float f[5];
 Khi biết chắc nhu cầu sử dụng đối tượng trước
khi thực sự xử lý : dùng
102
biến không động
Ví Dụ Hạn Chế Của Biến Tinh

 Khai báo mảng một chiều có thể chứa tối đa 100


phần tử:
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

int a[100];
int n; // Số phần tử xử dụng thực sự
 Nếu nhập n <100, dư vùng nhớ => lãng phí
 Nếu nhập n > 100 => thiếu chỗ !

103
Biến Động

 Không được khai báo tường minh, không có tên


gọi
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Xin khi cần, giải phóng khi sử dụng xong


 Được cấp phát trong heap
 Linh động về kích thước
 Vấn đề : biến động không có tên gọi tường minh,
làm sao thao tác ?

104
Kiểu con trỏ

 Kiểu con trỏ dùng lưu địa chỉ của một đối tượng dữ
liệu khác.
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Biến thuộc kiểu con trỏ Tp là biến mà giá trị của nó là


địa chỉ cuả một vùng nhớ ứng với một biến kiểu T,
hoặc là giá trị NULL.
 Khai báo trong C :
typedef int *intpointer;
intpointer p;
 Bản thân biến con trỏ là không động
 Dùng biến con trỏ để lưu giữ điạ chỉ của biến động =>
truy xuất biến động thông
105 qua biến con trỏ
Các thao tác trên kiểu con trỏ

 Tạo ra một biến động và cho con trỏ „p‟ chỉ đến nó:
 void* malloc(size);
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 void* calloc(n,size);
 new // hàm cấp phát bộ nhớ trong C++
 Hủy một biến động do p chỉ đến :
 Hàm free(p) huỷ vùng nhớ cấp phát bởi hàm
malloc hoặc calloc do p trỏ tới
 Hàm delete p huỷ vùng nhớ cấp phát bởi hàm new
do p trỏ tới
106
Sử dụng biến tinh, con trỏ và biến động
 &: Toán tử lấy địa chỉ
 *: Lấy giá trị tại vùng nhớ con trỏ đang lưu
int y = 5;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

int *yP,**q;
*yP = 10; // yP gets address of y
q=&yp;
printf(“%d,%d”,y,*yp,**q);

1f is address of a
111f 11f 1f

11f q 1f yP 5 y

 Giá trị yP là một địa chỉ


 Địa chỉ của biến y là giá trị của con trỏ yp

107
Ví dụ cấp phát động cho mảng một chiều
void main()
{
int *a, n;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

printf(“Nhap so phan tu cua mang n=”);


scanf(“%d”,&n);
a=(int*)malloc(n*sizeof(int));//new int[n];
for(int i=0;i<n;i++)
scanf(“%d”,(int*)a+i);
for(int i=0;i<n;i++)
printf(“%d ”,*((int*)a+i));
free (a);//delete a;
}
 Hạn chế: Các vùng nhớ phải trống một cách liên tục mới
cấp được

108
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

109
Hạn chế của cách cấp phát động cho mảng
Kiểu danh sách

 Danh sách = { các phần tử có cùng kiểu}


 Danh sách là một kiểu dữ liệu tuyến tính :
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Mỗi phần tử có nhiều nhất 1 phần tử đứng trước


 Mỗi phần tử có nhiều nhất 1 phần tử đứng sau
 Là kiểu dữ liệu quen thuộc trong thực tế :
 Danh sách học sinh
 Danh mục sách trong thư viện
 Danh bạ điện thoại
 Danh sách các nhân viên trong công ty
 … 110
Các hình thức tổ chức danh sách

 CTDL cho mỗi phần tử ?


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Thể hiện liên kết của các phần tử ?


 Hai hình thức cơ bản :
 Liên kết ngầm : Mảng
 Liên kết tường minh : Danh sách liên kết

111
Danh sách liên kết ngầm (mảng)
 Mối liên hệ giữa các phần tử được thể hiện ngầm:
 xi : phần tử thứ i trong danh sách
x0 … xi xi+1
 xi , xi+1 là kế cận trong danh sách
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Phải lưu trữ liên tiếp các phần tử trong bộ nhớ


 công thức xác định địa chỉ phần tử thứ i:
address(i) = address(1) + (i-1)*sizeof(T)
 Ƣu điểm : Truy xuất trực tiếp, nhanh chóng
 Nhƣợc điểm:
 Sử dụng bộ nhớ kém hiệu quả
 Kích thước cố định
 Các thao tác thêm
112
vào , loại bỏ không hiệu
Liên kết tuờng minh(Danh sánh liên kết)

 CTDL cho một phần tử


 Thông tin bản thân
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Địa chỉ của phần tử kế trong danh sách


x2
x0 x3
x1

 Mỗi phần tử là một biến động


 Ƣu điểm
+ Sử dụng hiệu quả bộ nhớ
+ Linh động về số lượng phần tử
113
Các loại danh sách liên kết

 Danh sách liên kết đơn: Mỗi phần tử liên kết với
phần tử đứng sau nó trong danh sách
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

A B C D

 Danh sách liên kết kép: Mỗi phần tử liên kết với
phần tử đứng trước và sau nó trong danh sách
A B C D

 Danh sách liên Vòng: Phần tử cuối danh sách


liên với phần tử đầu danh sách

114
Các loại danh sách liên kết (tt)
 Danh sách liên Vòng: Phần tử cuối danh sách liên với
phần tử đầu danh sách
 Danh sách liên kết đơn vòng
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

A B C D

 Danh sách liên kết đôi vòng

A B C D

115
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng NỘI DUNG

116
DANH SÁCH LIÊN KẾT ĐƠN (LIST)
Tổ Chức Của DSLK Đơn

x2
x0 x3
x1
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Mỗi phần tử liên kết với phần tử đứng liền sau trong
danh sách
 Mỗi phần tử trong danh sách liên kết đơn là một cấu trúc
có hai thành phần
 Thành phần dữ liệu: Lưu trữ thông tin về
bản thân phần tử
 Thành phần liên kết: Lưu địa chỉ phần tử
đứng sau trong danh sách hoặc bằng NULL
nếu là phần tử cuối
117
danh sách.
Bài tập áp dụng

 Dùng danh sách liên kết đơn để quản lý các sinh


viên trong 1 lớp học, biết rằng cấu trúc dữ liệu của
một sinh viên gồm tên (chuỗi ký tự), mã số (chuỗi
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

ký tự), điểm trung bình (số thực). Thực hiện các


yêu cầu sau:
1. Thêm 1 sinh viên vào lớp học (thêm đầu, thêm cuối)
2. Tìm kiếm 1 sinh viến có tên X trong lớp học (x
nhập).
3. Tìm 1 sinh viên có mã số bằng X (X nhập)
4. Liệt kê tên cung điểm trung bình của những sinh
viên có điểm trung bình >=5
5. Đếm số sinh viên có tên bằng X trong lớp học
118
6. Cho biết điểm trung bình cao nhất trong lớp học là
bao nhiêu
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

7. Liệt kê tên cùng điểm trung bình của những sinh


viên có điểm trung bình cao nhất trong lớp học.
8. Xóa sinh viên có mã số bằng x trong lớp học, nếu
không có thì thông báo không có
9. Xếp thứ hạng cho các sinh viên trong lớp
10. Sắp xếp danh sách sinh viên tăng theo điểm
trung bình

119
CTDL của DSLK đơn
 Cấu trúc dữ liệu của 1 nút trong List đơn
typedef struct tagNode
{ int Info; // Lưu thông tin bản thân
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

struct tagNode *pNext; //Lưu địa chỉ của Node đứng sau
}Node;
 Cấu trúc dữ liệu của DSLK đơn pNext
typedef struct Info
{ Node *pHead;//Lưu địa chỉ Node đầu tiên trong List
Node *pTail; //Lưu địa chỉ của Node cuối cùng trong
List
}List; // kiểu danh sách liên kết đơn

120
Node *p; //p3f
p->Info//4
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

p->pNext->Info//7
P->pNext->pNext->Info//6

121
Áp dụng cho bài “quản lý sinh viên”

typedef struct
{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

char ten[40];
char MSSV[40];
float ĐTB;
}SV;//Cấu trúc dữ liệu của một sinh viên
typedef struct tagNode
{
SV Info; // Lưu thông tin bản thân
struct tagNode* pNext; // Lưu địa chỉ của Node đứng sau
}Node;
122
 Cấu trúc dữ liệu của DSLK đơn
typedef struct tagList
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

{ Node *pHead;//Lưu địa chỉ Node đầu tiên


trong List
Node *pTail; //Lưu địa chỉ của Node cuối
cùng trong List
}List; // kiểu danh sách liên kết đơn

123
Cách truy xuất đến các thuộc tính của đối tƣợng

Node p,*q;
p.Info.DTB=9.0
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

p->pNext;//sai vì p không là con trỏ


q->Info.DTB=9.0
q.pNext;//sai vì q là con trỏ

124
Ví dụ tổ chức DSLK đơn trong bộ nhớ

pHead
pTail
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

3f 4f 5f
a 4f c 5f b NULL

Trong ví dụ trên thành phần dữ liệu là 1 số nguyên


void main()
{ List l1;
l1.pHead->pNext->Info.ten;
l1.pTail->Info
} 125
Các thao tác cơ bản trên DSLK đơn

 Tạo 1 danh sách liên kết đơn rỗng


 Tạo 1 nút có trường Infor bằng x
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Tìm một phần tử có Info bằng x


 Thêm một phần tử có khóa x vào danh sách
 Hủy một phần tử trong danh sách
 Duyệt danh sách
 Sắp xếp danh sách liên kết đơn

126
Khởi tạo danh sách liên kết

 Địa chỉ của nút đầu tiên, địa chỉ của nút cuối cùng
đều không có
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

void CreateList(List &l)


{
l.pHead=NULL;
l.pTail=NULL;
}

127
Tạo 1 phần tử mới

 Hàm trả về địa chỉ phần tử mới tạo


Node* CreateNode(int x)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

{ Node *p;
p = new Node;//Cấp phát vùng nhớ cho phần tử
if ( p==NULL) exit(1);
p ->Info = x; //gán dữa liệu cho nút
p->pNext = NULL;
return p;
}
128
Áp dụng cho bài quản lý sinh viên

Node* CreateNode(SV x)
{ Node* TamNode;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

TamNode = new Node; //Hàm cấp phát vùng nhớ động


if(TamNode==NULL)
{
printf(“không đủ bộ nhớ để cấp");
exit(1);
}
TamNode->Info =x;//Trường dữ liệu của Node
TamNode->Next = NULL; //Chưa có Node đứng sau
return TamNode;
} 129
Thêm 1 phần tử vào DSLK

 Nguyên tắc thêm: Khi thêm 1 phần tử vào List thì có


làm cho pHead, pTail thay đổi?
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Các vị trí cần thêm 1 phần tử vào List:


 Thêm vào đầu List đơn
 Thêm vào cuối List
 Thêm vào sau 1 phần tử q trong list

130
Thuật toán thêm 1 phần tử vào đầu DSLK

 Thêm nút p vào đầu danh sách liên kết đơn


Bắt đầu:
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

Nếu List rỗng thì


+ pHead = p;
+ pTail = pHead;
Ngược lại
+ p->pNext = pHead;
+ pHead = p

131
Hàm thêm 1 phần tử vào đầu List

void AddHead(List &l, Node* p)


{
if (l.pHead==NULL)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

{
l.pHead = p;
l.pTail = p;
}
else
{
p->pNext = l.pHead;
l.pHead = p;
}
}

132
Minh họa thuật toán thêm vào đầu

pHead 2f 3f 4f
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

3 3f 4 4f 8…
9f
10 2f
N
pHead=P P->pNext=pHead
P

133
Thuật toán thêm vào cuối DSLK

 Ta cần thêm nút p vào cuối list đơn


Bắt đầu:
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

Nếu List rỗng thì


+ pHead = p;
+ pTail = pHead;
Ngược lại
+ pTail->pNext=p;
+ pTail=p

134
Hàm thêm 1 phần tử vào cuối DSLKD

void AddTail(List &l, Node *p)


{
if (l.pHead==NULL)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

{
l.pHead = p;
l.pTail = l.pHead;
}
else
{
l.pTail->Next = p;
l.pTail = p;
}
}
135
Minh họa thuật toán thêm vào cuối

pTail
3f 4f 5f
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

4 4f 8 5f 5N
9f
pTail=P

pTail->pNext 9f
6N
P

136
Thuật toán them phần tử p vào sau phần tử q

 Ta cần thêm nút p vào sau nút q trong list đơn


Bắt đầu:
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

Nếu (q!=NULL) thì


B1: p->pNext = q->pNext
B2:
+ q->pNext = p
+ nếu q = pTail thì
pTail=p

137
Cài đặt thuật toán

void InsertAfterQ(List &l, Node *q, Node *p)


{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

if(q!=NULL)
{
p->pNext=q->Next;
q->pNext=p;
if(l.pTail==q)
l.pTail=p;
}
else
AddHead(l,p);// thêm q vào đầu list
}

138
Minh họa thuật toán

3f 4f q 5f
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

4 4f 8 5f
9f 5 ..
9f
7
q->pNext=P
N
5f
P->pNext=q->pNext
P

139
Chèn sinh viên vào lớp học tăng theo điểm TB

void Chen(List &l,SV sinhvien)


{ Node *Pos,*p,*Tam;//vi tri chua Node can them vao
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

p=l.pHead; Pos=NULL;
while((p!=NULL)&&(p->Info.DTB<sinhvien.DTB))
{ Pos=p;
p=p->Next;
}
Tam=CreateNode(sinhvien); //Hàm tạo một sinh viên
InsertAfterQ(l,Pos,Tam); //Thêm nút Tam vào sau nút Pos
}

140
Hủy phần tử trong DSLK đơn

 Nguyên tắc: Phải cô lập phần tử cần hủy trước hủy.

 Các vị trị cần hủy


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Hủy phần tử đứng đầu List

 Hủy phần tử có khoá bằng x

 Huỷ phần tử đứng sau q trong danh sách liên


kết đơn
 Ở phần trên, các phần tử trong DSLK đơn được cấp phát
vùng nhớ động bằng hàm new, thì sẽ được giải phóng
vùng nhớ bằng hàm delete.
141
Thuật toán hủy phần tử trong DSLK

 Bắt đầu:
 Nếu (pHead!=NULL) thì
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 B1: p=pHead
 B2:
+ pHead = pHead->pNext
+ delete (p)
 B3:
Nếu pHead==NULL thì pTail=NULL

142
Cài đặt thuật toán

 Hủy được hàm trả về 1, ngược lại hàm trả về 0


int RemoveHead(List &l, int &x)
{ Node *p;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

if(l.pHead!=NULL)
{ p=l.pHead;
x=p->Info; //lưu Data của nút cần hủy
l.pHead=l.pHead->pNext;
delete p;
if(l.pHead==NULL)
l.pTail=NULL;
return 1;
}
return 0;
}
143
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Minh hoạ thuật toán

pHead=pHead->pNext
pHead 2f 3f
1f 4f

7 2f 6 3f 3 4f 8 …

P=pHead
P

144
Hủy phần tử sau phần tử q trong List

 Bắt đầu
Nếu (q!=NULL) thì //q tồn tại trong List
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 B1: p=q->pNext;// p là phần tử cần hủy


 B2: Nếu (p!=NULL) thì // q không phải là phần tử cuối
+ q->pNext=p->pNext;// tách p ra khỏi xâu
+ nếu (p== pTail) // nút cần hủy là nút cuối
pTail=q;
+ delete p;// hủy p

145
Cài đặt thuật toán

int RemoveAfterQ(List &l, Node *q, int &x)


{ Node *p;
if(q!=NULL)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

{ p=q->pNext; //p là nút cần xoá


if(p!=NULL) // q không phài là nút cuối
{ if(p==l.pTail) //nút cần xoá là nút cuối cùng
l.pTail=q;// cập nhật lạ pTail
q->pNext=p->pNext; x=p->Info;
delete p;
}
return 1;
}
else
return 0; }
146
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng Minh họa thuật toán

p-=q->pNext
q p
2f 3f
pHead 1f 4f

7 2f 6 4f
3f 3 4f 8 …

q->pNext=p->pNext

147
Thuật toán hủy phần tử có khoá x

Bước 1:
Tìm phần tử p có khoá bằng x, và q đứng trước p
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

Bước 2:
Nếu (p!=NULL) thì //tìm thấy phần tử có khoá bằng x
Hủy p ra khỏi List bằng cách hủy phần tử
đứng sau q
Ngược lại
Báo không tìm thấy phần tử có khoá

148
Cài đặt thuật toán

int RemoveX(List &l, int x)


{ Node *p,*q = NULL; p=l.Head;
while((p!=NULL)&&(p->Info!=x)) //tìm
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

{ q=p;
p=p->Next;
}
if(p==NULL) //không tìm thấy phần tử có khoá bằng x
return 0;
if(q!=NULL)//tìm thấy phần tử có khoá bằng x
DeleteAfterQ(l,q,x);
else //phần tử cần xoá nằm đầu List
RemoveHead(l,x);
return 1;
}
149
Hủy 1 sinh viênc có mã số x – Cách 1

void RemoveX(List &l, char *X)


{ Node *p,*q;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

p=l.Head; q=NULL;
while((p!=NULL)&&(strcmp(p->Info.MSSV,X)!=0))
{ q=p;//lưu Node đứng trước p
p=p->Next;//Qua Node kế
}
if(p==NULL) printf(“không thấy sinh viên MS X”);
else if(q==NULL) RemoveHead(l);
else RemoveAfterQ(l,q);
}
150
Hủy 1 sinh viên có mã số x – Cách 2

void RemoveX(List &l, char *X)


{ Node *p,*q;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

p=l.Head; q=NULL;
while((p!=NULL)&&(strcmp(p->Info.MSSV,X)!=0))
{ q=p;//lưu Node đứng trước p
p=p->pNext;//Qua Node kế
}
if(p==NULL) printf(“không thấy sinh viên MS X”);

151
Hủy 1 sinh viên có mã số x – Cách 2 (tt)
else //Nút tìm thấy là p
{
if(q==NULL) //xóa đầu
{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

l.pHead=p->Next;
if(l.pHead==NULL) l.pTail=NULL
}
else
{ q->pNext=p->pNext;
if(p==l.pTail)
l.pTail = q;
}
delete p;
}
}
152
Tìm 1 phần tử trong DSLK đơn

 Tìm tuần tự (hàm trả về), các bước của thuật toán tìm nút
có Info bằng x trong list đơn
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

Bước 1: p=pHead;// địa chỉ của phần tử đầu trong list đơn
Bước 2:
Trong khi p!=NULL và p->Info!=x
p=p->pNext;// xét phần tử kế
Bước 3:
+ Nếu p!=NULL thì p lưu địa chỉ của nút có
Info = x
+ Ngược lại : Không có phần tử cần tìm

153
Hàm tìm 1 phần tử trong DSLK đơn

 Hàm tìm phần tử có Info = x, hàm trả về địa


chỉ của nút có Info = x, ngược lại hàm trả về
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

NULL

Node *Search(List l, int x)


{ Node *p;
p = l.pHead;
while((p!= NULL)&&(p->Info != x))
p = p->pNext;
return p;
154
Tìm sinh viên có tên x trong lớp học

void Search(List l, char *X)


{ Node *p;
p = l.pHead;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

while((p!= NULL)&&(strcmp(p->Info.ten, X)!=0)


p = p->pNext;
if( p==NULL)
printf(“tim khong thay”);
else
printf(“Tim thay”);
}
 Bài tập: Đếm số sinh viên có tên là X trong lớp
học, nếu không có thì thông báo không có
155
Minh họa thuật toán tìm phần tử trong DSLK

pHead 1f 2f 3f 4f 5f
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

34 3 4 8 56
P

X = 8 Tìm thấy, hàm trả


về địa chỉ của
nút tìm thấy là 4f

156
Duyệt danh sách

 Duyệt danh sách là thao tác thường được thực


hiện khi có nhu cầu cần xử lý các phần tử trong
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

danh sách như:


 Đếm các phần tử trong danh sách
 Tìm tất cả các phần tử trong danh sách thảo
điều kiện
 Hủy toàn bộ danh sách

157
Thuật toán duyệt danh sách

 Bước 1:
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

p = pHead;// p lưu địa chỉ của phần tử đầu trong List

 Bước 2:

Trong khi (danh sách chưa hết) thực hiện

+ xử lý phần tử p

+ p=p->pNext;// qua phần tử kế

158
Cài đặt in các phần tử trong List

void PrintList(List l)
{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

Node *p;
p=l.pHead;
while(p!=NULL)
{ printf(“%d ”, p->Info);
p=p->pNext;
}
}

159
In tên cùng điểm trung bình của sinh viên

void Duyet(List L)
{ Node *P;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

P=L.pHead;
while(P!=NULL)
{
puts(P->Info.ten);
printf(“%f ”, P->Info. ĐTB) ;
P=P->pNext;//qua phần tử kế
}
} 160
In tên cùng điểm trung bình của sinh viên có điểm
trung bình >=5
void Duyet(List L)
{ Node *P;
P=L.pHead;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

while(P!=NULL)
{
if(P->Info.DTB>=5)
{ puts(P->Info.ten);
printf(“%f ”, P->Info. ĐTB);
}
P=P->pNext;//qua phần tử kế
}
161
Hủy danh sách liên kết đơn

 Bước 1:
Trong khi (danh sách chưa hết) thực hiện
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

• B11:
p = pHead;
pHead = pHead->pNext;// cập nhật pHead
• B12:
Hủy p
 Bước 2:
pTail = NULL;// bảo toàn tính nhất quán khi xâu rỗng
162
Cài đặt thuật toán

void RemoveList(List &l)


{
Node *p;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

while(l.pHead!=NULL)//còn phần tử trong List


{
p = l.pHead;
l.pHead = p->pNext;
delete p;
}
l.pTail=NULL;
}

163
Minh họa thuật toán

pHead pTail
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

2f 3f
1f 4f 5f

7 2f 6 3f 3 4f 8 5f 9 N

164
Sắp xếp danh sách

 Có hai cách tiếp cận


 Cách 1: Thay đổi thành phần Info
pHead pTail
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

3f 4f 5f
4 4f 7 5f 6 N

pHead pTail

3f 4f 5f
4 4f 6 5f 7 N

165
Sắp xếp danh sách

 Cách 2: Thay đổi thành phần pNext (thay đổi trình


tự móc nối của các phần tử sao cho tạo lập nên
được thứ tự mong muốn)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

pHead pTail

3f 4f 5f
4 4f 7 5f 6 N

pHead
pTail
3f 4f 5f
4 5f 7 N 6 4f

166
Ƣu, nhƣợc điểm của 2 cách tiếp cận
 Thay đổi thành phần Info (dữ liệu)
 Ưu: Cài đặt đơn giản, tương tự như sắp xếp mảng
 Nhược:
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

• Đòi hỏi thêm vùng nhớ khi hoán vị nội dung của 2
phần tử -> chỉ phù hợp với những xâu có kích thước
Info nhỏ
• Khi kích thước Info (dữ liệu) lớn chi phí cho việc hoán
vị thành phần Info lớn
 Làm cho thao tác sắp xếp chậm
 Thay đổi thành phần pNext
 Ưu:
 Kích thước của trường này không thay đổi, do đó
không phụ thuộc vào kích thước bản chất dữ liệu lưu
tại mỗi nút.
 Thao tác sắp xếp nhanh
167
Dùng thuật toán SX SelectionSort để SX List
void SelectionSort(List &l) while(q!=NULL)
{ {
Node *p,*q,*min;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

if(q->Info<min->Info)
p=l.pHead; min=q;
while(p!=l.pTail) q=q->pNext;
{ }
min=p; Swap(min->Info,p->Info
q=p->pNext; p=p->pNext;
}
}

168
Hàm hoán vị thành phần dữ liệu của 2 nút

void Swap(SV &s1,SV &s2)


{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

SV tam;
tam=s1;
s1=s2;
s2=tam;
}

169
Sắp xếp danh sách sinh viên tăng theo điểm
void SelectionSortList(List &l)
{
Node *p,*q,*min;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

p=l.pHead;
while(p!=l.pTail)
{ min=p;
q=p->pNext;
while(q!=NULL)
{ if(q->Info.DTB<min->Info.DTB)
min=q;
q=q->pNext;
}
Swap(min->Info,p->Info);
p=p->pNext;
}
}
170
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng NỘI DUNG

171
CÂY NHỊ PHÂN TÌM KIẾM
Ðịnh nghĩa cây nhị phân tìm kiếm

 Cây nhị phân


 Bảo đảm nguyên tắc bố trí khoá tại mỗi nút:
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Các nút trong cây trái nhỏ hơn nút hiện hành
 Các nút trong cây phải lớn hơn nút hiện hành

Ví dụ: 18

13 37

15 23 40
172
Ƣu điểm của cây nhị phân tìm kiếm

 Nhờ trật tự bố trí khóa trên cây :


 Định hướng được khi tìm kiếm
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Cây gồm N phần tử :


 Trường hợp tốt nhất h = log2N
 Trường hợp xấu nhất h = N
 Tình huống xảy ra trường hợp xấu nhất?

173
Cấu trúc dữ liệu của cây nhị phân tìm kiếm

 Cấu trúc dữ liệu của 1 nút


typedef struct tagTNode
{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

int Key; //trường dữ liệu là 1 số nguyên


struct tagTNode *pLeft;
struct tagTNode *pRight;
}TNode;
 Cấu trúc dữ liệu của cây
typedef TNode *TREE;

//TREE t;
//Node *t;
174
Các thao tác trên cây nhị phân tìm kiếm

 Tạo 1 cây rỗng

 Tạo 1 nút có trường Key bằng x


CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Thêm 1 nút vào cây nhị phân tìm kiếm

 Duyệt cây nhị phân tìm kiếm

 Xoá 1 nút có Key bằng x trên cây

 Tìm 1 nút có khoá bằng x trên cây

175
Tạo cây rỗng

 Cây rỗng -> địa chỉ nút gốc bằng NULL


void CreateTree(TREE &T)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

{
T=NULL;
}

void main()
{
TREE t;
CreateTree(t);
}
176
Tạo 1 nút có Key bằng x

TNode *CreateTNode(int x)
{
TNode *p;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

p = new TNode; //cấp phát vùng nhớ động


if(p==NULL)
exit(1); // thoát
else
{
p->key = x; //gán trường dữ liệu của nút = x
p->pLeft = NULL;
p->pRight = NULL;
}
return p;
} 177
Thêm một nút x
 Rằng buộc: Sau khi thêm cây đảm bảo là cây nhị
phân tìm kiếm.
int insertNode(TREE &T, TNode *p)
{ if(T!=NULL)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

{ if(T->Key == p->Key) return 0; //trung khoa


else
if(T->Key > p->Key)
return insertNode(T->pLeft, p);
else
return insertNode(T->pRight, p);
}

T=p;
return 1;
} 178
Minh họa thêm 1 phần tử vào cây

44 44 < X
Theâm X=50
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

18 88 > X 88

13 37 59 108
59 > X

15 23 40 55 71
55 > X

50
179
Minh hoạ thành lập 1 cây từ dãy số
9, 5, 4, 8, 6, 3, 14,12,13
9
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

5 1
4

4 8 12

3 6 13

180
Tìm nút có khoá bằng x (không dùng đệ quy)
TNode * searchNode(TREE Root, int x)
{ TNode *p = Root;
while (p != NULL)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

{ if(x == p->Key)
return p;
else
if(x < p->Key)
p = p->pLeft;
else
p = p->pRight;
}
return p;
}
181
 Void main()
 { TREE t1;
TNode *p;
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

int x;
Nhap x can tim
p=SearchNode(t1,x);
if(p==NULL)
printf(“Tim khong thay” );
else
in du lieu tai p;

 }
182
Tìm nút có khoá bằng x (dùng đệ quy)

TNode *SearchTNode(TREE T, int x)


{
if(T!=NULL)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

{
if(T->key==x)
return T;
else
if(x>T->key)
return SearchTNode(T->pRight,x);
else
return SearchTNode(T->pLeft,x);
}
return NULL;
}
183
Minh hoạ tìm một nút

44
Tìm X=55
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

55
18 88

13 37 59 108

15 23 40 55 71

Tìm thấy X=55


184
Duyệt cây nhị phân tìm kiếm

 Có 6 phép duyệt cây như sau


 NLR (gốc, trái, phải)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 NRL (gốc, phải, trái)


 LNR (trái, gốc, phải)
 RNL (Phải, gốc,trái)
 LRN (trái, phải, gốc)
 RLN (phải, trái, gốc)

185
Thuật toán duệt cây nhị phân tìm kiếm

void NLR(TREE t)
{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

if(t!=NULL)
{
printf(“%d”, t->key);
NLR(t->pLeft);
NLR(t->pRight);
}
}

186
Thuật toán duệt cây nhị phân tìm kiếm

void LNR(TREE t)
{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

if(t!=NULL)
{
LNR(t->pLeft);
printf(“%d ”,t->key);
LNR(t->pRight);
}
}

187
Bài tập cho phần duyệt cây

Viết chương trình thực hiện các yêu cầu sau:


1. Đếm số nút trên cây
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

2. Tình tổng tất cả các khóa trên cây


3. Đếm số nút lá trên cây
4. Đếm số nút có duy nhất 1 cây con
5. Đếm số nút có 2 cây con
6. Cho biết khoá lớn nhất trong cây là bao nhiêu
7. Cho biết khóa nhỏ nhất trong cây là bao nhiêu

188
Viết hàm đếm số nút trong cây
void Dem(TREE t,int &s)
{
if(t!=NULL)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

{
s++;
Dem(t->pLeft,s);
Dem(t->pRight,s);
}
}
Void main()
{ TREE t1;
s=0;
Dem(t1,s);
}
189
Lời gọi hàm

void main()
{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

TREE t;
int s=0;
Dem(t,s);
printf(“so nut trong cay :=%d”,s);
}

190
9
8
2
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

1 5
6

12 4
10 3

 NLR: 9, 2, 6, 1, 10, 8, 5, 3, 7, 12, 4.


 LNR: 6, 2, 10, 1, 9, 3, 5, 8, 12, 7, 4.
 LRN: 6,10,1, 2, 3, 5, 12, 4, 7, 8,9
191
Hủy 1 nút có khoá bằng X trên cây

 Hủy 1 phần tử trên cây phải đảm bảo điều kiện ràng buộc
của Cây nhị phân tìm kiếm
 Có 3 trường hợp khi hủy 1 nút trên cây
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 TH1: X là nút lá
 TH2: X chỉ có 1 cây con (cây con trái hoặc cây con phải)
 TH3: X có đầy đủ 2 cây con
 TH1: Ta xoá nút lá mà không ành hưởng đến các nút khác
ttrên cây
 TH2: Trước khi xoá x ta móc nối cha của X với con duy
nhất cùa X.
 TH3: Ta dùng cách xoá gián tiếp
192
Minh hoạ hủy phần tử x có 1 cây con

Hủy X=37 44
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

18 88

13 37 59 108

15 23 55 71

193
Hủy 1 nút có 2 cây con

 Ta dùng cách hủy gián tiếp, do X có 2 cây con


 Thay vì hủy X ta tìm phần tử thế mạng Y. Nút Y có tối đa 1
cây con.
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

 Thông tin lưu tại nút Y sẽ được chuyển lên lưu tại X.
 Ta tiến hành xoá hủy nút Y (xoá Y giống 2 trường hợp
đầu)
 Cách tìm nút thế mạng Y cho X: Có 2 cách
 C1: Nút Y là nút có khoá nhỏ nhất (trái nhất)
bên cây con phải X
 C2: Nút Y là nút có khoá lớn nhất (phải nhất)
bên cây con trái của X

194
Minh họa hủy phần tử X có 2 cây con

Xoá nút có trƣờng


44
Key = 18, lúc đó nút có
khoá 23 là nút thế mạng
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

18 88

13 37 59 108

15 23 40 55 71

30
195
Cài đặt thao tác xoá nút có trƣờng Key = x

void DeleteNodeX1(TREE &T,int x)


{
if(T!=NULL)
{
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

if(T->Key<x) DeleteNodeX1(T->Right,x);
else
{
if(T->Key>x) DeleteNodeX1(T->Left,x);
else //tim thấy Node có trường dữ liệu = x
{ TNode *p;
p=T;
if (T->Left==NULL) T = T->Right;
else
{ if(T->Right==NULL) T=T->Left;
else ThayThe1(p, T->Right);// tìm bên cây con phải
}
delete p;
}
}
}
else printf("Khong tim thay phan can xoa tu");}

196
Hàm tìm phần tử thế mạng
void ThayThe1(TREE &p, TREE &T)
{ if(T->Left!=NULL)
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

ThayThe1(p,T->Left);
else
{
p->Key = T->Key;
p=T;
T=T->Right;
}
}
197
Tóm lƣợt các nội dung cần nắm
1. Các thuật toán tìm kiếm và sắp xếp
+ Cài đặt hàm tìm kiếm của 2 thuật toán tìm kiếm
+ Cài đặt hàm sắp xếp của các thuật toán sắp xếp
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT 1_Mai Xuân Hùng

+ Ghi kết quả từng bước khi áp dụng các thuật toán tìm
kiếm và sắp xếp vào 1 bộ dữ liệu cho trước
2. Áp dụng sách liên kết để giải quyết 1 bài toán trong đời
sống thực tế.
+ Quản lý sinh viên
+ Quản lý nhân viên trong 1 công ty.
+ Quản lý sách trong thư viện..vv
3. Cây nhị phân tìm kiếm
+ Vẽ hình dạng của cây khi thêm lần lượt 1 dãy số vào cây
+ Cho biết kết quả khi duyệt cây theo 1 thứ tự cho trước
+ Vẽ hình dạng của cây khi xoá 1 nút trên cây
+ Viết hàm tìm kiếm 1 nút trên cây, duyệt cây, đếm…
198

Вам также может понравиться