快排我接觸的也比較多了,從之前noip的時候演算法老師講的版本,到之前資料結構課上學習的版本,到現在《演算法導論》裡講的版本,我個人並不能不能區別它們的好壞,權且都寫出來,以後再來區別。三種實現方式如下:
noip:
void qsort1(int *a,int l,int r)
}if(l資料結構:
int partition(int *a,int l,int r)
{int temp;
while(l=flag) l++;
temp=a[l];a[l]=a[r];a[r]=temp;
while(l這個實現就是遇到大的就往後移,遇到小的就往前移。
演算法導論:
int partition(int *a,int l,int r)
{int i,j,x,temp;
x=a[r];
i=l-1;
for(j=l;jif(l演算法格式上來說,演算法導論的版本與資料結構類似,但是思路上有些不同:演算法導論是維護乙個相鄰的小佇列,當發現佇列右端的數比flag標籤小時,就將它與佇列中的乙個數調換,這樣可以輕易地將待排序陣列分為四段:最左側 l~i均小於flag,i+1~j均大於flag,j+1~r-1為未排序,r處即是flag標籤。
po完了三種版本的**,再來談一下快速排序,快排顧名思義就是非常快的排序,它是一種原地排序演算法(不需要輔助陣列),不穩定的,同時它的期望值是較為理想的o(nlgn),但最壞情況下會達到o(n^2)。
下面講述快排的幾種優化方法。
第一點,怎麼變穩定。這個應該不難,就是新增乙個標號陣列,記錄未排序時各元素的下標(b[i]=i),排序時加入雙關鍵字(先按照大小排,大小相同按照標號排)即可,這種方法對於快速排序的時間複雜度影響不是很大,因此有必要時可以這樣修改以適應不同情況。
第二點,快速排序的最壞情況是o(n^2),即每次劃分都劃分成(1,n-1)這樣的集合,這是我們無論如何也不想看到的情況。因此我們可以引入隨機化快排。
對於第一種版本,只要對mid進行小操作即可(mid=a[(l+r)/2]改為mid=a[random(l,r)]) //此處存疑,因為看了演算法導論之後才清楚認識到快排的最壞情況是什麼,這個演算法每次將集合劃分為等長的兩部分,按理說深度是lgn的,但之前好多情況過不了題目,後來使用隨機化確實過掉了。
第二種版本我並不知道如何使用隨機化-。-
第三種版本則是在x的選擇上動手腳(x=a[r]改為x=random(l,r);swap(a[x],a[r]);x=a[r];)這樣就從l,r之間隨機選擇了乙個數作為x,而不是原本的a[r]。
第三點,跟歸併排序的優化類似,就是在劃分到足夠小的集合時使用插入排序,這個在另一篇文章裡已經說過了,應當將集合劃分為lgn大小時使用插入排序,最好情況即此。
排序和順序統計學(演算法導論)
1.堆排序 堆資料結構是一種陣列物件,它可以被視為一顆完全二叉樹。存放時利用了二叉樹,父親節點序號 i 子節點序號 2 i,2 i 1 的性質 堆的建立,調整,輸出例項如下 include include includeusing namespace std root從data 1 開始存起 我想到...
演算法導論之排序和順序統計學
排序 對n個數的序列重排過程。待排序的數,一般是選擇記錄中資料集的關鍵字key作為排序的值,而資料集中其他資料 稱為 衛星資料 以key為中心移動。實際上,對於排序過程中,key的移動和交換,衛星資料並不定跟著,只要記錄的指標隨key交換即可,將資料移動量減小到最小。關鍵字和衛星資料所構成的資料集,...
中位數和順序統計學
1 最大值和最小值 對大小為n的陣列求最大值或最小值,僅需比較n 1次即可。minmum a,n min a 0 for i 1 iif a i min a i 對最大值也是如此。若同時取得最大值和最小值,按照上述方法,需比較2 n 1 次。事實上,至多3 2n次即可同時求得最大值和最小值。成對成對...