🌈个人主页 :@ꪔ小林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的相对位置并未发生改变,所以说这个排序是稳定的。

🎊本期数据结构------排序(二)的内容就结束了。如果文中有表述不准的地方,或是你有更清晰的理解思路,强烈欢迎在评论区留言交流------ 技术路上多碰撞,才能更快进步
觉得内容对你有帮助的话,别忘了点赞❤️➕收藏🌟,方便后续回顾复习;想跟着一起系统学习数据结构的朋友,也可以点击关注,下一期我们会聚焦更进一步的学习。不见不散✌️




