排序算法

原博客

1.選擇排序(Selection Sort):

選擇最小元素,移動(dòng)到首位置。

(1)算法描述和實(shí)現(xiàn):

  • 首先選擇數(shù)組中最小的元素,然后與數(shù)組的第一個(gè)元素交換;
  • 再?gòu)氖O碌臄?shù)據(jù)選擇最小的元素,與數(shù)組的第二個(gè)元素交換;
  • 如此往復(fù),直到整個(gè)數(shù)組排序;
template <class E>
void selectSort(E *arr,int n)
{
    for(int i=0;i<n;i++)
    {
        int minIndex=i;
        for(int j=i+1;j<n;j++)
        {
            if(arr[j]<arr[minIndex])
            {
                minIndex=j;
            }
        }
        if(minIndex!=i) swap(arr[i],arr[minIndex]);
    }
}

(2)選擇排序動(dòng)圖演示:


(3)算法分析

時(shí)間復(fù)雜度:

  • 最好情況:Θ(n2)
  • 最差情況:Θ(n2)
  • 平均情況 :Θ(n2)

輔佐空間:

2.冒泡排序(Bubble Sort)

對(duì)相鄰元素進(jìn)行比較調(diào)整的排序算法。它重復(fù)地走過排序的數(shù)列,比較相鄰元素,如果他們的順序錯(cuò)誤就把他們交換過來。如果沒有錯(cuò)誤的順序,說明數(shù)列已經(jīng)排序完成。這個(gè)算法名字的由來是因?yàn)檎麄€(gè)過程就像燒開水一樣,較小值像水中的氣泡一樣往上冒,而每一趟都有一個(gè)最大的元素沉底。

(1)算法描述和實(shí)現(xiàn):

  • <1>.比較相鄰的元素,如果第一個(gè)比第二個(gè)大,兩者交換。
  • <2>.對(duì)每一對(duì)相鄰元素做同樣的工作,從最開始的一對(duì)到最后一對(duì)。這樣,最后一個(gè)元素就是當(dāng)前序列的最大值。
  • <3>.如果中途發(fā)現(xiàn)無逆序元素,則排序結(jié)束;否則當(dāng)只剩下兩個(gè)元素沒排時(shí),排完這一趟就結(jié)束。

無優(yōu)化

template <class E>
void bubbleSort(E *arr,int n)
{
    for(int i=1;i<n;i++)//需要排n-1趟
    {
        for(int j=0;j<n-i;j++)
        {
            if(arr[j]>arr[j+1]) swap(arr[j],arr[j+1]);
        }
    }
}

改進(jìn)冒泡排序 1:設(shè)置一個(gè)標(biāo)志work,如果沒有逆序?qū)Γ瑒t說明序列已經(jīng)有序,算法結(jié)束。

template <class E>
void bubbleSort(E *arr,int n)
{
    int work;
    for(int i=1;i<n;i++)//需要排n-1趟
    {
        work=0;
        for(int j=0;j<n-i;j++)
        {
            if(arr[j]>arr[j+1])
            {
                swap(arr[j],arr[j+1]);
                work=1;
            }
        }
        if(!work) break;
    }
}

改進(jìn)冒泡排序 2:設(shè)置標(biāo)志位pos,用以記錄最后一次進(jìn)行交換的位置。由于pos之后的記錄都已經(jīng)交換到位,故在下一趟排序時(shí)只需要掃描到pos位置即可。

template <class E>
void bubbleSort(E *arr,int n)
{
    int pos,i=n-1;
    while(i>0)
    {
        pos=0;//每趟開始時(shí),無交換記錄
        for(int j=0;j<i;j++)
        {
            if(arr[j]>arr[j+1])
            {
                swap(arr[j],arr[j+1]);
                pos=j;//記錄交換的位置
            }
        }
        i=pos;//為下一趟做準(zhǔn)備
    }
}

改進(jìn)冒泡排序 3:傳統(tǒng)冒泡排序中每一趟排序操作只能找到一個(gè)最大值或最小值,我們考慮利用在每趟排序中進(jìn)行正向和反向兩遍冒泡的方法一次可以得到兩個(gè)最終值(最大者和最小者) , 從而使排序趟數(shù)幾乎減少了一半。

template <class E>
void bubbleSort(E *arr,int n)
{
    int low=0,high=n-1;
    while(low<high)
    {
        for(int i=low;i<high;i++)   //正向冒泡,找到最大值
        {
            if(arr[i]>arr[i+1]) swap(arr[i],arr[i+1]);
        }
        --high;                     //修改high值,前移一位
        for(int j=high;j>low;j--)   //反向冒泡,找到最小值
        {
            if(arr[j]<arr[j-1]) swap(arr[j],arr[j-1]);
        }
        ++low;                      //修改low值,后移一位
    }
}

(2)冒泡排序動(dòng)圖演示:


( 3 )算法分析
時(shí)間復(fù)雜度:

  • 最佳情況:Θ(n)(當(dāng)輸入數(shù)據(jù)為正序時(shí))
  • 最壞情況:Θ(n2)(當(dāng)輸入數(shù)據(jù)為反序時(shí))
  • 平均情況:Θ(n2)

輔佐空間:

3.插入排序(Insertion Sort )

通常人們整理牌的方法是將每一張牌插入到其他有序的牌中的合適位置,插入排序與此類似。

( 1 )算法描述和實(shí)現(xiàn)

  • <1>.從第一個(gè)元素開始,該元素可以認(rèn)為已經(jīng)被排序;
  • <2>.取出下一個(gè)元素,在已經(jīng)排序的元素序列中從后向前掃描;
  • <3>.如果該元素(已排序)大于新元素,將該元素移到下一位置;
  • <4>.重復(fù)步驟3,直到找到已排序的元素小于或者等于新元素的位置;
  • <5>.將新元素插入到該位置后;
  • <6>.重復(fù)步驟2~5。
template <class E>
void insertSort(E *arr,int n)
{
    for(int i=1;i<n;i++)
    {
        E key=arr[i];
        int j=i-1;
        while(j>=0&&arr[j]>key)
        {
            arr[j+1]=arr[j];
            j--;
        }
        arr[j+1]=key;
    }
}

改進(jìn)插入排序:查找合適位置時(shí)使用二分查找,這樣移動(dòng)元素就不需要一個(gè)個(gè)判斷大小關(guān)系了。二分查找

template <class E>
void insertSort(E *arr,int n)
{
    for(int i=1;i<n;i++)
    {
        E key=arr[i];
        int lef=0,rig=i,mid;
        while(lef<rig)//查找key的上界,即查找第一個(gè)大于key的元素,沒找到則lef=i
        {
            mid=(lef+rig)/2;
            if(arr[mid]<=key)
            {
                lef=mid+1;
            }
            else rig=mid;
        }
        int j=i-1;
        while(j>=lef)
        {
            arr[j+1]=arr[j];
            j--;
        }
        arr[lef]=key;
    }
}

插入排序動(dòng)圖演示:


(3)算法分析

時(shí)間復(fù)雜度

  • 最佳情況:輸入數(shù)組按升序排列。T(n) = Θ(n)
  • 最壞情況:輸入數(shù)組按降序排列。T(n) = Θ(n2)
  • 平均情況:T(n) = Θ(n2)

輔佐空間:

4.希爾排序( Shell Sort)

第一個(gè)突破O(n^2)的排序算法;是簡(jiǎn)單插入排序的改進(jìn)版;它與插入排序的不同之處在于,它會(huì)優(yōu)先比較距離較遠(yuǎn)的元素。希爾排序又叫縮小增量排序。希爾排序的核心在于間隔序列的設(shè)定。

(1)算法描述和實(shí)現(xiàn)

  • <1>.選擇一個(gè)增量序列t1,t2,...tk;其中,tk=1;
  • <2>.按增量序列個(gè)數(shù)k,對(duì)序列進(jìn)行k 趟排序;
  • <3>.每趟排序,根據(jù)對(duì)應(yīng)的增量ti,將待排序列分割成若干長(zhǎng)度為m 的子序列,分別對(duì)各子表進(jìn)行直接插入排序。僅增量因子為1 時(shí),整個(gè)序列作為一個(gè)表來處理,表長(zhǎng)度即為整個(gè)序列的長(zhǎng)度。
template <class E>
void shellSort(E *arr,int n)
{
    int h=1;
    while(h<n/3) h=3*h+1;
    while(h>=1)
    {
        for(int i=h;i<n;i++)
        {
            E key=arr[i];
            int j=i-h;
            while(j>=0&&arr[j]>key)
            {
                arr[j+h]=arr[j];
                j-=h;
            }
            arr[j+h]=key;
        }
        h/=3;
    }
}

希爾排序圖示(圖片來源網(wǎng)絡(luò)):


(2)算法分析:

時(shí)間復(fù)雜度

  • 最佳情況:T(n) = Θ(n^(1+c1))
  • 最壞情況:T(n) = Θ(n^(1+c2))
  • 平均情況:T(n) =Θ(n^(1+c3))

輔佐空間:

5.歸并排序(Merge Sort)

和選擇排序一樣,歸并排序的性能不受輸入數(shù)據(jù)的影響,但表現(xiàn)比選擇排序好的多,因?yàn)槭冀K都是O(n log n)的時(shí)間復(fù)雜度。代價(jià)是需要額外的內(nèi)存空間。歸并排序是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個(gè)非常典型的應(yīng)用。歸并排序是一種穩(wěn)定的排序方法。將已有序的子序列合并,得到完全有序的序列;即先使每個(gè)子序列有序,再使子序列段間有序。若將兩個(gè)有序表合并成一個(gè)有序表,稱為2-路歸并。

( 1 )算法描述和實(shí)現(xiàn)

  • <1>.把長(zhǎng)度為n的輸入序列分成兩個(gè)長(zhǎng)度為n/2的子序列;
  • <2>.對(duì)這兩個(gè)子序列分別采用歸并排序;
  • <3>.將兩個(gè)排序好的子序列合并成一個(gè)最終的排序序列。
template <class E>
void merge(E *arr,E *aux,int lef,int mid,int rig)
{
    int i=lef,j=mid+1,k;
    for(k=lef;k<=rig;k++)
    {
        aux[k]=arr[k];
    }
    k=lef;
    while(i<=mid&&j<=rig)
    {
        /*
        if(aux[i]<aux[j]) arr[k++]=aux[i++];//非穩(wěn)定排序
        else arr[k++]=aux[j++];
        */
        if(aux[i]<=aux[j]) arr[k++]=aux[i++];//穩(wěn)定排序
        else arr[k++]=aux[j++];
    }
    if(i>mid)
    {
        while(j<=rig)
        {
            arr[k++]=aux[j++];
        }
    }
    if(j>rig)
    {
        while(i<=mid)
        {
            arr[k++]=aux[i++];
        }
    }
}
template<class E>
void mergeSort(E *arr,E *aux,int lef,int rig)
{
    if(rig<=lef) return;//區(qū)間長(zhǎng)度小于等于1,不需要合并
    int mid=(lef+rig)/2;
    mergeSort(arr,aux,lef,mid);
    mergeSort(arr,aux,mid+1,rig);
    merge(arr,aux,lef,mid,rig);
}
template <class E>
void mergeSort(E *arr,int n)
{
    E *aux=new E[n];
    mergeSort(arr,aux,0,n-1);
}

歸并排序動(dòng)圖演示:


(3)算法分析

時(shí)間復(fù)雜度:

  • 最佳情況:T(n) = Θ(nlogn)
  • 最差情況:T(n) = Θ(nlogn)
  • 平均情況:T(n) = Θ(nlogn)

輔佐空間:

  • Θ(n)

6.快速排序(Quick Sort)

快速排序的基本思想:通過一趟排序?qū)⒋庞涗浄指舫瑟?dú)立的兩部分,其中一部分記錄的關(guān)鍵字均比另一部分的關(guān)鍵字小,則可分別對(duì)這兩部分記錄繼續(xù)進(jìn)行排序,以達(dá)到整個(gè)序列有序。

(2)算法描述和實(shí)現(xiàn)
快速排序使用分治法來把一個(gè)串(list)分為兩個(gè)子串(sub-lists)。
具體算法描述如下:

  • <1>.從數(shù)列中挑出一個(gè)元素,稱為 "基準(zhǔn)"(pivot);
  • <2>.重新排序數(shù)列,所有元素比基準(zhǔn)值小的擺放在基準(zhǔn)前面,所有元素比基準(zhǔn)值大的擺在基準(zhǔn)的后面(相同的數(shù)可以到任一邊)。在這個(gè)分區(qū)退出之后,該基準(zhǔn)就處于數(shù)列的中間位置。這個(gè)稱為分區(qū)(partition)操作;
  • <3>.遞歸地(recursive)把小于基準(zhǔn)值元素的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序。

首位置劃分

template <class E>
int partition(E *arr,int lef,int rig)
{
    int i=lef,j=rig+1;
    E x=arr[lef];
    while(true)
    {
        while(arr[++i]<x&&i<rig);
        while(arr[--j]>x);
        if(i>=j) break;
        swap(arr[i],arr[j]);
    }
    arr[lef]=arr[j];
    arr[j]=x;
    return j;
}
template <class E>
void quickSort(E *arr,int lef,int rig)
{
    if(lef<rig)
    {
        int q=partition(arr,lef,rig);
        quickSort(arr,lef,q-1);
        quickSort(arr,q+1,rig);
    }
}
template <class E>
void quickSort(E *arr,int n)
{
    quickSort(arr,0,n-1);
}

隨機(jī)劃分:先隨機(jī)找一個(gè)劃分點(diǎn),然后把這個(gè)劃分點(diǎn)與首位置交換,則其他的代碼與上面的一樣。

template <class E>
int partition(E *arr,int lef,int rig)
{
    int i=lef,j=rig+1;
    int q=rand()%(rig-lef+1)+lef;
    swap(arr[lef],arr[q]);
    E x=arr[lef];
    while(true)
    {
        while(arr[++i]<x&&i<rig);
        while(arr[--j]>x);
        if(i>=j) break;
        swap(arr[i],arr[j]);
    }
    arr[lef]=arr[j];
    arr[j]=x;
    return j;
}
template <class E>
void quickSort(E *arr,int lef,int rig)
{
    if(lef<rig)
    {
        int q=partition(arr,lef,rig);
        quickSort(arr,lef,q-1);
        quickSort(arr,q+1,rig);
    }
}
template <class E>
void quickSort(E *arr,int n)
{
    srand(int(time(0)));
    quickSort(arr,0,n-1);
}

快速排序動(dòng)圖演示:



( 2 )算法分析

時(shí)間復(fù)雜度:

  • 最佳情況:T(n) = Θ(nlogn)
  • 最差情況:T(n) = Θ(n2)
  • 平均情況:T(n) = Θ(nlogn)

輔佐空間:

7.堆排序(Heap Sort)

堆排序(Heapsort)是指利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計(jì)的一種排序算法。堆積是一個(gè)近似完全二叉樹的結(jié)構(gòu),并同時(shí)滿足堆積的性質(zhì):即子結(jié)點(diǎn)的鍵值或索引總是小于(或者大于)它的父節(jié)點(diǎn)。

( 2 )算法描述和實(shí)現(xiàn)

具體算法描述如下:

  • <1>.將初始待排序關(guān)鍵字序列(R1,R2....Rn)構(gòu)建成大頂堆,此堆為初始的無序區(qū);
  • <2>.將堆頂元素R[1]與最后一個(gè)元素R[n]交換,此時(shí)得到新的無序區(qū)(R1,R2,......Rn-1)和新的有序區(qū)(Rn),且滿足R[1,2...n-1]<=R[n];
  • <3>.由于交換后新的堆頂R[1]可能違反堆的性質(zhì),因此需要對(duì)當(dāng)前無序區(qū)(R1,R2,......Rn-1)調(diào)整為新堆,然后再次將R[1]與無序區(qū)最后一個(gè)元素交換,得到新的無序區(qū)(R1,R2....Rn-2)和新的有序區(qū)(Rn-1,Rn)。不斷重復(fù)此過程直到有序區(qū)的元素個(gè)數(shù)為n-1,則整個(gè)排序過程完成。
template <class E>
void sink(E *arr,int k,int n)
{
    int j;
    while(2*k+1<n)
    {
        j=2*k+1;
        if(j<n-1&&arr[j]<arr[j+1]) j++;
        if(arr[k]>=arr[j]) break;
        swap(arr[k],arr[j]);
        k=j;
    }
}
template <class E>
void heapSort(E *arr,int n)
{
    for(int i=(n-1)/2;i>=0;i--)//構(gòu)建堆
    {
        sink(arr,i,n);
    }
    while(n>1)//堆排序
    {
        swap(arr[0],arr[--n]);
        sink(arr,0,n);
    }
}

堆排序動(dòng)圖演示:



( 2 )算法分析

時(shí)間復(fù)雜度:

  • 最佳情況:T(n) = O(nlogn)
  • 最差情況:T(n) = O(nlogn)
  • 平均情況:T(n) = O(nlogn)

輔佐空間:

8.計(jì)數(shù)排序(Counting Sort)

計(jì)數(shù)排序的核心在于將輸入的數(shù)據(jù)值轉(zhuǎn)化為鍵存儲(chǔ)在額外開辟的數(shù)組空間中。
作為一種線性時(shí)間復(fù)雜度的排序,計(jì)數(shù)排序要求輸入的數(shù)據(jù)必須是有確定范圍的整數(shù)。

(1)算法簡(jiǎn)介

計(jì)數(shù)排序(Counting sort)是一種穩(wěn)定的排序算法。計(jì)數(shù)排序使用一個(gè)額外的數(shù)組C,其中第i個(gè)元素是待排序數(shù)組A中值等于i的元素的個(gè)數(shù)。然后根據(jù)數(shù)組C來將A中的元素排到正確的位置。它只能對(duì)整數(shù)進(jìn)行排序。

(2)算法描述和實(shí)現(xiàn)

具體算法描述如下:

  • <1>. 找出待排序的數(shù)組中最大和最小的元素;
  • <2>. 統(tǒng)計(jì)數(shù)組中每個(gè)值為i的元素出現(xiàn)的次數(shù),存入數(shù)組C的第i項(xiàng);
  • <3>. 對(duì)所有的計(jì)數(shù)累加(從C中的第一個(gè)元素開始,每一項(xiàng)和前一項(xiàng)相加);
  • <4>. 反向填充目標(biāo)數(shù)組:將每個(gè)元素i放在新數(shù)組的第C(i)項(xiàng),每放一個(gè)元素就將C(i)減去1。
void countingSort(int *unSort,int *sorted,int n)//假設(shè)arr元素的最大值是1000
{
    int c[1000];
    int minVal=0x3f3f3f,maxVal=-0x3f3f3f;
    memset(c,0,sizeof(c));
    for(int i=0;i<n;i++)
    {
        c[unSort[i]]++;
        minVal=minVal>unSort[i]?unSort[i]:minVal;
        maxVal=maxVal<unSort[i]?unSort[i]:maxVal;
    }
    for(int i=minVal;i<maxVal;i++)
    {
        c[i+1]=c[i+1]+c[i];
    }
    for(int i=0;i<n;i++)
    {
       int index=c[unSort[i]]-1;
       sorted[index]=unSort[i];
       c[unSort[i]]--;
    }
}

基數(shù)排序動(dòng)圖演示:



(3)算法分析
當(dāng)輸入的元素是n 個(gè)0到k之間的整數(shù)時(shí),它的運(yùn)行時(shí)間是 O(n + k)。計(jì)數(shù)排序不是比較排序,排序的速度快于任何比較排序算法。由于用來計(jì)數(shù)的數(shù)組C的長(zhǎng)度取決于待排序數(shù)組中數(shù)據(jù)的范圍(等于待排序數(shù)組的最大值與最小值的差加上1),這使得計(jì)數(shù)排序?qū)τ跀?shù)據(jù)范圍很大的數(shù)組,需要大量時(shí)間和內(nèi)存。

時(shí)間復(fù)雜度:

  • 最佳情況:T(n) = O(n+k)
  • 最差情況:T(n) = O(n+k)
  • 平均情況:T(n) = O(n+k)

輔佐空間:

  • 需要用一個(gè)數(shù)組c來記錄元數(shù)組元素出現(xiàn)的次數(shù),原數(shù)組的元素值對(duì)應(yīng)c數(shù)組的索引值,所以c的大小取決于原數(shù)組的數(shù)據(jù)范圍。

9.桶排序(Bucket Sort)

桶排序是計(jì)數(shù)排序的升級(jí)版。它利用了函數(shù)的映射關(guān)系,高效與否的關(guān)鍵就在于這個(gè)映射函數(shù)的確定。

(1)算法簡(jiǎn)介

桶排序 (Bucket sort)的工作的原理:假設(shè)輸入數(shù)據(jù)服從均勻分布,將數(shù)據(jù)分到有限數(shù)量的桶里,每個(gè)桶再分別排序(有可能再使用別的排序算法或是以遞歸方式繼續(xù)使用桶排序進(jìn)行排

(2)算法描述和實(shí)現(xiàn)

具體算法描述如下:

  • <1>.設(shè)置一個(gè)定量的數(shù)組當(dāng)作空桶;
  • <2>.遍歷輸入數(shù)據(jù),并且把數(shù)據(jù)一個(gè)一個(gè)放到對(duì)應(yīng)的桶里去;
  • <3>.對(duì)每個(gè)不是空的桶進(jìn)行排序;
  • <4>.從不是空的桶里把排好序的數(shù)據(jù)拼接起來。
template <class E>
void bucketSort(E *arr,int n,int bucketCount)
{
    E minval=arr[0],maxval=arr[0];
    for(int i=1;i<n;i++)    //找到最大值和最小值
    {
        minval=minval>arr[i]?arr[i]:minval;
        maxval=maxval<arr[i]?arr[i]:maxval;
    }
    //求出每一個(gè)桶的數(shù)值范圍
    double space=(maxval-minval+1)*1.0/bucketCount;//這里必須用double值
     //先創(chuàng)建好每一個(gè)桶的空間
    vector<E> *bucket=new vector<E> [bucketCount];
    for(int i=0;i<n;i++)
    {
        int index=(int)((arr[i]-minval)/space);
        if(bucket[index].size()==0) //如果桶里里沒有東西,直接放進(jìn)去
        {
            bucket[index].push_back(arr[i]);
        }
        else                        //否則,進(jìn)行插入排序
        {
            int j=bucket[index].size()-1;
            bucket[index].push_back(arr[i]);//先把數(shù)據(jù)加載進(jìn)桶,防止下面的bucket[index][j+1]出錯(cuò)
            while(j>=0&&bucket[index][j]>arr[i])
            {
                bucket[index][j+1]=bucket[index][j];
                j--;
            }
            bucket[index][j+1]=arr[i];
        }
    }

    //把桶內(nèi)的結(jié)果合并
    for(int i=0,index=0;i<bucketCount;i++)
    {
        for(int j=0;j<bucket[i].size();j++)
        {
            arr[index++]=bucket[i][j];
        }
    }
}

桶排序圖示(圖片來源網(wǎng)絡(luò)):

這里寫圖片描述

(3)算法分析

桶排序最好情況下使用線性時(shí)間O(n),桶排序的時(shí)間復(fù)雜度,取決與對(duì)各個(gè)桶之間數(shù)據(jù)進(jìn)行排序的時(shí)間復(fù)雜度,因?yàn)槠渌糠值臅r(shí)間復(fù)雜度都為O(n)。很顯然,桶劃分的越小,各個(gè)桶之間的數(shù)據(jù)越少,排序所用的時(shí)間也會(huì)越少。但相應(yīng)的空間消耗就會(huì)增大。

時(shí)間復(fù)雜度

  • 最佳情況:T(n) = Θ(n+k)
  • 最差情況:T(n) = Θ(n+k)
  • 平均情況:T(n) = Θ(n2)

輔佐空間:

  • Θ(n)

10.基數(shù)排序(Radix Sort)

基數(shù)排序也是非比較的排序算法,對(duì)每一位進(jìn)行排序,從最低位開始排序,復(fù)雜度為O(kn),為數(shù)組長(zhǎng)度,k為數(shù)組中的數(shù)的最大的位數(shù);

(1)算法簡(jiǎn)介

基數(shù)排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次類推,直到最高位。有時(shí)候有些屬性是有優(yōu)先級(jí)順序的,先按低優(yōu)先級(jí)排序,再按高優(yōu)先級(jí)排序。最后的次序就是高優(yōu)先級(jí)高的在前,高優(yōu)先級(jí)相同的低優(yōu)先級(jí)高的在前?;鶖?shù)排序基于分別排序,分別收集,所以是穩(wěn)定的。

(2)算法描述和實(shí)現(xiàn)

具體算法描述如下:

  • <1>.取得數(shù)組中的最大數(shù),并取得位數(shù);
  • <2>.arr為原始數(shù)組,從最低位開始取每個(gè)位組成radix數(shù)組;
  • <3>.對(duì)radix進(jìn)行計(jì)數(shù)排序(利用計(jì)數(shù)排序適用于小范圍數(shù)的特點(diǎn));
int getDigit(int val,int k)
{
    int arr[] = {1, 1, 10, 100,1000,10000,100000};
    return (val/arr[k]) % 10;
}
void countingSort(int *arr,int *res,int n,int k)
{
    int c[10];
    memset(c,0,sizeof(c));
    for(int i=0;i<n;i++)
    {
        c[getDigit(arr[i],k)]++;
    }
    for(int i=1;i<10;i++)
    {
        c[i]+=c[i-1];
    }
    for(int i=n-1;i>=0;i--)//為了保證準(zhǔn)確性,必須從高位開始排
    {
        int j=getDigit(arr[i],k);
        res[c[j]-1]=arr[i];
        c[j]--;
    }
}
void radixSort(int *arr,int n,int maxDigit)
{
    int *a1=arr,*a2=new int[n],*res;
    for(int i=1;i<=maxDigit;i++)
    {
        countingSort(a1,a2,n,i);
        res=a2;
        swap(a1,a2);
    }
    for(int i=0;i<n;i++)
    {
        arr[i]=res[i];
    }
}

基數(shù)排序LSD動(dòng)圖演示:


(3)算法分析

時(shí)間復(fù)雜度:

  • 最佳情況:T(n) = Θ(n * k)
  • 最差情況:T(n) = Θ(n * k)
  • 平均情況:T(n) = Θ(n * k)

輔佐空間:

  • Θ(n)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評(píng)論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,595評(píng)論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評(píng)論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評(píng)論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,814評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,224評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評(píng)論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,444評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,988評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,804評(píng)論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,998評(píng)論 1 370
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評(píng)論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,237評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評(píng)論 1 287
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,706評(píng)論 3 393
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,993評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容

  • Ba la la la ~ 讀者朋友們,你們好啊,又到了冷鋒時(shí)間,話不多說,發(fā)車! 1.冒泡排序(Bub...
    王飽飽閱讀 1,808評(píng)論 0 7
  • 總結(jié)一下常見的排序算法。 排序分內(nèi)排序和外排序。內(nèi)排序:指在排序期間數(shù)據(jù)對(duì)象全部存放在內(nèi)存的排序。外排序:指在排序...
    jiangliang閱讀 1,364評(píng)論 0 1
  • 概述 排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    蟻前閱讀 5,209評(píng)論 0 52
  • 當(dāng)我意識(shí)到日子每天都過得一樣時(shí),我感到恐懼。我想恐懼的不是日復(fù)一日,而是害怕突然有一天,寧靜被打破而不知所措。
    西爸閱讀 236評(píng)論 0 0
  • 你最好住在大教堂后的庭院式旅館,casa de Ildefonso 。一棟寬敞漂亮的19世紀(jì)建筑,淺藍(lán)色外墻,內(nèi)部...
    童雅閱讀 234評(píng)論 0 1