【数据结构】:排序(二)——归并与计数排序详解

🌈个人主页@ꪔ小林Y

个人专栏《C++小白闯关日记》《C语言小白闯关日记》,《数据结构入门------从原理到实战》

🍀代码信条 :每一行代码都是成长的脚印👣,每一次调试成功都是对坚持的回应

目录

接上节,这节内容继续围绕排序展开

排序

归并排序

归并排序的算法思想:归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序的核心步骤:

  • 代码实现:
c 复制代码
void _MergeSort(int* arr ,int left, int right, int* tmp)
{
	//分解
	if (left >= right)
	{
		return;
	}
	int mid = (left + right) / 2;
	//根据mid将[left,right]划分成左右两个序列:[left,mid],[mid+1,right]
	_MergeSort(arr, left, mid,tmp);
	_MergeSort(arr, mid + 1, right,tmp);
	//合并两个序列:[left,mid][mid+1,right]
	int begin1 = left, end1 = mid;
	int begin2 = mid + 1, end2 = right;
	int index = left;
	while (begin1<=end1 && begin2<=end2)
	{
		if (arr[begin1] < arr[begin2])
		{
			tmp[index++] = arr[begin1++];
		}
		else {
			tmp[index++] = arr[begin2++];
		}
	}
	//要么begin1序列中数据没有放完
	//要么begin2序列中数据没有放完
	while (begin1 <= end1)
	{
		tmp[index++] = arr[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[index++] = arr[begin2++];
	}
	//tmp-->arr
	for (int i = left;i <=right;i++)
	{
		arr[i] = tmp[i];
	}
}
//归并排序
void MergeSort(int* arr, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);//为后续合并做准备
	_MergeSort(arr, 0, n - 1,tmp);
	free(tmp);
}
  • 测试:
c 复制代码
void printArr(int* arr, int n)
{
	for (int i = 0;i < n;i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void test01()
{
	int a[] = {6,1,2,7,9,3};
	int n= sizeof(a) / sizeof(a[0]);
	printf("排序之前");
	printArr(a, n);
	//归并排序
	MergeSort(a, n);
	printf("排序之后");
	printArr(a, n);

}
int main()
{
	test01();
	return 0;
}
  • 运行结果:

时间复杂度:单次递归时间复杂度*总的递归次数

归并排序时间复杂度:n * logn

归并排序空间复杂度:n

非比较排序

计数排序

计数排序是对哈希直接定址法的变形应用:

(1)统计相同元素出现次数

(2)根据统计的结果将序列回收到原来的序列中

例:一个数组:{6,1,2,9,4,2,4,1,4}

数据及重复次数:1(2),2(2),4(3),6(1),9(1)

建立数组:

但是如果遇到数组{100,101,102,101,108,109,108},这种如果用上述排序会造成空间的浪费。所以我们采用映射 的方法将数组中的值全部保存在count数组中:

  • 代码实现:
c 复制代码
#include<memory.h>
//非比较排序------计数排序
void CountSort(int* arr, int n)
{
	//找min,max
	int min = arr[0], max = arr[0];
	for (int i = 1;i < n;i++)
	{
		if (arr[i] < min)
		{
			min = arr[i];
		}
		if (arr[i] > max)
		{
			max = arr[i];
		}
	}
	//确定count数组的大小------max-min+1
	int range = max - min + 1;
	int* count = (int*)malloc(sizeof(int) * (range));
	if (count == NULL)
	{
		perror("malloc fail");
		exit(1);
	}
	//对count初始化:calloc
	memset(count,0, sizeof(int)*(range));
	for (int i = 0;i < n;i++)
	{
		count[arr[i] - min]++;
	}
	//将count数组中的数据还原到原数组中
	int index = 0;
	for (int i = 0;i < range;i++)
	{
		while (count[i]--)
		{
			arr[index++] = i + min;
		}
	}
}
  • 测试运行:
c 复制代码
void printArr(int* arr, int n)
{
	for (int i = 0;i < n;i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void test01()
{
	int a[] = { 6,1,2,7,9,3 };
	int n= sizeof(a) / sizeof(a[0]);
	printf("排序之前");
	printArr(a, n);
	//计数排序
	CountSort(a, n);
	printf("排序之后");
	printArr(a, n);
}
int main()
{
	test01();
	return 0;
}
  • 运行结果:

计数排序时间复杂度:O(n+range)

空间复杂度:O(range)

各排序方法的比较

稳定性 :假定待排序的序列中,存在多个相同的数据,若经过排序,这些相同数据的相对次序保持不变,则称这种算法是稳定的;否则不稳定。

例:

归并排序:{1,3,3,2}

二分之后为{1,3}和{2,3}

再次排序之后为{1,2,3,3}

这样两个3的相对位置并未发生改变,所以说这个排序是稳定的。

🎊本期数据结构------排序(二)的内容就结束了。如果文中有表述不准的地方,或是你有更清晰的理解思路,强烈欢迎在评论区留言交流------ 技术路上多碰撞,才能更快进步

觉得内容对你有帮助的话,别忘了点赞❤️➕收藏🌟,方便后续回顾复习;想跟着一起系统学习数据结构的朋友,也可以点击关注,下一期我们会聚焦更进一步的学习。不见不散✌️

相关推荐
A尘埃1 小时前
超市购物篮关联分析与货架优化(Apriori算法)
算法
.小墨迹2 小时前
apollo学习之借道超车的速度规划
linux·c++·学习·算法·ubuntu
数智工坊2 小时前
【数据结构-树与二叉树】4.3 二叉树的存储结构
数据结构
独好紫罗兰2 小时前
对python的再认识-基于数据结构进行-a004-列表-实用事务
开发语言·数据结构·python
不穿格子的程序员2 小时前
从零开始刷算法——贪心篇1:跳跃游戏1 + 跳跃游戏2
算法·游戏·贪心
大江东去浪淘尽千古风流人物2 小时前
【SLAM新范式】几何主导=》几何+学习+语义+高效表示的融合
深度学习·算法·slam
铉铉这波能秀2 小时前
LeetCode Hot100数据结构背景知识之列表(List)Python2026新版
数据结构·leetcode·list
重生之我是Java开发战士2 小时前
【优选算法】模拟算法:替换所有的问号,提莫攻击,N字形变换,外观数列,数青蛙
算法
仟濹2 小时前
算法打卡 day1 (2026-02-06 周四) | 算法: DFS | 1_卡码网98 可达路径 | 2_力扣797_所有可能的路径
算法·leetcode·深度优先
yang)2 小时前
欠采样时的相位倒置问题
算法