【选择排序】手撕八大排序之直接选择排序和堆排序

目录

一.选择排序

1.直接选择排序

2.堆排序


一.选择排序

1.直接选择排序

选择排序(Selection Sort)是一种简单直观的排序算法。它的基本思想是每次遍历找到最小(或最大)的元素然后将其放置在已排序序列的末尾。在每次遍历过程中,选择排序从未排序部分中选择最小(或最大)的元素,依次放置到已排序序列的末尾,直到所有元素都排序完毕。

这里我们选择同时选择最大和最小的的数,然后放在数组头和数组尾。
这是非常好理解的,如下图所示:

//直接选择排序
void SelectSort(int* a, int left,int right)
{
	//注意这里的left和right都是下标
	while (left < right)
	{
		int begin = left;
		int end = right;
		int max = end;
		//注意这里的max和min的取值等于begin或者end,因为之后找最大和最小
		//都是在begin和end的区间找,如果你将min赋值为0,就会出错
		int min = end;
		for (int i = begin; i <= end; i++)
		{
			if (a[i] > a[max])
			{
				max = i;//找出最大数的下标
			}
			if (a[i] < a[min])
			{
				min = i;//找出最小数的下标
			}
		}
		Swap(&a[begin], &a[min]);
		if (begin == max)
		{
			max = min;
		}
		Swap(&a[end], &a[max]);
		left++;
		right--;
	}
}

注意这里还有一个很重要的点需要注意。 这个代码是什么意思?

if (begin == max)
{
	max = min;
}

可以看出,交换后,并没有使得最大和最小的数,放在数组的两端,就是数组没交换前,max就已经和begin重叠了, 这样原本max的值就跑到min上面去了,所以我们要加这个代码,避免这种情况。

直接选择排序的特性总结:
1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
2. 时间复杂度: O(N^2)
3. 空间复杂度: O(1)
4. 稳定性:不稳定

2.堆排序

这里我们把代码放在这里,之前小陈同学已经把堆排序写得很清楚了,不懂的可以点击链接跳转过去看:堆的实现+堆的应用

//交换函数
void Swap(int* p1, int* p2)
{
	int ret = *p1;
	*p1 = *p2;
	*p2 = ret;
}
//向下调整法
void AdjustDown(int* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child<n)
	{
		if (child+1<n&&a[child] < a[child + 1])
		{
			child++;
		}
		if (a[parent] < a[child])
		{
			Swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
//堆排序
void HeapSort(int* a, int n)
{
	for (int i = (n-1-1)/2; i>=0; i--)
	{
		AdjustDown(a, n, i);
	}
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[end], &a[0]);
		AdjustDown(a, end, 0);
		end--;
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值