給定陣列大小n和陣列q[n],對陣列進行排序。
快速排序的原理:基於分治
(1)確定分界點x:可以取x為q[l], q[l + r >> 1],q[r], 或者陣列中間隨機乙個值(建議取q[l + r >> 1], 原因在後面說)。這裡l和r是當前待排序陣列的左右端點。
(2)重新調整區間,使得調整後的區間,小於等於x的數都在x的左邊,大於等於x的數都在x的右邊(和x相等的數在左邊、右邊都可)。 調整區間的方法有兩種,後面說。
(3)遞迴處理分界點的左右兩段,最後拼接起來的區間就是有序的了。
調整區間的方法(一):
(1)額外開兩個陣列a, b
(2)掃瞄陣列q[l~r],如果當前的數q[i] <= x, 則把q[i]存入陣列a. 即q[i] -> a;
如果當前的數q[i]>=x,則把q[i]存入陣列b. 即q[i] -> b[i];
(3)此時a, b就分別是q的左半部分和右半部分了,把它們的值賦給q. 即a -> q, b -> q。
這種方法的優點是好理解。缺點也顯而易見:空間開銷大。
調整區間的方法(二):
有一種用雙指標來調整區間的優雅的方法。
(1)一開始,我們讓兩個指標i和j分別指向區間的兩個端點l和r;
(2)當q[i] < x時,i向右移動,若找到q[i] >= x,則i停下。 j向左移動,直到i和j相遇或者q[j] <= x;
(3)若i和j未相遇,則i和j此時指向的元素都是錯位的,交換這兩個數的位置:swap(q[i], q[j]);
(4) 重複上面的步驟,知道i和j相遇。
這種劃分區間方法的正確性證明:在任意時刻,左指標i左邊的數都是小於等於x的,j右邊的數都是大於等於x的,當i與j相遇時,
相遇點左邊的數都小於等於x,相遇點右邊的數都大於等於x,故區間調整正確。
這題**如下:
#includeusing namespace std;
const int n = 1e6 + 10;
int q[n];
void quick_sort(int q, int l, int r)
int x = q[l + r >> 1], i = l - 1, j = r + 1; //分界點x最好取中位數q[l + r >> 1],因為如果取邊界q[l]或者q[r],且區間是公升序或降序時,時間複雜度為o(n^2),在這題會超時
while(i < j)
}quick_sort(q, l, j); //遞迴處理左半部分區間
quick_sort(q, j + 1, r); //遞迴處理右半部分區間
}int main()
quick_sort(q, 0, n - 1);
for(int i = 0; i < n; ++i)
return 0;
}
排序 快速排序模板
以某個記錄 元素 為界 該記錄稱為支點或樞軸 將待排序列分成兩部分 一部分 所有記錄的關鍵字大於等於支點記錄的關鍵字 另一部分 所有記錄的關鍵字小於支點記錄的關鍵字 演算法描述 1 任取待排序記錄序列中的某個記錄 例如取第乙個記錄 作為基準 樞 按照該記錄的關鍵字大小,將整個記錄序列劃分為左右兩個子...
快速排序 模板
說明 經過本函式處理後,陣列itemarray中元素滿足prulefunc itemarray itemr itemarray iteml 為true,其中itemr iteml template t void quicksort itemarray,int iteml,int itemr,bool...
模板 快速排序
排序演算法可以說是從語言步入演算法的第一道坎了,其中最有代表性的莫過於快排。這裡模擬庫函式自帶sort的呼叫方式,寫起來相當自然清爽。樸素快速排序演算法的複雜度最好為o nlogn 最壞時能達到o n include include include include include include d...