排序算法总结: 1.桶排序 2.选择排序 3.冒泡排序 4.插入排序 5.归并排序 6.希尔排序 7.快速排序 8.基数排序 9.堆排序

排序算法的稳定性通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj,Ai原来在位置前,排序后Ai还是要在Aj位置前。

1.桶排序


按照顺序遍历桶中的每个元素,依次放到数组中,即可完成数组的排序。

"桶"是一种容器,这个容器可以用多种数据结构实现,包括数组、队列或者栈。

(下题原为leetcode题,但此处只为练习简单的桶排序,更改了条件整数数组 nums–>正整数数组 nums)

前 K 个高频元素
给你一个*正整数数组 nums* 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:输入: nums = [1], k = 1
输出: [1]提示:1 <= nums.length <= 10^5
k 的取值范围是 [1, 数组中不相同的元素的个数]
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

桶排序解答
Python

 bucketN=max(nums)+1 #准备nums中最大数值加一个桶buckets=[0]*bucketN #初始化所有桶的频次为0for i in nums:buckets[i]+=1 #nums中每个数对应桶的序号,桶中的值记载此数出现的频次result=sorted(enumerate(buckets),key=lambda X:X[1],reverse=True) #按照lambda X:X[1]排序,即按照桶中数值(数在nums中出现频次排序),且排序由小到大ans=[]for j in range(k):ans.append(result[j][0]) #输出前K个高频元素return ans

2.选择排序

基本思想:每一趟从待排序的数据元素中选择最小(或最大)的一个元素作为首元素,直到所有元素排完为止。

稳定性

选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n - 1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。

Python

#正宗选择排序
nums=[35,80,21,54,11,45,92,39]
n=len(nums)
for i in range(n-1):mid=i  #记录下此时未排序的首位置for j in range(i+1,n):if nums[j]<nums[mid]:mid=j  #如果在未排序的部分找到比首位置要小的部分,记录下其位置nums[i],nums[mid]=nums[mid],nums[i] #首位置的值和未排序的部分最小值交换
print(nums)#稍微修改了一下的选择排序,但是这种情况下交换的次数更多了,
nums=[35,80,21,54,11,45,92,39]
n=len(nums)
for i in range(n-1):for j in range(i+1,n):if nums[j]<nums[i]:nums[i],nums[j]=nums[j],nums[i] #遇到未排序的部分有比首位置更小的值,就直接交换
print(nums)

out: [11, 21, 35, 39, 45, 54, 80, 92]

3.冒泡排序

比较相邻的元素。如果第一个比第二个大,就交换他们两个。对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。针对所有的元素重复以上的步骤,除了最后一个。

稳定性

冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

Python

nums=[19,80,77,14,54]
n=len(nums)
for i in range(n-1):for j in range(1,n-i): #取到n-i,因为经过i次循环,后面i个数已经排好了顺序if nums[j-1]>nums[j]:nums[j-1],nums[j]=nums[j],nums[j-1]  #只要遇到左边的数大于右边,swap两数,这样一次j循环就能把最大的数送到数组末尾(未排序的部分)print(nums)

out:[14, 19, 54, 77, 80]

4.插入排序

只需要关注待排序部分的第一个元素,找出要把它插入已排序部分的哪个位置就好

稳定性

插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

Python

nums=[77,19,80,79,20,11]
n=len(nums)for i in range(n): #控制每个需要往前面已经排好序的i个数中插入的第i+1(序号为i)的数for j in range(i,0,-1): #内层循环实现把第i+1(序号为i)的数插入符合它排序的位置if nums[j-1]>nums[j]:nums[j-1],nums[j]=nums[j],nums[j-1]  #只要遇到左边的数大于右边,swap两数,通过和冒泡排序相似的方式”插入nums[i]“print(nums)

out:[11, 19, 20, 77, 79, 80]

5.归并排序

归并指的是把几个已排序的数据列合并成一个已排序的数据列的算法

只有几个数据列都是升序排序的时候,所有数据中的最小值才一定在各个数据列的起始元素中,当起始元素被取值后,第二个元素就会被设为起始元素,所以剩下的所有数据中的最小值一直都在各个数据列的起始元素中

稳定性

归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法


归并排序指利用分割和归并进行排序的排序算法,主要由分割和归并两个步骤组成

6.希尔排序

把数据以一定的间隔进行分组,并且对每个组进行排序的排序算法。
通过一定间隔的分组、排序后,大量的小数往前移动,大数往后移动,因此最后数据交换次数变少

稳定性

希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小, 插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比O(n^2)好一些。由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

7.快速排序

对大量数据进行高速排序操作时,快速排序是最常用的算法,首先从数据列中任意选取一个数据P作为基准值,接着,把比P小的值和比P大的值分离出来,得到新的数据列,这样P在最终排序好的数组中位置就确定了。
这个P的位置确定过程如下:
假设需要对 6 1 2 7 9 3 4 5 10 8 这10个数进行排序,首先需要在序列中找一个数作为基准数,假设找第一个6作为基准数,现在的目标是把所有大于基准数6的放到它的右边、所有小于基准数6的放到它的左边。设置变量 i 指向序列最左边、j 指向序列最右边,也即 i 指向数字6,j 指向数字8,首先需要让 j 先出动,j - -, 直到找到一个小于6的数停下来;然后 i++ ,直到找到一个大于6的数停下来,二者交换所指向数。重复这个过程,直到 i 和 j 相遇,把 i 和 j 相遇位置的值和基准数调换,最后得到 3 1 2 5 4 6 9 7 10 8

为什么要让 j 先出动?让 i 先出动不行嘛?
因为 j 的任务是找到比基准数小的值,若 j 先行,则可以保证 i 与 j 相遇的位置小于等于基准数(如果相遇时是 j 在走,相遇在 i 上一轮交换完指向的值,那么这个值小于等于基准值;如果相遇时是 i 在走,相遇时的值不能保证小于等于基准值)
之所有要有 i 与 j 相遇的位置小于等于基准数这个保障,是因为 i 与 j 相遇的位置的值需要和基准数做交换。

稳定性:

在基准元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为5 3 3 4 3 8 9 10 11,现在基准元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在基准元素和a[j] 交换的时刻。

参考:
【1】稳定排序和不稳定排序

提醒:(多图预警)
1.本文中拍摄的图片来源于书籍:
《写给大家看的算法书》 【日】杉浦贤 著;绝云 译
2.本文中排序算法默认升序

排序算法的总结 排序算法及其稳定性相关推荐

  1. 排序算法 | 直接选择排序,算法的图解、实现、复杂度和稳定性分析

    排序算法 | 直接选择排序,算法的图解.实现.复杂度和稳定性分析 目录 1.直接选择排序的原理 2.图解直接选择排序 3.算法代码实现 4.算法复杂度分析.稳定性分析 直接选择排序 1.直接选择排序的 ...

  2. 【数据结构、算法】八大排序算法概述(算法复杂度、稳定性)

    前言   排序是计算机程序设计中一个非常重要的操作,它将一个数据元素(或记录)的任意序列重新排列成一个按关键字有序的序列.在有序的序列中查找元素的效率很高,(例如,折半查找法的平均查找长度为log2( ...

  3. 排序算法 | 希尔shell排序,算法的图解、实现、复杂度和稳定性分析

    希尔shell排序 1.希尔排序--定义 2.希尔排序--步骤描述 3.希尔排序--算法实现 4.希尔排序--复杂度.稳定性分析 1.希尔排序--定义 希尔排序按其设计者希尔(Donald Shell ...

  4. 【算法】计数排序 + 各个排序算法的稳定性

    之前介绍的排序算法: [算法]插入排序--希尔排序+直接插入排序_Rinne's blog-CSDN博客 [算法]选择排序--堆排序+直接选择排序_Rinne's blog-CSDN博客 [算法]交换 ...

  5. 伍六七带你学算法 进阶篇-排序算法

    给定一个整数数组 nums,将该数组升序排列. 示例 1: 输入:[5,2,3,1] 输出:[1,2,3,5] 示例 2: 输入:[5,1,1,2,0,0] 输出:[0,0,1,1,2,5] 各排序算 ...

  6. 算法导论——计数排序

    2019独角兽企业重金招聘Python工程师标准>>> /*** 计数排序* * 不用比较的排序算法,时间可以突破O(NlgN)* * 时间复杂度O(N),稳定* * 适用于所有需要 ...

  7. 我的Java开发学习之旅------gt;Java经典排序算法之希尔排序

    一.希尔排序(Shell Sort) 希尔排序(Shell Sort)是一种插入排序算法,因D.L.Shell于1959年提出而得名. Shell排序又称作缩小增量排序. 二.希尔排序的基本思想 希尔 ...

  8. 我的Java开发学习之旅------Java经典排序算法之希尔排序

    一.希尔排序(Shell Sort) 希尔排序(Shell Sort)是一种插入排序算法,因D.L.Shell于1959年提出而得名. Shell排序又称作缩小增量排序. 二.希尔排序的基本思想 希尔 ...

  9. ef 排序string转int_排序算法之基本排序算法

    基本排序算法 选择排序 选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未 ...

最新文章

  1. jquery 插件
  2. 为什么要强制弃坑Fastjson而主推Jackson?
  3. 第二章--电商项目DB规划
  4. mysql如何增加分区maxvalue_oracle range分区表已经有了MAXVALUE 分区,如何添加分区?要不能删除MAXVALUE分区里的数据,不影响在线应用。...
  5. Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
  6. 《社交网站界面设计(原书第2版)》——1.12 传感器在交互中的作用
  7. FileUtils类 使用举例
  8. 映射文件实现进程通信
  9. 【项目实战】Python基于决策树多分类模型实现水色图像的水质评价
  10. 基于深度学习的商品检索技术
  11. 语音通知事件提醒功能实现流程
  12. 独孤求败--之--InnoDB、MyISAM索引实现过程
  13. html 大转盘游戏,HTML5 Canvas大转盘抽奖活动页面代码
  14. Java顺序表 实现扑克牌游戏简单 (梭哈 / 斗牛)
  15. 海洋cms解析接口最新
  16. 使用 Packer 自动执行 VMware vsphere 模板
  17. 《 Android物联网开发从入门到实战》
  18. PermissionError: [Errno 13] Permission denied:‘xxx.csv‘
  19. 一般梯度、随机梯度、相对梯度和自然梯度
  20. WZOI-293表演

热门文章

  1. (轉貼) 未來台北捷運路線圖 (News)
  2. Linux下bcm43142a0蓝牙无法正常搜索设备的解决办法
  3. Spring通过工厂创建对象的三种方法详解(工厂设计模式)
  4. 无锡会计培训——初级会计考试难吗?
  5. word如何一次性修改中英文及数字为不同字体
  6. linux 内核ioctl,Linux ioctl与内核交换数据
  7. PX4FLOW光流模块DIY(含部分代码讲解)
  8. 【计算机网络学习笔记(一)】之 OSI参考模型,网络传输方式分类,网络设备分类,网络组成结构
  9. JavaScript动画上下、左右、对角移动
  10. 博客项目搭建(码神之路)