当前位置: 首页 > news >正文

DS快速排序和归并排序的非递归实现(16)

文章目录

  • 前言
  • 一、快排的非递归实现
  • 二、归排的非递归实现
  • 总结


前言

  打破递归桎梏,迎接迭代解放!


一、快排的非递归实现

  我们要替代递归,就要用到迭代或者循环,也就是说,其核心思想是不变的,只是换一种方式来实现而已
  我们操控的是两个边界,利用栈来实现,这时候也就要考验你前面的知识是否学透了

void QuickSortNonR(int* arr, int n)
{// 初始化Stack st;StackInit(&st);// 先把最开始的两边界入栈StackPush(&st, n - 1);StackPush(&st, 0);// 进入循环,结束条件为空栈while (!isStackEmpty(&st)){int left = StackTop(&st);StackPop(&st);int right = StackTop(&st);StackPop(&st);int key = Partition(arr, left, right);// 先排左边,因此先让右边界进栈if (key + 1 < right){StackPush(&st, right);StackPush(&st, key + 1);}if (left < key - 1){StackPush(&st, key - 1);StackPush(&st, left);}}StackDestroy(&st);
}

  栈的特性是先进后出,我们可以先将最外层的区间值入栈,即将 begin 与 end 入栈,之后进行选 key 划分的操作,判断左右区间是否合法,合法才能入栈,继续循环,如果所有区间都非法,栈就空了,循环也就结束了

二、归排的非递归实现

  归并排序属于后序排序因此不是通过使用栈去模拟非递归实现归并排序,因此在这里我们的基本思路是整个序列分为以gap为子序列,结束条件为gap < n(gap = n - 1 表示归并最后一次)
在这里插入图片描述
  这其实有点像归排里面的合并操作,只是由于是迭代版本,我们对于边界的处理要格外注意

下面是三种可能出现的边界问题

在这里插入图片描述
 对于一二两种,我们直接跳出循环,对于第三种,那说明还是有数据需要递归的,这时候我们修改下end2即可

void MergeSortNonR(int* arr, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);int gap = 1;while (gap < n){for (int i = 0 ; i < n ; i += 2 * gap){// 拆成[i, i+gap-1],[i+gap, i+2*gap-1]两个区间int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;// 没有右区间,其实就是第一二种情况if (begin2 >= n){break;}// 右区间过长if (end2 >= n){end2 = n - 1;}// 归并int index = begin1; // index是tmp的下标while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] < arr[begin2]){tmp[index++] = arr[begin1++];}else {tmp[index++] = arr[begin2++];}}while (begin1 <= end1){tmp[index++] = arr[begin1++];}while (begin2 <= end2){tmp[index++] = arr[begin2++];}// 拷贝for (int j = i ; j <= end2 ; j++){arr[j] = tmp[j];}}gap *= 2;}free(tmp);
}

总结

  我们的排序篇基本就结束拉!大家可以自己推导总结一下排序的稳定性!


http://www.mrgr.cn/news/55042.html

相关文章:

  • Java笔试05
  • SQL 自学:事务处理的COMMIT 和 ROLLBACK 语句的运用
  • 3.1.1ReactOS系统中搜索给定长度的空间地址区间函数的实现
  • [Redis] 在Linux中安装Redis并连接图形化工具详细过程(附下载链接)
  • smbms(2)
  • Linux工具的使用-【git的理解和使用】【调试器gdb的使用】
  • 【Javaee】网络编程-TCP Socket
  • Linux常用命令详细解析(含完整命令演示过程)
  • windows C++ 有效利用异步代理库(二)
  • 上海市货运资格证二寸照片要求及手机拍照方法
  • C++编程语言:抽象机制:运算符重载(Bjarne Stroustrup)
  • PostgreSQL模板数据库template0和template1的异同点
  • 033 商品搜索
  • 音视频入门基础:FLV专题(17)——FFmpeg源码中,提取Video Tag的VIDEODATA的实现
  • Linux:基础IO
  • 软件测试技巧-如何定位前后端bug?
  • 营销新境界:解码品牌增长策略
  • [OpenCV] 数字图像处理 C++ 学习——17模板匹配详细讲解+附完整代码
  • 3.订阅者Subscriber的编程实现以及话题消息定义与使用后续课程
  • pgAdmin不显示template1数据库,该如何设置才可以显示?
  • ACM与蓝桥杯竞赛指南 基本输入输出格式二
  • 波浪理论(Elliott Wave Theory)
  • autosar-port/interface学习总结
  • Docker compose 安装Jenkins
  • c++迷宫游戏
  • 揭秘CSS浮动盒:掌握高度塌陷修复、文字环绕特效示艺的秘籍!!(重点秘籍!!)