算法回顾(一):排序算法(上)

本文深入讲解了十种经典的排序算法,包括冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序和基数排序。每种算法都有详细的解释和代码实现,帮助读者理解排序算法的工作原理和时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法回顾(一):排序算法(上)

排序算法是最基本的算法之一,基本上所有的开发人员都接触过排序算法,所以在回顾算法时,第一个想到的就是排序算法。常见的排序算法有:

  • 冒泡排序
  • 选择排序
  • 插入排序
  • 希尔排序
  • 归并排序
  • 快速排序
  • 堆排序
  • 计数排序
  • 桶排序
  • 基数排序

接下了详细介绍这些算法:

冒泡排序

冒泡排序的冒泡可以很形象的表示该排序过程,简单来说,就是通过比较相邻的两个数,将较小的和较大的交换位置,这样不停的交换,最大的数就像“水泡”一样浮到最上面(数组的最后位置)。
代码如下:

void BubbleSort(int *x, int len)
{
    int i = 0, j = 0;
    for (i = 0; i < len-1; i++)
    {
        for (j = 0; j < len-i-1; j++)
        {
            if (x[j] > x[j+1])
            {
                Swap(x, j, j+1);
            }
        }
    }
}

选择排序

选择排序就是遍历一遍数组,找到最大值所在的位置,将其与数组最后的位置进行交换,然后在剩余数组中重复此操作。
代码如下:

void SelectSort(int *x, int len)
{
    int i = 0, j = 0, tmp = 0;
    for (i = 0; i < len-1; i++)
    {
        tmp = i;
        for (j = i; j < len; j++)
        {
            if (x[j] < x[tmp])
            {
                tmp = j;
            }
        }
        Swap(x, tmp, i);
    }
}

插入排序

在现实生活中,即使是没有接触过算法的人都不由自主的使用过插入排序算法,最基本的应用是:在打牌时,玩家基本都会使用插入的方式来将牌理顺,他们保持自己手牌是顺序的,然后摸到新的牌后,根据牌的大小将该牌插入到合适的位置。
假设有数组 x[n],将其升序排序。
插入排序的基本思想为:在插入新的数x[k+1]时,认为x[1…k]已经排好序了,只要将x[k+1]插入到x[1…k]中的合适位置,就可以保证x[1…k+1]是有序的。
代码如下:

void isort(int *x, int len)
{
    int i = 0, j = 0;
    for (i = 0; i < len; i++)
    {
        for (j = i; j > 0 && x[j] < x[j-1]; j--)
        {
            Swap(x, j, j-1);
        }
    }
}

可以看出插入排序的时间复杂度为O(n2),但是在数组基本为降序的情况下,插入排序的效果最差。

希尔排序

希尔排序可以被看做为插入排序的升级版,是在原始数组的不同子数组上进行排序,算法的简单步骤如下:

  1. 选择增量,根据增量可以将数组分割成不同子数组
  2. 对于每个子数组,进行排序,使用简单的排序方法,我们使用的是插入排序对于每个子数组,进行排序,使用简单的排序方法,我们使用的是插入排序
  3. 减小增量,重新执行以第1步,直到增量为1减小增量,重新执行以第1步,直到增量为1

代码如下:

void ShellSort(int *x, int len)
{
    int step = len/2;
    int i,j;
    while (step >= 1)
    {
        for (i = step; i < len; i++)
        {
            for (j = i-step; j >= 0; j-=step)
            {
                if (x[j] > x[j+step])
                {
                    Swap(x, j, j+step);
                }

            }
        }
        step /= 2;
    }
}

归并排序

归并排序是使用递归的思想进行排序的,简单来说,就是将两个有序子序列合并成一个大的有序子序列。所以可以将归并排序简单表述为以下步骤:

  1. 长度为n的数组划分为n/2的子数组
  2. 分别对子数组进行归并排序,使其变得有序
  3. 将两个子数组进行合并形成一个最终的有序数组

代码如下:

//合并
void Merge(int *x, int len, int l, int h)
{
    int mid = (l+h)/2;
    int i = l, j = mid, k = 0;
    int *tmp = new int[h-l];
    while(1)
    {
        if (i == mid)
        {
            for(; j<h; j++)
            {
                tmp[k++] = x[j];
            }
            break;
        }
        if (j == h)
        {
            for(; i < mid; i++)
            {
                tmp[k++] = x[i];
            }
            break;
        }
        if (x[i] > x[j])
        {
            tmp[k++] = x[j++];
        }
        else
        {
            tmp[k++] = x[i++];
        }
    }
    for (k=0; k<h-l; k++)
    {
        x[l+k] = tmp[k];
    }
}
//归并排序
void MergeSort(int *x, int len, int l, int h)
{
    if (h-l <= 1)
        return;
    int mid  = (l+h)/2;
    MergeSort(x, len, l, mid);
    MergeSort(x, len, mid, h);
    Merge(x, len, l, h);
}

参考:十大经典排序算法(动图演示)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值