数据结构 经典排序算法总结(二)

  • 交换排序
    • 冒泡排序
    • 快速排序(重要)
  • 归并排序
    • 归并排序
  • 非比较排序
    • 计数排序

交换排序

冒泡排序

冒泡排序:是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
思想:对所有相邻记录的关键字值进行比效,如果是逆顺(a[j]>a[j+1]),则将其交换,最终达到有序化;
适用情况:数据量少且不考虑效率
时间复杂度和稳定性:O(n)~O(n2) 稳定

1、比较相邻的元素。如果第一个比第二个大,就交换它们两个;
2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
3、针对所有的元素重复以上的步骤,除了最后一个;
4、重复步骤1~3,直到排序完成。

代码实现:(优化两次后的冒泡排序)

void BubbleSort(int* arr, int size)
{int n = size - 1;//用于记录每轮冒泡最后交换的位置,优化。int pos = 0;for (int i = 0; i < size; ++i){//用于标记该轮冒泡是否有数据交换 优化bool flag = false;for (int j = 0; j < n; ++j){if (arr[j] > arr[j + 1]){Swap(arr, j, j + 1);flag = true;//最后一次交换位置,下轮冒泡时后面就不用遍历了。pos = j;}}if (flag != true){//元素未交换,说明已有序,退出break;}n = pos;}
}

运行结果:

快速排序(重要)

由于篇幅和重要性的问题,博主将快速排序单独写在一篇博客中 数据结构 快速排序的三种实现 (hoare版本 挖坑法 前后指针版本)与非递归实现

归并排序

归并排序

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
思想:归并排序,首先把一个数组中的元素,按照某一方法,先拆分了之后,按照一定的顺序各自排列,然后再归并到一起,使得归并后依然是有一定顺序的
时间空间复杂度和稳定性:O(nlog) O(n) 稳定

假设现在有一个待排序的序列,[3, 2, 6, 8, 1, 4, 9, 7],那么我们就需要将该序列进行分治,先将其分成两份:[3, 2, 6, 8]和[1, 4, 9, 7],再将这两份分别分成两份:[3, 2]和[6, 8];[1,4]和[9,7],最后将这四部分再次分别分为两份,最后就将整个序列分为了八份。需要注意的是,在分的过程中,不需要遵循任何规则,关键在于归并,归并的过程中便实现了元素的排序。

动画:(颜色相同为一组,开始一个元素为一组)

动画看不懂没关系,再看图

这是一个自底向上的排序。归并排序理解起来相对比较难,下面代码我也写很很多注释

代码:

//合并序列函数
void Merge(int* arr, int begin, int mid, int end, int* tmp)
{//区间1[begin, mid]int begin1 = begin;int end1 = mid;//区间2[mid+1, end]int begin2 = mid + 1;int end2 = end;//辅助空间的起始位置int idx = begin;//合并有序序列while (begin1 <= end1 && begin2 <= end2){//谁小谁先进if (arr[begin1] <= arr[begin2]){tmp[idx++] = arr[begin1++];}else{tmp[idx++] = arr[begin2++];}}//判断是否有未合并的元素,有就将剩余元素全部拷贝if (begin1 <= begin1){memcpy(tmp + idx, arr + begin1, sizeof(int) * (end1 - begin1 + 1));}if (begin2 <= begin2){memcpy(tmp + idx, arr + begin2, sizeof(int) * (end2 - begin2 + 1));}//合并之后的序列考到原始数组的对应区间memcpy(arr + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}void _MergeSort(int* arr, int begin, int end, int* tmp)
{//单个元素已经有序,不用排序if (begin >= end)return;//获得中间索引int mid = begin + (end - begin) / 2;//首先合并子序列//左边[begin, mid]_MergeSort(arr, begin, mid, tmp);//右边[mid+1,end]_MergeSort(arr, mid + 1, end, tmp);//合并两个有序的子序列[begin, mid]  [mid + 1, end]Merge(arr, begin, mid, end, tmp);
}//归并排序
void MergeSort(int* arr, int n)
{//申请辅助空间int* tmp = (int*)malloc(sizeof(int) * n);_MergeSort(arr, 0, n - 1, tmp);free(tmp);
}

运行结果

非递归版本

代码 + 注释

//合并序列函数
void Merge(int* arr, int begin, int mid, int end, int* tmp)
{//区间1[begin, mid]int begin1 = begin;int end1 = mid;//区间2[mid+1, end]int begin2 = mid + 1;int end2 = end;//辅助空间的起始位置int idx = begin;//合并有序序列while (begin1 <= end1 && begin2 <= end2){//谁小谁先进if (arr[begin1] <= arr[begin2]){tmp[idx++] = arr[begin1++];}else{tmp[idx++] = arr[begin2++];}}//判断是否有未合并的元素,有就将剩余元素全部拷贝if (begin1 <= begin1){memcpy(tmp + idx, arr + begin1, sizeof(int) * (end1 - begin1 + 1));}if (begin2 <= begin2){memcpy(tmp + idx, arr + begin2, sizeof(int) * (end2 - begin2 + 1));}//合并之后的序列考到原始数组的对应区间memcpy(arr + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}void MergeSortNoR(int* arr, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);//步长:处理sept为一组的数据int step = 1;while (step < n){//处理每一组的数据for (int idx = 0; idx < n; idx += 2 * step){//扎到两个待合并的子序列区间//[begin, mid]  [mid + 1, end]int begin = idx;int mid = idx + step - 1;//判断是否存在第二个序列if (mid >= n - 1){//不存在第二个子序列,直接跳过continue;}int end = idx + 2 * step - 1;//判断第二个子序列是否越界if (end >= n){end = n - 1;}//合并Merge(arr, begin, mid, end, tmp);}//更新步长step *= 2;}
}

运行结果

非比较排序

计数排序

计数排序(Counting sort)是一种非基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中以达到排序的效果
时间空间复杂度和稳定性:O(MAX(N,范围)) O(范围) 稳定

计数数组的下标对应的是待排序数组的值

但是我们发现,假如只有两个数据[1,100000],我们的计数数组要遍历100000次才可以排序,是比较浪费的,且也是非常的浪费空间,我们可以进行优化。

代码:

void CountSort(int* arr, int size)
{//找到最大和最小值int max, min;min = max = arr[0];for (int i = 1; i < size; ++i){if (arr[i] > max)max = arr[i];if (arr[i] < min)min = arr[i];}//范围int range = max - min + 1;//计数数组int* countArr = (int*)calloc(range, sizeof(int));//将数据存在计数数组中for (int i = 0; i < size; ++i){countArr[arr[i] - min]++;}//实际元素的下标int idx = 0;//遍历计数数组for (int i = 0; i < range; ++i){while (countArr[i]--){arr[idx++] = i + min;}}
}

运行结果:

数据结构 10分钟让你掌握经典排序(二)相关推荐

  1. 数据结构 10分钟让你掌握经典排序(一)

    数据结构 经典排序算法总结(一) 排序总结 插入排序 直接插入排序 希尔排序 选择排序 简单选择排序 堆排序 推荐阅读 排序总结 经典排序算法是数据结构体系中最重要的内容之一,这一块必须要非常熟练的掌 ...

  2. 数据结构与算法笔记 —— 十大经典排序及算法的稳定性

    一.十大经典排序算法 排序算法是<数据结构与算法>中最基本的算法之一. 排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全 ...

  3. 大屏监控系统实战(13)-10分钟投票增量曲线制作(二)

    因为内容太多,所以我们分成了两部分,接前文 大屏监控系统实战(11)-10分钟投票增量曲线制作(一) 八.投票网站最近72小时10分钟投票走势和增量数据爬取 在SchedulingTest中添加方法如 ...

  4. 我用 Python 3分钟实现9种经典排序算法的可视化

    导读:最近在某网站上看到一个视频,是关于排序算法的可视化的,看着挺有意思的,也特别喜感. 不知道作者是怎么做的,但是突然很想自己实现一遍,而且用python实现特别快,花了一天的时间,完成了这个项目. ...

  5. 10分钟HTML5入门基础知识(二)

    html5开发与旧式浏览器的兼容 我们已经讨论了HTML5许多很酷的新功能,包括新的语义元素.为画图而生的canvas标签,以及音频与视频支持. 你可能会想:这些东西是很好,但当用户的浏览器不兼容HT ...

  6. mysql书写规则_每天10分钟带你学会MySQL(二)SQL语句的基本书写规则

    SQL语句时必须要遵守一些规则.这些规则都非常简单,接下来就让我们逐一认识一下吧. 1,SQL语句以分号(;)结尾. ■SQL语句要以分号(;)结 尾 一条SQL语句可以描述一个数据库操作.在RDBM ...

  7. sql 全角转半角_每天10分钟带你学会MySQL(二)SQL语句的基本书写规则

    SQL语句时必须要遵守一些规则.这些规则都非常简单,接下来就让我们逐一认识一下吧. 1,SQL语句以分号(;)结尾. ■SQL语句要以分号(;)结 尾 一条SQL语句可以描述一个数据库操作.在RDBM ...

  8. 十大经典排序算法动画与解析,看我就够了!(附代码)

    作者 | 程序员小吴 来源 | 五分钟学算法(ID:CXYxiaowu) 排序算法是<数据结构与算法>中最基本的算法之一.排序算法可以分为内部排序和外部排序.内部排序是数据记录在内存中进行 ...

  9. 10分钟HTML5入门基础知识(一)

    毫无疑问,对于开发人员而言, HTML5 已是一个热点话题.如果你需要快速了解HTML5的功能的基本原理,阅读本文是你最好的选择. 本文来自The Code Project的付费搜索位置,由Solut ...

最新文章

  1. JNI中java类型的简写
  2. 【深度学习】手把手教你实现一个人工智能案例(蓄电池爬碱识别)
  3. CentOS 7 官方yum库安装 MySQL
  4. rowspan不显示 wpf_wpf的datagrid绑定datatable列不自动更新解决方案
  5. gradle的groovy语法案例详解
  6. 各版本Sql Server下载地址全
  7. SQL Server 2005 分页SQL
  8. 微信小游戏代码包侵权(最新)
  9. 云计算-Micheal Miller 著 姜进磊 孙瑞志 向勇 史美林 译
  10. Android选择/拍照 剪裁 base64/16进制/byte上传图片+PHP接收图片
  11. 关不掉,新版微信这功能引用户怨声载道...
  12. ubuntu conda 更新、下载模块包权限问题 'Permission denied'
  13. unity制作坦克大战
  14. HE3342E单节 2A 开关型锂离子电池充电芯片
  15. GetElementByName
  16. Django----做一个简单网页的教程(适合初学者)
  17. 一个很棒的字帖生成器
  18. 广州宇信易诚科技有限公司面试题
  19. 【网络基础】数据链路层实现的三大功能
  20. RSA共模攻击(包括原理)

热门文章

  1. android 传感器 应用,Android移动设备中传感器的应用
  2. html 的css骚操作,意想不到的 CSS 伪元素 before/after 各种骚操作 - 文章教程
  3. java 手动加载数据库驱动_JAVA加载数据库驱动(JDBC)
  4. mysql select不走索引_避免写出不走索引的SQL, MySQL
  5. python如何另存文件_脚本将.py保存到文件中的另一个目录
  6. html追加到末尾,css – wkhtmltopdf – 将内容添加到最后一页的底部
  7. java 电子杂志,java毕业设计_springboot框架的时尚电子杂志网站
  8. 剑指offer:数据流中的中位数(小顶堆+大顶堆)
  9. 最简单的SpringMVC + Maven配置
  10. 百度地图开源代码使用