常用排序演算法總結

weixin_34119545發表於2015-03-30

氣泡排序

時間複雜度:O(N²)

 

原理:從陣列的第個位置開始兩兩比較array[index]和array[index+1],如果array[index]大於array[index+1]則交換array[index]和array[index+1]的位置,直到陣列結束。

void Bubble(int array[], int size)
{
    int i,j;

    for(i=0; i<size; i++)
    {
        for(j=i+1; j<size; j++)
        {
            if(array[i]>array[j])
            {
                array[i]=array[i]^array[j];
                array[j]=array[i]^array[j];
                array[i]=array[j]^array[i];
            }
        }
    }

 

二、選擇排序

時間複雜度:O(N^2),與氣泡排序相比減少了陣列交換的次數

 

原理:選擇個 array[0]作為標杆,然後迴圈找到除這個外最小的 (查詢小於標杆的最小 ),交換這兩個,這時最小就被放到了array[0]上,然後再將array[1]作為標杆,從剩下未排序的 中找到最小 ,並交換。

void Sort(int array[], int size)
{
    int i,j,k;

    for(i=0; i<size; i++)
    {
        k=i;
        for(j=i+1; j<size; j++)
        {
            if(array[j]<array[k])
            {
                k=j;
            }
        }

        if(i!=k)
        {
            array[i]=array[i]^array[k];
            array[k]=array[k]^array[i];
            array[i]=array[i]^array[k];
        }
    }
}

 

三、插入排序

時間複雜度:插入排序對隨即順序的序列的時間複雜度也為O(N^2),但是對於基本有序的序列進行排序時間複雜度為O(N)

適用:一般不用在資料大於1000的場合或者重複排序超過200資料項的序列使用插入排序

 

原理:插入排序的思想是陣列是部門有序的,然後將無序的部分迴圈插入到已有序的序列中。

void InsertSort(int array[], int size)
{
    int i,j,temp;

    for(i=2; i<size; i++)
    {
        temp=array[i];

        for(j=i-1; j>=0 && array[j]>temp; j--)
        {
            array[j+1]=array[j];
        }

        array[j+1]=temp;
    }

}

 

四、希爾排序/縮小增量排序

時間複雜度:n的1.2次冪

適用:適合於資料量在5000以下並且速度並不是特別重要的場合。

 

原理:先將整個待排元素序列分割成若干個子序列(由相隔某個“增量”的元素組成的)分別進行直接插入排序,然後依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。因為直接插入排序在元素基本有序的情況下(接近最好情況),效率是很高的,因此希爾排序在時間效率上比前兩種方法有較大提高。

void shellSort(int array[], int size)
{
    int i,j,temp;
    int increment=size;

    do
    {
        increment=increment/3+1;
        for(i=increment+1; i<size; i++)
        {
            temp=array[i];

            for(j=i-increment; j>=0 && array[j]>temp; j-=increment)
            {
                array[j+increment]=array[j];
            }

            array[j+increment]=temp;
        }
    }while(increment>1);

}

 

五、堆排序

時間複雜度:O(N*logN)

適用:適合於資料量非常大的場合(百萬資料)

 

原理:利用大頂堆(小頂堆)堆頂記錄的是最大關鍵字(最小關鍵字)這一特性,使得每次從無序中選擇最大記錄(最小記錄)變得簡單。
其基本思想為(大頂堆):
1)將初始待排序關鍵字序列(R1,R2....Rn)構建成大頂堆,此堆為初始的無須區;
2)將堆頂元素R[1]與最後一個元素R[n]交換,此時得到新的無序區(R1,R2,......Rn-1)和新的有序區(Rn),且滿足R[1,2...n-1]<=R[n];
3)由於交換後新的堆頂R[1]可能違反堆的性質,因此需要對當前無序區(R1,R2,......Rn-1)調整為新堆,然後再次將R[1]與無序區最後一個元素交換,得到新的無序區(R1,R2....Rn-2)和新的有序區(Rn-1,Rn)。不斷重複此過程直到有序區的元素個數為n-1,則整個排序過程完成。

//array是待調整的堆陣列,i是待調整的陣列元素的位置,nlength是陣列的長度
//本函式功能是:根據陣列array構建大根堆
void HeapAdjust(int array[],int i,int nLength)
{
    int nChild;
    int nTemp;
    for(;2*i+1<nLength;i=nChild)
    {
        //子結點的位置=2*(父結點位置)+1
        nChild=2*i+1;
        //得到子結點中較大的結點
        if(nChild<nLength-1&&array[nChild+1]>array[nChild])++nChild;
        //如果較大的子結點大於父結點那麼把較大的子結點往上移動,替換它的父結點
        if(array[i]<array[nChild])
        {
            nTemp=array[i];
            array[i]=array[nChild];
            array[nChild]=nTemp;
        }
        else break; //否則退出迴圈
    }
}
//堆排序演算法
void HeapSort(int array[],int length)
{
    int i;
    //調整序列的前半部分元素,調整完之後第一個元素是序列的最大的元素
    //length/2-1是最後一個非葉節點,此處"/"為整除
    for(i=length/2-1;i>=0;--i)
    HeapAdjust(array,i,length);
    //從最後一個元素開始對序列進行調整,不斷的縮小調整的範圍直到第一個元素
    for(i=length-1;i>0;--i)
    {
        //把第一個元素和當前的最後一個元素交換,
        //保證當前的最後一個位置的元素都是在現在的這個序列之中最大的
        array[i]=array[0]^array[i];
        array[0]=array[0]^array[i];
        array[i]=array[0]^array[i];
        //不斷縮小調整heap的範圍,每一次調整完畢保證第一個元素是當前序列的最大值
        HeapAdjust(array,0,i);
    }
}

相關文章