带你学懂数据结构中的八大排序(上)
创始人
2024-05-01 14:00:21
0

✨个人主页: Yohifo
🎉所属专栏: 数据结构 | C语言
🎊每篇一句: 图片来源

  • Every challenge, every adversity, contains within it the seeds of opportunity and growth.
    • 每个挑战,每次逆境,里面都藏有机会与成长的种子。

道阻且长,行则将至


文章目录

  • 📘前言
  • 📘正文
    • 📖插入排序
      • 📃直接插入排序
      • 📃希尔排序
    • 📖选择排序
      • 📃简单选择排序
      • 📃堆排序
    • 📖排序小结
  • 📘总结


📘前言

排序(Sort)是初阶数据结构中的最后一块内容,所谓排序,就是通过某种手段,使目标数据变为递增或递减,排序有很多种方式:插入、选择、交换、归并、映射 等等,本文会介绍这些方式下的详细实现方法,因篇幅较长,故分为上下文的形式介绍,本文是上半部分。

下面是通过排序生成的排行榜

TIOBE编程语言排行榜


📘正文

📖插入排序

插入,指将数据插入到合适位置,这个分类中包含了两种排序算法:直接插入希尔,其中希尔排序又称缩小增量排序,是一种非常快但不稳定的排序,它的时间复杂度计算极为复杂,下面详细来看看这两个排序吧

📃直接插入排序

思路:从第二个数开始,假设此数为 tmp ,逐个往前进行比对,如果前数大于 tmp ,就将前数值赋值到 tmp 处,然后继续往前比对,直到找到小于或等于 tmp 的数(或者比对至数据首)就停止,最后将 tmp 的值赋值到此处就行了

//直接插入排序
void InsertSort(int* pa, int n)
{assert(pa);//从后往前比较,找到合适位置就插入for (int i = 1; i < n; i++){int end = i;int tmp = pa[end];while (end){if (pa[end - 1] > tmp)pa[end] = pa[end - 1];elsebreak;end--;}pa[end] = tmp;}
}

动图展示
直接插入排序

时间复杂度:

  • 最坏:数据为一个逆序的等差数列 O(N^2)
  • 最好:顺序有序 O(N)

空间复杂度:

  • 仅仅只需要一个 tmp 变量 O(1)

稳定性:

  • 稳定,当两个相同数相遇时,后者是不会跑到前者前面去的

📃希尔排序

希尔排序是在直接插入排序上进行优化的一种排序,希尔排序分为两步:

  • 1、预排序,使得数据尽可能接近有序
  • 2、直接插入排序,最后调用一次直接插入排序,快速的完成排序

思路:预排序是通过区间划分实现的,假设当前区间为 gap,那么 1、1+gap*n 可以分成一组,同理2、3、4 都可以分,将这些组分别进行直接插入排序(数据少,效率高)。每完成一次分组排序,gap 就会缩小,直到 gap 为1时,进行一次直接插入排序,整个希尔排序就完成了

//希尔排序
void ShellSort(int* pa, int n)
{assert(pa);//思路:在插入排序的基础上,先分为n个区间,使数组尽可能有序(预排序)int gap = n;while (gap > 1){gap = gap / 3 + 1;	//确保gap最后为1for (int i = 0; i < n - gap; i++){int end = i;int tmp = pa[end + gap];while (end >= 0){//此时的end位于tmp之前sif (pa[end] > tmp)pa[end + gap] = pa[end];elsebreak;end -= gap;}pa[end + gap] = tmp;}}
}

动图展示(图太长了,分段展示)
1、预排序
希尔排序(预排序)
2、直接插入排序
直接插入排序

时间复杂度:

  • 希尔的时间复杂度计算是一个极其复杂的过程,需要用到高等数学的知识,这里直接记就行 O(N^1.3)

空间复杂度:

  • 仅仅只需要一个 tmp 变量 O(1)

稳定性:

  • 不稳定,当两个相同数被不同区间选中时,可能会发生交换现象,示例 1 4 2 2 3

📖选择排序

选择排序下也可以分为两种:简单选择与之前学过的堆排序,两者的本质是一样的,都是依赖于不断的比对,选到合适数后进行交换

📃简单选择排序

思路:选到最大的数,然后与 end 值交换;优化:选最大与最小,分别与 end 值和 begin 值交换

void swap(int*pnum1, int* pnum2)
{assert(pnum1 && pnum2);int tmp = *pnum1;*pnum1 = *pnum2;*pnum2 = tmp;
}//简单选择排序
void SelectSort(int* pa, int n)
{assert(pa);//思路:选最小的放前面,选最大的放后面int begin = 0;int end = n - 1;while (begin < end){int maxi = begin;int mini = begin;for (int i = begin + 1; i <= end; i++){if (pa[i] > pa[maxi])maxi = i;if (pa[i] < pa[mini])mini = i;}swap(&pa[begin], &pa[mini]);if (maxi == begin)maxi = mini;swap(&pa[end], &pa[maxi]);begin++, end--;}
}

动图展示:
简单选择排序

时间复杂度:

  • 这是一个比较糟糕的排序,因为不管是什么情况都是 O(N^2)

空间复杂度:

  • 仅借助变量辅助交换 O(1)

稳定性:

  • 不稳定,在选择时,可能把相同数中的后者选到前面,示例 1 4 2 2 3

注意:

  • 当交换 min 值与 begin 值后,如果 max 等于此时的 begin ,那么就要将 max 赋为 min,即 max = min

📃堆排序

思路:堆排序用到了堆的知识,如果想排升序的话建大堆,因为大堆中堆顶是最大值,将堆顶值与堆低值交换后,执行向下调整,使其再次变为大堆,就这样反复交换、调整,堆排序就完成了

void swap(int*pnum1, int* pnum2)
{assert(pnum1 && pnum2);int tmp = *pnum1;*pnum1 = *pnum2;*pnum2 = tmp;
}void AdjustDown(int* pa, int n, int parent)
{assert(pa);//大堆,找大孩子,调整int child = parent * 2 + 1;while (child < n){if (child + 1 < n && pa[child + 1] > pa[child])child++;if (pa[child] > pa[parent]){swap(&pa[child], &pa[parent]);parent = child;child = parent * 2 + 1;}elsebreak;}
}//堆排序
void HeapSort(int* pa, int n)
{assert(pa);//思路:升序建大堆,将堆顶元素沉底,然后再调整int parent = (n - 1 - 1) / 2;	//找父亲for (int i = parent; i >= 0; i--)AdjustDown(pa, n, i);//将堆顶元素沉底后调整int end = n - 1;while (end > 0){swap(&pa[0], &pa[end]);AdjustDown(pa, end--, 0);}
}

动图展示:
1、调整建堆
建堆
2、向下调整排序(上)
排序主体,上
3、向下调整排序(下)
排序主体,下

时间复杂度:

  • 向下调整+交换 O(N*logN)

空间复杂度:

  • 仅借助变量辅助交换 O(1)

稳定性:

  • 不稳定,当两个相同值分别位于首尾时,向下调整会打乱相对顺序,示例 2 4 1 3 2

📖排序小结

排序名称时间复杂度空间复杂度稳定性
直接插入排序O(N^2)O(1)稳定
希尔排序O(N^1.3)O(1)不稳定
简单选择排序O(N^2)O(1)不稳定
堆排序O(N*logN)O(1)不稳定

更多排序将在下篇文章中讲解


📘总结

排序有很多种,有好的、有坏的,我们要重点掌握优秀的排序,比如希尔堆排,当前其他排序的思想也得清楚,知道怎么实现就行了。本文只是排序的上半部分,涉及的排序都还算简单,下一篇文章中将会介绍排序大哥:快排,以及同样优秀的归并排序,知识点很难,但也很重要,敬请期待吧

如果你觉得本文写的还不错的话,期待留下一个小小的赞👍,你的支持是我分享的最大动力!

如果本文有不足或错误的地方,随时欢迎指出,我会在第一时间改正

星辰大海

相关文章推荐
关于“堆”,看看这篇文章就够了(附堆的两种应用场景)
听说你还不了解二叉树?赶紧进来轻松解决
听说Linux基础指令很多?这里都帮你总结好了

感谢支持

相关内容

热门资讯

安卓系统自带的网页,功能与特色... 你有没有发现,每次打开安卓手机,那熟悉的系统界面里总有一个默默无闻的小家伙——安卓系统自带的网页浏览...
美咖云系统安卓版,开启智能生活... 你有没有发现,最近手机上多了一个叫“美咖云系统安卓版”的小家伙?它就像一个魔法师,轻轻一点,就能让你...
安卓系统推荐最好的手机,盘点性... 你有没有想过,拥有一部性能卓越的手机,就像是拥有了移动的宝藏库?在这个信息爆炸的时代,一部好手机不仅...
安卓11系统能精简吗,释放潜能 你有没有发现,随着手机越来越智能,系统也越来越庞大?安卓11系统,这个最新的操作系统,是不是也让你觉...
安卓自动重启系统软件,揭秘原因... 手机突然自动重启,是不是感觉整个人都不好了?别急,今天就来和你聊聊这个让人头疼的安卓自动重启系统软件...
苹果手机x刷安卓系统,探索安卓... 你有没有想过,你的苹果手机X竟然也能刷上安卓系统?是的,你没听错,就是那个一直以来都和我们苹果手机X...
安卓系统智商低吗,智商低下的真... 你有没有想过,为什么安卓系统的智商总被调侃得好像有点低呢?是不是觉得它总是慢吞吞的,有时候还犯点小错...
安卓系统手机联系人,揭秘你的社... 你有没有发现,手机里的联系人列表就像是一个小小的社交圈呢?里面藏着我们的亲朋好友、工作伙伴,甚至还有...
安卓系统免费铃声下载,打造个性... 手机里那首老掉牙的铃声是不是让你觉得有点out了呢?别急,今天就来给你支个招,让你轻松给安卓手机换上...
安卓系统用哪个桌面好,打造个性... 你有没有发现,手机桌面可是我们每天都要面对的“脸面”呢?换一个好看的桌面,心情都能跟着好起来。那么,...
虚拟大师是安卓10系统,功能与... 你知道吗?最近在手机圈里,有个新玩意儿引起了不小的轰动,那就是虚拟大师!而且,更让人惊喜的是,这个虚...
安卓系统与苹果优缺点,系统优缺... 说到手机操作系统,安卓和苹果绝对是两大巨头,它们各有各的特色,就像两道不同的美味佳肴,让人难以抉择。...
安卓win双系统主板,融合与创... 你有没有想过,一台电脑如果既能流畅运行安卓系统,又能轻松驾驭Windows系统,那该有多爽啊?没错,...
安卓系统可精简软件,轻松提升手... 你有没有发现,手机里的安卓系统越来越庞大,软件也越装越多,有时候感觉手机就像个“大肚子”,不仅运行速...
安卓系统基于linux的代码,... 你有没有想过,那个陪伴你每天刷抖音、玩游戏、办公的安卓系统,其实背后有着一套复杂的基于Linux的代...
苹果和安卓的拍照系统,谁更胜一... 你有没有发现,现在手机拍照已经成为我们生活中不可或缺的一部分呢?无论是记录生活的点滴,还是捕捉美丽的...
苹果和安卓系统不同吗,系统差异... 你有没有想过,为什么你的手机里装的是苹果的iOS系统,而朋友的手机却是安卓系统呢?这两种系统,看似都...
安卓系统有多少级,揭秘其多级架... 你有没有想过,那个陪伴我们日常生活的安卓系统,它其实有着丰富的层级结构呢?没错,就是那个让我们的手机...
华为鸿蒙系统与安卓的,技术融合... 你知道吗?最近科技圈可是炸开了锅,华为鸿蒙系统与安卓的较量成为了大家热议的话题。这不,今天我就来给你...
什么安卓手机是苹果系统,搭载苹... 你有没有想过,为什么有些人宁愿花大价钱买苹果手机,而有些人却对安卓手机情有独钟呢?其实,这个问题背后...