經常使用排序算法 持續更新

前言

開坑!而後。。。沒有而後 就這樣
github地址html


提綱

  1. 插入排序&希爾排序
  2. 計數排序
  3. 選擇排序
  4. 冒泡排序
  5. 快速排序
  6. 歸併排序
  7. 基數排序
  8. 桶排序
  9. 堆排序
  10. 列排序

1.插入排序&希爾排序

插入排序( insertion sort )

就是找到原有序序列中新元素要插入的位置而後把新元素放進去git

核心代碼:github

for (j=1;j<n;j++)
{
    key=s[j];
    i=j-1;
    while ((i>=0)&&(s[i]>key))
    {
        s[i+1]=s[i];
        i=i-1;
    }
    s[i+1]=key;
}

時間複雜度: O(n^2)
空間複雜度: O(1)
算法穩定性: 穩定算法

希爾排序( shell sort )

是直接插入排序的改進版本, 也稱縮小增量排序。簡單的說就是把序列分組處理shell

核心代碼:api

for (gap=n/2;gap>0;gap/=2)
{
    for (i=0;i<gap;i++)
    {
        for (j=i+gap;j<n;j+=gap)
        {
            key=s[j];
            k=j-gap;
            while ((k>=0)&&(s[k]>key))
            {
                s[k+gap]=s[k];
                k=k-gap;
            }
            s[k+gap]=key;
        }
    }
}

時間複雜度: O(n^1.25) (時間複雜度根據增量變化)
空間複雜度: O(1)
算法穩定性: 不穩定數組


2.計數排序(counting sort)

計數排序對輸入的數據有附加的限制條件:函數

  1. 輸入的線性表的元素屬於有限偏序集S;
  2. 設輸入的線性表的長度爲n,|S|=k(表示集合S中元素的總數目爲k),則k=O(n)。

(PS:好像要跑至關遠啊有限偏序集,先放着,恩)優化

個人理解是 在 1 4 7 6 2 3 這個數列中,比4小的有三個,那毫無疑問生成的數列(1 2 3 4 6 7)中4排在第四位
計數排序是一個非基於比較的排序算法,並且須要處理重複數據的情形 比較排序算法下界O(nlogn) 因此這個算法有時候會比比較排序算法快ui

核心代碼:

for (i=0;i<=k;i++)
    c[i]=0;
for (j=0;j<n;j++)
    c[s[j]]++;
for (i=1;i<=k;i++)   
    c[i]=c[i]+c[i-1];
for (j=n-1;j>=0;j--)
{
    out[c[s[j]]-1]=s[j];
    c[s[j]]=c[s[j]]-1;
}

時間複雜度: O(n+k)

假設n個輸入元素中的每個都是在0到k區間內的一個整數,其中k爲某個整數。當k=O(n)時,運行時間爲O(n)。——《算法導論》

空間複雜度: O(n+k)
算法穩定性: 穩定


3.選擇排序(selection sort)

選出數列中最小的那個放在第一位 重複這個過程就好啦

核心代碼:

for (i=0;i<n-1;i++)
{
    min=i;
    for (j=i+1;j<n;j++)
        if (s[j]<s[min])
            min=j;
    swap=s[i];s[i]=s[min];s[min]=swap;
}

時間複雜度: O(n^2)

空間複雜度: O(1)
算法穩定性: 不穩定


4.冒泡排序(bubble sort)

把小的元素一點點往前調 好像泡泡本身冒上來23333333

核心代碼:

for (j=0;j<n-1;j++)
{
    for (i=0;i<n-1-j;i++)
        if (s[i]>s[i+1])
        { swap=s[i];s[i]=s[i+1];s[i+1]=swap;}
}

時間複雜度: O(n^2)
空間複雜度: O(1)
算法穩定性: 穩定


5.快速排序(quick sort)

經過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的全部數據都比另一部分的全部數據都要小,而後再按此方法對這兩部分數據分別進行快速排序,整個排序過程能夠遞歸進行,以此達到整個數據變成有序序列。

快排,之前是靠背的,如今。。。仍是很難本身寫
不過竟然有qsort( )在stdlib.h裏面真開心hhhh

頭文件:stdlib.h
用 法: void qsort(void base,int nelem,int width,int (fcmp)(const void ,const void ));
參數:
1 待排序數組首地址
2 數組中待排序元素數量
3 各元素的佔用空間大小
4 指向函數的指針,用於肯定排序的順序
(來自 百度百科)

而後 據我一個高中NOIP的同窗說 他用快排都是直接STL的 查了一下STL裏面有個sort( ) 好的我決定留坑STL sort 函數實現詳解 by fengcc

核心代碼:

int quicksort(int *a,int l,int r)
 {
     int i,j,key;

     if ( l>=r ) return 0;
     i=l;j=r;key=a[i];
     while (i<j)
     {
         while ((i<j)&&(key<=a[j]))
             j--;
         a[i]=a[j];
         while ((i<j)&&(key>=a[i]))
             i++;
         a[j]=a[i];
     }
     a[i]=key;
     quicksort(a,l,i-1);
     quicksort(a,i+1,r);
     return 0;
 }

時間複雜度: O(nlogn)
空間複雜度: O(logn)
算法穩定性: 不穩定


6.歸併排序(merge sort)

分治法,對兩個子序列歸併排序

核心代碼:

int MergeSort(int *a,int le,int ri)
 {
     int q;
     if (le<ri)
     {
         q=(le+ri)/2;
         MergeSort(a,le,q);
         MergeSort(a,q+1,ri);
         Merge(a,le,q+1,ri);
     }
 }

時間複雜度: O(nlogn)
空間複雜度: O(n)
算法穩定性: 穩定


7.基數排序(radix sort)

基數排序是先按最低有效位進行排序來解決卡片排序問題的。 ——《算法導論》

看起來很反常規可是我簡單的這樣理解
較高有效位進行比較的時候能夠忽視較低有效位,換言之較高有效位和較低有效位不是在一個層次上
因此較高位的變化不會影響到較低位已經排好的順序

核心代碼:

int dig[N];
int di=1,k=0,flag=1,wid;//1 still have a number having k on digit i
while (flag==1)
{
    flag=0;
    wid=pow(10,di);
    for (k=0;k<n;k++)
    {
        dig[k]=(x[k]/(wid/10))%10;
        if (x[k]/wid!=0) flag=1;
    }   
    int i=0,j=0,c[N],y[N];
    for (i=0;i<=10;i++)
        c[i]=0;
    for (j=0;j<n;j++)
        c[dig[j]]++;
    for (i=1;i<=10;i++)   
        c[i]=c[i]+c[i-1];
    for (j=n-1;j>=0;j--)
    {
        y[c[dig[j]]-1]=x[j];
        c[dig[j]]=c[dig[j]]-1;
    }
    for (i=0;i<n;i++)
        x[i]=y[i];
    di++;
}

時間複雜度: O(d(n+k)) (給定n個d位數,每個數位有k個可能取值) PS:程序中採用 k=10
空間複雜度: O(kd+n)
算法穩定性: 穩定

8.桶排序(BucketSort)

桶排序將[0,1)區間劃分紅n個相同大小的子區間,或稱爲桶。而後,將n個輸入數分別放到各個桶中。
咱們先對每一個桶中的數進行排序,而後遍歷每一個桶,按照次序把各個桶的元素列出來便可。 ——《算法導論》

核心代碼:

for (i=0;i<n;i++)
{
    j=0;
    while (!((min+step*j<=a[i])&&(min+step*(j+1))))
    {
        j++;
    }
    b[j][next[j]]=a[i];
    next[j]++;
}
for (i=0;i<length;i++)
    InsertionSort(next[i],b[i]);
int now=0;
for (i=0;i<length;i++)
{
    for (j=0;j<next[i];j++)
    {
        a[now]=b[i][j];
        now++;
    }
}

時間複雜度: O(n)
空間複雜度: O(n+m)(m爲桶的數量)
算法穩定性: 穩定

9.堆排序(HeapSort)

二叉堆是一個數組,它能夠被當作一個近似的徹底二叉樹 ——《算法導論》

二叉堆能夠分爲最大堆和最小堆。最大堆除根節點外的節點i都知足下列不等式A[PARENT(i)]>=A[i]

開始的時候,堆排序把數據建成一個最大堆,因爲數組中最大元素總在根節點A1中,只要不斷「取出」當前狀態下的A1,排序就能夠完成。

核心代碼:

int HeapSize;//還沒有「取出」的元素數
int HeapLength;//總元素數

int HeapSort(int *arr,int n)
{
    HeapLength=n;
    int b[N],i,temp;

    ChangeArray(arr,b,n);//將從0開始的數組改成從1開始,方便計算子節點和父節點的座標
    BuildMaxHeap(b);

    for (i=HeapLength;i>=2;i--)
    {
        temp=b[1];
        b[1]=b[i];
        b[i]=temp;
        HeapSize-=1;
        MaxHeapify(b,1);//重構新的最大堆
    }

    RecoverArray(b,arr,n);//恢復數組爲從0開始
    return 0;

}

時間複雜度: O(nlgn)
空間複雜度: O(1)
算法穩定性: 不穩定

僞·後記 2017.01.14

排序題很經典,因此真的要的話這些排序一搜就會有更好的歸納
爲何我還要寫呢?
又是初中複賽的那幾天(咦我爲何要說又),我第一次聽到了「桶排序」這個概念。不記得怎麼提起來的反正我是一臉懵逼的 可是當時動規都還沒太懂就要考試了就放一邊去了
而後就沒有而後了(瞬間想起前言的舉爪讓我看見大家
因此此次想起來了,就來作一份,看成是完成一個老早以前的願望罷
順便複習一下快排2333333333333333
嘛 先這樣吧 歸併雖然《算法導論》看過一遍了可是我還不太會
剩下那三個是什麼能夠吃的(疑惑臉
啊 我知道我沒寫各個算法的優化那是由於我還不會 會了我再補上

僞·後記 2017.02.02

用".h"把這些排序作成了一個程序 再補上了歸併和基數 有點小慢……最近有點懈怠呢 快點吧還剩兩個呢 恩

相關文章
相關標籤/搜索