冒泡排序/堆排序

冒泡排序:每一趟循环两两比较,大的向后挪动,最终最大值放在最后,n个数据需要跑n-1趟。

 

代码如下:

//冒泡排序  时间复杂度O(n^2) 空间复杂度O(1)  稳定性:稳定
void BubbleSort(int* arr, int len)
{
	assert(arr != NULL);
	for (int i = 0; i < len-1; ++i)
	{
		for (int j = 0; j < len - 1 - i; ++j)
		{
			if (arr[j+1] < arr[j])
			{
				int tmp = arr[j+1];
				arr[j+1] = arr[j];
				arr[j] = tmp;
			}
		}
	}
}

我想大多数人刚开始写的代码是上边的类型,但之后有人对冒泡进行优化,但优化的可以说是优化很小

//冒泡排序  时间复杂度O(n^2) 空间复杂度O(1)  稳定性:稳定
void BubbleSort(int* arr, int len)
{
	assert(arr != NULL);

	bool tag = true;//标记  首先赋初值为真
	//从头到尾遍历一般,没有交换操作,则可以认定完全有序
	//反过来说:只要有一次交换操作,则不能认定完全有序
	for (int i = 0; i < len-1; ++i)
	{
		tag = true;
		for (int j = 0; j < len - 1 - i; ++j)
		{
			if (arr[j+1] < arr[j])
			{
				int tmp = arr[j+1];
				arr[j+1] = arr[j];
				arr[j] = tmp;
				tag = false;
			}
		}
		if (tag)
		{
			break;
		}
	}
}

就是加了一个bool类型,只要头到尾遍历一般,没有交换操作,则可以认定完全有序,直接退出。

堆排序:

先搞清楚什么是大顶堆,小顶堆

大顶堆:父节点的值大于孩子节点(从小到大排序用大顶堆)

 

小顶堆:父节点的值小于孩子节点(从大到小排序用小顶堆)

 

1。我们需要先将原始数据想象成一个完全二叉树

 2.从最后一个非叶子节点开始调整,调整为大顶堆

 

此时我们会发现根节点的值是数组中最大的那个值

 3.将根节点和最后一个节点的值进行交换,然后将这个尾结点踢除我们的排序数组即可

 

 4.重复2,3步骤

代码如下:

//一次调整函数 时间复杂度O(logn)
void HeapAdjust(int arr[], int start, int end)
{
	//assert
	int tmp = arr[start];    
	for(int i=start*2+1; i<=end; i=start*2+1)//start*2+1 相当于是start这个节点的左孩子
	{                     //i<end  退出for循环  触发的是情况1
		if(i<end && arr[i+1] > arr[i])//i<end 代表存在右孩子,且右孩子的值还大于左孩子
		{
			i++;//则此时,让i指向右孩子
		}
		//此时i肯定已经指向较大的那个孩子

		if(arr[i] > tmp)//子大于父
		{
			arr[start] = arr[i];
			start = i;
		}
		else
		{
			break;//退出for循环,触发情况2
		}
	}

	arr[start] = tmp;
}

//堆排序:时间复杂度O(n*logn)  空间复杂度O(1)  稳定性:不稳定
void HeapSort(int *arr, int len)
{
	//1.整体从最后一个非叶子节点开始由内到外调整一次
	//首先需要知道最后一个非叶子节点的下标
	for(int i=(len-1-1)/2; i>=0; i--)//因为最后一个非叶子节点肯定是 最后一个叶子节点的父节点
	{
		HeapAdjust(arr, i, len-1);//调用我们一次调整函数  //这里第三个值比较特殊,没有规律可言,则直接给最大值len-1
	}

	//此时,已经调整为大顶堆了

	//接下来,根节点的值和当前最后一个节点的值进行交换,然后将尾结点剔除掉
	for(int i=0; i<len-1; i++)
	{
		int tmp = arr[0];
		arr[0] = arr[len-1-i];//len-1-i 是我们当前的尾结点下标
		arr[len-1-i] = tmp;

		HeapAdjust(arr, 0, (len-1-i)-1);//len-1-i 是我们当前的尾结点下标,然后再给其-1则相当于将其剔除出我们的循环
	}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值