Tải bản đầy đủ (.docx) (13 trang)

CÁC GIẢI THUẬT SẮP XẾP (CÓ VÍ DỤ CỤ THỂ)

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (156.77 KB, 13 trang )

Giải Thuật Selection Sort
 Ý tưởng thuật toán


Ta chọn phần tử nhỏ nhất trong N phần tử ban đầu, đưa phần tử này về đầu
dãy hiện hành.



Sau đó, ta không quan tâm đến nó nữa, ta xem dãy hiện hành chỉ còn N-1
phần tử của dãy ban đầu tính từ vị trí thứ 2.



Cứ vậy, cho đến khi dãy hiện hành chỉ còn 1 phần tử, ta được 1 dãy sắp
tăng.

 Mã CODE
void SelectionSort(int arr[],int spt)
{
int i,j,min;
for(i = 0;i < spt -1; i++)
{
min = i;
for ( int j = i+1; j < spt; j++)
{
if (arr[j] < arr[min])
{
swap( arr[min], arr[j] );
}
}


}


}
 Ví dụ minh họa
 Độ phức tạp
o Để chọn được phần tử nhỏ nhất, ta cần duyệt qua n phần tử (tốn
n-1 phép so sánh) và sau đó hoán vị nó với phần tử đầu tiên của
dãy hiện hành. Để tìm phần tử nhỏ nhất tiếp theo, ta cần duyệt qua
n-1 phần tử (tốn n-2 phép so sánh). Cứ như vậy, ta thấy ngay thuật
toán sẽ tốn (n-1) + (n-2) + … + 1 = n(n-1)/2 = O(n2) phép so sánh.
o Mỗi lần duyệt, ta luôn phải hoán vị 1 lần (1 hoán vị tương
đương với 3 phép gán), nghĩa là thuật toán sẽ tốn 3(n-1) + 3(n-2) +
… + 3 = 3n(n-1)/2 = O(n2) phép gán.

Tổng kết lại, ta luôn có độ phức tạp của thuật toán Selection Sort là O(n2)
trong mọi trường hợp.
Sưu Tầm

Giải Thuật Merge Sort
 Ý tưởng thuật toán
+ Cho dãy ban đầu a1, a2, …, an. Ta luôn có thể coi nó là tập hợp
liên tiếp của các dãy có thứ tự. Ta gọi các dãy có thứ tự này là các
dãy con.
+ Trong phương pháp Merge Sort, vấn đề là ta tìm cách phân hoạch
dãy ban đầu thành các dãy con. Sau khi phân hoạch xong, dãy ban
đầu sẽ được tách thành hai dãy phụ theo nguyên tắc phân phối luân
phiên dãy con. Sau đó, ta trộn từng cặp dãy con của hai dãy phụ
thành một dãy con của dãy ban đầu. Ta nhận thấy số dãy con của
dãy ban đầu lúc này giảm đi ít nhất là một nửa. Cứ thế sau một số

bước, ta sẽ nhận được dãy ban đầu với số dãy con bằng 1, có nghĩa
là ta đã sắp xếp xong.
+ Trộn trực tiếp: đây là phương pháp trộn đơn giản nhất. Việc phân
hoạch dãy ban đầu đơn giản như sau: Với dãy ban đầu có n phân tử,
ta cứ phân hoạch thành n dãy con. Vì rằng mỗi dãy con chỉ có 1


phần tử nên nó là dãy có thứ tự. Cứ mỗi lần tách – trộn, chiều dài
của dãy con sẽ được nhân đôi.
 Mã CODE
void Merge( int A[] , int a , int c , int b)
{
int i = a;
int j = c + 1;
int k = 0;
int n = b - a + 1;
int B[n];
while (( i < c +1 ) && ( j < b +1 ))
if ( A [i] < A[j])
B[k ++] = A[i ++];
else
B[k ++] = A[j ++];
while ( i < c + 1)
B[k ++] = A[i++];
while ( j < b +1)
B[k ++] = A[ j ++];
i = a;
for ( k = 0 ; k < n ; k ++)
A[i ++] = B [k];
}



void MergeSort( int A[ ], int a, int b)
{
if (a < b)
{
int c = (a + b)/2;
MergeSort(A,a,c);
MergeSort(A,c+1,b);
Merge(A,a,c,b);
}
}
 Ví dụ minh họa
 Độ phức tạp

T(n)=

C1

nếu n=1

2T()+C2n nếu n>1

Vì T()=21T()+C2*

Nên T(n)= 2[ 21T()+C2*] + C2n
= 4T()+C2n+C2n
= 4T()+2C2n



= 22T()+2C2n
Vì T()=21T()+C2*
Nên T(n) = 23T()+3C2n
 T(n) = 2iT()+iC2n

Giả sử n=2k
Logarit 2 vế  log22k=log2n
 k=log2n
T(n)= nT(1) + log2n*C2n

Độ phức tạp : O(nlog2n)
Sưu Tầm

Giải Thuật Heap Sort
 Ý tưởng thuật toán
Để tìm phần tử nhỏ nhất ở bước i, phương pháp sắp xếp chọn trực tiếp
đã không tận dụng được các thông tin đã có được do các phép so sánh
ở bước i-1. Phương pháp Heap Sort khắc phục được nhược điểm này.
o Định nghĩa heap:
 Giả sử xét trường hợp sắp xếp tăng dần, khi đó Heap
được định nghĩa là một dãy các phần tử a l,..,ar thoã các
quan hệ sau với mọi i [l,r]
 ai  a2i
 ai  a2i+1
(ai,a2i), (ai,a2i+1) là các cặp phần tử liên đới
o Tính chất của heap:
 Tính chất 1: Nếu al,.,ar là một Heap thì khi cắt bỏ một số
phần tử ở hai đầu của Heap thì dãy con còn lại vẫn là một
Heap .
 Tính chất 2: Nếu các phần tử a1,..,an là một Heap thì



phần tử a1 (đầu heap) luôn là phần tử lớn nhất trong Heap.
 Tính chất 3: Mọi dãy al,al+1,…,ar với 2l > r là một Heap
o Giải thuật
Giải thuật heap sort gồm hai giai đoạn sau:
 Giai đoạn 1: Hiệu chỉnh dãy số ban đầu thành Heap
 Giai đoạn 2: Sắp xếp dãy số dựa trên Heap
o Bước 1:Đưa phần tử lớn nhất về vị trí đứng ở cuối dãy
 r = n;
 Hoán vị (a1,ar)
o Bước 2: Loại bỏ phần tử lớn nhất ra khỏi Heap r=r-1;
 Hiệu chỉnh phần còn lại của dãy từ al đến ar thành một
Heap.
o Bước 3:Nếu r >1 ( heap còn phần tử) : lặp lại bước 2
 Ngược lại: dừng
o Dựa vào tính chất 3, ta có thể thực hiện giai đoạn 1 bằng cách
bắt đầu từ heap mặc nhiên an/2+1, an/2+2,…,an, lần lượt thêm vào các
phần tử an/2, an/2-1,…,a1. ta sẽ nhận được Heap theo mong muốn.
Như vậy giải đoạn 1 tương đương với n/2 lần thực hiện bước 2 của
giai đoạn 2.
o Cài đặt
o Để cài đặt Heap sort cần xây dựng một số thủ tục phụ trợ:
1.Thủ tục hiệu chỉnh một dãy al,ar thành heap
o Giả sử có al,al+1,…ar, trong đó đoạn al+1,…ar, đã là một heap. ta
cần xây dựng al,al+1,…,ar thành một heap. để làm điều này ta lần
lượt xét quan hệ của một phần tử a i nào đó với các phần tử liên đới
của nó trong dãy là a2i và a2i+1, nếu nó vi phạm quan hệ của heap
thì đổi chổ ai với phần tử liên đới thich hợp của nó – việc đổi này
có thể gây phản ứng dây chuyền.

2.Hiệu chỉnh ao,..,an-1 thành heap.
 Cho một dãy bất kỳ al,…,ar , theo tính chất 3 ta có dãy
an/2+1, an/2+2,…,an đã là một heap. Ghép thêm phần tử an/2 vào
bên trái của heap hiện hành và hiệu chỉnh lại dãy
an/2,an/2+1,..,ar thành heap.
 Mã CODE
void Tao_heap(int a[], int Left,int Right, int &gan, int &ss)
{
int khonglantruyen =0 , max;
gan ++;
do
{
ss++ ;
if( (2*Left) == Right) // co 1 lien doi
{
max = 2*Left;
gan++ ;
}
ss++;


if((2*Left) < Right) // co 2 Leftien doi
{
ss++;
if(a[2*Left - 1] > a[2*Left]) // tim max 2 lien doi
{
max = 2*Left; gan ++;
}
else
{

max = 2*Left+1; gan++;
}
}
ss++;
if(a[max -1] > a[Left -1]) // dua phan tu max ve dau
{
hoanvi(&a[Left -1],&a[max -1]); gan+=3;
Left = max; gan++;
khonglantruyen =0; gan++;
}
else
{
khonglantruyen = 1;
gan ++;
}
ss++;gan++;
}
while ( (2*Left <= Right) && (khonglantruyen == 0) );
}
void Heap_sort(int a[],int n, int &gan, int &ss)
{
int Right, Left;
for(Right=n , gan++, ss++ ; Right>1 ; Right--, gan++) // ss++ la lan dau tien ss dieu kien, lan
sau khong con gia tri nua
{
for(Left = Right/2, gan++ , ss++ ; Left>=1 ; Left--, gan++) // Tim phan tu lon nhat ve dau
{
Tao_heap(a,Left,Right,gan,ss);
ss++; // So sanh dieu kien vong lap 2
}

hoanvi(&a[0],&a[Right-1]); gan+=3;
ss++; // So sanh dieu kien vong lap 1
}
}

 Ví dụ minh họa
Cho 1 dãy gồm các số nguyên : 5 6 1 9 8 6
STT

l

j
a[0]

a[1]

a[2]

a[3]

a[4]

a[5]


0
2

4


5

6

1

9

8

6

1

3

5

6

8

9

1

6

0


1

5

9

8

6

1

6

1

2

9

5

8

6

1

6


2

5

9

8

5

6

1

6

0

5

9

8

6

6

1


5

0

1

5

8

6

6

1

9

1

2

8

5

6

6


1

9

0

4

8

6

5

6

1

9

0

1

1

6

5


6

8

9

1

3

6

1

5

6

8

9

0

3

6

6


5

1

8

9

0

1

1

6

5

6

8

9

1

2

6


1

5

6

8

9

0

2

6

5

1

6

8

9

1
2
3
4

5
6
7
8
9
10
11
12
13
14


15
0

1

1

5

6

6

8

9

0


1

5

1

6

6

8

9

1

5

6

6

8

9

16
17


 Độ phức tạp



Trường hợp tốt nhất : dãy đã được sắp xếp sẵn=> độ phức tạp là
O(1)



Trường hợp xấu nhất : O(nlog2n)

Sưu Tầm

Giải Thuật Tìm Kiếm Nhị Phân
 Ý tưởng thuật toán
Tiến hành so sánh phần tử cần tìm cho trước với phần tử nằm ở vị trí giữa của dãy
tìm kiếm , dựa vào kết quả so sánh này để quyết định giới hạn dãy tìm kiếm ở
bước tiếp theo là nửa trên hay nửa dưới của phần tử giữa được so sánh cho đến
khi đoạn so sánh bằng 0.
 Mã CODE
int timnhiphan(int a[], int n, int x)
{
int left=0 ; right=n-1 ;
int mid ;


do {
mid=(left+right)/2 ;
if(x==a[mid]) return mid ;
else if(x

else left=mid+1 ;
} while(left<=right) ;
return -1 ;
}

 Ví dụ minh họa
Cho dãy số a : 12 8 2 14 3 5
Tìm x=3
left =0, right=5, mid=3
12

8

2

14

3

5

14

3

5

x=3

left =4, right=5, mid=4

12

8

2

x=3

Tìm thấy x=3


 Độ phức tạp
Trường hợp tốt nhất a[mid]= x .
T(n)=T(1)

O(1)

Trường hợp xấu nhất O(log2n)
Sưu Tầm

Giải Thuật Tìm Kiếm Tuyến Tính(tuần
tự)
 Ý tưởng thuật toán
Tìm kiếm tuyến tính là một kỹ thuật đơn giản.Thuật toán tiến hành so sánh phần
tử đã cho trước với các phần tử thứ nhất ,thứ hai … của mảng cho đến khi tìm
thấy phần tử hoặc đã tìm hết mảng mà không thấy phần tử.
 Mã CODE
int TimTuyenTinh(int a[],int n,int x)
{
int i=0 ;

a[n]=x ;
while(a[i] !=x) i++ ;
if(i==n) return -1 ;
else
return i ;
}
 Ví dụ minh họa


Cho dãy số a : 12 8 2 14 3 5
Tìm x=3
i=0
12

8

2

14

3

5

14

3

5


14

3

5

14

3

5

x=3

i=1
12

8

2

x=3

i=2
12

8

2


x=3

i=3
12

8

2

x=3


i=4
12

8

2

14

3

5

x=3

Tìm thấy x=3
 Độ phức tạp
Trường hợp tốt nhất a1= x .T(n)=T(1)


O(1)

Trường hợp xấu nhất không tìm thấy phần tử x
T(n)=T(n)

O(n)

Sưu Tầm

Link tham khảo: />


×