排序嘉年华———选择排序和快排原始版

一.选择排序

在进行大佬“快排”之前先来一道开胃小菜————选择排序
选择排序是一种简单直观的排序算法,它的基本思想是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

选择排序的具体步骤如下:

1.在未排序序列中找到最小(或最大)的元素,存放到排序序列的起始位置。
2.从剩余未排序元素中继续寻找最小(或最大)的元素,放到已排序序列的末尾。
3.重复步骤2,直到所有元素均排序完毕。


在这里插入图片描述
两端同时选择进行排序整理。

void Selectsort(int* a, int n)
{
	int begin = 0, end = n - 1;
	while (begin < end)
	{
		int mini = begin, maxi = begin;
		for (int i = begin + 1; i <= end; i++)
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}
			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}
		Swap(&a[begin], &a[mini]);
		if (maxi == begin)
		{
			maxi = mini;
		}
		Swap(&a[end], &a[maxi]);
		begin++;
		end--;
	}
}

每次有两个数被整理到队首和队尾,但由于先更新的是最小值mini所以,如果begin刚好是最大值的话,在进行

Swap(&a[begin], &a[mini]);

时,把最大值下标与最小值下标交换了,因此我们需要加一步判断

if (maxi == begin)
		{
			maxi = mini;
		}

在这里插入图片描述

二.霍尔版快速排序

在这里插入图片描述
霍尔版快速排序的基本思想是通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的数据小,然后再按此方法对这两部分数据分别进行快速排序,递归地进行下去,直到整个序列有序。

霍尔版快速排序的具体步骤如下:

1.选择一个基准元素,通常是序列中的第一个元素。
2.设置两个指针,一个指向序列的起始位置,另一个指向序列的末尾。
3.移动指针,使得左指针指向大于等于基准元素的值,右指针指向小于等于基准元素的值,然后交换两个指针所指向的元素。
4.重复步骤3,直到两个指针相遇。
5.将基准元素与相遇位置的元素交换。
6.递归地对基准元素左右两部分进行快速排序。

1.单趟思想

int left = begin, right = end;
	int keyi = begin;
	while (left < right)
	{
		//右边找小
		while (left < right && a[right] >= a[keyi])
		{
			right--;
		}
		//左边找大
		while (left < right && a[left] <= a[keyi])
		{
			left++;
		}
		Swap(&a[left], &a[right]);
	}
	Swap(&a[left], &a[keyi]);

在这里插入图片描述
由于从右边开始找大,所以结束时左右相遇点一定小于等于key,则最后要将left与keyi交换

2.递归多趟

将keyi更新为相遇点即left/right递归keyi的左边和右边keyi这个位置算已经排好

keyi = left;//更新相遇点为keyi
	//递归
	Quiksort(a, begin, keyi - 1);
	Quiksort(a, keyi + 1, end);

结束条件为左边或右边只有一个数或没有值

//递归条件
	if (begin > end)
		return;

在这里插入图片描述
通过多次递归,左边的每一个值都带上了五角星符号,意味着排序成功

3.寻找中间值作为key

如果在排序有序,或者数据太过极端时,盲目使用left作为keyi,会降低排序效率,这时候就需要在找keyi时进行筛选。
在这里插入图片描述
如图这样就无法发挥好快排的双线优势

所以此时我们需要找到中间值进行交换
int GetMidi(int* a, int begin, int end)
{
	int midi = (begin + end) / 2;
	// begin end midi三个数选中位数
	if (a[begin] < a[midi])
	{
		if (a[midi] < a[end])
			return midi;
		else if (a[begin] > a[end])
			return begin;
		else
			return end;
	}
	else//a[begin]>=a[midi]
	{
		if (a[midi] > a[end])
			return midi;
		else if (a[begin] < a[end])
			return begin;
		else return end;
	}
}
int midi = GetMidi(a, begin, end);
	Swap(&a[midi], &a[begin]);

选取10万个数据随机数进行效率检测

void TestOP()
{
	srand(time(0));
	const int N = 100000;
	int* a1 = (int*)malloc(sizeof(int) * N);
	int* a2 = (int*)malloc(sizeof(int) * N);
	int* a3 = (int*)malloc(sizeof(int) * N);
	int* a4 = (int*)malloc(sizeof(int) * N);
	int* a5 = (int*)malloc(sizeof(int) * N);
	

	for (int i = 0; i < N; i++)
	{
		a1[i] = rand();
		a2[i] = rand();
		a3[i] = rand();
		a4[i] = rand();
		a5[i] = rand();
		

	}
	int begin1 = clock();
	Insertsort(a1, N);
	int end1 = clock();
	int begin2 = clock();
	Bubblesort(a2, N);
	int end2 = clock();
	int begin3 = clock();
	Shellsort(a3, N);
	int end3 = clock();
	int begin4 = clock();
	Quiksort(a4, 0,N-1);
	int end4 = clock();
	int begin5 = clock();
	Heapsort(a5, N);
	int end5 = clock();

	printf("Insertsort:%d\n", end1 - begin1);
	printf("Bubblesort:%d\n", end2 - begin2);
	printf("Shellsort:%d\n", end3 - begin3);
	printf("Qucksort:%d\n", end4 - begin4);
	printf("Heapsort:%d\n", end5 - begin5);

	free(a1);
	free(a2);
	free(a3);
	free(a4);
	free(a5);
	
}

在这里插入图片描述
如图所示,希尔排序,堆排序和快速排序是一个量级,冒泡排序略慢
不了解堆排序和希尔排序请关注往期作品:
链接1: 希尔排序
连接2:堆排序
完整代码如下:

void Quiksort(int* a, int begin,int end)
{
	//递归条件
	if (begin > end)
		return;

	int midi = GetMidi(a, begin, end);
	Swap(&a[midi], &a[begin]);
	int left = begin, right = end;
	int keyi = begin;
	while (left < right)
	{
		//右边找小
		while (left < right && a[right] >= a[keyi])
		{
			right--;
		}
		//左边找大
		while (left < right && a[left] <= a[keyi])
		{
			left++;
		}
		Swap(&a[left], &a[right]);
	}
	Swap(&a[left], &a[keyi]);
	keyi = left;//更新相遇点为keyi
	//递归
	Quiksort(a, begin, keyi - 1);
	Quiksort(a, keyi + 1, end);
}

在这里插入图片描述

  • 45
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 26
    评论
意大利威尼斯是一个位于亚得里亚海的城市,被众多运河和桥梁所穿越,因其独特的地理位置和美丽的建筑而闻名于世。威尼斯也被称为“水城”或“浪漫之都”,其历史可以追溯到公元5世纪。 威尼斯的建筑风格独特,充满了浪漫和优雅的氛围。这座城市的建筑物大多建立在木桩上,因为城市被水所包围,没有用车辆行驶的道路。取而代之的是一系列运河和水道,人们需要乘坐船只或步行来穿越城市。 威尼斯对艺术和文化的贡献也是不可忽视的。文艺复兴时期,该城市是绘画、建筑和音乐的重要中心。许多著名的艺术家,如提香、蒂基安、巴拉托、威尔斯基和莫宁等,都在威尼斯创作了许多杰作。 除了艺术,威尼斯还以其独特的娱乐活动而著称。威尼斯嘉年华是世界上最古老、最盛大的狂欢节之一。每年,数以万计的游客和当地居民涌向威尼斯,穿着华丽的面具和服饰,参加各种游行、舞会和音乐会。 然而,威尼斯也面临着一些问题。城市的底层由于不断的垂直沉降而被淹没,建筑物也面临着沉降和腐蚀的风险。此外,游客数量的不断增加也给城市的环境和基础设施带来了压力。 总的来说,威尼斯是一个富有历史、文化和艺术底蕴的城市。尽管面临一些挑战,但它仍然是一个独特而迷人的旅游目的地,吸引着来自世界各地的游客。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

强sir的世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值