排序和顺序统计学(2)——快速排序
快排我接觸的也比較多了,從之前NOIP的時候算法老師講的版本,到之前數據結構課上學習的版本,到現在《算法導論》里講的版本,我個人并不能不能區別它們的好壞,權且都寫出來,以后再來區別。三種實現方式如下:
noip:
void qsort1(int *a,int l,int r)
{
int i,j,mid,temp;
i=l;j=r;mid=a[(i+j)/2];
while(i<=j)
{
while(a[i]<mid) i++;
while(a[j]>mid) j--;
if(i<=j)
{
temp=a[i];a[i]=a[j];a[j]=temp;
i++;j--;
}
}
if(l<j) qsort1(a,l,j);
if(i<r) qsort1(a,i,r);
}
思路即是選取中間數作為參考值,i,j分別從兩端向另外一端枚舉,然后從左邊找到一個比它小的數,從右邊找到一個比它大的數,互換位置,直到i,j位置互調,然后進行下一輪遞歸。
數據結構:
int partition(int *a,int l,int r)
{
int temp;
while(l<r)
{
while(l<r&&a[l]>=flag) l++;
temp=a[l];a[l]=a[r];a[r]=temp;
while(l<r&&a[r]<=flag) l++;
temp=a[l];a[l]=a[r];a[r]=temp;
}
return l;
}
void qsort2(int *a,int l,int r)
{
if(l<r)
{
int flag = partition(a,l,r);
qsort2(a,l,flag-1);
qsort2(a,flag+1,r);
}
}
這個實現就是遇到大的就往后移,遇到小的就往前移。
算法導論:
int partition(int *a,int l,int r)
{
int i,j,x,temp;
x=a[r];
i=l-1;
for(j=l;j<r;j++)
if(a[j]<x)
{
i++;
temp=a[i];a[i]=a[j];a[j]=temp;
}
temp=a[i+1];a[i+1]=a[r];a[r]=temp;
return i+1;
}
void qsort3(int *a,int l,int r)
{
if(l<r)
{
int flag = partition(a,l,r);
qsort3(a,l,flag-1);
qsort3(a,flag+1,r);
}
}
算法格式上來說,算法導論的版本與數據結構類似,但是思路上有些不同:算法導論是維護一個相鄰的小隊列,當發現隊列右端的數比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大小時使用插入排序,最好情況即此。
?
轉載于:https://www.cnblogs.com/kangyun/p/4356735.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的排序和顺序统计学(2)——快速排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tiny4412 串口驱动分析九 ---
- 下一篇: listview 的 selection