面試題之排序總結


面試題之排序總結

插入排序

分析: 插入排序就是通過數字插入有序數組的方式進行排序的, 代碼簡單, 且易理解。時間復雜度O(N*N)

代碼如下:

template <typename T>
void InsertSort(vector<T>& array)
{
    for(int i=0; i<array.size(); ++ i)
    {
        for(int j=i; j>0; -- j)
        {
            if(array[j] < array[j-1])
                swap(array[j], array[j-1]);
            else
                break;
        }
    }
}

冒泡排序

分析:冒泡排序多次遍歷數組,每次遍歷將當前位置與后面位置的數進行比較,大的放后面, 這樣每次遍歷最后一位數字必為整個數組中最大的元素, 經過n-1次遍歷后,整個數組有序。時間復雜度O(N*N)

分析:

template <typename T>
void BubbleSort(vector<T>& array)
{
    for(int i=array.size()-1; i>0; -- i)
    {
        for(int j=0; j<i; ++ j)
        {
            if(array[j] > array[j+1])
                swap(array[j], array[j+1]);
        }
    }
}

歸並排序

分析:兩個有序數組的合並,應該都很熟悉。現在將一個數組N個元素,將它看做N個數組, 每個數組一個元素,這樣任意一個數組都是有序的,然后兩兩合並(有序數組的合並),會得到N/2個有序數組,然后在兩兩合並... ,直到數組數量為1, 即為歸並排序。時間復雜度O(N*log(N))

template <typename T>
void Merge(vector<T> &array, vector<T> &res, int b, int e)
{
    if(b < e)
    {
        int mid = (b + e) >> 1;
        Merge(array, res, b, mid);
        Merge(array, res, mid+1, e);

        int i = b, j = mid + 1;
        int k = b;
        while(i <= mid && j <= e)
        {
            if(array[i] < array[j])
                res[k ++] = array[i ++];
            else
                res[k ++] = array[j ++];
        }

        while(i <= mid)
            res[k ++] = array[i ++];

        while(j <= e)
            res[k ++] = array[j ++];

        for( ; b <= e; ++ b)
            array[b] = res[b];
    }
}


template <typename T>
void MergeSort(vector<T> &array)
{
    vector<int> tmp(array.size());
    Merge(array, tmp, 0, array.size()-1);
}

快速排序

分析:最常用的算法就是快速排序,既然常用就有必要知道它的排序原理了。

首先從數組中選擇一個數字X(最好是數組中的中位數,原因往下看),然后用首尾指針將大於X的放在數組的右邊,小於X的放在數組左邊,這樣在X的左邊的數字全部為小於X的數字,在X右邊的數字全部為大於X的數字。對於數字X,它的位置已經確定;然后將X左邊和X右邊依次遞歸進行這樣的過程,最后得到的數字即為有序。

選取數組中的中位數(實際上采用三數中值分割的方法),會將遞歸的層數減少(每次少一半,),使復雜度趨近N*log(N);

如果每次選取的數字為待排序部分中,最小或最大的,會加大遞歸層數(每次少1), 復雜度趨近 N*N


//從首尾中,三個數字中,選取中間的數字作為數字X
template <typename  T>
T getMid(int b, int e, vector<T> &array)
{
    int mid = (b + e) >> 1;
    if(array[b] > array[mid])
        swap(array[b], array[mid]);
    if(array[b] > array[e])
        swap(array[b], array[e]);
    if(array[mid] > array[e])
        swap(array[mid], array[e]);

    swap(array[mid], array[e]);

    return array[e];
}

template <typename  T>
void InsertSort(vector<T> &array, int b, int e)
{
    for(int i=b; i<e; ++ i)
    {
        for(int j = i; j > b; -- j)
        {
            if(array[j] < array[j-1])
                swap(array[j], array[j-1]);
            else
                break;
        }
    }
}

template <typename  T>
void Qsort(vector<T> &array, int b, int e)
{
    if(b + 3 > e)
    {
        T mid = getMid(b ,e, array);

        int i = b, j = e;
        for(;;)
        {
            while(array[++ i] <= mid);
            while(array[-- j] > mid);

            if(i < j)
                swap(array[i], array[j]);
            else
                break;
        }
        swap(array[i], array[e]);

        Qsort(array, b, i-1);
        Qsort(array, i+1, e);
    }
    else
        InsertSort(array, b, e);
}

template <typename  T>
void QuickSort(vector<T> &array)
{
    Qsort(array, 0, array.size()-1);
}

基數排序

分析: 基數排序和桶排序類似,不過這里的桶只有10個(與數字進制數有關),然后進行多趟桶式排序;首先, 按照數字的個位進行排序分桶,然后在用十位進行分桶,直到最高位,最后桶里面的數據即為有序。

舉例說明:

用12,3,6, 24,61,57,69,85, 18,30 十個數字進行通排序

按照個位將數字分在10個桶中

0 1 2 3 4 5 6 7 8 9
數字 30 61 12 3 24 85 6 57 18 69

然后再按照十位數(原順序不能變)將數字分在桶中

0 1 2 3 4 5 6 7 8 9
數字 3,6 12,18 24 30 57 61,69 85

這樣數組中的數字即為有序

代碼如下:

class SortBaseNum
{
public:
    void sort_base_num(vector<int>& arr)
    {
        list<int> lst[10];
        vector<int> mk(10);

        uint32_t tmp = 1;
        for(int i = 0; i < arr.size(); ++ i)
        {
            lst[arr[i] / tmp % 10].push_back(arr[i]);
        }

        while(true)
        {
            bool isB = true;

            for(int i = 0; i < 10; ++ i)
                mk[i] = lst[i].size();

            tmp *= 10;

            for(int i = 0; i < 10; ++ i)
            {
                while(mk[i] --)
                {
                    int res = lst[i].front();
                    lst[i].pop_front();

                    lst[res / tmp % 10].push_back(res);

                    if(res / tmp != 0)
                        isB = false;
                }
            }

            if(isB)
                break;
        }

        int i = 0;
        while(i < arr.size())
        {
            arr[i] = lst[0].front();
            lst[0].pop_front();
            i ++;
        }
    }
};


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM