当前位置:网站首页>排序3-选择排序与归并排序(递归实现+非递归实现)
排序3-选择排序与归并排序(递归实现+非递归实现)
2022-07-28 15:27:00 【世_生】
前言

一、选择排序
选择排序:指每次选择所要排序的数组中的最大(小)值的数组元素,将这个数组元素的值与最前面的没有进行排序的数组元素的值进行交换。
由于比较好理解,那么我直接上代码(改版的)最大值和最小值一起排列
void SelectSort(int *arr, int n)
{
for (int i = 0; i < n - 1;i++)
{
int maxi = i;
int mini = i;
for (int j = i + 1; j < n; j++)
{
//找大
if (arr[j]>arr[maxi])
{
maxi = j;
}
//找小
if (arr[j] < arr[mini])
{
mini = j;
}
}
Swap(&arr[i], &arr[maxi]);
if (i==mini)//判断最小值是否是在未排序数组的首元素上
{
mini = maxi;
}
Swap(&arr[n - 1], &arr[mini]);
n--;
}
}
}
细节:上面代码中,当最小值在未排序的数组的首元素位置时,我们要进行判断一下,否则为排序失败,所以我在上面代码中加了一个if语句。
总结:
- 时间复杂度:O(N2)
- 空间复杂度:O(1)
- 稳定性:不稳定
二、归并排序
归并排序:原理是假设初始排序含有n个元素,则可以看成是n个子序列,每个子序列的长度为1,然后进行两两归并,得到【n/2】个长度为2或1的有序子序列;两两归并,…,如此重复,直到得到一个长度为n的有序序列为止。
递归实现
- 分解:先把初始序列分解成n个子序列,就如同树一样
- 合并:然后再两两归并成有序的子序列,如此重复(像树的后序遍历)
- 我们合并到新数组总,然后拷贝到原数组中

代码:
void _MergeSort(int* a, int left, int right, int* tmp)
{
if (left >= right)
return;
//分解的位置
int mid = (left + right) >> 1;
// [left, mid]
// [mid+1, right]
_MergeSort(a, left, mid, tmp);
_MergeSort(a, mid+1, right, tmp);
int begin1 = left, end1 = mid;
int begin2 = mid + 1, end2 = right;
int index = left;
//合并
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] <= a[begin2])
tmp[index++] = a[begin1++];
else
tmp[index++] = a[begin2++];
}
//如果一条子序列合并完了,另一子序列还剩一部分未合并完,则直接合并
while (begin1 <= end1)
{
tmp[index++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[index++] = a[begin2++];
}
//拷贝到原数组
for(int j=left;j<=right;j++)
{
a[j]=tmp[j];
}
//memcpy(a+left, tmp+left, sizeof(int)*(right - left+1));
}
void MergeSort(int* a, int n)
{
assert(a);
int* tmp = (int*)malloc(sizeof(int)*n);//开辟空间
_MergeSort(a, 0, n - 1, tmp);
free(tmp);//最后释放空间
}
总结:
- 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
- 时间复杂度:O(N*log2N)
- 空间复杂度:O(N)
- 稳定性:稳定
迭代实现(非递归)
这才是我们的大菜,在非递归实现中我们用到了希尔排序中的一些思想(分组),但是我们分组是直接合并,没有递归中分解的部分。
- 把n个子序列两两分组,直接排序合并成有序的(n/2)个子序列,如此往复。
- 这时候我们定义一个数(gap)来分割他们,且每进行一次大的合并后gap会进行改变,以便下一次分割。
- 每一个子序列都是一个待合并的区间

细节:
上图是正常的情况,非正常情况如下

综合上图中的情况:我们要进行判断和修正。
- 情况一和情况三的问题,我们可以if掉,当没有与之待排序的第二区间,就跳出合并
- 对于情况二,我们可以修正一下区间的范围
代码:(注意看一下区间的划分)
void _MergeSort(int* a,int* tmp,int begin1,int end1,int begin2,int end2)
{
int i = begin1;
int j = begin1;
while(begin1 <= end1 && begin2 <= end2)
{
// 得到a[begin1]和a[begin2]中较小的数,再移动较小的值
if (a[begin1] < a[begin2])
tmp[i++] = a[begin1++];
else
tmp[i++] = a[begin2++];
}
// 将[begin1,end1]剩余的数放到tmp数组中
while (begin1 <= end1)
tmp[i++] = a[begin1++];
// 将[begin1,end1]剩余的数放到tmp数组中
while (begin2 <= end2)
tmp[i++] = a[begin2++];
// 将tmp数组的值拷贝到a数组中
memcpy(a+j, tmp+j, sizeof(int) * i);
}
void MergeSortNonR(int* a,int* tmp,int n)
{
int gap = 1;
while(gap < n)
{
int i = 0;
for(i = 0;i < n;i += 2 * gap)
{
int begin1 = i,end1 = i + gap - 1,begin2 = i + gap,end2 = i + 2 * gap - 1;
// 第二个区间不存在
if(begin2 >= n)
break;
// 第二个区间数据不够gap个,修正区间范围
if(end2 >= n)
end2 = n - 1;
_MergeSort(a,tmp,begin1,end1,begin2,end2);
}
gap *= 2;
}
}
总结
有问题的地方欢迎指出,共同学习,我们下期见。
边栏推荐
- 为什么学编程的人大多数都去了深圳和北京?
- PHP gets the applet code, and the applet jumps with parameters
- Detailed explanation of QT qstring
- curl无输出返回空白或者null问题解决
- 加速投资的小红书,“病急乱投医”?
- Stm32cube infrared remote control: input capture
- Sdl2 concise tutorial (4): using SDL_ Image library importing pictures
- Numpy ndarray learning < I > Foundation
- LabVIEW LINX Toolkit控制Arduino设备(拓展篇—1)
- redis源码优化--绑核
猜你喜欢
随机推荐
解决电脑恶意广告弹窗的思路
大地坐标系转换火星坐标系
在abaqus中使用PyQt设计GUI
PHP图片合成技术
Zhaoqi science and technology innovation and entrepreneurship competition talent introduction platform, mass entrepreneurship and entrepreneurship competition high-level talent introduction
关于web对接针式打印机问题,Lodop使用
后台弹出layer提示
不懂就问,快速成为容器服务进阶玩家!
LwIP development | realize TCP server through socket
Curl returns blank or null without output. Solve the problem
Pop up layer prompt in the background
Headline article_ signature
Fifth uncle's thinking
【Multisim仿真】LM339过零电路仿真
Reentrant and non reentrant
Why do most people who learn programming go to Shenzhen and Beijing?
Wei Jianjun couldn't catch up with Li Shufu by riding a BMW
JS queue
R language ggplot2 visually draws line plots, and uses gghighlight package to highlight the lines that meet the combination judgment conditions in the line graphs (satisfies both condition a and b)
How to measure the vibrating wire sensor by vibrating wire acquisition module?








