在十大经典排序算法(动画演示)这篇博客的指导下,博主一点一点码出了十大排序算法,并写了菜鸟级注释,源码戳这里,下面记录一下自己的总结,基本上是从注释搬来的。

排序算法主要分两类,一类是比较类排序,一类是非比较类排序。

一、比较类排序

通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。比较类排序算法和核心在于比较,只是比较的方法不一样,主要有交换排序、插入排序、选择排序。

1.1 交换排序

即通过数与数之间地交换,如冒泡排序和快速排序。
冒泡排序:通过相邻两个数之间的比较,交换两个数的位置使之满足统一的规律(比如左边始终比右边小),不断将最大/小数“冒”出来放在顶端;
快速排序:还是通过不断交换,使得选中的基准数交换到属于它的位置(即左边全部小于或大于它,右边反之),然后固定不动,对左右两边的数重复这一操作,直到所有的数都固定不动。使用的是分治法,其实思路很简单,假设基准是左边第一个数,左边全是小于基准的数,操作就是把左边出现的大于基准的数与右边出现的小于基准的数对调位置,最后把最后一个小于基准的数和基准对调位置即可,然后对左右两边重复操作。

public static void QuickSort(int[] num, int left, int right) {//如果left等于right,即数组只有一个元素,直接返回if(left>=right) {return;}//设置最左边的元素为基准值int key=num[left];//数组中比key小的放在左边,比key大的放在右边,key值下标为iint i=left;int j=right;while(i<j){//j向左移,直到遇到比key小的值while(num[j]>=key && i<j){j--;}//i向右移,直到遇到比key大的值while(num[i]<=key && i<j){i++;}//i和j指向的元素交换if(i<j){int temp=num[i];num[i]=num[j];num[j]=temp;}}num[left]=num[i];num[i]=key;count++;QuickSort(num,left,i-1);QuickSort(num,i+1,right);}

1.2 插入排序

通过不断将数据插入到数组中的排序,主要有简单插入排序和希尔排序。
简单插入排序:依次选定数据向前(向数组首端)插入到合适的位置后重复操作,直到最后一个数。
希尔排序:听名字挺高级的,不过就是加了增量数列而已啦。根据增量划分为几个组,然后在同一个组中进行插入排序。比简单插入排序“聪明”一点的地方就是不再是一个一个去比较,而是分组插入排序。

1.3 选择排序

不断选择出最大/小数,将其置于顶端,如简单选择排序、堆排序。
简单选择排序:选择操作,即将当前无序数组中最大/小值的下标找出来,然后与无序区的第一个元素交换位置,那么这个元素就算是加入到与之相邻的有序区啦,反复操作。虽然冒泡排序也是选最大/小值,但还是不同的,这里是选下标就好了,找最大/小值的过程中没有发生交换,而冒泡排序选最大/小值是一路交换过去的。所以相比而言,冒泡排序还要稍微“聪明一点”,因为最佳情况下冒泡的时间复杂度为O(n),即数组为一个有序数组,而简单排序需要O(n^2),因此被称为最稳(sha)定(*)的算法之一。
堆排序:借助了堆的属性,稍微麻烦一点,但是思路也很简单,就是不断将堆顶元素和叶子节点的值做交换,只要记得每次交换之后检查新的数组是否满足堆的属性就好了。

1.4 归并排序

归并排序:采用的也是分治法,先分完再合并,这里的分完指左右两支都出现了,记得分到一个元素的时候要返回这个元素,否则就是个死循环。合并的思路比较简单,两个待合并的数组元素中谁小先push谁,反之也可以。

public class MergeSortTest {public static void main(String[] args) {int[] data = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };print(data);mergeSort(data);System.out.println("排序后的数组:");print(data);}public static void mergeSort(int[] data) {sort(data, 0, data.length - 1);}public static void sort(int[] data, int left, int right) {if (left >= right)return;// 找出中间索引int center = (left + right) / 2;// 对左边数组进行递归sort(data, left, center);// 对右边数组进行递归sort(data, center + 1, right);// 合并merge(data, left, center, right);print(data);}/*** 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序* * @param data*            数组对象* @param left*            左数组的第一个元素的索引* @param center*            左数组的最后一个元素的索引,center+1是右数组第一个元素的索引* @param right*            右数组最后一个元素的索引*/public static void merge(int[] data, int left, int center, int right) {// 临时数组int[] tmpArr = new int[data.length];// 右数组第一个元素索引int mid = center + 1;// third 记录临时数组的索引int third = left;// 缓存左数组第一个元素的索引int tmp = left;while (left <= center && mid <= right) {// 从两个数组中取出最小的放入临时数组if (data[left] <= data[mid]) {tmpArr[third++] = data[left++];} else {tmpArr[third++] = data[mid++];}}// 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)while (mid <= right) {tmpArr[third++] = data[mid++];}while (left <= center) {tmpArr[third++] = data[left++];}// 将临时数组中的内容拷贝回原数组中// (原left-right范围的内容被复制回原数组)while (tmp <= right) {data[tmp] = tmpArr[tmp++];}}public static void print(int[] data) {for (int i = 0; i < data.length; i++) {System.out.print(data[i] + "\t");}System.out.println();}}

二、 非比较排序

不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。非比较排序理解起来就是按顺序收集数据。这个顺序是由所谓的“桶”决定的。简单理解来说就是画个数轴,然后把数轴上的点和待排序的数组元素关联起来,再按数轴的顺序输出就可以了。

2.1 计数排序

最基本的非比较排序,数轴长度为最大值 - 最小值,然后把每个元素值xbucket[i]一一对应,如果有多个数,说明这些数都是相等的,记录一下一共有多少个数就可以了。那么索引i与元素值x一一对应,bucket[i]就是x出现的次数,然后按照索引的顺序输出就可以了。

2.2 桶排序

改进的计数排序,改进点在于不再是一一对应(太浪费空间了),而是一个区间一个区间地对应,比如[10,19]这个区间的数都放在bucket[1]这个桶里面,1表示桶的索引,注意是放在桶里面,即此时的桶bucket[i]是一个容器,比如array,或者vector什么的。

2.3 基数排序

改进的计数排序,改进点是我一位一位地比较,这里的位表示个位、十位、百位,当然是先低位比较再高位比较,这样最后结果才是高位优先嘛。所以这里的桶只要10个,存储0~9就好啦,比较完一次之后覆盖原数组进行比较下一位。

实现

源码戳这里

十大经典排序算法小结(附源码和菜鸟版注释)相关推荐

  1. 按复杂度有效性递减排序_十大经典排序算法:python源码实现,通俗深入讲解

    概述 提示:本文上万字,陆陆续续疏理知识点加测试代码,耗时近一个月.阅读时长40分钟左右. 本文将十大经典排序算法进行汇总,从源码实现.复杂度.稳定性进行分析,并对每种排序的特性进行点评.对典型算法, ...

  2. 终于,把十大经典排序算法汇总了!(Java实现版)

    转载自  终于,把十大经典排序算法汇总了!(Java实现版) 最近几天在研究排序算法,看了很多博客,发现网上有的文章中对排序算法解释的并不是很透彻,而且有很多代码都是错误的,例如有的文章中在" ...

  3. 十大经典排序算法(附代码、动画及改进方案)

    前言说明 十大排序算法可以说是每个程序员最早接触的也是最重要的算法,这一块必须要非常熟练的掌握,应该要理解每种排序的思想,对各个排序的性能的了解也是基础且重要的.为了方便自己和大家学习,决定整合成一篇 ...

  4. 一文读懂Python版的十大经典排序算法(附动图演示)

    来源:大数据DT 本文约5200字,建议阅读10分钟 排序算法是<数据结构与算法>中最基本的算法之一.本文介绍10种常见的内部排序算法,及如何用Python实现. 排序算法可以分为内部排序 ...

  5. 利用Python实现十大经典排序算法(附代码流程)

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 作者:hustcc 来源:https://github.com/hustcc/JS ...

  6. 【完整可运行源码+GIF动画演示】十大经典排序算法系列——冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序

    以前也零零碎碎发过一些排序算法,但总是不系统, 这次彻底的对排序系列做了一个整体的规划, 小伙伴们快快mark哦~ [GIF动画+完整可运行源代码]C++实现 冒泡排序--十大经典排序算法之一 [GI ...

  7. 11月14日云栖精选夜读 | 动画+原理+代码,解读十大经典排序算法

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

  8. 十大经典排序算法详解(一)冒泡排序,选择排序,插入排序

    养成习惯,先赞后看!!! 你的点赞与关注真的对我非常有帮助.如果可以的话,动动手指,一键三连吧!!! 目录 1.算法的评判标准 2.排序算法的分类 3.十大经典排序算法-冒泡排序,选择排序,插入排序 ...

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

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

最新文章

  1. C++ 随机数生成的2种方法--生成指定范围内的随机数
  2. php实现java socket_php与java通过socket通信的实现代码
  3. Salted Password Hashing
  4. 前端学习(1318):同步api和异步api
  5. 成功解决 ProxyError: Conda cannot proceed due to an error in your proxy configuration
  6. 希望得到学术会议的及时回复该怎么说_张烨:在“选矿”博士的世界里,脚踏实地从来都不是说说而已!| 中南达人NO.188...
  7. win下anaconda装python2.7和3.5以及jupyter共存 (本篇实践通过)
  8. Google是否投资你,得看AI支持不支持
  9. python中冒号的语法错误_找不出python的语法错误该如何解决?
  10. 邮件服务器备案,关于企业邮箱域名备案事项通知
  11. 优缺点 快速扫描 硬盘监测_用硬盘检测工具检测硬盘超实用的技巧!
  12. 单词发音,为语音识别准备素材
  13. JeePlus:代码生成器
  14. 【随机过程】【研究生考试专用】备考笔记/知识点整理
  15. 视频伪原创工具 剪辑过的视频md5会改变吗
  16. kafak集群python外网无法访问:kafka.errors.NoBrokersAvailable: NoBrokersAvailable
  17. web前端-前端三剑客之CSS(1)
  18. 矩池云 | Tony老师解读Kaggle Twitter情感分析案例
  19. 百度每个月的收录时间
  20. 旺季即将来临,亚马逊促销码设置出现的坑和应对方法值得你看!

热门文章

  1. ASCII对照表 维基百科,自由的百科全书。
  2. ios emjoi java_前端App开发,实际工作中三端(android,ios,前端H5)emoji表情显示解决方案...
  3. Java设计模式【之】工厂方法模式【场景:制作咖啡】
  4. 双绞线、同轴电缆、光纤
  5. Blender图解教程:新手练习-Lowpoly人物模型
  6. 视频教程-Unity快速入门系列课程(第1部)-Unity3D
  7. 人口流向数据_中国人口流入流出前二十的城市(2019)
  8. 关于内网用户申银万国无法登陆问题解决
  9. 开一家鞋店,就这么简单
  10. java计算机毕业设计鞋店销售管理源程序+mysql+系统+lw文档+远程调试