shell排序_常用排序算法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);
}
速度比较如下

5219292fc8c594146616baa1393a6171.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值