筆記二:計數排序、選擇排序、冒泡排序、插入排序

計數排序

1、 名次 :所謂名次,通俗理解即爲該元素在序列中排行老幾的意思。

2.、如何求名次:依次對每一個元素進行比較,若排在自己(該元素)前面的元素比自己大,則前面的元素在排行計數上加1,反之則自己加1。

3、利用附加數組的計數排序:根據自身名次重新整理一份排序序列存儲在附加數組中,然後將附加數組值拷貝到原序列中。
1)代碼:

template<typename T> void SortClass<T>::rank(T a[], int n, int r[])
{
    //給數組a[0: n-1]的n個元素排名次
    //結果在r[0: n-1]中返回
    for (int i = 0; i < n; i++)
        r[i] = 0;

    //比較所有元素,每次比較中較大元素計數器加1
    for (int i = 0; i < n; i++)
        for (int j = 0; j < i; j++)
            if (a[j] <= a[i])
            {
                ++r[i];
            }
            else
            {
                ++r[j];
            }   
}//rank

template<typename T> void SortClass<T>::rearrange(T a[], int n)
{
    T *u = new T[n];        //臨時數組,存儲排序元素
    int *r = new int[n];    //存儲數組元素名次
    rank(a, n, r);

    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;
    delete[] r;

}//rearrange

2)運行:

這裏寫圖片描述

3)時間複雜度分析:在求名次rank()操作中,針對第i個元素,比較的次數爲i次,因此總的比較次數爲:1+2+3+…+(n-1)=(n-1)n/2次。在rearrange()中有2次for循環進行賦值操作,總的移動次數是2n。兩者相加,得出附加數組的計數排序時間複雜度爲:(n-1)n/2+2n =O(n2)(注:2爲n的上標)

4、原地排序:所謂原地排序就是指在對序列元素進行名次計算之後,根據名次調整原序列的順序,不借助附加數組。

1)思路:假設第一個元素a[0]的名次r[0]=3,那麼,a[0]的值應該交換到下標爲3的位置,即a[0]與a[3]交換。由於元素位置交換了,那麼相應的,元素對應名次也要交換。停止交換的前提是a[0]元素對應的r[0]正好爲0,則此時a[0]纔是正確的元素。對其他位置元素,同理。

這裏寫圖片描述

2 ) 代碼:

template<typename T> void SortClass<T>::selfrearrange(T a[], int n)
{
    int *r = new int[n];    //存儲數組元素名次
    rank(a, n, r);

    for (int i = 0; i < n; i++)
        while (i != r[i])       //當i == r[i]時,表明名次對應的下標存儲元素正確
        {
            int tmp = r[i];
            swap(a[i], a[tmp]); //元素交換
            swap(r[i], r[tmp]); //排名交換
        }

    delete[] r;
}//selfrearrange

3)運行:

這裏寫圖片描述

4)時間複雜度分析:名次比較次數:1+2+3+…+(n-1)=(n-1)n/2次。交換次數:當序列有序時,交換0次,當序列無序時,由於每次交換,至少使一個元素交換到正確位置,那麼對任意一個元素而言,最多的交換次序是(n-1)次,在這(n-1)次交換中,其他元素也被交換正確,故最多的交換次數爲(n-1)次原地重排最壞的時間複雜度爲:(n-1)n/2+(n-1)=O(n2)


選擇排序

1、定義:第一次遍歷序列,找出最大元素,將該元素排到末尾去;第二次遍歷序列,找出次最大元素,將該元素排到末尾前一位置去;同理,繼續下去,直到最後一個元素爲止。

2、思路:
這裏寫圖片描述

3、基礎選擇排序:按照2中思路進行設計

1)代碼:

template<typename T> void SortClass<T>::selectionSort(T a[], int n)
{
    for (int i = n - 1; i > 0; i--)     //移動的目標位置
    {
        int indexOfMax = 0;         
        for (int j = 0; j < i; j++)         //找最大元素
            if (a[indexOfMax] < a[j])
                indexOfMax = j;

        swap(a[i], a[indexOfMax]);      //將最大值移到目標位置
    }
}//selectionSort

2)運行:

這裏寫圖片描述

3)時間複雜度分析:在進行查找最大元素值過程中,比較次數爲(n-1)n/2。一次swap()操作,實際包含3步tmp=a;a=b;b=a;,故移動次數爲3(n-1)基礎選擇排序的時間複雜度爲(n-1)n/2+3(n-1)=O(n2)

4、及時終止選擇排序:在查找最大元素時,同時檢查數組是否有序,減少不必要的迭代。
1)代碼:

template<typename T> void SortClass<T>::selectionSortByOrder(T a[], int n)
{
    bool sorted = false;
    for (int i = n - 1; i > 0 && !sorted; i--)  //未排好序的情況下進行選擇排序
    {
        int indexOfMax = 0;
        sorted = true;
        for (int j = 0; j < i; j++)
        if (a[indexOfMax] < a[j])
        {
            indexOfMax = j;     
        }
        else
        {
            sorted = false;
        }

        swap(a[i], a[indexOfMax]);
    }
}//selectionSortByOrder

2)運行:

這裏寫圖片描述


冒泡排序

1、定義:簡單來講,相鄰元素之間的比較,若前者較大,則交換。一輪比較即爲一次冒泡過程。

2、基礎冒泡排序:
1)代碼:

template<typename T> void SortClass<T>::bubbleSort(T a[], int n)
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n - 1; j++)
            if (a[j] > a[j + 1])
                swap(a[j], a[j + 1]);
}//bubbleSort

2)運行:

這裏寫圖片描述

3、及時終止的冒泡排序:

1)代碼:

template<typename T> void SortClass<T>::bubbleSortByOrder(T a[], int n)
{
    bool sorted = true;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n - 1; j++)
            if (a[j] > a[j + 1])
            {
                swap(a[j], a[j + 1]);
                sorted = false;     //只要交換順序,表明排序未結束
            }

        if (sorted)
            break;
    }



}//bubbleSortByOrder

2)運行:

這裏寫圖片描述


插入排序

1、定義: 把序列第一個元素看做一個有序數組,將第2個元素按順序插入到這個數組中,則這兩個數組組成一個新的有序數組。將第3個元素插入到上述有序數組中,那麼這3個有序數組又組成新的有序數組。如此,依次將後續元素插入到前面已排好的序列中,直至最後一個元素爲止

2、將要插入元素與已知排序數組進行比較,從後往前逐一比較,若該元素較小,則將有序數組中元素後移一位,直到騰出可以插入的空位即可。

3、插入排序:
1)代碼:

template<typename T> void SortClass<T>::insertSort(T a[], int n)
{
    for (int i = 1; i < n; i++)
    {
        int j;
        int tmp = a[i];
        for (j = i - 1; j >= 0 && a[j] > tmp; j--)  //將大於a[i]的元素依次後移
        {
            a[j + 1] = a[j];
        }
        a[j + 1] = tmp; //將a[i]元素按順序插入到a[0:i-1]中
    }
}//insertSort

2)運行:
這裏寫圖片描述





附全代碼:

#include<iostream>
using namespace std;

template <typename T> class SortClass
{
public:
    void rank(T a[], int n, int r[]);   //名次計算
    void rearrange(T a[], int n);       //利用附加數組計數排序
    void selfrearrange(T a[], int n);   //原地排序
    void selectionSort(T a[], int n);   //選擇排序
    void selectionSortByOrder(T a[], int n);    //及時終止的選擇排序
    void bubbleSort(T a[], int n);      //冒泡排序
    void bubbleSortByOrder(T a[], int n);       //及時終止的冒泡排序
    void insertSort(T a[], int n);      //插入排序
};

template<typename T> void SortClass<T>::rank(T a[], int n, int r[])
{
    //給數組a[0: n-1]的n個元素排名次
    //結果在r[0: n-1]中返回
    for (int i = 0; i < n; i++)
        r[i] = 0;

    //比較所有元素,每次比較中較大元素計數器加1
    for (int i = 0; i < n; i++)
        for (int j = 0; j < i; j++)
            if (a[j] <= a[i])
            {
                ++r[i];
            }
            else
            {
                ++r[j];
            }   
}//rank

template<typename T> void SortClass<T>::rearrange(T a[], int n)
{
    T *u = new T[n];        //臨時數組,存儲排序元素
    int *r = new int[n];    //存儲數組元素名次
    rank(a, n, r);

    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;
    delete[] r;

}//rearrange

template<typename T> void SortClass<T>::selfrearrange(T a[], int n)
{
    int *r = new int[n];    //存儲數組元素名次
    rank(a, n, r);

    for (int i = 0; i < n; i++)
        while (i != r[i])       //當i == r[i]時,表明名次對應的下標存儲元素正確
        {
            int tmp = r[i];
            swap(a[i], a[tmp]); //元素交換
            swap(r[i], r[tmp]); //排名交換
        }

    delete[] r;
}//selfrearrange

template<typename T> void SortClass<T>::selectionSort(T a[], int n)
{
    for (int i = n - 1; i > 0; i--)     //移動的目標位置
    {
        int indexOfMax = 0;         
        for (int j = 0; j < i; j++)         //找最大元素
            if (a[indexOfMax] < a[j])
                indexOfMax = j;

        swap(a[i], a[indexOfMax]);      //將最大值移到目標位置
    }
}//selectionSort

template<typename T> void SortClass<T>::selectionSortByOrder(T a[], int n)
{
    bool sorted = false;
    for (int i = n - 1; i > 0 && !sorted; i--)  //未排好序的情況下進行選擇排序
    {
        int indexOfMax = 0;
        sorted = true;
        for (int j = 0; j < i; j++)
        if (a[indexOfMax] < a[j])
        {
            indexOfMax = j;     
        }
        else
        {
            sorted = false;
        }

        swap(a[i], a[indexOfMax]);
    }
}//selectionSortByOrder

template<typename T> void SortClass<T>::bubbleSort(T a[], int n)
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n - 1; j++)
            if (a[j] > a[j + 1])
                swap(a[j], a[j + 1]);
}//bubbleSort

template<typename T> void SortClass<T>::bubbleSortByOrder(T a[], int n)
{
    bool sorted = true;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n - 1; j++)
            if (a[j] > a[j + 1])
            {
                swap(a[j], a[j + 1]);
                sorted = false;     //只要交換順序,表明排序未結束
            }

        if (sorted)
            break;
    }



}//bubbleSortByOrder

template<typename T> void SortClass<T>::insertSort(T a[], int n)
{
    for (int i = 1; i < n; i++)
    {
        int j;
        int tmp = a[i];
        for (j = i - 1; j >= 0 && a[j] > tmp; j--)  //將大於a[i]的元素依次後移
        {
            a[j + 1] = a[j];
        }
        a[j + 1] = tmp; //將a[i]元素按順序插入到a[0:i-1]中
    }
}//insertSort

int main(int argc, char *argv[])
{
    int a[6] = { 6, 5, 8, 4, 3, 1 };
    cout << "原始數組順序:        ";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;
    SortClass<int> SClass;
    /*SClass.rearrange(a, 6);
    cout << "採用附加數組計數排序:";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;*/

    /*SClass.selfrearrange(a, 6);
    cout << "採用重排計數排序:    ";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;*/ 

    /*SClass.selectionSort(a, 6);
    cout << "採用選擇排序:        ";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;*/

    /*SClass.selectionSortByOrder(a, 6);
    cout << "採用及時終止選擇排序:";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;*/

    /*SClass.bubbleSort(a, 6);
    cout << "採用冒泡排序:        ";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;*/

    /*SClass.bubbleSortByOrder(a, 6);
    cout << "採用及時終止冒泡排序:";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;*/

    SClass.insertSort(a, 6);
    cout << "採用插入排序:        ";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;


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