快速排序及其優化和快速選擇演算法

2021-10-25 10:11:18 字數 3200 閱讀 9002

本文主要內容是快速排序的**編寫及其優化,還有快速選擇演算法(在無序的數中尋找第k大或小的元素)

上**:

#include #include #include #include #include #include #include #include #include #include using namespace std;

#define max_n 10000

// arr :用來儲存待排序的元素

// n :代表元素數量

// output :輸出過程中的除錯資訊

// debug = 1 開啟除錯資訊

// debug = 0 關閉除錯資訊

int arr[max_n + 5];

int n;

#define debug 1

void output(int,int,int);

// 快速排序: 對arr中 l 到 r 位進行排序

// arr: 待排序陣列

// l : 待排序區間起始座標

// r : 待排序區間結束座標

void quick_sort(int *arr,int l,int r)

//將基準值pivot放到陣列x位

arr[x] = pivot;

output(l,x,r);

quick_sort(arr,l,x-1);

quick_sort(arr,x+1,r);

return;

}void output(int l,int x,int r)

for(int i = 1; i < l; i++) printf("%d ",arr[i]);

printf("[");

for(int i = l; i <= r; i++)

printf("]");

for(int i = r + 1; i <= n; i++) printf("%d ",arr[i]);

printf("\n");

for(int i = 0; i < cnt; i++) printf(" ");

printf("^\n");

for(int i = 0; i < cnt; i++) printf(" ");

printf("|\n");

printf("\n");

return;

}void read_data()

while(getchar() != '\n');

return;

}int main()

printf("\n");

return 0;

}

下面再來看下對快速排序的優化。

主要分三點優化:

1)單邊遞迴優化--本層函式呼叫中完成本層的partition後,依舊在本層對左半邊進行partition,對右半邊進行遞迴呼叫,這樣一來,函式呼叫的次數會減半,大大降低了演算法的時間複雜度.

2)基準值選擇優化--三點取中,對排序區間最左邊的值、中間值、最右邊的值進行取中值作為基準值,這樣會使得演算法的時間複雜度穩定在o(nlogn)

3)對partition操作進行優化,利用兩個指標分別從前向後、從後向前,交換比基準值小和比基準值大的元素,直到兩指標相遇.

看**:

#include #include #include #include #include #include #include #include #include #include #include using namespace std;

#define time(func) ()

void quick_sort_old(int *arr, int l, int r)

arr[x] = z;

quick_sort_old(arr, l, x - 1);

quick_sort_old(arr, x + 1, r);

return ;

}int select_value(int a, int b, int c)

void quick_sort_new(int *arr, int l, int r)

}while(x <= y);

quick_sort_new(arr,x,r);

//單邊遞迴優化

r = y;

}return;

}#define max_n 1000000

int a1[max_n + 5], a2[max_n + 5];

void test_one(int t)

int t1 = time(quick_sort_old(a1,0,max_n - 1));

int t2 = time(quick_sort_new(a2,0,max_n - 1));

printf("第%d輪測試,quick_sort_old(%dms), quick_sort_new(%dms)\n", t, t1, t2);

return;

}void test_random(int n)

return;

}int main()

看完上述**,相信你對快速排序演算法有了一定的認知,如果我問你,如何在無序的數中選擇第k大的元素呢,我們的第一反應可能是對所有元素排序,然後取第k大的元素,仔細想想,有必要嗎?

其實,在我們完成一次partition操作之後,我們就可以知道基準值的排名, 假設為ind,我們可以比較ind和k的大小,如果ind和k相等,那麼基準值就是第k大的值,如果ind比k大,那麼我們只需在左半邊遞迴查詢第k大的值即可,如果ind比k小,那麼我們只需在右半邊遞迴查詢第k-ind大的值即可,因為已經可以排除左半邊的元素,而左半邊的元素有ind個。

這樣說你理解了嗎?接下來看**如何實現.

//arr :待查詢陣列

//l--r:待查詢區間

//k :待查詢元素的排名

//在arr陣列的l到r區間內,查詢排名為k的元素

int quick_select()

arr[x] = z;

//ind為當前基準值的排名

int ind = x - l + 1;

if(ind == k) return arr[x];

if(ind > k) return quick_select(arr,l,x-1,k);

return quick_select(arr,x+1,r,k-ind);

}

快速排序及其優化

include include 呼叫c 自帶sort include include include using namespace std define max 1000000 define k 12 ifdef debug define new new normal block,file lin...

快速排序及其優化

快速排序是比較經典 常用的演算法,下面簡要介紹其思路。對於乙個陣列,選取某個元素作為切分元素 比如第乙個元素 然後把比這個元素小的都放到它前面,比這個元素大的都放到它後面,這樣切分元素的最終位置就確定了,並且陣列被劃分為兩個子陣列。然後再用同樣的方法分別對子陣列進行排序,最終整個陣列將變成有序的。這...

快速排序及其優化

package com.zc.algorithm public class quicksort 如果不大於,則把右邊的數賦值給左邊 arr left arr right 如果左邊的數小於基數,則向右移動 while left arr right 把最大值放在陣列的末尾 if arr mid arr ...