非递归实现快排排序及归并排序(尾篇)

1.快速排序(双指针实现)

2.非递归实现快排

3.递归实现归并排序

4.非递归实现归并排序

5.总代码

1.快速排序(双指针实现)

俩有个指针一前一后的排放着,cur先走并且去找比kye对应值小的数组值,一旦找到后prev就会往前一步然后与cur对应的值进行交换,直至cur走出数组,key对应的值与prev对应的值进行交换,第一躺就完成了,接下来用递归去走分支(排序中篇已经阐述过)去完成其它俩边的排序。

代码实现:

#include<stdio.h>
void swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
void QuickSort2(int* a, int left,int right)
{if (left >= right)return;int keyi = left;int prev = left;int cur = prev + 1;/*while (cur<=right){if (a[cur] < a[keyi]){++prev;swap(&a[prev], &a[cur]);}++cur;	}*/代码1while (cur <= right){if (a[cur] <= a[keyi] && ++prev != cur)swap(&a[prev], &a[cur]);cur++;}//代码2swap(&a[keyi], &a[prev]);QuickSort2(a, left, prev - 1);QuickSort2(a, prev + 1, right);
}
int main()
{int a[] = { 1,4,6,7,9,3,2,5,8,8,8,8,8,99 };int size = sizeof(a) / sizeof(a[0]);QuickSort2(a,0,size-1);for (int i = 0; i < size; i++){printf("%d ", a[i]);}return 0;
}

 代码分析:

循环的条件是cur小于等于right边界值才能一直执行,触发交换的条件是cur找到了比key小的值,这里有俩种写法,1是在里面++prev再交换,cur++之所以写在外面是因为不管你触不触发if都要加加,不然会死循环,

因为cur和prev会先重叠然后交互(前提是如果出门就发现了比key小的值) ,但如果prev和cur之间有距离差时就不会出现了,if的触发条件再加一个只有prev和cur不相等时才交换。

代码二则就相对简洁一些,在if判断里就可以实现prev++,但是需要注意的是判断++prev和cur是否相等要在后面,因为&&是前面满足才会看后面,如果写在前面就是不管找没找到都++prev,这样子prev就跑到cur前面去了,是不合理的,还有是pre停下来的位置是上一次交换完的位置,所以比keyi小,交换完后key的左边都是比key小,右边比key大。

2.非递归实现快排

快速排序用递归实现是相对简单的,但也可以使用非递归来实现。

首先要用到栈的知识,递归实现快排是一直开辟栈区来实现的,而开辟的栈区里面的内容有传过去的数组和left和right,但主要是left和right这俩个边界值,因为变的边界值,在每个开辟的栈区数组a都是同一个,但是边界值是不一样的,所以可以使用栈去存边界值left和right这俩个整型,然后用循环去更新边界值,每次从栈中取俩个值left和right,因为是单个单个放进去的,取也是单个单个取,每次获取边界值就跟递归一次效果差不多,但栈为空时就说明已经排好序了。

代码实现:
 

#include<stdio.h>
#include"Stack.h"
void swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
int PartSort2(int* a, int left, int right)
{int keyi = left;int prev = left;int cur = prev + 1;while (cur <= right){if (a[cur] < a[keyi] && ++prev != cur)swap(&a[prev], &a[cur]);cur++;}swap(&a[prev], &a[keyi]);return prev;
}
void QuickSortNonR(int* a, int left, int right)
{ST s;STInit(&s);STPush(&s, right);STPush(&s, left);while (!STEmpty(&s)){int begin = STTop(&s);STPop(&s);int end = STTop(&s);STPop(&s);int keyi = PartSort2(a, begin, end);if (keyi + 1 < end){STPush(&s,end);STPush(&s, keyi + 1);}if (keyi - 1 > begin){STPush(&s, keyi - 1);STPush(&s, begin);}}
}
int main()
{int a[] = { 9,8,7,6,5,4,3,3,2,1,55,66,0};int size = sizeof(a) / sizeof(a[0]);QuickSortNonR(a,0,size-1);for (int i = 0; i < size; i++){printf("%d ", a[i]);}return 0;
}

代码分析:

先建立一个栈并初始化,然后把left和right放进去,这里循环的条件是栈是否为空,取出栈顶的俩个值,然后出栈俩次,把取出的值作为参数得到一个keyi值,再把keyi作为参考分出俩个新的区间,然后先判断新的区间是否满足条件,满足则就放入栈里面,这里是以前序去排序(深度优先遍历),队列也可以实现(广度优先遍历),但是在一些情况下是不满足的.

3.递归实现归并排序

归并排序就是把一个数组对半分,一直分到只有一个,然后然后在俩个俩个比,比好就返回去,然后再俩个俩个比,此时俩个数是排好序的,比完后就变成个数为4的有序数组,然后在四个四个比,得到一个个数为8的有序数组,就是把整个分成若干个,在让这些小数组跟别的小数组比较合成一个新的有序数组,一直合成就变成与原来一样大的有序数组,就像魔方直接扣下来重新按颜色装好差不多。

代码实现:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void _MergeSort(int* a, int* tmp, int left, int right)
{if (left >= right)return;int mid = (left + right) / 2;_MergeSort(a, tmp, left, mid);_MergeSort(a, tmp, mid+1, right);int begin1 = left,end1 = mid;//不能在逗号隔开后再加intint begin2 = mid + 1,end2 = right;int i = left;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[i++] = a[begin1++];}else{tmp[i++] = a[begin2++];}}while (begin1 <= end1){tmp[i++] = a[begin1++];}while ( begin2 <= end2){tmp[i++] = a[begin2++];}memcpy(a + left, tmp + left, (right - left + 1) * sizeof(int));
}void MergeSort(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp==NULL){perror("malloc fail:");return;}_MergeSort(a, tmp, 0, n - 1);free(tmp);tmp=NULL;
}
int main()
{int a[] = { 9,8,7,6,5,4,3,2,1 };int size = sizeof(a) / sizeof(a[0]);MergeSort(a, size);for (int i = 0; i < size; i++){printf("%d ", a[i]);}return 0;
}

代码分析:

通过递归会把边界值一直缩小,直至长度为1,这是if条件会触发,不能再往下递归开始走后面的程序,此时边界是相等的(left=right),等于是二叉树的兄弟结点进行比大小,谁小谁在前面,俩俩比较,而最小面的俩个while是防止一个数组的值都比较小先放完了,但是还有数据没放完,因为是有序的,所以直接while依次放入,执行完后会返回去跟上一层次的兄弟结点比,最后到第二层时就是原来数组对半分,比完后合并则原来的数组就变成有序的。

4.非递归实现归并排序

思想是通过循环来代替递归,先取gap组,俩俩gap个大小的进行比对后并放到tmp数组中,然后每次循环完后就改变区间到下一个区间去比较,end1-begin1=end2-begin2,但是有时候数组个数不一定能分均匀,有俩个if条件来判断,第一个if是俩个中有一个越界也就是不存在,所以不进行下面的合并,begin1是一定不会越界的,因为begin=i<n,所以只判断其他边界是否越界情况,end1越不越界不重要,要看后面的begin2是否越界,只要begin2越界了那么就不用合并了,第二个if则是判断end2有没有越界,越界了但是begin2没有,还有有效数据存在,所以要修正end2的值变为n-1,不让其越界访问,总的就是,用for循环来实现每俩个gap组能比较,while循环来控制gap的大小,来类比递归的效果。

代码实现:

void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");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;int j = i;if (begin2 >= n)//end1>n和end1小于n无所谓  只要begin2大于n就不用归并 俩个结果是一样的{break;}if (end2 >= n){end2 = n - 1;}while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[j++] = a[begin1++];}else{tmp[j++] = a[begin2++];}}while (begin1 <= end1){tmp[j++] = a[begin1++];}while (begin2 <= end2){tmp[j++] = a[begin2++];}//memcpy(a +begin1, tmp +begin1, sizeof(int) * (end2 - begin1 + 1));这样是不行的,因为在上面的代码中begin1已经不是原来的值了,memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));}gap = 2*gap;}
}
int main()
{int a[] = { 9,8,7,6,5,4,3,2,1,4343,521,0,5,4,3,3 };int size = sizeof(a) / sizeof(a[0]);MergeSortNonR(a, size);for (int i = 0; i < size; i++){printf("%d ", a[i]);}return 0;
}

5.归并排序的时间复杂度

 因为每次会对半分,直到分成一个,所以能分成logn层,而每个层数访问数据个数都是n,所以总的时间复杂度就是O(N*logN),图片虽然是个三角形,但是每层个数都是n,这里的层数代表是分出的个数,可以理解为上面虽然比下面的短但是是一样重的。

总代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void _MergeSort(int* a, int* tmp, int left, int right)
{if (left >= right)return;int mid = (left + right) / 2;_MergeSort(a, tmp, left, mid);_MergeSort(a, tmp, mid+1, right);int begin1 = left,end1 = mid;//不能在逗号隔开后再加intint begin2 = mid + 1,end2 = right;int i = left;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[i++] = a[begin1++];}else{tmp[i++] = a[begin2++];}}while (begin1 <= end1){tmp[i++] = a[begin1++];}while ( begin2 <= end2){tmp[i++] = a[begin2++];}memcpy(a + left, tmp + left, (right - left + 1) * sizeof(int));
}void MergeSort(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp==NULL){perror("malloc fail:");return;}_MergeSort(a, tmp, 0, n - 1);
}
void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");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;int j = i;if (begin2 >= n)//end1>n和end1小于n无所谓  只要begin2大于n就不用归并 俩个结果是一样的{break;}if (end2 >= n){end2 = n - 1;}while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[j++] = a[begin1++];}else{tmp[j++] = a[begin2++];}}while (begin1 <= end1){tmp[j++] = a[begin1++];}while (begin2 <= end2){tmp[j++] = a[begin2++];}//memcpy(a +begin1, tmp +begin1, sizeof(int) * (end2 - begin1 + 1));这样是不行的,因为在上面的代码中begin1已经不是原来的值了,memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));}gap = 2*gap;}
}
int main()
{int a[] = { 9,8,7,6,5,4,3,2,1,4343,521,0,5,4,3,3 };int size = sizeof(a) / sizeof(a[0]);MergeSortNonR(a, size);for (int i = 0; i < size; i++){printf("%d ", a[i]);}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/341334.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

隐藏 IP 地址的重要性是什么?

在当今的数字时代&#xff0c;保护我们的在线身份至关重要。从保护个人信息到保护隐私&#xff0c;互联网用户越来越多地寻求增强在线安全性的方法。保持匿名和保护敏感数据的一个关键方面是隐藏您的 IP 地址。在这篇博文中&#xff0c;我们将深入探讨隐藏 IP 地址的重要性&…

Java中条件运算符的嵌套使用技巧总结

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

从零开始:如何通过美颜SDK构建自己的直播美颜工具

今天&#xff0c;我将详细介绍如何通过美颜SDK从零开始构建自己的直播美颜工具。 一、了解美颜SDK 什么是美颜SDK 开发者可以通过集成SDK&#xff0c;快速在应用中实现这些功能&#xff0c;而无需从头编写复杂的图像处理算法。 选择合适的美颜SDK 选择时可以根据以下几个方…

PS系统教程11

HUD拾色器 作用&#xff1a;它可以帮助使用者更加高效地选择和使用颜色&#xff0c;从而提高工作效率和设计质量。 先确定色相值改变饱和度改变亮度使用HUD拾色器选中画笔工具画笔模式-正常shiftAlt右键 色相轮 上下移动从黑到白亮度变化左右移动从浅到深饱和度的变化选中颜…

Docker基础篇之Docker常规软件安装

文章目录 1. 总体步骤2. 安装tomcat3. 安装Mysql4. 安装Redis 1. 总体步骤 安装软件的总体步骤如下所示&#xff1a; 搜索镜像拉取镜像查看镜像启动镜像停止容器移除容器 2. 安装tomcat docker hub上查找tomcat镜像 或者使用一下命令查找&#xff1a; docker search tomca…

Mac硬件设备系统环境的升级/更新 macOS

Mac硬件设备上进行系统环境的升级/更新macOS 1.大版本(升级)判断(比如&#xff1a;我买的这台电脑设备最高支持Monterey) 点击进入对应的大版本描述说明页查看相关的兼容性描述&#xff0c;根据描述确定当前的电脑设备最高可采用哪个大版本系统(Sonoma/Ventura/Monterey/Big Su…

“探索‘循环购‘:快消品行业的新商业模式与增长策略“

大家好&#xff0c;我是吴军&#xff0c;来自一家深耕于软件开发和商业模式创新的科技公司。我们的专长在于为各类企业量身打造商城系统&#xff0c;并提供个性化的商业模式解决方案。迄今为止&#xff0c;我们已经助力众多企业成功实施了超过200种前沿的商业模式&#xff0c;实…

Python函数进阶

文章目录 1 函数多返回值2 函数多种传参方式2.1 位置参数2.2 关键字参数2.3 缺省参数2.4 不定长参数 3 匿名函数函数作为参数传递lambda匿名函数 1 函数多返回值 def test_return():return 1,2,3 x,y,z test_return() print(x) print(y) print(z)2 函数多种传参方式 2.1 位置参…

Java集合简略记录

一、集合体系结构 单列集合&#xff1a;Collection 双列集合&#xff1a;Map 二、单列集合 List系列集合&#xff1a;添加的元素是有序、可重复、有索引 有序指的是存和取的顺序是一致的&#xff0c;和之前排序的从小到大是没有任何关系的 Set系列集合&#xff1a;添加的元素是…

STM32自己从零开始实操04:显示电路原理图

一、TFT-LCD 屏接口 1.1指路 以下是该部分的设计出来后的实物图&#xff0c;我觉得看到实物图可能更方便理解这部分的设计。 图1 实物图 这部分设计的是一个屏幕的接口&#xff0c;很简单。使用的屏幕是&#xff1a;2.8inch 16BIT Module MRB2801。 1.2数据手册 &#xff0…

【python深度学习】——torch.einsum|torch.bmm

【python深度学习】——torch.einsum|torch.bmm 1. 基本用法与示例2. torch.bmm 1. 基本用法与示例 基本用法: torch.einsum(equation, *operands)equation: 一个字符串&#xff0c;定义了张量操作的模式。 使用逗号来分隔输入张量的索引&#xff0c;然后是一个箭头&#xff…

免费的维吾尔语翻译器:维汉翻译通App,最近新增了什么功能呢?让我们一起来看看!好用的维语翻译工具支持语音评分功能、支持汉语查拼音等等。

“阿拉伯语是知识&#xff0c;波斯语是糖&#xff0c;印度语是盐&#xff0c;而维吾尔语则是艺术。” 这是一句流传在西域的古老谚语&#xff0c;它不仅道出了维吾尔语言的独特魅力&#xff0c;也表达了人们对语言艺术的无限热爱。 而今&#xff0c;我们带着这份热爱&#x…

颠沛流离学二叉树(完结撒花篇)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

文献解读-肿瘤测序-第五期|《局部晚期或转移性儿童及青少年分化型甲状腺癌的基因特征与临床特征及131I疗效的关系》

关键词&#xff1a;应用遗传流行病学&#xff1b;群体测序&#xff1b;肿瘤测序&#xff1b; 文献简介 标题&#xff08;英文&#xff09;&#xff1a;The relationship between genetic characteristics and clinical characteristics and the efficacy of 131I therapy in c…

2024年端午节放假通知

致尊敬的客户以及全体同仁&#xff1a; 2024年端午节将至&#xff0c;根据国务院办公厅通知精神&#xff0c;结合公司的实际情况&#xff0c;现将放假事宜通知如下&#xff1a; 2024年6月8日&#xff08;星期六&#xff09;至6月10日&#xff08;星期一&#xff09;&#xff…

vue3 setup 使用 beforeRouteEnter 组件内路由守卫

vue3 setup 使用 beforeRouteEnter 组件内路由守卫 setup 中只有onBeforeRouteLeave、onBeforeRouteUpdate两个钩子函数&#xff0c; 没有beforeRouteEnter对应的钩子函数&#xff0c;所以无法在setup中直接使用 <script setup> onBeforeRouteLeave((to, from) > {// …

PMP考试难吗?考试通过率有多少?

我们通常以考试的通过率来评判一个考试的难易程度。通常通过率达到60%以上&#xff0c;这个考试就不太难&#xff1b;达到80% &#xff0c;这个考试就是不难的。 PMP考试难吗&#xff1f; 不少想要考PMP的小伙伴都会有这样的疑惑&#xff0c;首先以PMP的含金量来说&#xff0…

人工智能--深度神经网络

目录 &#x1f349;引言 &#x1f349;深度神经网络的基本概念 &#x1f348;神经网络的起源 &#x1f34d; 神经网络的基本结构 &#x1f349;深度神经网络的结构 &#x1f348; 卷积神经网络&#xff08;CNN&#xff09; &#x1f348;循环神经网络&#xff08;RNN&…

车来了冲刺上市:业绩波动明显,依赖广告业务,滴滴、阿里入股

近日&#xff0c;MetaLight Inc.&#xff08;下称“元光科技”或“车来了”&#xff09;向港交所递交招股说明书&#xff0c;中金公司为其独家保荐人。 据招股书介绍&#xff0c;元光科技专注于利用时序数据&#xff08;按时间顺序排列的数据点&#xff09;来发现及预测分析对…

css网格背景样式

空白内容效果图 在百度页面测试效果 ER图效果 注意&#xff1a;要给div一个宽高 <template><div class"grid-bg"></div> </template><style scoped> .grid-bg {width: 100%;height: 100%;background: url(data:image/svgxml;base…