在计算机科学中,排序算法是算法研究中的基本问题之一。在生活和应用中,有很多地方需要对信息进行排序,如图书馆书号排序、教务系统学生成绩排序、银行支票排序等。
排序算法目的是将输入的序列(可能以数组或者链表的形式)按照一定的数值顺序进行排列,使得输入数据项(记录)中的关键字有序。对于一些含有较大卫星数据的记录,通常重新排列记录的指针数组,以减少数据移动量。排序算法的数学描述:

常用的排序算法有冒泡排序、选择排序、归并排序、快速排序、堆排序、基数排序、计数排序、希尔排序等。排序算法根据根据不同的分类标准可以分为不同的形式。如根据内存使用量,可以分为原址排序(in-place,使用较少的附加内存)和移动排序;根据算法的稳定性,可以分为稳定排序(排序后不改变相同元素的相对顺序)和不稳定排序。

下面介绍常用排序算法的主要思想,并给出相应的C++代码。

  1. 选择排序
    选择排序是一种基于比较的原址排序算法。把输入数组分为两部分,从左往右逐渐构建一个排序后的左子数组,和剩余的部分组成未排序的右子数组。
    初始时:排序子数组为空,未排序子数组为输入数组。
    排序时:查找未排序子数组中的最大值或最小值,与最左边未排序边界元素交换,然后往右边移动一个单位的子数组边界。
    排序后:左子数组为排序后的数组,右数组为空。

  2. 归并排序
    归并排序是一种基于比较的稳定排序算法,使用了分治的思想。
    把未排序的数组分割成n个子数组,每个子数组只包含一个元素,此时单元数子数组有序。然后重复归并子数以产生新的排序的子数组,直到仅剩下一个子数组,也就是排序后的数组。

  3. 快速排序
    快速排序是一种高效常用的基于比较的不稳定排序算法,也采用了分治的思想。通俗地讲,快速排序算法就是选择一个轴关键字(pivot),把数组分为两个子数组,使得左子数组全不大于右子数组。递归对左右两半部分进行上述操作,直到数组中的元素全部有序。选择轴关键字和划分子数组的步骤可以有几种不同的实现方式,决定了排序算法有不同的实现。轴关键字选择可以直接选择边界值,或者随机选择,或者三数取中。

  4. 堆排序
    堆排序主要是借助了一种称为二叉堆的抽象数据结构实现排序。
    二叉堆是一个完全二叉树,一个大根堆是指根节点的值不小于其他节点的值。主要操作有获得父节点、左孩子、右孩子、从无序输入构造堆、维护堆的性质、堆排序等操作。

/** 2017.01.04 常用排序算法总结和实现* 参考资料《算法导论》《数据结构与算法分析——C语言描述》*/
#include <algorithm>
#include <assert.h>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;//模板元编程
template <typename T> void Swap(T &arr, T &b) {T c = arr;arr = b;b = c;
}//选择排序算法
void selectSort(vector<int> &arr) {int n = arr.size();if (n <= 1)return;/* arr[0] to arr[n-1] is the array to sort */int i, j;/* advance the position through the entire array *//*   (could do j < n-1 because single element is also min element) */for (j = 0; j < n - 1; j++) {/* find the min element in the unsorted arr[j .. n-1] *//* assume the min is the first element */int iMin = j;/* test against elements after j to find the smallest */for (i = j + 1; i < n; i++) {/* if this element is less, then it is the new minimum */if (arr[i] < arr[iMin]) {/* found new minimum; remember its index */iMin = i;}}if (iMin != j) {Swap(arr[j], arr[iMin]);}}return;
}//使用临时数组,辅助归并排序
void merge(vector<int> &arr, vector<int> &tmpArr, int lpos, int rpos, int rend) {int lend = rpos - 1, tmpPos = lpos, nums = rend - lpos + 1;while (lpos <= lend && rpos <= rend) {if (arr[lpos] < arr[rpos])tmpArr[tmpPos++] = arr[lpos++];elsetmpArr[tmpPos++] = arr[rpos++];}while (lpos <= lend) {tmpArr[tmpPos++] = arr[lpos++];}while (rpos <= rend) {tmpArr[tmpPos++] = arr[rpos++];}//从临时数组拷贝到输入输出数组中for (int i = 0; i < nums; ++i, --rend) {arr[rend] = tmpArr[rend];}return;
}//归并排序的递归算法
void mergeSort(vector<int> &arr, vector<int> &tmpArr, int left, int right) {int center;if (left < right) {center = (left + right) / 2;mergeSort(arr, tmpArr, left, center);       //左边递归调用mergeSort(arr, tmpArr, center + 1, right);  //右边递归调用merge(arr, tmpArr, left, center + 1, right);//归并}
}
//归并排序主程序
void mergeSort(vector<int> &arr) {vector<int> tmpArr = vector<int>(arr.size(), 0);mergeSort(arr, tmpArr, 0, arr.size() - 1);
}//选择主元,并把无序数组分割为两个部分
int partition(vector<int> &arr, int low, int high) {assert(low >= 0 && low <= high && high < arr.size());int pivot = arr[low];while (low != high) {while (low < high && arr[high] > pivot) {--high;}arr[low] = arr[high];while (low < high && (arr[low] <= pivot)) {++low;}arr[high] = arr[low];}arr[low] = pivot;return low;
}//快排的递归算法
void quickSort(vector<int> &arr, int low, int high) {// low == high代表只有一个数了,此时退出循环if (low < high) {int idx = partition(arr, low, high);quickSort(arr, low, idx - 1);quickSort(arr, idx + 1, high);}
}
void quickSort(vector<int> &arr) {assert(arr.size() > 0);quickSort(arr, 0, arr.size() - 1);
}//使用数组标示的大根二叉堆,辅助堆排序。这里选择从0开始,而不是算法导论中的从1开始。
inline int parenti(int i) { return (i - 1) >> 1; }
inline int lchildi(int i) { return (i << 1) + 1; }
inline int rchildi(int i) { return (i << 1) + 2; }//维护二叉堆的性质
void maxHeapify(vector<int> &arr, int i, int n) {// int n=arr.size();int l = lchildi(i), r = rchildi(i);int m;if (l < n && arr[l] > arr[i])m = l;elsem = i;if (r < n && arr[r] > arr[m])m = r;if (m != i) {Swap(arr[i], arr[m]);maxHeapify(arr, m, n);}
}//构造二叉堆
void buildMaxHeap(vector<int> &arr) {// 从具有叶子节点的最后一个节点向前开始,组元素维护堆的性质。for (int i = (arr.size() - 2) / 2; i >= 0; --i) {maxHeapify(arr, i, arr.size());}
}//堆排序
void heapSort(vector<int> &arr) {//首先构造大根堆buildMaxHeap(arr);//从叶子节点到根节点的左孩子开始循环,交换当前元素和根节点(最大值),//相当于把当前最大元素移动到“最后”,也就是把最大元素弹出二叉树。//然后维护堆的性质。for (int i = arr.size() - 1; i >= 1; --i) {Swap(arr[0], arr[i]);maxHeapify(arr, 0, i);}
}int main() {vector<int> Arr = {3, 2, 1, 0, 11, 12, 13};{vector<int> arr = Arr;selectSort(arr);copy(arr.begin(), arr.end(), ostream_iterator<int>(cout, " "));cout << endl;}{vector<int> arr = Arr;mergeSort(arr);copy(arr.begin(), arr.end(), ostream_iterator<int>(cout, " "));cout << endl;}{vector<int> arr = Arr;quickSort(arr);copy(arr.begin(), arr.end(), ostream_iterator<int>(cout, " "));cout << endl;}{vector<int> arr = Arr;heapSort(arr);copy(arr.begin(), arr.end(), ostream_iterator<int>(cout, " "));cout << endl;}return 0;
}

转载于:https://www.cnblogs.com/ausk/p/6363885.html

[2017.01.04] 经典排序算法思想及其实现相关推荐

  1. Jerry 2017年的五一小长假:8种经典排序算法的ABAP实现

    2017年4月29日~5月1日,国际劳动节, 三天的小长假. 在国内,小长假往往是这样的: 然而我当时在戏称为"德村"(德国农村)的Walldorf出差并且住在Wiesloch, ...

  2. 【Python】用Python实现十大经典排序算法

    来源:Python数据之道 (ID:PyDataLab) 作者:阳哥 大家好,我是阳哥. 最近一段时间,我在微信视频号「Python数据之道」上陆陆续续发布了10种经典排序算法的动画实现. 今天,想以 ...

  3. 手撕前端面试之经典排序算法

    作者 | 霍语佳       责编 | 欧阳姝黎 排序算法是面试中的高频考察点,我们需要熟练掌握.本文整理了最经典.最常用的排序算法并且搭配了动图和视频,希望能够帮助你更加轻松的理解它们. 首先,根据 ...

  4. 用 Python 实现十大经典排序算法

    作者 | 我是阳哥 来源 | Python数据之道 今天,详细的跟大家分享下 10 种经典排序算法. 10种经典排序算法包括冒泡排序.选择排序.快速排序.归并排序.堆排序.插入排序.希尔排序.计数排序 ...

  5. 用Python实现十大经典排序算法

    来源:Python数据之道 (ID:PyDataLab) 作者:阳哥 大家好,我是阳哥. 最近一段时间,我在微信视频号「Python数据之道」上陆陆续续发布了10种经典排序算法的动画实现. 今天,想以 ...

  6. 【每日算法】C语言8大经典排序算法(2)

    接上文--->[每日算法]C语言8大经典排序算法(1) 二.插入类排序 插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中 ...

  7. c语言代码先来先服务算法_C语言十大经典排序算法(动态演示+代码,值得收藏)...

    以前也零零碎碎发过一些排序算法,但排版都不太好,又重新整理一次,排序算法是数据结构的重要部分,系统地学习很有必要. 时间.空间复杂度比较 排序算法 平均时间复杂度 最差时间复杂度 空间复杂度 数据对象 ...

  8. 十大经典排序算法解析及优化

    前言 在上篇文章<十大经典排序算法(动图演示)>中,已经能够了解各种排序算法的思想逻辑,虽然其中提供了代码,但对其解析却并不够全面,而且使用的是js来进行编写演示.本人根据其上代码转换为P ...

  9. 十大经典排序算法(建议收藏)

    来自:Damonare的个人博客 原文:http://blog.damonare.cn/2016/12/20/十大经典排序算法总结(javascript描述)/ 0.算法概述  0.1 算法分类 十种 ...

  10. python遍历数组冒泡排序_经典排序算法(冒泡排序,选择排序,插入排序,快速排序,堆排序)python实现...

    最近在复习经典排序算法,自己用python也实现了一下,这里不会涉及到原理(因为网上方法已经很详细啦),就把函数贴上来,可以让大家自己试着运行下,再结合别处的原理也可以更好地理解它们的实现. 如果有错 ...

最新文章

  1. python自学流程-Python系统学习流程图,教你一步步学习python
  2. 本地连接出来的很慢解决方法
  3. kali字典_Web渗透测试——暴力破解字典制作工具的使用2
  4. 电力系统——基于10机39节点的电力系统仿真(Matlab)
  5. stata15中文乱码_Stata14打开13数据乱码处理办法
  6. 视频教程-网站建设-1小时学会建站,采用PHPWAMP搭建网站[全程实战]-PHP
  7. 基于jsp的新闻发布系统
  8. H5/web前端工程简历中的项目经验
  9. 目前我国每小时就有1名电动自行车骑行者死于交通事故
  10. tablayou设置固定下划线和根据文字显示长短显示下划线
  11. 围棋棋盘怎么编程python_python围棋_python围棋程序_python实现围棋ai - 云+社区 - 腾讯云...
  12. SubstanceDesigner制作PBR材质制作并且同步到Unity小尝试
  13. 使用GPU硬件加速FFmpeg视频转码
  14. (翻译)9种清晰直观的图标应用原则
  15. java编程官方教程_Java编程入门官方教程
  16. 【python】windows定时运行python脚本
  17. HTML 标签列表(字母排序)
  18. 系统监理工程师学习笔记
  19. JS 二维数组转变成一维数组
  20. Java中文件流的基本用法

热门文章

  1. 前段之路心得——(1)
  2. c语言:编辑一个有趣的死循环程序并对其修改,仅仅是一个“=”号的差别
  3. php echo substr('hello',1,-2);-2是什么意思 为什么结果是 el
  4. 关于win10家庭版不能开启虚拟机的问题
  5. AVIator -- Bypass AV tool
  6. BZOJ4530:[BJOI2014]大融合
  7. ARPG游戏打击感相关的技术简单总结
  8. [MATLAB]MATLAB中SIMULINK常用命令表
  9. 【leetcode】数组的度-两个map关联初探
  10. Node.js 应该用在什么地方