赞
踩
目录
排序一共有八种:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序和计数排序这八种排序算法。
排序在我们现实生活中其实是非常常见的,而且很多地方的分不开它们,当我们在某软件网购的时候,我们可以使用价格排序,销量排序,好评排序来筛选我们想要的商品。
这里我选择销量和价格两个条件,软件就会自动的给顾客排好序,这底层的逻辑就是使用的排序算法,可知排序算法是非常重要的,只不过现在学习的八大排序是很基础的,后面的红黑树和AV树才是真正的巨头,现在的我们必须要打牢基础,脚踏实地的学习。
插入排序顾名思义,就是一个一个的插入,如同我们摸扑克牌一样,当摸第一张牌上来的时候,直接放到手里面即可,摸第二张的时候,就和手里面的比较,看是放在后面还是前面。依次类推,每次摸牌起来的时候,手里的牌都是有序的,只需要把这张牌插入到有序的牌中即可。
注意:这里我们的排序都是排的升序。
- //直接插入排序
- void InsertSort(int* a, int n)
- {
- for (int i = 1; i < n; i++)
- {
- int end = i - 1;//这是有序数组的最后一个元素
- int temp = a[i];
- while (end >= 0)
- {
- if (temp < a[end])//待插入的数和最后这个数进行比较
- {
- a[end+1]=a[end];
- end--;//交换了,end就往前移一位,再继续进行比较
- }
- else
- {
- break;
- }
- }
- a[end + 1] = temp;
- }
- }
这里动图不太理解,我们还是一样画图来理解。
第一次:
第二次:
第三次:
这时已经退出while循环了,但是数组中还有一位是空缺的,并且end已经不指向数组的位置了,所以最后一句的a[end+1]=temp,就是为了把这个位置给填上。
就这样不断简单的重复,就可以把这个无序的数组排序为一个升序的数组。
希尔排序是由美国计算机科学家 Donald Shell 在1959年提出的。当时,他发表了一篇名为 “A High-Speed Sorting Procedure” 的论文,介绍了这种排序算法。
希尔排序本质上是插入排序的一种改进版本。传统的插入排序在排序一个逆序的序列时效率较低,因为它每次只能将一个元素移动一个位置。为了解决这个问题,Shell 提出了一种逐步缩小增量的方法,即先比较距离较远的元素,然后逐渐缩小间隔,最终达到相邻元素之间的比较。
希尔排序的核心概念是使用一个增量序列,将待排序的序列分割成多个子序列,对每个子序列进行插入排序。然后逐渐缩小增量,直至增量为1,进行最后一次插入排序。通过这种方式,希尔排序能够高效地排序序列。
最后增量为1时,也就变成了直接插入排序了。
动画演示:
第一次设置间隔为5,那么49和13比较然后进行排序,38和27进行比较然后进行排序。依次类推,直到把所有间隔为5的数先排序完。
第二次就把间隔缩小,继续排序,直到间隔为1了之后,再次排序就成立直接插入排序,这样排序了之后还数组的数据就变成有序的了。
但是这里有一个点需要我们注意,那就是如何将间隔逐渐缩小,到最后为1,这就需要对数组的大小做文章了。
- //希尔排序
- void ShellSort(int* a, int n)
- {
- int gap = n;
- while (gap > 1)//gap等于1,那么就排序完毕了,即退出循环
- {
- gap = gap / 3 + 1;
- //不管n是偶数还是奇数,只要最后+1,最后的gap一定会变成1
- for (int i = 0; i < n - gap; i += gap)
- //注意这里i要小于n-gap,不然下面的temp可能就会越界
- {
- int end = i;
- int temp = a[i + gap];
- while (end >= 0)
- //注意下面的逻辑和直接插入排序的逻辑是一样的,只是间隔不一样罢了
- {
- if (temp < a[end])
- {
- Swap(&a[end + gap], &a[end]);
- end -= gap;
- }
- else
- {
- break;
- }
- }
- a[end + gap] = temp;
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。