Sắp xếp theo kiểu : Quick sort

Chia sẻ: Đặng Quang Hưng | Ngày: | Loại File: DOC | Số trang:9

0
220
lượt xem
64
download

Sắp xếp theo kiểu : Quick sort

Mô tả tài liệu
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Nếu đoạn đó có ít hơn 2 khóa thì không cần làm gì cả,nếu đoạn đó có ít nhất 2 khóa,ta chọn một khóa ngẫu nhiên nào đó làm chốt(pivot).Mọi khóa nhỏ hơn khóa chốt được xếp vào vị trí đứng trước chốt,mọi khóa lớn hơn chốt được xếp vào vị trí sau chốt.Sau phép hoán chuyển như vậy thì đoạn đang xét được chia làm 2 đoạn khác rỗng mà mọi khóa trong đoạn đầu đều =chốt

Chủ đề:
Lưu

Nội dung Text: Sắp xếp theo kiểu : Quick sort

  1. Thuật toán dựa trên kỹ thuật chia để trị,được đề xuất bởi C.A.R Hoare Ý tưởng như sau:Sắp xếp dãy khóa k[1..n] thì có thể coi là sắp xếp đoạn từ chỉ số 1 tới chỉ số n trong dãy khóa đó. Nếu đoạn đó có ít hơn 2 khóa thì không cần làm gì cả,nếu đoạn đó có ít nhất 2 khóa,ta chọn một khóa ngẫu nhiên nào đó làm chốt(pivot).Mọi khóa nhỏ hơn khóa chốt được xếp vào vị trí đứng trước chốt,mọi khóa lớn hơn chốt được xếp vào vị trí sau chốt.Sau phép hoán chuyển như vậy thì đoạn đang xét được chia làm 2 đoạn khác rỗng mà mọi khóa trong đoạn đầu đều =chốt.Vấn đề trở thành sắp xếp 2 đoạn mới được tạo ra (độ dài ngắn hơn độ dài đoạn ban đầu ) bằng phương pháp tương tự (gọi đệ quy) Độ phức tạp là O(n*lgn) #include #include #define MAX 10000 char *input="day_so.inp"; float a[MAX]; int N; void quick_sort(int l,int r) { float tg; float pivot; int i,j; if (l
  2. /* Doc du lieu vao tu FILE */ f=fopen(input,"r"); fscanf(f,"%d",&N); for (i=0;i
  3. Quick sort là phương pháp đổi chỗ từng phần (partition exchange), đây là phương pháp rất hiệu quả, rất thông dụng.. Nội dung của phương pháp này như sau: Chọn một nút bất kỳ trong danh sách(Giả sử là nút đầu tiên) gọi là nút làm trục (pivot node), xác định vị trí hợp lệ của nút này trong danh sách (gọi là vị trí pivot). Tiếp theo chúng ta phân hoạch các nút còn lại trong danh sách cần sắp xếp sao cho từ vị trí 0 đến vị trí pivot-1 đều có nội dung nhỏ hơn hoặc bằng nút làm trục, các nút từ vị trí pivot+1 đến n-1 đều có nội dung lớn hơn nút làm trục. Quá trình lại tiếp tục như thế với hai danh sahs con từ trị trí 0 đến vị trí pivot-1 và từ vị trí pivot+1 đến vị trí n-1, ... Sau cùng chúng ta sẽ được danh sách có thứ tự. Mô tả giải thuật Quick sort Code: Giai thuat: QuickSort(nodes[], low, up) Mo Ta; Giair thuat QuickSort, dung phuong phap de qui sawp xep va cac nut trong danh sach giua hai vi tri low va up Du Lieu nhap: - Danh sach cac nut chua sap xep (giua hai vi tri low va up) - low va up Du Lieu Xuat: Danh sach cac nut (giua hai vi tri low va up) da duoc sap xep Hanh dong if(low >= up) // dieu kien dung ket thuc giai thuat if(low < up) - Phan hoach: partition(nodes[], low, up, pivot) + partition phan danh sach thanh ba phan: * nut lam truc: nodes[low] tro thanh nodes[pivot] * danh sach con 1: nodes[i] nodes[pivot] (voi i > pivot) - Goi de qui: QuickSort(nodes[], low, pivot-1) - Goi de qui: QuickSort(nodes[], pivot+1, up) Ket Thuc Giải thuật Partion vấn đề tiếp theo là giải thuật partition giúp phân danh sách làm ba phần: • Nút đầu (nút làm trục) đặt ở vị trí pivot • Danh sách con 1 từ vị trí low đến pivot-1 có nội dung nhỏ hơn hay bằng nút làm trục. • Danh sách con 2 từ vị trí low đến pivot+1 có nội dung lớn hơn hay bằng nút làm trục. Người ta xử lý giải thuật partition theo mô tả như sau: 1. Chọn nodes[low] (nút đầu tiền) là nút làm trục. 2. Quét danh sách theo hai hướng để đổi chỗ các cặp nút "sai" vị trí, nơi gặp nhau của hai hướng quét chính là vị trí pivot:
  4. Quét từ low lên: con trỏ l xuất phát từ vị trí low và tăng dần lên, dừng lại khi gặp nút có nội dung lớn hơn nút làm trục, ghi nhận vị trí l lúc này. • Quét từ up xuống: con trỏ u xuất phát từ vị trí up và giảm dần xuống, dừng lại khi gặp nút có nội dung nhỏ hơn hay bằng nút làm trục, ghi nhận vị trí u lúc này. • Đổi chỗ hai nút tại vi trí l và u. • Cứ tiếp tục quét theo hai hướng và đổi chỗ các cặp nút "sai" vị trí, quá trình này dừng lại khi l = u (hai hướng quét gặp nhau), nợi gặp nhau chính là vị trí pivot (pivot = u = l). 3. Đổi chỗ hai nút tại vị trí low (nút làm trục) và nút tại vị trí pivot. Sau đây là giải thuật partition Code: Giai Thuat: partition(nodes[], low, up, pivot) Mo Ta: Giai thuat partition, phan danh sach thanh 3 phan ... Du Lieu Nhap: Danh sach cac nut trong khoang vi tri tu low den up. Du Lieu Xuat: Dua nut lam truc ve vi tri pivot, doi cho cac nut trong danh sach sao cho cac nut co noi dung nho hon hay bang nut lam truc duoc bo tri truoc nut lam truc, cac nut co noi dung lon hon nut lam truc duoc bo tri sau nut lam truc. Hanh Dong 1. Chon nodes[low] la nut lam truc Gan: l = low; u = up; 2. while(l < u) // vong lap xu ly hai huong quet { Quet huong tu low len, dung lai khi gap nut lon hon nut lam truc, ghi nhan vi tri l luc nay Quet huong tu up xuong, dung lai khi gap nut nho hon hay bang nut lam truc, ghi nhan vi tri u luc nay Doi cho hai nut tai hai vi tri l va u } 3. Doi cho hai nut tai hai vi tri low va u (luc nay pivot = u) Ket Thuc Cài đặt giải thuật QuickSort Sau đây là hàm QuickSort() dùng phương pháp đệ qui, hàm này có gọi hàm partition() để phân hoạch danh sách con thành 3 phần. Hàm QuickSort() void QuickSort(int nodes[], int low, int up) { int pivot; if(low >= up) // dieu kien dung return;
  5. if(low < up) { partition(nodes, low, up, &pivot); QuickSort(nodes, low, pivot - 1); QuickSort(nodes, pivot + 1, up); } } Hàm partition(): void partition(int nodes [], int low, int up, int *pivot) { int nuttruc, l, u, temp; nuttruc = nodes[low]; // Chon nut dau lam nut truoc l = low; u = up; while(l < u) { while(nodes[l] nuttruc) u--; if(l < u) { // doi cho cap nut sai vi tri temp = nodes[l]; nodes[l] = nodes[u]; nodes[u] = temp; } } // doi cho hia nut tai low va u (luc nay u la vi tri nut truc) nodes[low] = nodes[u]; nodes[u] = nuttruc; *pivot = u; } Nhận xét, so sánh • Quick Sort phức tạp hơn Bubble Sort nhưng hiệu quả hơn. • Quick Sort thích hợp cho danh sách ban đầu chưa có thứ tự. • Quick Sort kém hiệu quả khi danh sách ban đầu gần có thứ tự. Đặc biệt với danh sách dã có thứ tự (lớn dần hoặc nhở dần) lại là trường hợp xấu nhất của giải thuật Quick Sort. Chương trình minh họa sắp xếp một mảng kiểu int #include #include void partition(int nodes [], int low, int up, int *pivot); void QuickSort(int nodes[], int low, int up) { int pivot;
  6. if(low >= up) // dieu kien dung return; if(low < up) { partition(nodes, low, up, &pivot); QuickSort(nodes, low, pivot - 1); QuickSort(nodes, pivot + 1, up); } } void partition(int nodes [], int low, int up, int *pivot) { int nuttruc, l, u, temp; nuttruc = nodes[low]; // Chon nut dau lam nut truoc l = low; u = up; while(l < u) { while(nodes[l] nuttruc) u--; if(l < u) { // doi cho cap nut sai vi tri temp = nodes[l]; nodes[l] = nodes[u]; nodes[u] = temp; } } // doi cho hia nut tai low va u (luc nay u la vi tri nut truc) nodes[low] = nodes[u]; nodes[u] = nuttruc; *pivot = u; } void main() { int mang[7]; for(int i = 0;i < 7;i++) { cout
  7. } QuickSort(mang, 0, 7); cout
  8. Ý tưởng: Gần giống như merge sort , ta sẽ chia đôi mảng cần xếp rồi sắp xếp các mảng con , sau đó sẽ ghép mảng con đã sắp xếp thành mảng ban đầu nhưng đã sắp xếp Điểm khác nhau: Là chổ ta chia đôi mảng con theo nguyên tắc riêng : Gọi điểm mà tại đó ta chia đôi mảng ban đầu có trị là pivot (không nhất thiết là nằm đúng vị trí chính giữa . Nhưng giải thuật sẽ chạy tốt nếu nó nằm gần điểm chính giữa) và ta sẽ không cần merge 2 dãy con (do đó nhìn chung sẽ chạy nhanh hơn ) , thỏa điều kiện là tất cả những phần tử bên trái pivot đều nhỏ hơn pivot và nằm bên phải pivot thì lớn hơn pivot VD : 2 4 6 7 18 14 13 Ta chọn phần tử pivot = 7 ( do bên trái của nó nhỏ hơn pivot = 7 , bên phải lớn hơn pivot = 7 ) (Thực ra ta phải tìm pivot , do ở đây làm bằng tay nên dễ thấy ) Chia đôi : A = { 2 4 6 } B = { 18 14 13 } + Sắp A + Trong dãy A ta cũng chọn phần tử pivot là 4 + Được 2 dãy con là A11 = {2 } A12 = {6} + Sắp A11 ( sắp sẵn rồi ) + Sắp A12 ( sắp sẵn rồi ) + Tạo lại mảng A = { A11 được sắp , pivot , A12 được sắp } = {2 4 6 } +Sắp B . Trong B ta không thấy được pivot do chọn cái nào ta cũng không thấy thỏa . Nhưng mục tiêu của quick sort là làm sao ta được dãy pivot < D= dãy có trị lớn hơn pivot > Sắp 2 dãy con C , D rồi ghép lại ta được dãy sắp thứ tự . Vì vậy áp dụng một giải thuật tìm pivot trong B( sẽ trình bày sau ) ta sẽ được C = { 13} D = {18} và pivot là 14 . + Sắp dãy con C , D ( do chỉ có một phần tử nên không sắp , hoặc tìm pivot) + Ghép lại tạo thành mảng B được sắp B = { 13 14 18 } +Ghép A và B để tạo thành mảng được sắp xếp ban đầu Code: void Sortable_List::quick_sort() { recursive_quick_sort(0 , count -1 ) ; } void Sortable_List::recursive_quick_sort(int low , int high ) { int pivot_position ; if (low < high ) { pivot_position = partition (low , high ) ; recursive_quick_sort(low , high ) ; recursive_quick_sort(pivot_position +1 , high ) ;
  9. } } int Sortable_List::partition(int low , int high ) { Record pivot ; int i , last_small; swap ( low , (low +high) /2 ; pivot = entry[low] ; last_small = low ; for ( i = low +1 ; i
Đồng bộ tài khoản