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

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

13 203 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 13
Dung lượng 33,84 KB

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

Nội dung

Giải Thuật Bubble Sort Giải thuật Bucket Sort hay Bin Sort Giải Thuật Heap Sort Giải thuật Insert Sort Giải Thuật Interchange Sort Giải Thuật Merge Sort Giải Thuật Quick Sort Giải Thuật Radix Sort Giải Thuật Selection Sort Giải Thuật Shell 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 N1 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 (arrj < arrmin) { swap( arrmin, arrj ); } } } }  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 n1 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 n1 phần tử (tốn n2 phép so sánh). Cứ như vậy, ta thấy ngay thuật toán sẽ tốn (n1) + (n2) + … + 1 = n(n1)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(n1) + 3(n2) + … + 3 = 3n(n1)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 Bn; while (( i < c +1 ) ( j < b +1 )) if ( A i < Aj) Bk ++ = Ai ++; else Bk ++ = Aj ++; while ( i < c + 1) Bk ++ = Ai++; while ( j < b +1) Bk ++ = A j ++; i = a; for ( k = 0 ; k < n ; k ++) Ai ++ = 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) + log2nC2n Độ phức tạp : O(nlog2n) Sưu Tầm

Trang 1

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

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] );

}

}

}

Trang 2

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(n 2 ) 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

Trang 3

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];

}

Trang 4

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

Trang 5

= 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(nlog 2 n)

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ử al, ,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ì

Trang 6

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 a l ,a r 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ử ai 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 a o , ,a n-1 thành heap.

 Cho một dãy bất kỳ al,…,ar , theo tính chất 3 ta có dãy

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

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++;

Trang 7

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

a[0] a[1] a[2] a[3] a[4] a[5]

Trang 8

1

2

3

4

5

6

7

8

9

10

11

12

13

14

Trang 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 ;

Trang 10

do {

mid=(left+right)/2 ;

if(x==a[mid]) return mid ;

else if(x<a[mid]) right =mid-1 ;

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

x=3

left =4, right=5, mid=4

x=3

Tìm thấy x=3

Trang 11

Độ 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

Trang 12

Cho dãy số a : 12 8 2 14 3 5

Tìm x=3

i=0

x=3

i=1

x=3

i=2

x=3

i=3

x=3

Trang 13

i=4

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: https://sites.google.com/site/nguoisaigonblog/giai-thuat-sap-xep-tinh-te

Ngày đăng: 02/04/2019, 19:38

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w