进阶算法——希尔,快速,堆排序,归并排序

希尔算法:

希尔算法是在插入排序上的改进,因为插入排序在基本有序的队列中,会排序很快,所以希尔算法相比插入排序,是通过循环将数组变成基本有序。

先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前三种方法有较大提高。

 

分组规则:分组数=数据总数/3+1

 

void ShellSort(int arr[], int length)
{
	int increasement = length;
	int i, j, k;
	do 
	{
		//确定分组的增量
		increasement = increasement / 3 + 1;
		for (i = 0; i < increasement;i++)
		{

			for (j = i + increasement; j < length;j+=increasement)
			{
				//从小到大
				if (arr[j]<arr[j-increasement])
				{
					int temp = arr[j];
					for (k = j - increasement; k >= 0 && temp < arr[k];k-=increasement)
					{
						arr[k + increasement] = arr[k];

					}
					arr[k + increasement] = temp;
				}
			}
		}
	} while (increasement>1);
}

快速排序

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法

分治法基本思想

先从数列中取出毅哥数作为基准数(枢轴)。

分区过程将比这个数大的数全放到他的右边,小于或者等于的数全放在左边(升序)。

在对左右区间重复第二步,指导各区间只有一个数字。

排序思想:

//快速排序 从小到大
void QuickSort(int arr[], int start, int end)
{
	int i = start;
	int j = end;

	///基准数
	int temp = arr[start];
	if (i<j)
	{
		while (i < j)
		{
			//从右向左找比基准数小的
			while (i<j&&temp<=arr[j])
			{
				j--;
				
			}
			//填坑
			if (i < j)
			{
				arr[i] = arr[j];
				i++;
			}
			//从左向右 找比基准数大
			while (i<j&&temp>arr[i])
			{
				i++;
				
			}
			//填坑
			if (i < j)
			{
				arr[j] = arr[i];
				j--;
			}
			
		}
		//把基准数放到i或者j位置
		arr[i] = temp;
		//递归
		//对左半部分,快速排序
		QuickSort(arr, start, i - 1);
		//对右半部分,快速排序
		QuickSort(arr, i+1, end);
	}
	
}

当第一次循环结束后,标志位左边应该都小于上述代码的temp,右边都大于。在分别左右两边进行排序,所以要用到递归。

 

归并算法:

基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了?

可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序

1.将数组分为两组,然后分别对两组再次进行分组,当每组数字为一个时,这时每组可以看作有序数组。

2.将每组合并,在合并过程中进行排序,将排序后的数组放入临时数组中。

 

下图为数组分组,用到了递归

//合并算法 从小到大
void Merge(int arr[], int start, int end, int mid, int *temp)
{
	int i_start = start;
	int i_end = mid;
	int j_start = mid + 1;
	int j_end = end;
	int length = 0;//辅助空间长度
	//合并两个有序序列
	while (i_start<=i_end&&j_start<=j_end)
	{
		if (arr[i_start]<arr[j_start])
		{
			temp[length] = arr[i_start];
			i_start++;
			length++;
		}
		else
		{
			temp[length] = arr[j_start];
			j_start++;
			length++;
		}
	}
	//i这个序列 上个步骤遍历结束之后 i,j中不知道哪一个序列中会有一个数字没有输出
	while (i_start<=i_end)
	{
		temp[length] = arr[i_start];
		i_start++;
		length++;
		
	}
	//j这个序列
	while (j_start <= j_end)
	{
		temp[length] = arr[j_start];
		j_start++;
		length++;

	}
	//把辅助空间 覆盖原空间
	for (int i= 0; i< length;i++)
	{
		arr[start + i] = temp[i];
	}
}

 

 

堆算法:

完全二叉树

堆排序用到的就是完全二叉树的模型

堆排序的核心思想就是要首先初始化大顶堆(每个节点都大于他的子节点,所以上图中A的值最大,B,C为第二大第三大)。

最后一个有子节点的数 = 总节点数/2

E的位置= 10/2 = 5

 

 1.初始化大顶堆 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值