這道題用傳統快排(如下所示)的結果就是最後三個點tle:
void swap(int &a, int &b)
void quicksort(int a, int left, int right)
quicksort(a, left, i-1);
quicksort(a, j+1, right);
}
因為快排對於一些特殊的情況(例如序列原本就有序、有大量重複元素等等)會進行很多完全不必要的操作,耗費大量時間。為此,我們基於上述普通快速排序演算法一步步進行優化。
如果永遠取第乙個元素作為樞軸的話,在陣列已經有序的情況下每次劃分都將得到最壞的結果,時間複雜度退化為o(n^2)。因為其中乙個子串行每次都只比原序列少乙個元素,該側的遞迴深度將達到最大。
然而,我們可以通過隨機選取樞軸元素來打破這種固定模式,這樣每次都是最壞劃分的概率就非常小了。實現起來只需要先將隨機選中的元素和第乙個元素交換一下位置作為樞軸元素,然後就可以接著用原來的方法進行排序了。
void quicksort(int a, int left, int right)
quicksort(a, left, i-1);
quicksort(a, j+1, right);
}
當序列長度分割到足夠小後,繼續使用快速排序遞迴分割的效率反而沒有直接插入排序高。因此我們可以增加乙個判斷,當區間長度小於10以後改為使用插入排序。
void insertsort(int a, int left, int right)
void quicksort(int a, int left, int right)
** int i = left, j = right, pivot = rand() % (right - left + 1) + left;
swap(a[left], a[pivot]);
while (i < j)
quicksort(a, left, i-1);
quicksort(a, j+1, right);
}
void quicksort(int a, int left, int right)
int i = left, j = right, k, flag = 0, pivot = rand() % (right - left + 1) + left;
swap(a[left], a[pivot]);
//到這以前都和原來一樣,主要就是下面的兩個子while迴圈裡分別增加了乙個大的if判斷
while (i < j)
if (k == i) //如果k等於i,說明沒找到,這時i和j之間都是重複元素了
flag = 1; //標記表明聚攏已完成
break;
}else continue; //如果找到了乙個異於樞軸元素的元素完成了交換,那麼繼續向前掃瞄
}j--;
}if (flag) break; //如果聚攏已完成,則直接跳出大迴圈進行分割,i無需再向後掃瞄
while (i < j && a[i] <= a[left]) //i向後掃瞄的過程基本類似
}if (k == j)
else continue;
}i++;
}if (flag) break;
//這裡以後也和原來一樣
swap(a[i], (i == j) ? a[left] : a[j]);
}quicksort(a, left, i-1);
quicksort(a, j+1, right);
}
為了追求更快的速度,建議用scanf()和printf()來進行輸入輸出。經過這幾步優化,最後快排終於也能順利通過了!
完整ac**如下:
#include #include #include #include using namespace std;
int n, a[100010];
void swap(int &a, int &b)
void insertsort(int a, int left, int right)
void quicksort(int a, int left, int right)
int i = left, j = right, k, flag = 0, pivot = rand() % (right - left + 1) + left;
swap(a[left], a[pivot]);
while (i < j)
if (k == i)
flag = 1;
break;
}else continue;
}j--;
}if (flag) break;
while (i < j && a[i] <= a[left])
}if (k == j)
else continue;
}i++;
}if (flag) break;
swap(a[i], (i == j) ? a[left] : a[j]);
}quicksort(a, left, i-1);
quicksort(a, j+1, right);
}int main()
洛谷 P1177 模板 快速排序
洛谷 p1177 模板 快速排序 1.翻書,該題很容易解決,但不算掌握。2.憑空編寫,邊界點的取值有些問題,等號去還是不取。3.想了乙個辦法,寫出一組資料進行手動模擬,弄明白了,程式再開始根據模擬進行編制。4.很久沒寫快排了,如果能一次性編寫成功,這次可以說快排掌握了。5.開始動手,6.第一次取a ...
洛谷 P1177 模板 快速排序
利用快速排序演算法將讀入的 n 個數從小到大排序後輸出。快速排序是資訊學競賽的必備演算法之一。對於快速排序不是很了解的同學可以自行上網查詢相關資料,掌握後獨立完成。c 選手請不要試圖使用stl,雖然你可以使用sort一遍過,但是你並沒有掌握快速排序演算法的精髓。第 1 行為乙個正整數 n,第 2 行...
洛谷 P1177 模板 快速排序
題目所在 題面說是快排的板子題,可將純純快排的板子扔上去之後 t 的一塌糊塗.看來沒這麼簡單。對於快排,我的理解,一趟快排所做的事 從結果上來看 就是 把標準值扔到它最終該待的地方並且使它左邊的值都小於它,右邊的值都大於它。把這個過程扔到遞迴中去做足夠多的的次數,就能夠使一串數字排好順序。我們知道,...