【快速排序】網絡上的挖坑法和一些自己的理解

參考網址:白話經典算法系列之六 快速排序 快速搞定

前言-碎碎念

從學計算機到現在,快速排序至少反覆學了5次了,
第一次沒搞懂,第二次沒記住,第三次忘了重新看,第四次認真背下來,第五次就在兩週前
但是今天騰訊面試官問我的時候,我還是做不出來。有點絕望,好像人生剩下的大多數都是遺忘和遺憾。
有時候想想自己擅長什麼,其實沒什麼擅長的,
問問自己大學四年都學到了什麼,其實好像也沒學到什麼,
問問自己大學四年做成了什麼事,好像也沒做成什麼。
好像還是最初入學考了第一次考試,看着別人拿着20分的滿分,自己拿着13分快不及格的那個自己。
難道我真的是個蠢人嗎……
也許方法不對吧,也許我真的是個沒有毅力的人,
但是我對自己說,至少你還知道很多其他的東西,別放棄啊。
看到的不能若理解無用,理解了才能認識,認識了才能感受它

正題:

挖坑法的核心就是,在序列的某個位置挖一個坑,然後用坑的左右的數字去填坑
例如:(用 # 表示坑)

1 2 4 56 9 5 4 0

k=0的位置挖一個坑:
並且用中間變量把坑裏的數字保存下來 得到# 2 4 56 9 5 4 0
爲了使得序列有序,自然要把大的往右邊挪動,小的往左邊挪動,以坑裏的內容爲參照進行移動。建立遊標i和j,如果j位置的值比坑裏的數字大,j就左移,直到找到比坑裏的數字小的數字,就原地挖坑,把坑裏的東西丟到之前的那個坑裏(無論何時,路上的坑只有一個);然後看i,如果數組在i位置的值比原來坑裏的小,i就右移直到找到比坑裏的數字大的數字,原地挖坑,並填好之前的坑。

i=0           j=8  #=1
# 2 4 56 9 5 4 0

這樣一來比原先的坑大的一定在現在的坑的右邊了,
比原來的坑小的一定在現在的坑左邊了,
把最後挖出來的填到最初的坑裏(所以這個坑的位置就是該數字的位置!
從而可以對坑左右再進行快排(分治的思路),這樣一來,每一次快排都可以找到一個固定的位置
從而得到結果有序。
在這裏插入圖片描述
第一次排出紅圈中內容,第二次排出藍括號內容,
所以說是挖坑+分治
python語言版本:

def quick_sort(li):
    # 被分解的Nums小於1則解決了
    if len(li) <= 1:
        return li
    
    # 分解    
    temp = li[0]
    left = [i for i in li[1:] if i < temp xss=removed>= temp]
    
    # 遞歸求解即分治
    left = quick_sort(left)
    right = quick_sort(right)
    # 合併
    return left + [temp] + right
 
quick_sort(nums2)

C語言版本:

#include <stdio.h>
void print(int a[],int p,int e)
{
    int i=0;
    for(i=p; i<=e; i++)
    {
        printf("%d ",a[i]);
    }
    printf("\n");
}


void quick_sort(int s,int k,int a[])
{
    if(s<k)
    {
        int i=s,j=k;
        int tmp=a[i];
        while(i<j)
        {

            while(i<j && a[j]>=tmp)
            {
                j--;
            }
            if(i<j)
            {
                a[i]=a[j];
                i++;
            }

            while(i<j && a[i]<tmp)
            {
                i++;
            }
            if(i<j)
            {
                a[j]=a[i];
                j--;
            }
        }
        a[i]=tmp;
        quick_sort(s,i-1,a);
        quick_sort(i+1,k,a);
    }


}

int main()
{
    int length;
    scanf("%d", &length);
    int i=0;
    int num[20];
    for(i=0; i<length; i++)
    {
        scanf("%d",&num[i]);
    }
    quick_sort(0,length-1,num);
    for(i=0; i<length; i++)
    {
        printf("%d ",num[i]);
    }
}

進一步:快速排序優化:

參考網址快速排序優化
(1)分而治之時候,分到了最後,數組已經很小,這時候採用插入排序代替快速排序。
(2)基準值的選取,我們隨機取出來3個數,取中間大小的爲基準值。
(3)取三個變量切分數組,將數組分爲大於,等於,小於基準元素三部分,這樣在遞歸時就可以剔除相等的元素,減小比較的次數、

在最優的情況下,快速排序算法的時間複雜度爲O(nlogn)O(nlogn)
在最壞的情況下,最終其時間複雜度爲O(n2)O(n2)
快速排序的平均時間複雜度爲OnlognO(nlog(n))

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章