排序演算法小結(C++)

來源:互聯網
上載者:User
排序演算法:
1、計數排序(rank sort)

先計算名次:
template<class T>
void Rank(T a[],int n,int r[])
{//計算a[0:n-1]中n個元素的排名
    for(int i=0;i<n;i++)
        r[i]=0;//初始化
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            if(a[j]<=a[i])
                r[i]++;
            else
                r[j]++;
}
可以根據a的元素之間所進行的比較操作來估算程式的時間複雜性,這些比較操作是由if語句來完成的。總的比較次數為(n-1)n/2。

再按名次排序:
template <class T>
void Rearrange(T a[],int n,int r[])
{//按序重排數組a中的元素,使用附加數組u
    T *u=new T[n+1];
    //在u中移動到正確的位置
    for(int i=0;i<n;i++)
        u[r[i]]=a[i];
    for(int i=0;i<n;i++)
        a[i]=u[i];
    delete []u;
}
在函數Rearrange執行期間移動元素的次數為2n。完成整個排序需要執行(n-1)n/2次比較操作和2n次移動操作。

另外一種重排元素的函數如下,該函數沒有使用附加數組u。
假定已經使用函數Rank計算出一個數組中每個元素的名次。
template <class T>
void Rearrange(T a[],int n,int r[])
{//原地重排數組元素
    for(int i=0;i<n;i++)
    //擷取應該排在a[i]處的元素
        while(r[i]!=i)
        {
            int t=r[i];
            Swap(a[i],a[t]);
            Swap(r[i],r[t]);
        }
}
template <class T>
inline void Swap(T& a,T& b)
{
    T temp=a;a=b;b=temp;
}
此程式執行的最少交換次數為0(初始數組已經是按序排列),最大交換次數為2(n-1)。當使用本函數來代替上面的函數時,最壞情況下所需要的執行時間將增加,因為需要移動更多的元素(每次交換需要移動三次),不過程式所需要的記憶體減少了。
綜上考慮,兩種計數排序方法各有利弊。

2、選擇排序(selection sort)
template <class T>
void SelectionSort(T a[],int n)
{//對數組a[0:n-1]中的n個元素進行排序
    for(int size=n;size>1;size--)
    {
        int j=Max(a,size);
        Swap(a[j],a[size-1]);
    }
}
template<class T>
int Max(T a[],int n)
{//尋找a[0;n-1]中的最大元素
    int pos=0;
    for(int i=1;i<n;i++)
        if(a[pos]<a[i]
            pos=i;
    return pos;
}
每次調用max(a,size)需要執行size-1次比較,所以總的比較次數為1+2+3+...+n-1=(n-1)n/2。元素的移動次數為3(n-1)。選擇排序所需要的比較次數與按名次排序所需要的比較次數相同,但所需要的元素移動次數多出50%。

上述選擇排序函數的一個缺點是:即使元素已經按序排列,程式仍然繼續運行。為了終止不必要的迴圈,在尋找最大元素的期間,可以順便檢查數組是否已按序排列。下面程式給出了一個按照這種思想實現的選擇排序函數。在該函數中,把尋找最大元素的迴圈直接與函數SelectionSort合并在一起,而不是把它作為一個獨立的函數。
template <class T>
void SelectionSort(T a[],int n)
{//及時終止的選擇排序
    bool sorted=false;
    for(int size=n;!sorted && (size>1);size--)
    {
        int pos=0;
        sorted=true;
        //找最大元素
        for(int i=1;i<size;i++)
            if(a[pos]<=a[i])
                pos=i;//如果已經按序排列,那麼就不會有else的機會,sorted也就一直為true,最紅將終止外部for迴圈。
            else
                sorted=false;//非未按序排列,表示需要外部for迴圈
        Swap(a[pos],a[size-1]);
    }
}
其最好的情況出現在數組a最初是有序數組的情形,此時外部for迴圈僅執行一次,a中元素之間的比較次數為n-1。在最壞情況下,外部for迴圈一直迴圈到size=1,執行的比較次數為(n-1)n/2。最好和最壞情況下的交換次數與上面的最佳化前的程式完全相同,但最壞情況下,最佳化後的程式可能要略微慢一些,因為它必須進行變數維護的額外工作。
綜上所述,最佳化後的選擇排序函數是最佳選擇。

3、冒泡排序(bubble sort)
template <class T>
void Bubble(T a[],int n)
{//把數組a[0:n-1]中最大元素通過冒泡移到右邊
    for(int i=0;i<n-1;i++)
        if(a[i]>a[i+1])
            Swap(a[i],a[i+1]);
}
template <class T>
void BubbleSort(T a[],int n)
{//對數組a[0:n-1]中的n個元素進行冒泡排序
    for(int i=n;i>1;i--)
        Bubble(a,i);
}
元素比較次數為(n-1)n/2,與SelectionSort相同。
與選擇排序情形一樣,可以重新設計一個及時終止的冒泡排序函數。如果在一次冒泡過程中沒有發生元素互換,則說明書中已經按序排列,沒有必要再繼續進行冒泡過程。下面程式給出了一個及時終止的冒泡排序函數。
template <class T>
bool Bubble(T a[],int n)
{//把a[0:n-1]中最大元素冒泡至右端
    bool swapped=false;//尚未發生交換
    for(int i=0;i<n-1;i++)
        if(a[i]>a[i+1])
        {
            Swap(a[i],a[i+1]);
            swapped=true;
        }
    return swapped;
}
template<class T>
void BubbleSort(T a[],int n)
{//及時終止的冒泡程式
    for(int i=n;i>1 && Bubble(a,i);i--);
}
在最壞情況下所執行的比較次數與原來的函數一樣,在最好的情況下比較次數為n-1。

4、插入排序(insertion sort)
template <class T>
void Insert(T a[],int n,const T &x)
{//向有序數組a[0:n-1]中插入元素x
    int i;
    for(i=n-1;i>=0 && x<a[i];i--)
        a[i+1]=a[i];
    a[i+1]=x;
}
template <class T>
void InsertionSort(T a[],int n)
{//對a[0:n-1]進行排序
    for(int i=1;i<n;i++)
    {
        T t=a[i];
        Insert(a,i,t);
    }
}
在最好的情況下比較次數為n-1,而在最壞情況下比較次數為(n-1)n/2。

綜上所述,利用"附加數組重排數組元素"和"原地重排數組元素"使用的是同一個計算名次的函數Rank,比較次數為(n-1)n/2。
但移動元素的次數不一樣,"附加數組重排數組元素"需要執行2n次移動操作,而"原地重排數組元素"的最少交換次數為0,最大的交換次數為2(n-1),注意每次交換需要移動三次。

"選擇排序"總的比較次數也為(n-1)n/2,但元素移動次數為3(n-1),比計數排序所需移動次數多出50%。"及時終止的選擇排序"最好的情況是比較次數為n-1,最壞的情況下,比較次數為(n-1)n/2。
"冒泡排序"總的比較次數為(n-1)n/2,元素移動次數視具體資料而定,"及時終止的冒泡排序"在最好的情況下比較次數為n-1,最壞的情況為(n-1)n/2。
"插入排序"最好的情況下比較次數為n-1,而在最壞情況下比較次數為(n-1)n/2。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.