快速排序和归并排序的非递归实现
创作时间:
作者:
@小白创作中心
快速排序和归并排序的非递归实现
引用
CSDN
1.
https://blog.csdn.net/hdxbufcbjuhg/article/details/144775846
快速排序和归并排序是两种非常重要的排序算法,它们通常以递归方式实现。然而,在某些场景下,递归实现可能会导致栈溢出等问题。因此,掌握它们的非递归实现方式是非常有必要的。本文将详细介绍如何使用栈和队列来实现快速排序的非递归版本,以及如何实现归并排序的非递归版本。
一、非递归版快速排序
1. 使用栈实现非递归版快速排序
在学习非递归版快速排序前,建议先了解递归版的快速排序。递归的本质是在内存的栈区开辟新的函数栈帧,而栈区的压栈方式与数据结构中的压栈类似,因此可以通过栈这个数据结构来模拟递归调用的行为。
具体实现时,需要一个栈来存储数组的左右下标。每次将指定数组序列的左右下标存入栈中,为了保证取出时是左右的顺序,需要将右下标先入栈,再入栈左下标。
void NonRQuickSort1(int* arr, int left, int right)
{
ST st;
STInit(&st);
STPush(&st, right);
STPush(&st, left);
while (!STEmpty(&st))
{
int left = STTop(&st);
STPop(&st);
int right = STTop(&st);
STPop(&st);
if (left >= right) continue;
int keyi = _QuickSort(arr, left, right);
// [left, keyi - 1] [keyi + 1, right]
if (right > keyi + 1)
{
STPush(&st, right);
STPush(&st, keyi + 1);
}
if(left < keyi - 1)
{
STPush(&st, keyi - 1);
STPush(&st, left);
}
}
STDestroy(&st);
}
2. 使用队列实现非递归版快速排序
队列版快速排序的实现思路与栈版类似,主要区别在于使用队列来存储下标。由于快速排序的左右区间一旦划分就互不影响,可以使用层序遍历的思想,将划分出来的左右区间依次进行处理。
void QuickSortNonR2(int* arr, int left, int right)
{
Queue q;
QueueInit(&q);
QueuePush(&q, left);
QueuePush(&q, right);
while (!QueueEmpty(&q))
{
int left = QueueFront(&q);
QueuePop(&q);
int right = QueueFront(&q);
QueuePop(&q);
int keyi = _QuickSort(arr, left, right);
// [left, keyi - 1] [keyi + 1, right]
if (left < keyi - 1)
{
QueuePush(&q, left);
QueuePush(&q, keyi - 1);
}
if (right > keyi + 1)
{
QueuePush(&q, keyi + 1);
QueuePush(&q, right);
}
}
QueueDestroy(&q);
}
二、非递归版归并排序
归并排序的非递归实现不能使用栈或队列,因为后序遍历需要左右子树的信息,而栈只能模拟先处理根的情况。非递归版归并排序的本质是对数组进行分组,然后两两一组进行排序,最后进行合并。
具体实现时,首先将数组的一个元素划分为一组,然后两两一组进行合并。合并完成后,将gap
乘以2来调整每组元素的个数,用新的gap
来划分数组,直到gap
大于或等于数组长度。
void MergeSortNonR(int* arr, int n)
{
int* tmp = (int*)malloc(n * sizeof(n));
if (tmp == NULL)
{
perror("malloc");
return;
}
int gap = 1;
while (gap < n)
{
for (int i = 0; i < n; i += 2 * gap)
{
int begin1 = i, end1 = i + gap - 1;
int begin2 = i + gap, end2 = i + 2 * gap - 1;
if (end1 >= n || begin2 >= n)
{
break;
}
else if (end2 >= n)
{
end2 = n - 1;
}
int j = begin1;
while (begin1 <= end1 && begin2 <= end2)
{
if (arr[begin1] < arr[begin2])
tmp[j++] = arr[begin1++];
else
tmp[j++] = arr[begin2++];
}
while (begin1 <= end1)
{
tmp[j++] = arr[begin1++];
}
while (begin2 <= end2)
{
tmp[j++] = arr[begin2++];
}
for (int j = i; j <= end2; j++)
{
arr[j] = tmp[j];
}
}
gap *= 2;
}
}
总结
本文详细介绍了快速排序和归并排序的非递归实现方式。通过使用栈和队列,可以有效地避免递归带来的栈溢出问题。对于算法学习者来说,理解这些实现方式对于深入掌握排序算法具有重要意义。
本文原文来自CSDN
热门推荐
贵阳生育津贴领取条件
厦心医院专家王斌:在专科医院打通连接之道
Android下的Touch事件分发详解

全面解析:卫生法律法规在现代社会的重要性与作用
唐朝教育制度:兼容并蓄与开放多元
2025年,成都楼市走势如何?
中国古代大铁矿
如何用C语言输出质数
三国志战略版法正值得练吗?战法及武将搭配攻略
概率论与因果关系在证据法中的交织:乘法定理的适用探讨
皮肤偏黑?这些美白护肤步骤助你提亮肤色
信用债和利率债都是什么?有什么区别?
H钢和工字钢哪个适合做梁?详解两种钢材的特点与应用场景
如何利用人才盘点四象限分析优化企业人力资源配置
消费者投诉在高德地图买迪士尼门票被篡改日期,客服不承认错误
涨停板背后的市场逻辑与投资机会
为什么说绝大多数800V电车,充电速度其实和400V电车没有差距?
血战武汉!枪炮未响领袖先就义,士兵高呼:此时不反,更待何时
胃肠镜术后三天食谱
写了借条是否还能算诈骗
《七日世界》鱼类全收集 让你成为天才小钓手(第二期)
问hr面试结果不回复还要继续询问吗
如何利用自动生成测试用例提升测试效率?
没有房产证的房子能买吗?买房风险有哪些?
古代对梦境的分类
企业人才盘点全流程指南:从目标设定到结果应用
银行的信用卡境外消费手续费怎么算?
Mini LED背光技术原理详解
喉咙痰多怎么化痰
眼睛度数增加100度需要重新配眼镜吗