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 201 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

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

Giải Thuật Selection Sort  Ý tưởng thuật toán  Ta chọn phần tử nhỏ N phần tử ban đầu, đưa phần tử đầu dãy hành  Sau đó, ta khơng quan tâm đến nữa, ta xem dãy hành N-1 phần tử dãy ban đầu tính từ vị trí thứ  Cứ vậy, dãy hành phần tử, ta dãy tăng  Mã CODE void SelectionSort(int arr[],int spt) { int i,j,min; for(i = 0;i < spt -1; i++) { = i; for ( int j = i+1; j < spt; j++) { if (arr[j] < arr[min]) { swap( arr[min], arr[j] ); } } } }  dụ minh họa  Độ phức tạp o Để chọn 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) sau hốn vị với phần tử dãy hành Để tìm phần tử nhỏ tiếp theo, ta cần duyệt qua n-1 phần tử (tốn n-2 phép so sánh) Cứ vậy, ta thấy thuật toán tốn (n-1) + (n-2) + … + = n(n-1)/2 = O(n2) phép so sánh o Mỗi lần duyệt, ta phải hoán vị lần (1 hoán vị tương đương với phép gán), nghĩa thuật toán tốn 3(n-1) + 3(n-2) + … + = 3n(n-1)/2 = O(n2) phép gán Tổng kết lại, ta ln có độ phức tạp thuật toán Selection Sort O(n2) 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 ln coi tập hợp liên tiếp dãy có thứ tự Ta gọi dãy có thứ tự dãy + Trong phương pháp Merge Sort, vấn đề ta tìm cách phân hoạch dãy ban đầu thành dãy Sau phân hoạch xong, dãy ban đầu tách thành hai dãy phụ theo nguyên tắc phân phối luân phiên dãy Sau đó, ta trộn cặp dãy hai dãy phụ thành dãy dãy ban đầu Ta nhận thấy số dãy dãy ban đầu lúc giảm nửa Cứ sau số bước, ta nhận dãy ban đầu với số dãy 1, có nghĩa ta xếp xong + Trộn trực tiếp: phương pháp trộn đơn giản Việc phân hoạch dãy ban đầu đơn giản sau: Với dãy ban đầu có n phân tử, ta phân hoạch thành n dãy dãy có phần tử nên dãy có thứ tự Cứ lần tách – trộn, chiều dài dãy 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 = ; 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); } }  dụ minh họa  Độ phức tạp T(n)= C1 n=1 2T()+C2n n>1 T()=21T()+C2* Nên T(n)= 2[ 21T()+C2*] + C2n = 4T()+C2n+C2n = 4T()+2C2n = 22T()+2C2n T()=21T()+C2* Nên T(n) = 23T()+3C2n  T(n) = 2iT()+iC2n Giả sử n=2k Logarit 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 tốn Để tìm phần tử nhỏ bước i, phương pháp xếp chọn trực tiếp không tận dụng thông tin có phép so sánh bước i-1 Phương pháp Heap Sort khắc phục nhược điểm o Định nghĩa heap:  Giả sử xét trường hợp xếp tăng dần, Heap định nghĩa dãy phần tử a l, ,ar thoã quan hệ sau với i [l,r]   a2i   a2i+1 (ai,a2i), (ai,a2i+1) cặp phần tử liên đới o Tính chất heap:  Tính chất 1: Nếu al,.,ar Heap cắt bỏ số phần tử hai đầu Heap dãy lại Heap  Tính chất 2: Nếu phần tử a1, ,an Heap phần tử a1 (đầu heap) phần tử lớn Heap  Tính chất 3: Mọi dãy al,al+1,…,ar với 2l > r 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 Heap o Bước 1:Đưa phần tử lớn 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 khỏi Heap r=r-1;  Hiệu chỉnh phần lại dãy từ al đến ar thành Heap o Bước 3:Nếu r >1 ( heap phần tử) : lặp lại bước  Ngược lại: dừng o Dựa vào tính chất 3, ta thực giai đoạn cách heap an/2+1, an/2+2,…,an, thêm vào phần tử an/2, an/2-1,…,a1 ta nhận Heap theo mong muốn Như giải đoạn tương đương với n/2 lần thực bước giai đoạn o Cài đặt o Để cài đặt Heap sort cần xây dựng số thủ tục phụ trợ: 1.Thủ tục hiệu chỉnh dãy al,ar thành heap o Giả sử có al,al+1,…ar, đoạn al+1,…ar, heap ta cần xây dựng al,al+1,…,ar thành heap để làm điều ta xét quan hệ phần tử a i với phần tử liên đới dãy a2i a2i+1, vi phạm quan hệ heap đổi chổ với phần tử liên đới thich hợp – việc đổi gây phản ứng dây chuyền 2.Hiệu chỉnh ao, ,an-1 thành heap  Cho dãy al,…,ar , theo tính chất ta có dãy an/2+1, an/2+2,…,an heap Ghép thêm phần tử an/2 vào bên trái heap hành 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 ++; { ss++ ; if( (2*Left) == Right) // co lien doi { max = 2*Left; gan++ ; } ss++; if((2*Left) < Right) // co Leftien doi { ss++; if(a[2*Left - 1] > a[2*Left]) // tim max 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 1 ; Right , gan++) // ss++ la lan dau tien ss dieu kien, lan sau khong 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 } hoanvi(&a[0],&a[Right-1]); gan+=3; ss++; // So sanh dieu kien vong lap } }  dụ minh họa Cho dãy gồm số nguyên : STT l j a[0] a[1] a[2] a[3] a[4] a[5] 6 9 6 6 6 6 5 6 6 6 1 6 6 6 1 6 6 6 9 10 11 12 13 14 15 1 6 6 6 16 17  Độ phức tạp  Trường hợp tốt : dãy xếp sẵn=> độ phức tạp O(1)  Trường hợp xấu : 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í dãy tìm kiếm , dựa vào kết so sánh để định giới hạn dãy tìm kiếm bước nửa hay nửa phần tử so sánh đoạn so sánh  Mã CODE int timnhiphan(int a[], int n, int x) { int left=0 ; right=n-1 ; int mid ; { mid=(left+right)/2 ; if(x==a[mid]) return mid ; else if(x

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

w