快速排序的實現過程包括兩個主要部分:分割和遞歸。
創(chuàng)新互聯(lián)是專業(yè)的王屋網站建設公司,王屋接單;提供成都網站設計、做網站、成都外貿網站建設公司,網頁設計,網站設計,建網站,PHP網站建設等專業(yè)做網站服務;采用PHP框架,可快速的進行王屋網站開發(fā)網頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網站,專業(yè)的做網站團隊,希望更多企業(yè)前來合作!首先選取一個基準元素(通常是數組的第一個元素)。
從數組的左端開始,掃描整個數組,如果當前元素小于基準元素,就交換它和基準元素前面的元素,掃描結束后,基準元素左邊的元素都比它小,右邊的元素都比它大。
然后將基準元素與數組的最后一個元素交換,這樣基準元素就位于數組的中間位置,左邊的元素都比它小,右邊的元素都比它大。
接下來,對基準元素左右兩邊的子數組分別重復上述過程,直到左右子數組的元素個數小于等于1。
整個排序過程通過遞歸來實現,遞歸的終止條件是左右子數組的元素個數小于等于1。
通過這樣的分治和遞歸過程,可以將原始數組排序為有序數組。
需要注意的是,在選擇基準元素時需要注意避免最壞情況發(fā)生,例如每次都選擇大或最小的元素作為基準元素。
快速排序的時間復雜度為O(nlogn),空間復雜度為O(logn) ~ O(n)
代碼模板#includeusing namespace std;
void qsort(int a[], int l, int r) {
int i = l, j = r, flag = a[(l + r) / 2];
do {
while (a[i]< flag) i++;
while (a[j] >flag) j--;
if (i<= j) swap(a[i], a[j]), i++, j--;
} while (i<= j);
if (i< r) qsort(a, i, r);
if (j >l) qsort(a, l, j);
}
int main() {
int n;
cin >>n;
int a[n];
for (int i = 0; i< n; i++)
scanf("%d", &a[i]);
qsort(a, 0, n - 1);
for (int i = 0; i< n; i++)
cout<< a[i]<< ' ';
return 0;
}
//注意模板中有很多小細節(jié)
sort函數sort(a, a+n) //表示從a[0]到a[n-1]升序排列
sort(a+1, a+n+1) //表示從a[1]到a[n]升序排列
sort(a, a+n, cmp) //cmp是自定義函數,返回的是排序規(guī)則,比如return x >y,表示前一個大于后一個,也就是降序排列
例題1:獎學金(洛谷P1093)
優(yōu)化前#includeusing namespace std;
const int N = 305;
int student[N][4], number[N], sum[N];
bool cmp(int x, int y) {
return ((sum[x] >sum [y]) || (sum[x] == sum[y] && student[x][1] >student[y][1]) ||
(sum[x] == sum[y] && student[x][1] == student[y][1] && x< y));
}
int main() {
int n;
cin >>n;
for (int i = 1; i<= n; i++) {
number[i] = i;
cin >>student[i][1] >>student[i][2] >>student[i][3];
sum[i] = student[i][1] + student[i][2] + student[i][3];
}
sort(number + 1, number + 1 + n, cmp);
for (int i = 1; i<= 5; i++) {
cout<< number[i]<< ' '<< sum[number[i]]<< endl;
}
return 0;
}
優(yōu)化后#include#include
using namespace std;
const int N = 305;
int chinese[N], id[N], sum[N]; //改成一維數組,只記錄語文成績
bool cmp(int x, int y) {
return
sum[x] >sum [y] ||
sum[x] == sum[y] && chinese[x] >chinese[y] ||
sum[x] == sum[y] && chinese[x] == chinese[y] && x< y;
}
int main() {
int n;
cin >>n;
for (int i = 1; i<= n; i++) {
int math, english; //英語和數學成績不重要,不用記錄
id[i] = i;
cin >>chinese[i] >>math >>english;
sum[i] = chinese[i] + math + english;
}
sort(id + 1, id + 1 + n, cmp);
? ?
? ? //比如原來id[1]=1,id[2]=2...
? ? //現在 id[1]=5,id[2]=6...
? ? //成績最好的成績記為編號1,他的學號是id[1],成績是sum[id[i]]
for (int i = 1; i<= 5; i++) {
cout<< id[i]<< ' '<< sum[id[i]]<< endl;
}
return 0;
}
兩種不常用算法
冒泡排序冒泡排序是一種簡單的排序算法,它重復地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。
冒泡排序的實現過程如下:
首先,將第一個元素與第二個元素進行比較,如果第一個元素大于第二個元素,就交換這兩個元素的位置。
接著,將第二個元素與第三個元素進行比較,如果第二個元素大于第三個元素,就交換這兩個元素的位置。
按照上面的方式,重復地將相鄰的元素進行比較和交換,直到比較到數組的最后一個元素。
此時,數組的最后一個元素就是大的元素。
重復上面的過程,但是不再比較最后一個元素,因為它已經是大的元素了。
接著,重復上面的過程,但是不再比較倒數第二個元素,因為它已經是第二大的元素了。
以此類推,直到整個數組都有序。
冒泡排序的時間復雜度為O(n^2),空間復雜度為O(1)
代碼模板#includeusing namespace std;
const int N = 100;
int main() {
int a[N];
int n;
cin >>n;
for (int i = 0; i< n; i++)
cin >>a[i];
for(int i = 0; i< n-1; i++)
for(int j = 0; j< n-i-1; j++){
if(a[j] >a[j+1]) swap(a[j], a[j+1]);
}
for (int i = 0; i< n; i++)
cout<< a[i]<< ' ';
return 0;
}
計數排序計數排序是一種非比較型排序算法,它適用于數據范圍較小的情況。
它的基本思想是,對于待排序的數組中的每一個元素,確定其在整個數組中出現的次數,然后根據這個次數將元素放到最終結果的對應位置上。
具體實現過程如下:
創(chuàng)建一個計數數組 counts,用來存儲每個元素在數組中出現的次數。
遍歷待排序的數組,統(tǒng)計每個元素出現的次數,存入 counts 數組中。
遍歷 counts 數組,將 counts[i] 個元素 i 放入結果數組的對應位置。
返回結果數組。
由于計數排序是一種線性排序算法,因此時間復雜度為 O(n),空間復雜度為 O(k),其中 n 為數組大小,k 為數據范圍。
由于計數排序不需要進行元素之間的比較,因此它是一種穩(wěn)定排序算法。但是,由于它的空間復雜度隨著數據范圍的增大而增大,所以它在數據范圍較大的情況下不太適用。
計數排序需要預先知道數據的范圍
代碼模板#includeusing namespace std;
const int MAX = 100; //數組元素的大值
const int N = 100;
int arr[N], counts[MAX];
int main() {
int n; //數組的長度
cin >>n;
for (int i = 0; i< n; i++) {
cin >>arr[i];
counts[arr[i]]++;
}
int j = 0;
for (int i = 0; i< MAX; i++) { //遍歷0到大值,根據之前統(tǒng)計的每個數字的個數,來給數組重新賦值
while (counts[i]--) {
arr[j++] = i;
}
}
for (int i = 0; i< n; i++) {
cout<< arr[i]<< " ";
}
return 0;
}
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧