排序一:插入排序和希尔排序

 今天开始给大家介绍一些排序,之前海量数据还有一部分没总结完,在总结布隆过滤的时候遇到了一些问题,所以之后我会给大家继续总结。

  今天介绍的排序是插入排序和希尔排序。

  

首先要说的是插入排序,插入排序是一个相对容易理解的排序,从他的名字就可以看出,他是通过插入的方式来进行排序的。当你拿到一个数组的时候,首先你要确定你的数组是要升序还是降序。这里我们拿升序来举例子。拿到数组的时候从你的第二个元素开始比较,拿这个数组来说从3开始,因为你要做的是升序,所以当你拿的3和9比较的时候,3比9小那一定是3在9前边的,所以就要3和9交换位置

 

交换完成之后,就要读取下一个数字也就是4,这时候4和9比较,4比9小,然后交换位置,之后4和3比较4比3大就停止交换。2也是如此

 

当读取到2,并且把2交换完之后数组就是上图的样子,这时候读取下一个数字6,6 比9小,6和9交换,再往前6比4大,不交换了,这时候还需要将6和4之前的元素比较吗?不需要了,因为你读取到6的时候6之前的数组已经是有序的了。一直这样下去直到最后一个元素,这时候数组就排序完成了。

void InsertSort(int *a, int num)

{

int Index = 0;

int j = 0;

int temp = 0;

for (Index = 1; Index < num; Index++)

{

j = Index-1;

temp = a[Index];

while (j >= 0 && temp < a[j])

{

//走到这里说明temp比你的a[i]要大 就需要让你现在这个j元素往后移动

a[j + 1] = a[j];

j--;

}

//走到这里说明你的a[j]比你的temp小了  这里的大小看你是升序还是降序我这里一直在找比他小的所以是升序排序

a[j + 1] = temp;

}

 

}

 

代码实现起来也并不难这里交换其实用的是覆盖法,因为我在读取到当前数组元素的时候我已经通过temp把这个元素保存下来了,所以当需要交换的时候直接将他之前的那个元素把他覆盖了就可以了。

 

  我们之前所常见的排序就是冒泡排序,这里的插入排序时间复杂度理想情况来说是小于冒泡排序的,但是也不排除,你现在想升序,但是你的数组现在就是降序有序的数组,这时候,时间复杂度就是十分高的。

  所以,有人为了为了减少在这种情况下的排序时间复杂度,所以就有了我接下来说的希尔排序。

假如我现在的数组是

 

现在我让你排成升序,这就是最极端的情况,但是希尔排序是怎么做的呢?简单来说,希尔排序是将你的数组先进行一个预排序。

 

这里在写数组下标的时候....从1开始了理解意思就好。

这里希尔排序做的是先将数组下标是1,4,7这三个数进行一下预排序。然后将2,5,8,三个数进行一下预排序,最后将你的3,6,9进行一下预排序,然后再将你的数组进行一下插入排序。这就是希尔排序做的事情,先跳着将你的数组进行一个预排序,这里是极端情况,在进行预排序后数组已经有序了,但是这也是极少数情况。

void ShellSort(int *a, int num)

{

int gap = 3;//间隔值,也就是预排序的时候的跳过的间隔

//首先要进行的是预排序

int end = num;

int temp = a[end];

while (gap >= 1)

{

 

for (int i = gap; i < num ; i++)//i++是一个很巧妙的地方

{

temp = a[i];

end = i - gap;

while (end>0 && a[end] > temp)

{

a[end + gap] = a[end];

end = end - gap;

}

a[end + gap] = temp;

}

if (gap == 1)

break;

gap = gap / 3 + 1;

}

}

希尔排序并不是说我先通过一个固定的gap间隔值来进行预排序一趟之后就按照以前的插入排序进行排,这里是不断的缩小你的间隔值来不断的接近之前间隔为1的插入排序,这到最后间隔值变成1,也就是完全和以前的插入排序一样了。

其他方面其实和插入排序完全一样,插入排序是读取的你当前数字的下一个数字,但是希尔排序读取的就是你当前数字距离为gap的数字。

 在这里读取数据的时候,我选择的是从数组后边向前读,也可以从前往后读。然后整个程序最巧妙的地方在于for循环中的i++,在上边的程序中我也标注出来了,为什么说他巧妙。

 

图里红色的数据是间隔为gap的值,绿色和蓝色也都是,也就是说,你需要将下标为0、3、6的三个数据进行比较,之后需要将绿色下标为1、4、7的数据进行比较,如果是按当前的方法的话,进行完第一个轮排序之后,也就是红色数据比较完之后,你就找不到你的绿色第一个数据,还需要一些中间值进行保存数据,但是这里用i++的思想是,首先让你0和3比较,比较完之后不会继续去找6,而是去让1和4比较,之后是2和5比较,然后当所有都结束之后,开始让3和6比较,4和7比较,其实这里我解释多了之后反倒很难理解自己稍微一思考就能明白。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值