希尔排序,堆排序,归并排序

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_kab777/article/details/102736029

希尔排序

思想:
(1)在直接插入排序的思想上,如果先使数组尽可能有序,则就可使时间复杂度趋近O(n)。因此,算法也集中在使数组有序。首先用分组的方法将数组分组,这里举例假设数组有11个数,我们可以分为3个为1组,再1个为1组。
(2)给定一个数组分组的宽度,则外层循环就可直接从i=0+width开始,并用tmp保存当前arr[i]的值,然后i++向后直到遍历完数组;内层循环j需要从外层循环当前小组中的左邻第一个开始倒退,每次走width个长度,即j-=width,每次都需要与tmp计较,如果tmp小于arr[j],则将arr[j]赋给arr[j+width],然后j倒退;否则直接使跳出本次内层循环,内层循环结束后将tmp的值赋给arr[j+width]。然后进入下一次外层循环。
时间复杂度:O(n ^1.3~ n ^1.5)
空间复杂度:O(1)
稳定性:不稳定

堆排序

思想:
(1)将数组模拟划分为一个完全二叉树,此时我们可以得知完全二叉树的特性:已知父节点或者左右子节点的任意一个就可求出剩余的两个。比如:已知父节点为n,则左子节点为2n+1,右子节点为2n+2;已知左或右子节点为n,则父节点为(n-1)/2。
(2)堆排序,首先得构造最大堆,从当前叶子节点的根节点开始,使得父节点不能小于子节点。先用tmp保存开始位置的值arr[start],外层循环i从start开始,i–倒退,直到i=0;内层循环j从当前start的左子节点开始,下一次循环每次到当前j的左子节点,并限制j在数组长度-1范围内。进入内层循环,首先判断左子节点的值是否大于右子节点,如果小于则令j++保证j当前的值存储子节点中的较大值。然后比较tmp与当前arr[j]的值,如果tmp>arr[j],则跳出本次内层循环,否则arr[start]=arr[j]并令start=j,内层循环条件结束后,令arr[start]=tmp;
(3)在构建最大堆的基础上,从0开始,逐步遍历需要循环len-1次,将当前树的第一个父节点与树的最后一个节点交换,然后再进行一次调整,即就是调用构建最大堆的内层循环。
时间复杂度:O(nlogn)
空间复杂度:O(1)
稳定性:不稳定

归并排序

思想:( 1 )通过长度循环乘2的方式分组,在组内逐步找到较小的值赋给另一个数组,每次循环都可以保证各组内有序,从而下一次循环就相当于将小组内的右半组中的数有序的与左半组一同赋值给另一个数组,再由另一个数组传给当前数组。
( 2 )组内实现:分两种情况
第一种:存在右半组;即就是low2<len;
判断:只有在low1<=high1&&low2<=high2的情况下循环比较arr[low1]与arr[high1],小的值赋值给brr。
不符合条件后,判断是左半组还是右半组有剩余,判断条件为low小于等于high,然后将剩余的数赋值给brr。

第二种:只有左半组,即就是low1<len。直接将组内的数赋个brr。

时间复杂度:O(nlogn)
空间复杂度:O(n)
稳定性:不稳定

猜你喜欢

转载自blog.csdn.net/weixin_kab777/article/details/102736029