七种排序算法(C++)
排序算法
- 引言
- 冒泡排序
- 简单选择排序
- 直接插入排序
- 希尔排序
- 堆排序
- 归并排序
- 快速排序
引言
排序中主要包含数据元素的比较和交换,本文以C++实现以下七种排序算法,以从小到大排序为例。
如有错误,万望指正。笔者的邮箱为:wuxiaofang555555@163.com 。本文的代码亦可以从笔者的GitHub上获取:https://github.com/wuerfang/Sort/tree/master。
排序分类一
- 简单算法:
冒泡排序
、简单选择排序
、直接插入排序
- 改进算法:
希尔排序
、堆排序
、归并排序
、快速排序
- 简单算法:
排序分类二
复杂度对比
排序方法 平均情况 最好情况 最坏情况 辅助空间 稳定性 冒泡排序 O ( n 2 ) O(n^2) O(n2) O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1) 稳定 简单选择排序 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1) 稳定 直接插入排序 O ( n 2 ) O(n^2) O(n2) O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1) 稳定 希尔排序 O ( n l o g n ) O(nlogn) O(nlogn)~ O ( n 2 ) O(n^2) O(n2) O ( n 1.3 ) O(n^{1.3}) O(n1.3) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1) 不稳定 堆排序 O ( n l o g n ) O(nlogn) O(nlogn) O ( n l o g n ) O(nlogn) O(nlogn) O ( n l o g n ) O(nlogn) O(nlogn) O ( 1 ) O(1) O(1) 不稳定 归并排序 O ( n l o g n ) O(nlogn) O(nlogn) O ( n l o g n ) O(nlogn) O(nlogn) O ( n l o g n ) O(nlogn) O(nlogn) O ( n ) O(n ) O(n) 稳定 快速排序 O ( n l o g n ) O(nlogn) O(nlogn) O ( n l o g n ) O(nlogn) O(nlogn) O ( n 2 ) O(n^2 ) O(n2) O ( l o g n ) O(logn) O(logn)~ O ( n ) O(n) O(n) 不稳定 交换函数
swap
void swap(vector<int> &v, int i, int j) {int temp = v[i];v[i] = v[j];v[j] = temp; }
冒泡排序
冒泡排序:两两比较相邻记录的关键字,如果反序则交换,直到没有反序。较小的数字如同气泡般慢慢浮到上面(或是较大的数字慢慢沉到下面)。
时间复杂度为 O ( n 2 ) O(n^2) O(n2),有三种实现方法,如下所示。
BubbleSort0
(不是真正意义上的冒泡排序)void BubbleSort0(vector<int> &v) {for (int i = 0; i < v.size(); ++i) {for (int j = i + 1; j < v.size(); ++j) {if (v[i] > v[j])swap(v, i, j);}} }
BubbleSort
(正宗的冒泡排序)void BubbleSort(vector<int> &v) {for (int i = 0; i < v.size(); ++i) {for (int j = v.size() - 1; j > i; --j) {if (v[j - 1] > v[j])swap(v, j - 1, j);}} }
BubbleSort2
(优化的冒泡排序方法)void BubbleSort2(vector<int> &v) {bool flag = true;for (int i = 0; i < v.size() && flag; ++i) {flag = false;for (int j = v.size() - 1; j > i; --j) {if (v[j - 1] > v[j]) {swap(v, j - 1, j);flag = true;} }} }
简单选择排序
选择排序的时间复杂度为 O ( n 2 ) O(n^2) O(n2),但性能略优于冒泡排序,因为选择排序交换次数少
SelectionSort
void SelectionSort(vector<int> &v) {int min;for (int i = 0; i < v.size(); ++i) {min = i;for (int j = i + 1; j < v.size(); ++j) {if (v[min] > v[j])min = j;}if (min != i)swap(v, i, min);} }
直接插入排序
插入排序的基本思想是将待排序的元素逐个插入已经安排好的序列中,时间复杂度为 O ( n 2 ) O(n^2) O(n2),但性能略优于冒泡排序和选择排序。
InsertSort
(两种实现方式)//方式一 void InsertSort(vector<int> &v) {for (int i = 1, j; i < v.size(); ++i) {int t = v[i]; //待插入的元素for (j = i; j > 0; --j) { //查找插入的位置if (v[j-1] < t)break;v[j] = v[j-1]; //逐个向后移动元素 }v[j] = t; //将待插入的元素放入正确的位置} }
//方式二 void InsertSort(vector<int> &v) {for (int i = 1, j; i < v.size(); ++i) {if (v[i] < v[i-1]) { //判断待插入元素是否移动位置int t = v[i]; //待插入的元素for (j = i; j > 0 && v[j - 1] > t; --j) { //查找插入的位置 v[j] = v[j - 1]; //逐个向后移动元素}v[j] = t; //将待插入的元素放入正确的位置} }}
希尔排序
希尔排序是对插入排序的一种改进,其将排序的元素分组,分别使用插入排序方法后得到基本有序的排列,时间复杂度为 O ( n 3 / 2 ) O(n^{3/2}) O(n3/2)
- 排序原理
ShellSort
void ShellSort(vector<int> &v) {int gap = v.size();do {gap = gap / 3 + 1;//gap = gap / 2;for (int i = gap, j; i < v.size(); ++i) {int t = v[i];for (j = i - gap; j >= 0; j -= gap) {if (v[j] < t)break;v[j + gap] = v[j];}v[j + gap] = t;}} while (gap > 1); }
堆排序
堆排序是对简单选择排序的一种改进,其利用堆进行排序,将待排序的数据构造成一个大顶堆,此时整个序列最大的最大值就是堆顶的根结点,将其移走(即将其与数组尾元素交换),此时末尾元素就是最大值,然后再将前n-1个数据进行重新构造成一个大顶堆,依次进行。 时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)
- 排序原理
HeapSort
void HeapSort(vector<int> &v) {for (int i = v.size() / 2 - 1; i >= 0; --i) { //构建大顶堆(利用了完全二叉树的概念)HeapAdjust(v, i, v.size() - 1);}for (int i = v.size() - 1; i > 0; --i) { swap(v, 0, i); //将堆顶元素与当前未经排序的尾元素交换HeapAdjust(v, 0, i - 1); //将子数组v[0...i-1]重新调整为大顶堆 } }
HeapAdjust
void HeapAdjust(vector<int> &v, int s, int m) {int temp = v[s];for (int j = 2 * s + 1; j <= m; j = 2 * j + 1) {//完全二叉树中左节点为2s+1,右节点为2s+2if (j < m && v[j] < v[j + 1])j++;if (v[j] < temp)break;v[s] = v[j];s = j;}v[s] = temp; }
归并排序
归并排序就是利用归并的思想实现的排序方法,其假设初始序列含有n个元素,则可以堪称是n个有序的子序列,每个子序列的长度为1,然后两两合并,得到n/2个长度为2或1 的有序序列,再两两合并,…,如此重复,亦称谓2路归并排序。 时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)。
- 排序原理
MergeSort
void MergeSort(vector<int> &v) {MSort(v, v, 0, v.size() - 1); }
MSort
void MSort(const vector<int> &v, vector<int> &v1, int s, int t) {int m;vector<int> v2(v.size());if (s == t) {v1[s] = v[s];}else {m = (s + t) / 2;MSort(v, v2, s, m); //递归将v[s...m]归并为有序的v2[s...m]MSort(v, v2, m + 1, t); //递归将v[m+1...t]归并为有序的v2[m+1...t]Merge(v2, v1, s, m, t); //将有序的v2[s...m]和v2[m+1...t]归并为v1中} }
Merge
void Merge(const vector<int> &v, vector<int> &v1, int s, int m, int t) {int j, k;for (j = m + 1, k = s; s <= m && j <= t; ++k) {if (v[s] < v[j])v1[k] = v[s++];elsev1[k] = v[j++];}if (s <= m) {for (; s <= m; ++s, ++k)v1[k] = v[s];}if (j <= t) {for (; j <= t; ++j, ++k)v1[k] = v[j];} }
快速排序
快速排序是对冒泡排序的一种改进,其通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行。 时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)
- 排序原理
QuickSort
void QuickSort(vector<int> &v) {QSort(v, 0, v.size() - 1); }
QSort
//对子数组进行快速排序 void QSort(vector<int> &v, int low, int high) {int pivot; //枢轴if (low < high) { pivot = Partition(v, low, high); //将v[low...high]一分为二,并计算出枢轴值pivotQSort(v, low, pivot - 1); //对低子数组递归排序QSort(v, pivot + 1, high); //对高子数组递归排序} }
Partition
//交换待排序数组中的顺序,是位于枢轴pivot左边的值都小于该值,使其右边的值都大于该值 int Partition(vector<int> &v, int low, int high) {int pivotvalue = v[low];while (low < high) {while (low < high&&v[high] >= pivotvalue)high--;swap(v, low, high);while (low < high&&v[low] <= pivotvalue)low++;swap(v, low, high);}return low; }
七种排序算法(C++)相关推荐
- java 算法 排序算法_Java七种排序算法以及实现
Java常见七种排序算法以及实现 最近学习一些排序算法,怕自己以后忘记就打算整理起来供自己复习 萌新一枚学习Java没多久,以下仅供参考.如有错误希望大佬指正,欢迎大家在评论区交流探讨. 1.冒泡排序 ...
- 数据结构(三) 用java实现七种排序算法。
很多时候,听别人在讨论快速排序,选择排序,冒泡排序等,都觉得很牛逼,心想,卧槽,排序也分那么多种,就觉得别人很牛逼呀,其实不然,当我们自己去了解学习后发现,并没有想象中那么难,今天就一起总结一下各种排 ...
- 【数据结构】用java实现不同的七种排序算法和性能比较
文章目录 1.直接插入排序 2.希尔排序 3.冒泡排序 4.快速排序 5.选择排序 6.堆排序 7.归并排序 1.直接插入排序 public class DifferentSort {public s ...
- Python实现经典七种排序算法
#2018-06-02 June Saturday the 22 week, the 153 day SZ #数组排序算法大全用Python3实现 #参考https://www.cnblogs.com ...
- 数据结构常用的七种排序算法总结
前言 排序算法在数据结构里属于最为重要的一部分,例如我们熟悉的冒泡.选择.插入.归并等,这些当初在第一次学习的时候,并没有很好的掌握,现在因为在备战考研,刚刚进行完数据结构的一轮简单复习在开始整理一轮 ...
- 常见七种排序算法对比(超全!!!)
文章目录 一, 直接插入排序 二,希尔排序 三.选择排序 四,堆排序 五,冒泡排序 六,快速排序 如何优化快排呢? 三数取中法优化快排 七,归并排序 怎么判断是不是稳定的排序呢? 如果当前这个序列,在 ...
- Java常见的几种排序算法-插入、选择、冒泡、快排、堆排等
本文就是介绍一些常见的排序算法.排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序.选择排序.冒泡排 ...
- 归并排序改良 java_Java 八种排序算法总结
image 前言 好久没复习基础了,写个冒泡排序都要想一会.感觉自己好像老了好多,今天手痒总结一下排序算法.目前网上博客普遍都有详细介绍,写的很清楚.说实话我是没必要再写一遍的,感觉就是在啰嗦.还是重 ...
- php常用的四种排序算法
纯当练习,高手请绕过.以一维数组为例. 1.插入排序 思想: 每次将一个待排序的数据元素插入到前面已经排好序的数列中,使数列依然有序,知道待排序数据元素全部插入完为止. 示例: [初始关键字] [49 ...
最新文章
- 如何查看已安装的CentOS版本信息
- be sure to bring water with you while studying
- 集合框架 Queue---BlockingQueue详解
- 地铁框架保护的原理_继电保护的基础知识和原理(地铁)
- 降维系列之 LDA 线性判别分析
- SQL Server 2008文件与文件组的关系
- Ubuntu 20.04 配置vim编辑器
- Java网络编程(精简版)
- Turbo码基本框架
- 苏州外壳防护试验IP防尘防水测试IP65 IP66 IP69K
- wecp 启动 php,WEPE工具箱VIP版及网络版合盘20171102
- 如何用excel做正交分析_excel表格分析正交数据处理-excel中怎么对正交试验进行F值检验...
- 下方点击出项上方对应的插件_魔兽世界MiDKP3.0插件使用说明
- 【PPT】跨境电商的N个知识点普及
- root后充电很慢,root后开机慢
- Java实现微信开发者-测试账号申请及配置
- ChatGPT初体验——开发好帮手
- 如何实现简单的随机点名
- SEO图片代码优化技巧汇总
- 2020-11-20java数据类型及关键字
热门文章
- stacking算法基本思想
- ConcurrentLinkedQueue非阻塞无界链表队列
- 誓约-markdown编辑器学习
- android-ndk-r17c,Cannot use old NDK (android-ndk-r17c) after Catalina upgrade due to new security
- php获取重定向post数据,使用POST数据进行PHP重定向
- 编程必备的23种设计模式
- 接口taobao.tbk.sc.order.get(淘宝客订单查询)避坑指南
- css——兼容 ie
- c语言实现python语法_用C语言扩展Python的功能
- 连接远程linux服务器