news 2026/10/20 3:32:36

归并排序与快速排序

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
归并排序与快速排序

归并排序

介绍

有时候我们需要把两个有序的序列进行合并从而得到有序的大序列,基于这个思想,便引出了归并排序,其思路就是把一个无序序列拆分成多个有序序列(当序列的元素为1时就是有序序列),然后对所有序列进行合并操作,最终得到一整个有序序列。

实现

typedef int ElementType; void Merge(ElementType A[],ElementType TmpArray[],int Lpos,int Rpos,int RightEnd) { int i,LeftEnd,NumElements,TmpPos; LeftEnd=Rpos-1; TmpPos=Lpos; NumElements=RightEnd-Lpos+1; while (Lpos<=LeftEnd && Rpos<=RightEnd) { if (A[Lpos]<=A[Rpos]) { TmpArray[TmpPos++]=A[Lpos++]; }else { TmpArray[TmpPos++]=A[Rpos++]; } } while (Lpos<=LeftEnd) { TmpArray[TmpPos++]=A[Lpos++]; } while (Rpos<=RightEnd) { TmpArray[TmpPos++]=A[Rpos++]; } for (i=0;i<NumElements;i++,RightEnd--) { A[RightEnd]=TmpArray[RightEnd]; } } void Msort(ElementType A[],ElementType TmpArray[],int Left,int Right) { int Center; if (Left<Right) { Center=(Left+Right)/2; Msort(A,TmpArray,Left,Center); Msort(A,TmpArray,Center+1,Right); Merge(A,TmpArray,Left,Center+1,Right); } } void MergeSort(ElementType A[],int N) { ElementType *TmpArray; TmpArray = (ElementType*)malloc(N*sizeof(ElementType)); if (TmpArray!=NULL) { Msort(A,TmpArray,0,N-1); free(TmpArray); }else { printf("Not enough memory for Merge Sort\n"); } }

算法有两个重要的操作,一个是将大序列分成小序列的操作,一个是将两个有序序列合并成有序大序列的操作。

合并操作的逻辑:假设要合并序列A和序列B(都是升序),首先创建一个空间大小为A和B元素数量之和的大小。然后比较A和B最左边的元素,较小的放新序列里,较大的那个和另一个序列的下一个元素比,持续这个过程直到其中一个序列遍历完,那就把另一个序列剩下的元素放到新序列里就可以了。

递归拆分的逻辑:将数组从中间拆成左右两部分,再对左右两部分再以中间拆成两部分,一直这样拆到小序列只要一个元素,然后再对这两个小序列进行合并操作,一步一步合并直至左右两大部分的序列进行最后一次合并成为最终完成排序的总序列。

这里开了一个临时变量TmpArray为了方便后面进行合并操作时频繁新辟用于存两个序列的新数组。

分析

归并操作包括拆分和合并,将数组拆分成许多小数组的的过程一共要进行LogN次,每一层的合并最坏要比较N次,所以总的时间复杂度为O(LogN)。

归并排序是稳定排序,因为每一次的拆分都是相邻序列的拆分,合并时若两元素相等,也是先将左数组的元素放入临时数组,这不改变相同元素的相对位置。

快速排序

介绍

当得到一个无序数组,那我们随机选其中一个元素,然后让剩下的元素中小于它的排在它左边,大于它的元素排在它右边,这样我们就让这个元素归位了,它所在的位置不会在变了。接着再对剩下的元素重复进行这样的操作,这样随着一个个元素的归位,序也就排好了。

实现

typedef int ElementType; #define Cutoff (3) void Swap(ElementType *a,ElementType *b) { ElementType Tmp=*a; *a=*b; *b=Tmp; } void InsertionSort(ElementType A[],int N) { int j,P; ElementType Tmp; for (P=1;P<N;P++) { Tmp=A[P]; for (j=P;j>0&&A[j-1]>Tmp;j--) { A[j]=A[j-1]; } A[j]=Tmp; } } ElementType Median3(ElementType A[],int Left,int Right) { int Center = (Left+Right)/2; if (A[Left]>A[Center]) { Swap(&A[Left],&A[Center]); } if (A[Left]>A[Right]) { Swap(&A[Left],&A[Right]); } if (A[Center]>A[Right]) { Swap(&A[Center],&A[Right]); } Swap(&A[Center],&A[Right-1]); return A[Right-1]; } void Qsort(ElementType A[],int Left,int Right) { int i,j; ElementType Pivot; if (Left+Cutoff<=Right) { Pivot=Median3(A,Left,Right); i=Left; j=Right-1; for (;;) { while (A[++i]<Pivot) {} while (A[--j]>Pivot) {} if (i<j) { Swap(&A[i],&A[j]); }else { break; } } Swap(&A[i],&A[Right-1]); Qsort(A,Left,i-1); Qsort(A,i+1,Right); }else { InsertionSort(A+Left,Right-Left+1); } } void QuickSort(ElementType A[],int N) { Qsort(A,0,N-1); }

这里的排序操作比较灵活,算法步骤如下:

为了提高算法效率防止出现快速排序最坏的情况(避免选到极值做枢轴),先找到待排序数组的左端点,中点和右端点这三个位置,然后对这三个位置进行排序,排好序后将中点的元素和Right-1处的元素进行交换并且将其作为枢轴(枢轴的左边所有元素小于枢轴本身,枢轴的右边所有元素大于枢轴本身)。

快速排序的核心操作(此操作没有新辟一块空间来存储经交换后快速排序的数组,所以空间复杂度较低):使用双指针i,j分别从数组最左端和Right-2两次开始遍历,先i右移直到找比枢轴大的元素后,再j左移直到找到比枢轴小的元素,这样如果顺利的话会出现i位置的元素小于j位置的元素,那就交换这两个元素,然后i,j指针接着移动重复上面的操作,若出现i的元素大于等于j位置的元素,说明i,j指针已经不在正确的左右区间了,即此时i的位置的元素是第一个大于枢轴的元素的位置,那就将枢轴和i位置进行交换,这样枢轴的左侧全是小于它的元素,枢轴右侧都是大于它的元素。

接着再对枢轴左侧的子数组(left到i-1)和右侧数组(i+1到Right)递归地进行快速排序的核心操作,直到某个小数组的长度小于3,数组长度太小用快速排序还是太烦琐了,使用就对数组长度小于3的小序列进行插入排序。这样就逐步完成了整个序列的排序

分析

和归并排序一样,选数组的操作及递归层数为LogN,每一层最坏要遍历N个元素,所以快速排序的时间复杂度是O(NLogN)。

快速排序是不稳定排序,双指交换元素时可能会打乱相同元素的相对位置。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 10:32:00

Hackintool黑苹果工具完全攻略:从新手到专家的系统配置指南

还在为黑苹果系统配置而烦恼吗&#xff1f;Hackintool作为黑苹果社区的多功能工具&#xff0c;能够帮助你轻松解决各种系统配置难题。无论你是刚接触黑苹果的新手&#xff0c;还是想要优化现有系统的资深用户&#xff0c;这款工具都能为你提供强大的支持。本文将带你深入了解Ha…

作者头像 李华
网站建设 2026/10/19 17:41:19

FLUX.1-dev + Git安装配置手册:构建高效AI开发工作流

FLUX.1-dev Git 工作流构建&#xff1a;打造可复现的AI图像生成开发体系 在生成式AI迅猛发展的今天&#xff0c;文生图模型早已不再是“能不能画出来”的问题&#xff0c;而是演进为“能否稳定、高效、可控地生产符合预期的图像内容”。面对日益复杂的提示工程、微调实验和团…

作者头像 李华
网站建设 2026/10/18 12:42:20

音乐格式转换完全指南:快速解锁加密音频文件的终极方案

你是否曾经遇到过这样的情况&#xff1a;花了很多钱购买的音乐&#xff0c;却只能在特定的App里播放&#xff0c;想要换个播放器或者保存到本地&#xff0c;结果发现文件被加密了&#xff01;那些.ncm、.qmc、.kgm格式的音乐文件&#xff0c;就像被限制在特定环境中的小鸟&…

作者头像 李华
网站建设 2026/10/20 6:33:32

数字乐谱实验室:网页版MIDI编辑终极指南

你是否曾经有过一段美妙的旋律在脑海中盘旋&#xff0c;却因为复杂的音乐软件而无法快速记录下来&#xff1f;或者想要为视频制作背景音乐&#xff0c;却被专业DAW的高门槛劝退&#xff1f;现在&#xff0c;这个免费网页版音乐制作工具将彻底改变你的创作体验&#xff0c;让你在…

作者头像 李华
网站建设 2026/10/19 15:59:32

AI企业级智能体远不止聊天,一张图揭秘AI如何革新软件与业务

过去两年&#xff0c;很多人都经历过类似的心路历程&#xff1a;第一次用到 ChatGPT&#xff0c;被“秒出答案”的流畅和智能惊艳到&#xff0c;觉得这是改变世界的技术拐点。但回到公司&#xff0c;一落地就开始尴尬&#xff1a;要么是开了个“AI助手”入口&#xff0c;几乎没…

作者头像 李华
网站建设 2026/10/19 5:51:54

如何快速掌握网页视频下载:m3u8下载器终极指南

如何快速掌握网页视频下载&#xff1a;m3u8下载器终极指南 【免费下载链接】m3u8-downloader m3u8 视频在线提取工具 流媒体下载 m3u8下载 桌面客户端 windows mac 项目地址: https://gitcode.com/gh_mirrors/m3u8/m3u8-downloader 还在为网页视频无法保存而苦恼吗&…

作者头像 李华