直接插入排序和希尔排序

直接插入排序非常容易理解,只需要在【0,end】这个有序区间内把end+1按照大小比较插入到相应位置即可。其中直接插入排序复杂度为O(N^2),而希尔排序接近O(N^1.3),和O(N)差不太多。

void InsertSort(int* a, int n)
{
    for (int i = 0;i < n - 1;++i)
    {
        int end = i;
        int tmp = a[end + 1];
        while (end >= 0)
        {
            if (a[end] > tmp)
            {
                a[end + 1] = a[end];
                end--;
            }
            else
            {
                break;
            }
        }
        a[end + 1] = tmp;
    }
}

这里的参数是首地址,n代表数组内的个数。首先需要理解的是先定义一个tmp来保存end+1的值(在后续的后移过程中会被覆盖),下面进行while 循环,如果end>=0则进行操作。在a[end]>tmp时需要后移同时需要对end--。剩下就是在合适的位置放入即可,这个放入数值需要注意2点。

第一点是在while结束时,也就是比如说要插入的值是最小的,那么end需要一直减,最后减为-1跳出了while循环。

第二点是找到了合适的位置(找到了应该插入的位置)但因为end--的作用,使得在插入时应该是end+1的位置赋值。

这两种情况对应的插入都是end+1位置赋值,所以在while循环中使用了break来跳出。

剩下需要思考的就是end的数值了,这里是利用for循环进行遍历,从0开始,到达的位置是n-2!这是因为在while循环操作中,虽然有n 个数值,但是最后一个数值对应的下标是n-1,只有在end为n-2时,进行插入赋值的end+1才到达n-1,这才不会出现数组越界的问题。

希尔排序是在直接插入排序的基础上进行的,其主要思想就是先进行分块,每一块排好序,最终再实现全排序。

void ShellSort(int* a, int n)
{
    int gap = n;
    while (gap > 0)
    {
        gap = gap / 2;
        for (int i = 0;i < n - gap;i++)
        {
            int end = i;
            int tmp = a[end + gap];
            while (end >= 0)
            {
                if (a[end] > tmp)
                {
                    a[end + gap] = a[end];
                    end -= gap;
                }
                else
                {
                    break;
                }
            }
            a[end + gap] = tmp;
        }
        
    }
    

}

里面的内容还是直接插入排序的,只不过将1替换成了gap而已。使用gap来分为具体的块数来进行跳级操作。这里需要确定一下gap的数值,可以根据数组里面数值的个数来确定,通过对n 的除法(除以2可以得到gap为1的情况,此时也就是直接插入排序了)以及while循环来进行gap的变更。

下面是测试用例和全代码

#include<iostream>
using namespace std;
void InsertSort(int* a, int n)
{
    for (int i = 0;i < n - 1;++i)
    {
        int end = i;
        int tmp = a[end + 1];
        while (end >= 0)
        {
            if (a[end] > tmp)
            {
                a[end + 1] = a[end];
                end--;
            }
            else
            {
                break;
            }
        }
        a[end + 1] = tmp;
    }
}
void ShellSort(int* a, int n)
{
    int gap = n;
    while (gap > 0)
    {
        gap = gap / 2;
        for (int i = 0;i < n - gap;i++)
        {
            int end = i;
            int tmp = a[end + gap];
            while (end >= 0)
            {
                if (a[end] > tmp)
                {
                    a[end + gap] = a[end];
                    end -= gap;
                }
                else
                {
                    break;
                }
            }
            a[end + gap] = tmp;
        }
        
    }
    

}
void PrintArray(int* a, int n)
{
    for (int i = 0;i < n;i++)
        cout << a[i] << " ";
}
int main()
{
    int a[] = { 3,5,2,7,8,6,1,9,4,0 };
    InsertSort(a, sizeof(a) / sizeof(int));
    PrintArray(a, sizeof(a) / sizeof(int));
    cout << "\n";
    cout << "The Another Sort:" << endl;
    ShellSort(a, sizeof(a) / sizeof(int));
    PrintArray(a, sizeof(a) / sizeof(int));
    return 0;
}

下面是输出结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值