1. 程式人生 > 其它 >c語言實現高響應比演算法_常用排序演算法C語言實現

c語言實現高響應比演算法_常用排序演算法C語言實現

技術標籤:c語言實現高響應比演算法

#include <iostream>
#include <algorithm>
using namespace std;
/**    排序相關演算法
 * 插入排序:
 *      1.直接插入排序   穩定
 *      2.折半插入排序   穩定
 *      3.希爾排序      不穩定
 * 快速排序:
 *      4.氣泡排序      穩定
 *      5.快速排序      不穩定
 * 選擇排序:
 *      6.簡單選擇排序  不穩定
 *      7.堆排序        不穩定
 * 歸併排序:
 *      8.二路歸併排序  穩定
 */
/**1.直接插入排序
 * 思想:(1)第一個記錄是有序的
 *      (2)從第二個記錄開始,按關鍵字的大小將每個記錄插入到已排好序的序列中
 *      (3)一直進行到第n個記錄
 */

void InsertionSort(int list[], int length)
{
    if (!length || !(length - 1)) //空陣列或只有一個元素直接返回
        return;
    for (int i = 1; i < length; i++)
    {
        int j;
        int shell = list[i]; //設當前元素為哨兵
        for (j = i - 1; j >= 0 && list[j] > shell; j--)
            list[j + 1] = list[j]; //比哨兵大,後移
        list[j + 1] = shell;       //找到恰當位置了,插入
    }
}
//折半插入排序
void BiInsertionSort(int list[], int length)
{
    if (!length || !(length - 1))
        return;
    for (int i = 1; i < length; i++)
    {
        int j;
        int shell = list[i];
        int low = 0, high = i - 1;
        while (low <= high) //與直接插入排序相比,多了一個二分查詢插入位置
        {
            int m = (low + high) / 2;
            if (shell > list[m])
                low = m + 1;
            else
                high = m - 1;
        }
        for (j = i - 1; j >= high + 1; j--)
            list[j + 1] = list[j];
        list[j + 1] = shell;
    }
}
//希爾排序
void ShellInsert(int *list, int length, int dk)
{
    if (!length || !(length - 1))
        return;
    for (int i = dk; i < length; i++)
    {
        int shell = list[i];
        int j;
        for (j = i - dk; j >= 0 && shell < list[j]; j -= dk)
            list[j + dk] = list[j];
        list[j + dk] = shell;
    }
}
void ShellSort(int *delta, int k, int *list, int length)
{
    for (int i = 0; i < k; i++)
        ShellInsert(list, length, delta[i]); //進行增量為delta[i]的直接插入排序
}
//氣泡排序
void BubbleSort(int *list, int length)
{
    int i = length, lastEx;
    while (i > 0)
    {
        lastEx = 0;
        for (int j = 0; j < i; j++)
        {
            if (list[j] > list[j + 1]) //把未排序部分的最大值上浮,使得每趟排序後完成的部分至少加一
            {
                int temp = list[j];
                list[j] = list[j + 1];
                list[j + 1] = temp;
                lastEx = j;
            }
        }
        i = lastEx; //最後一次交換後面的已經完成排序
    }
}
//快速排序
void QuickSort(int *list, int low, int high)
{
    int Olow = low, Ohigh = high; //記錄原來的上界和下界
    if (low < high)
    {
        auto midOfThree = [](int a, int b, int c) { return min(a, max(b, c)); };
        int shell = midOfThree(list[low], list[high], list[(low + high) / 2]); //用low,high以及中間的數三個數的中位數做軸
        while (low < high)                                                     //根據軸將左右分為小於軸的部分和大於軸的部分
        {
            while (low < high && list[high] >= shell) //找到比軸小的數,放低半區
                --high;
            list[low] = list[high];                  //low原來的值已經拷貝,放心賦值
            while (low < high && list[low] <= shell) //找到比軸大的數,放高半區
                ++low;
            list[high] = list[low]; //high原來的值賦給了上面,不用擔心丟失
        }
        list[low] = shell;
        QuickSort(list, Olow, low - 1);  //對低半區遞迴
        QuickSort(list, low + 1, Ohigh); //對高半區遞迴
    }
}
//簡單選擇排序
void SelectSort(int *list, int length)
{
    for (int i = 0; i < length - 1; i++)
    {
        int shell = list[i], minindex = i; //記錄當前的值
        for (int j = i; j < length; j++)
        {
            if (list[j] < list[minindex]) //尋找未排序部分最小值
                minindex = j;
        }
        if (i != minindex) //如果當前值不是未排序部分最小值,進行交換
        {
            list[i] = list[minindex];
            list[minindex] = shell;
        }
    }
}
//堆排序
//對於從0開始的陣列
//parent = [(i - 1)/2]  [x]表示對x向下取整
//lChild = 2*i + 1
//rChild = 2*i + 2
void Heapify(int *list, int root, int high)
{
    if (root >= high) //越界了,直接返回
        return;
    int lChild = 2 * root + 1;
    int rChild = 2 * root + 2;
    int maxi = root;
    if (lChild < high && list[lChild] > list[maxi])
        maxi = lChild;
    if (rChild < high && list[rChild] > list[maxi])
        maxi = rChild;
    //找到了三者最大值,若不是根節點
    if (maxi != root)
    {
        int temp = list[maxi];
        list[maxi] = list[root];
        list[root] = temp;         //最大者上浮
        Heapify(list, maxi, high); //可能破壞了交換的那一邊的堆結構,重新heapify一下
    }
}
void HeapSort(int *list, const int length)
{
    for (int i = length / 2; i >= 0; i--) //length/2之後的都是葉子節點,已經符合要求,不需要heapify
    {
        Heapify(list, i, length); //一定是自底向上開始建堆,因為只有兩個孩子都是堆的情況下才能heapify整體,而葉子節點我們認為已經heapify
    }
    for (int i = length - 1; i >= 0; i--) //上面建的大根堆,最大值在頭上
    {
        int temp = list[i];
        list[i] = list[0];
        list[0] = temp;      //交換0,i位置的值,讓未排序最大值加入到排好序的地方,未排序部分長度減一
        Heapify(list, 0, i); //對0->i-1重新建堆
    }
}
//歸併排序
void MSort(int *list, int *helper, int low, int high)
{
    if (low == high)//遞迴結束
        return;
    int mid = (low + high) / 2;
    MSort(list, helper, low, mid);//前一半排好序
    MSort(list, helper, mid + 1, high);//後一半排好序
    int i = low, j = mid + 1;
    int k = low;
    while (k <= high)
    {
        if (j > high || i <= mid && helper[i] <= helper[j])//前後兩半歸併在一起
        {
            list[k++] = helper[i++];
        }
        else
        {
            list[k++] = helper[j++];
        }
    }
    for (int i = low; i <= high; i++)
        helper[i] = list[i];
}
void MergeSort(int *list, int length)
{
    int *helper = (int *)malloc(sizeof(int) * length);
    for (int i = 0; i < length; i++)
        helper[i] = list[i];
    MSort(list, helper, 0, length - 1);
    free(helper);
}
速度比較如下

7e398aaffad7d1e97187512579e6263d.png