七种常见经典排序算法总结(C++实现)
排序算法是非常常见也非常基础的算法,以至于大部分情况下它们都被集成到了语言的辅助库中。排序算法虽然已经可以很方便的使用,但是理解排序算法可以帮助我们找到解题的方向。
1. 冒泡排序 (Bubble Sort)
冒泡排序是最简单粗暴的排序方法之一。它的原理很简单,每次从左到右两两比较,把大的交换到后面,每次可以确保将前M个元素的最大值移动到最右边。
步骤
- 从左开始比较相邻的两个元素x和y,如果 x > y 就交换两者
- 执行比较和交换,直到到达数组的最后一个元素
- 重复执行1和2,直到执行n次,也就是n个最大元素都排到了最后
|
|
交换的那一步可以不借助temp,方法是
|
|
复杂度分析
由于我们要重复执行n次冒泡,每次冒泡要执行n次比较(实际是1到n的等差数列,也就是(a1 + an) * n / 2),也就是 O(n^2)。 空间复杂度是O(n)。
2. 插入排序(Insertion Sort)
插入排序的原理是从左到右,把选出的一个数和前面的数进行比较,找到最适合它的位置放入,使前面部分有序。
步骤
- 从左开始,选出当前位置的数x,和它之前的数y比较,如果x < y则交换两者
- 对x之前的数都执行1步骤,直到前面的数字都有序
- 选择有序部分后一个数字,插入到前面有序部分,直到没有数字可选择
|
|
复杂度分析
因为要选择n次,而且插入时最坏要比较n次,所以时间复杂度同样是O(n^2)。空间复杂度是O(n)。
3. 选择排序(Selection Sort)
选择排序的原理是,每次都从乱序数组中找到最大(最小)值,放到当前乱序数组头部,最终使数组有序。
步骤
- 从左开始,选择后面元素中最小值,和最左元素交换
- 从当前已交换位置往后执行,直到最后一个元素
|
|
复杂度分析
每次要找一遍最小值,最坏情况下找n次,这样的过程要执行n次,所以时间复杂度还是O(n^2)。空间复杂度是O(n)。
4. 希尔排序(Shell Sort)
希尔排序从名字上看不出来特点,因为它是以发明者命名的。它的另一个名字是“递减增量排序算法“。这个算法可以看作是插入排序的优化版,因为插入排序需要一位一位比较,然后放置到正确位置。为了提升比较的跨度,希尔排序将数组按照一定步长分成几个子数组进行排序,通过逐渐减短步长来完成最终排序。
例子
例如 [10, 80, 70, 100, 90, 30, 20]
如果我们按照一次减一半的步长来算, 这个数组第一次排序时以3为步长,子数组是:
10 80 7090 30 20100
这里其实按照列划分的4个子数组,排序后结果为
10 30 2090 80 70100
也就是 [10, 30 20 90 80 70 100]
然后再以1为步长生成子数组
103020..
这个时候就是一纵列了,也就是说最后一定是以一个数组来排序的。
步骤
- 计算当前步长,按步长划分子数组
- 子数组内插入排序
- 步长除以2后继续12两步,直到步长最后变成1
|
|
复杂度分析
希尔排序的时间复杂度受步长的影响,具体分析在维基百科。
5. 归并排序(Merge Sort)
归并排序是采用分治法(Divide and Conquer)的一个典型例子。这个排序的特点是把一个数组打散成小数组,然后再把小数组拼凑再排序,直到最终数组有序。
步骤
- 把当前数组分化成n个单位为1的子数组,然后两两比较合并成单位为2的n/2个子数组
- 继续进行这个过程,按照2的倍数进行子数组的比较合并,直到最终数组有序
|
|
这个实现中加了一个temp,是和原数组一样大的一个空间,用来临时存放排序后的子数组的。
复杂度分析
在merge_array过程中,实际的操作是当前两个子数组的长度,即2m。又因为打散数组是二分的,最终循环执行数是logn。所以这个算法最终时间复杂度是O(nlogn),空间复杂度是O(n)。
6. 快速排序(Quick Sort)
快速排序也是利用分治法实现的一个排序算法。快速排序和归并排序不同,它不是一半一半的分子数组,而是选择一个基准数,把比这个数小的挪到左边,把比这个数大的移到右边。然后不断对左右两部分也执行相同步骤,直到整个数组有序。
步骤
- 用一个基准数将数组分成两个子数组
- 将大于基准数的移到右边,小于的移到左边
- 递归的对子数组重复执行1,2,直到整个数组有序
|
|
解法2: 不需要辅助空间
|
|
复杂度分析
快速排序也是一个不稳定排序,时间复杂度看维基百科。空间复杂度是O(n)。
7. 堆排序(Heap Sort)
堆排序经常用于求一个数组中最大k个元素时。因为堆实际上是一个完全二叉树,所以用它可以用一维数组来表示。因为最大堆的第一位总为当前堆中最大值,所以每次将最大值移除后,调整堆即可获得下一个最大值,通过一遍一遍执行这个过程就可以得到前k大元素,或者使堆有序。
在了解算法之前,首先了解在一维数组中节点的下标:
- i节点的父节点 parent(i) = floor((i-1)/2)
- i节点的左子节点 left(i) = 2i + 1
- i节点的右子节点 right(i) = 2i + 2
步骤
- 构造最大堆(Build Max Heap):首先将当前元素放入最大堆下一个位置,然后将此元素依次和它的父节点比较,如果大于父节点就和父节点交换,直到比较到根节点。重复执行到最后一个元素。
- 最大堆调整(Max Heapify):调整最大堆即将根节点移除后重新整理堆。整理方法为将根节点和最后一个节点交换,然后把堆看做n-1长度,将当前根节点逐步移动到其应该在的位置。
- 堆排序(HeapSort):重复执行2,直到所有根节点都已移除。
|
|
复杂度分析
堆执行一次调整需要O(logn)的时间,在排序过程中需要遍历所有元素执行堆调整,所以最终时间复杂度是O(nlogn)。空间复杂度是O(n)。
0. 参考
七种常见经典排序算法总结(C++实现)的更多相关文章
- 七种常见经典排序算法总结(C++)
最近想复习下C++,很久没怎么用了,毕业时的一些经典排序算法也忘差不多了,所以刚好一起再学习一遍. 除了冒泡.插入.选择这几个复杂度O(n^2)的基本排序算法,希尔.归并.快速.堆排序,多多少少还有些 ...
- python3实现几种常见的排序算法
python3实现几种常见的排序算法 冒泡排序 冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来.走访数列的工作是重复地进行直到没有再需要 ...
- java讲讲几种常见的排序算法(二)
java讲讲几种常见的排序算法(二) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 堆排序 思路:构建一个小顶堆,小顶堆就是棵二叉树,他的左右孩子均大于他的根节点( ...
- java讲讲几种常见的排序算法
java讲讲几种常见的排序算法(一) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 以数组array={6,3,20,8,15,1}为例 冒泡排序 思路:从第0个到 ...
- java几种常见的排序算法总结
/*************几种常见的排序算法总结***************************/ package paixu; public class PaiXu { final int ...
- Python全栈开发之5、几种常见的排序算法以及collections模块提供的数据结构
转载请注明出处http://www.cnblogs.com/Wxtrkbc/p/5492298.html 在面试中,经常会遇到一些考排序算法的题,在这里,我就简单了列举了几种最常见的排序算法供大家学习 ...
- 用php实现四种常见的排序算法
几种常见的排序 排序是一个程序员的基本功,对于初级phper,更是可以通过排序算法来锻炼自己的思维能力. 所谓排序,就是对一组数据,按照某个顺序排列的过程.下面就总结四种常用的php排序算法,分别是冒 ...
- Java几种常见的排序算法
一.所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.排序算法,就是如何使得记录按照要求排列的方法.排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面. ...
- Java实现7种常见的排序算法
数据结构中的内部排序:不需要访问外存便能完成,是一个逐步扩大记录的有序序列长度的过程. 可以分为5类: 1.插入排序:直接插入排序,稳定排序,时间复杂度为O(n^2)非递减有序,设置r[0]为哨兵进行 ...
随机推荐
- Hive鲜为人知的宝石-Hooks
本来想祝大家节日快乐,哎,无奈浪尖还在写文章.谴责一下,那些今天不学习的人.对于今天入星球的人,今天调低了一点价格.减少了20大洋.机不可失失不再来.点击阅读原文或者扫底部二维码. hive概述 Hi ...
- (简单模拟)P1003 铺地毯
题解: 从最后一个输入的数据开始排查,如果说你找到了这个点上面有地毯,那么就直接输出这个值,如果没找到就按照题干的意思输出-1. #include<iostream>#include< ...
- JavaSE--java是值传递还是引用传递
引用是已定义的变量的别名. 按引用传递就是一个变量使用两个名称. 两个变量在内存中的地址都是一样的. 按值传递, 传递的是值的拷贝. C++中可以通过传引用来改变传入的参数的值.在C++中可以通过以下 ...
- 基于图灵api的Python机器人
一.注册图灵机器人 先注册并登录图灵机器人官网: 点击创建机器人 复制机器人的key 二.搭建Python机器人 Python版本:3.6 注意替换第三行代码的apikey import reques ...
- 13. react 基础 redux 的基本介绍 及 用 antd 编写 TodoList 的样式
1. redux 简述 当 store 内的 数据进行变更的时候 多个组件感知到 store 内的数据变化 将会被自动更新 2. redux 工作流 Store 代表数据存储 (例如: 图书馆管理 ...
- Delphi流的操作_文件合并
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- OSS 图片处理流程
1.步骤一 2.步骤二 3.步骤三 4.步骤四 5.步骤五(步骤4完成会自动添加cname用户解析,不需要自己去加,只需要点击进来看下是否添加成功即可) 通过以上步骤就可以实现了图片服务的配置
- hdu 2072(字典树模板,set,map均可做)
地址:http://acm.hdu.edu.cn/showproblem.php?pid=2072 lily的好朋友xiaoou333最近很空,他想了一件没有什么意义的事情,就是统计一篇文章里不同单词 ...
- tensorflow笔记(北大网课实战)
1. tf.multiply(x,y1) # 对应元素相乘 tf.matmul(x,y2) # 矩阵相乘 2.会话:执行计算图中的节点运算的. with tf.Session() as sess: p ...
- Python—异步任务队列Celery简单使用
一.Celery简介 Celery是一个简单,灵活,可靠的分布式系统,用于处理大量消息,同时为操作提供维护此类系统所需的工具.它是一个任务队列,专注于实时处理,同时还支持任务调度. 中间人boker: ...