[C语言]冒泡,插入,希尔排序

文章介绍了三种常见的排序算法:冒泡排序、插入排序和希尔排序。冒泡排序和插入排序是稳定的,时间复杂度为O(n^2)。希尔排序通过设置增量序列改进了排序效率,减少了数据移动次数,但不保证稳定性。希尔排序在处理顺序表时尤其有效,而对于链表等结构,其优势不明显。
摘要由CSDN通过智能技术生成

排序的稳定性, 稳定就是相等的项, 不会改变原来的位置顺序.
在这里插入图片描述

冒泡排序

稳定, 时间复杂度O(n^2).
在这里插入图片描述
由图可知, 冒泡排序是双层循环, 外层循环的效果即为每一层最后一个就会出现一个排序完成的元素; 内层循环的效果即为每相邻两个元素都进行比较大小, 然后大的放后面小的在前面.
外层循环次数: n-1次
内层循环次数: n-i-1次

//实现代码

//交换两个数字
void swapNum(int* num1, int* num2)
{
    *num1 = *num1 ^ *num2;
    *num2 = *num1 ^ *num2;
    *num1 = *num1 ^ *num2;
}
//冒泡排序
void bubbleSort(int source[], int sz)
{
    if (source == NULL)
    {
        return;
    }

    for (int i = 0; i < sz - 1; i++)
    {
        for (int j = 0; j < sz - i - 1; j++)
        {
            if (source[j] > source[j + 1]) //从小到大顺序
            {
                swapNum(&source[j], &source[j + 1]);
                count++;
            }
        }
    }
}

插入(直插)排序

稳定, 时间复杂度O(n^2)
在这里插入图片描述
外层循环的逻辑即为,排列好前n个元素, 内层循环即为依次判断进行向后移动, 特点是前面的元素是有序的, 所以内层条件判断为只要待插元素小于前面的元素就执行移动.
外层循环次数: i从1开始, n-1次
内层循环次数: i次

//直接插入排序
void directInsertSort(int source[], int sz)
{
    if (source == NULL)
    {
        return;
    }

    for (int i = 1; i < sz; i++)
    {
        int temp = source[i];
        int j;

        for (j = i; j > 0 && source[j - 1] > temp; j--) //判断前者大于后者
        {
            source[j] = source[j - 1];
        }
        source[j] = temp;
    }
}

希尔排序

不稳定, 时间复杂度与采用的增量序列有关.
逻辑: 将顺序表分为多个子列, 将子列进行排序, 将原来的无序数组改为有些序的数组, 经过几次子列的排序来实现整体的排序.
步长: 每一个子列的间距, 如步长为2, 就是奇数偶数子列.

希尔排序的增量序列

  1. 原始的希尔排序, n/2, n/4, n/8 … 1
  2. Hibbard增量序列, 1, 3, 7, … , 2^k - 1. 时间复杂度为O(n^3/2)
  3. Sedgewick增量序列
  4. Knuth增量序列.
    在这里插入图片描述
    分组为逻辑上的分组, 物理上的位置还是依旧分来的, 但是顺序表的特性,以及知道步长可以很轻松找到一组的下一个元素的地址. 可以看到图上的经过了一次的移动就可以完成了排序, 使用直插和冒泡都会经过3次移动, 提高了效率.
void shellSort(int source[], int sz)
{
    if (source == NULL)
    {
        return;
    }

    int n = 5, step, temp, i, j;
    while (n != 0)
    {
        step = (1 << n) - 1; //步长
        
        //直插
        for (i = step; i < sz; i++) //从第二组开始,但是不能超过最大长度
        {
            temp = source[i];
            for (j = i; j >= step && temp < source[j - step]; j -= step)
            {
                    source[j] = source[j - step];
            }
            source[j] = temp;
        }
        --n;
    }
}

希尔排序的最大优点,不是时间复杂度,而是数据移动次数大量减少,如果是顺序表,每一个节点都是大量的数据,减少移动次数,是很必要的,虽然增加了比较次数,但是不需要大量的数据移动操作了。
顺序存取也就是顺序表的结构,读取写入速度快,但是想要移动元素慢,因为移动一个磁盘就要转一圈。
如果是随机存取结构,链表的结构,读取写入速度慢,但是移动很快。
所以,从硬件层面来看,如果是顺序表,希尔排序快很多,如果是链表,希尔排序优势不大。希尔排序不稳定也是一个缺点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值