1. 冒泡排序

  冒泡排序(Bubble Sort)是稳定排序,其基本思想是:遍历待排序列,依次两两比较,如果顺序错误就交换。如果从头开始遍历,把较大的交换到后面,结果就是越大的数据越往下沉,所以也可以称为“下沉排序”;如果从尾开始向前遍历,把较小的交换到前面,结果就是越小的数据越往上浮,这就是“冒泡排序”名称的由来。冒泡排序比较简单,python实现如下:

  1. def bubble_sort(array):
  2. length = len(array)
  3. for i in range(0, length): # 这轮遍历只是表示整个排序最大需要几轮
  4. j = length - 1 # 这个例子从后开始遍历,演示的是“上浮冒泡排序”
  5. while j >= i: # 每轮遍历只需要剩下的比较未排序的序列,前i个元素已经有序了(也就是说整个序列下标小于i的元素都已经有序)
  6. if array[j] < array[j-1]:
  7. array[j-1], array[j] = array[j], array[j-1]
  8. j -= 1

上面的例子是不管待排序列本身是否有序,全部遍历。而实际上待排序列可能本身就已经有序(或部分有序),这样在遍历并比较的过程中就不会交换数据。也就是说如果在某一轮的遍历过程中没有交换数据,就说明整个序列已经有序了。所以上面的代码还可以略做优化:

  1. def optimized_bubble_sort(array):
  2. length = len(array)
  3. has_switched = True # 是否有数据交换
  4. for i in range(0, length): # 这轮遍历只是表示整个排序最大需要几轮
  5. # 没有数据交换,说明序列有序,退出循环,完成排序
  6. if has_switched is False:
  7. break
  8. has_switched = False # 每轮比较,初始假设没有数据交换
  9. j = length - 1 # 这个例子从后开始遍历,演示的是“上浮冒泡排序”
  10. while j >= i: # 每轮遍历只需要剩下的比较未排序的序列,前i个元素已经有序了(也就是说整个序列下标小于i的元素都已经有序)
  11. if array[j] < array[j-1]:
  12. array[j-1], array[j] = array[j], array[j-1]
  13. has_switched = True # 有数据交换
  14. j -= 1

2. 选择排序

  选择排序(Selection Sort)是不稳定排序,它的过程为:从整个序列中找出最小的元素和第一个元素交换,然后再从剩下的序列中找出最小的和第二个元素交换...,共需重复待排序列的长度减一的次数,最终得到一个有序序列。Python实现如下:

  1. def simple_selection_sort(array):
  2. length = len(array) # 获取最后一个元素的下标
  3. # 需要遍历 len(array) - 1 次。因为前面的都排好序后,最后只剩一个元素,
  4. # 而且最后的这个元素是前面比较替换之后确定的一个元素,自然是有序的
  5. for i in range(length-1):
  6. index_min_value = i # index_min_value 为最小元素对应的下标,假设下标为i的元素最小
  7. # 从剩下的元素里面找出最小的
  8. for j in range(i+1, length):
  9. if array[j] < array[index_min_value]:
  10. index_min_value = j
  11. # 如果第i个元素不是最小的,将最小元素与第i个元素交换位置
  12. if index_min_value != i:
  13. array[i], array[index_min_value] = array[index_min_value], array[i]

3. 插入排序

  插入排序(Insertion Sort)是稳定排序,它的基本操作是将一条记录插入到已经排好序的有序序列中,从而得到一个新的、记录数增1的有序序列。具体实现为:从待排序列的第二个元素开始,将当前元素抽出来插入到前面的有序序列中。第一步抽出第2个元素(它的前面就只有一个元素,可以看做是只包含一个元素的有序序列),然后将这第2个元素插入到前面的有序序列中,得到一个有两个元素的有序序列。第二步抽出第3个元素,重复第一步的操作。最后就得到一个完整的有序序列。

  1. def insertion_sort(array):
  2. # i 从第2个元素开始
  3. for i in range(1, len(array)):
  4. # 第i个元素之前的序列是有序序列,这里将第i个元素插入到之前的有序序列中
  5. # 插入第i个元素完成后的有序序列长度会多一个,这里先将第i个元素暂存起来,空出位置
  6. temp_value = array[i]
  7. # 第i个位置已经是空位了,从第i-1个元素逆向遍历,将 temp_value 插入到合适的位置
  8. j = i
  9. while j > 0 and array[j-1] > temp_value:
  10. array[j] = array[j-1] # 就是将第j-1个元素后移一个位置
  11. j -= 1
  12. # 最后第j个位置就是 temp_value 需要插入的位置
  13. array[j] = temp_value

4. 归并排序

  归并排序(Merge Sort)是稳定排序。归并排序采用D&C(分治,divide and conquer)策略,首先将待排序列分解成有序序列(空序列或只包含一个元素的序列可以看做是有序序列),再讲每个有序序列归并,最终得到一个完整的有序序列。

  1. def merge_sort(array):
  2. if len(array) <= 1: # 基线条件,此时的序列就是有序序列,分解的停止条件
  3. return array
  4. # 分解待排序列
  5. mid = len(array) // 2
  6. left = merge_sort(array[:mid]) # 递归调用自身,直到子序列有序,即达到上面的基线条件
  7. right = merge_sort(array[mid:])
  8. # 合并有序的子序列
  9. return merge(left, right)
  10. def merge(left, right):
  11. """
  12. 合并left、right,left和right均为有序序列
  13. """
  14. result = [] # 结果集
  15. left_pointer = 0 # 指向left的指针,初始指向left的第一个元素
  16. right_pointer = 0 # 指向right的指针,初始指向right的第一个元素
  17. # 从left的第一个元素和right的第一个元素开始对比,
  18. # 哪边的元素较小则将哪边的元素放入result,并将较小元素的指针往后移一位
  19. while left_pointer < len(left) and right_pointer < len(right):
  20. if left[left_pointer] < right[right_pointer]:
  21. result.append(left[left_pointer])
  22. left_pointer += 1
  23. else:
  24. result.append(right[right_pointer])
  25. right_pointer += 1
  26. if left_pointer == len(left):
  27. # 左边的指针已经指向left的最后一个元素,说明左边的元素已经全部添加到result了,直接把右边剩下的依次追加到result
  28. for i in right[right_pointer:]:
  29. result.append(i)
  30. else:
  31. # 否则就是右边的元素已经全部添加到result了,直接把左边剩下的依次追加到result
  32. for i in left[left_pointer:]:
  33. result.append(i)
  34. return result

5. 快速排序

  快速排序(Quick Sort)是不稳定排序。快速排序也采用了D&C策略,首先选取一个基准值,然后通过一次遍历将待排序列分成三部分(这被称为分区,partitioning):所有元素都小于或者等于基准值的一个序列less_array、基准值、所有元素都大于基准值的一个序列grater_array。这个时候对整个序列排序就很容易了:less_array + 基准值 + grater_array,对于less_array和grater_array再分别采用递归的方式进行快速排序,最后得到整个待排序列的一个有序序列。

  1. def quick_sort(array):
  2. if len(array) < 2: # 退出递归的基线条件
  3. return array
  4. pivot = array[0] # 基准值,可随便选取
  5. # 分区
  6. less_array = [i for i in array[1:] if i <= pivot]
  7. grater_array = [j for j in array[1:] if j > pivot]
  8. # 采用一次遍历分区的方法,偶尔会报错:RecursionError: maximum recursion depth exceeded while calling a Python object
  9. # less_array, grater_array = [], []
  10. # for num in array:
  11. # if num <= pivot:
  12. # less_array.append(num)
  13. # else:
  14. # grater_array.append(num)
  15. return quick_sort(less_array) + [pivot] + quick_sort(grater_array)

排序算法整理(Python实现)的更多相关文章

  1. 常用排序算法的python实现和性能分析

    常用排序算法的python实现和性能分析 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试 ...

  2. 八大排序算法的 Python 实现

    转载: 八大排序算法的 Python 实现 本文用Python实现了插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个 ...

  3. (排序算法整理)NEFU 30/32

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/caihongshijie6/article/details/26165093        事实上, ...

  4. 十大经典排序算法总结 (Python)

    作业部落:https://www.zybuluo.com/listenviolet/note/1399285 以上链接是自己在作业部落编辑的排序算法总结- Github: https://github ...

  5. 一些排序算法的Python实现

    ''' Created on 2016/12/16 Created by freeol.cn 一些排序算法的Python实现 @author: 拽拽绅士 ''' '''值交换''' def swap( ...

  6. 排序算法整理C++(初赛)

    排序算法整理 常见考点 将一个乱掉的字符串排回有序(以交换为基本操作)的最少操作,就是冒泡排序. 排序算法的稳定性 排序算法的时间复杂度 排序算法的稳定性 稳定性是指排序前两个元素a1 = a2,a1 ...

  7. 常见排序算法整理(python实现 持续更新)

    1 快速排序 快速排序是对冒泡排序的一种改进.  它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行 ...

  8. 【Python】常用排序算法的python实现和性能分析

    作者:waterxi 原文链接 背景 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试题整 ...

  9. 面试中常用排序算法的python实现和性能分析

    这篇是关于排序的,把常见的排序算法和面试中经常提到的一些问题整理了一下.这里面大概有3个需要提到的问题: 虽然专业是数学,但是自己还是比较讨厌繁琐的公式,所以基本上文章所有的逻辑,我都尽可能的用大白话 ...

  10. 基本排序算法的Python实现

    本篇主要实现九(八)大排序算法,分别是冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序,计数排序.希望大家回顾知识的时候也能从我的这篇文章得到帮助. 为了防止误导读者,本文所有概念性 ...

随机推荐

  1. Teradata 数据库

    笔者大学所学计算机专业,读书时接触过Oracle.mysql和SQL SERVER,一度坐井观天觉得数据库应该也就这些了,但自笔者毕业进入数据仓库这个行业,接触的第一个商业数据库即是Teradata, ...

  2. ppt和pptx转图片完整代码,解决2003版和2007版中文乱码问题

    引入所需依赖,注意poi版本,新版本不支持,最好使用和我一样的版本. <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --& ...

  3. Codeforces 1340B Nastya and Scoreboard(dp,贪心)

    题目链接OvO 题目大意   给你\(n\)串数字,\(1\)代表该位置是亮的,\(0\)代表是灭的.你必须修改\(k\)个数字,使某些\(0\)变为\(1\).注意,只能把原来的\(0\)改成\(1 ...

  4. Spring Cloud 系列之 Sleuth 链路追踪(三)

    本篇文章为系列文章,未读前几集的同学请猛戳这里: Spring Cloud 系列之 Sleuth 链路追踪(一) Spring Cloud 系列之 Sleuth 链路追踪(二) 本篇文章讲解 Sleu ...

  5. php 全局变量和超全局变量

    global 全局变量(在当前页面全部地方有效) $GLOBALS['name'] 超全局变量(在整个网站全部地方有效) 一个包含了全部变量的全局组合数组.变量的名字就是数组的键.还有_GET,_PO ...

  6. centos 服务器上部署 xxl-job 通过 feign 访问 eureka 上注册的 service timeout

    部署方式 1.使用 jar 包部署 出现的问题 1.通过 feign 调用其他服务,出现超时的问题,该问题不是 ribbon.hystrix 没有配置导致的超时,经过测试,即使配置了也没有作用,该方法 ...

  7. Hexo博客插入图片的方法

    Hexo博客插入图片的方法 hexo图片blog hexo blog 插入图片的方法总结 hexo 的blog 内容是根据 markdown 文件的内容生成的html文件, 生成的文件全部在 /pub ...

  8. vue2.x学习笔记(三十二)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12684060.html. 深入响应式原理 vue最独特的特性之一,是其非侵入式(耦合度低)的响应式系统:数据模型仅 ...

  9. Redis介绍及字符串操作

    一.前言 不同程序之间实现通信的方法? A.通过不同程序之间建立socket,实现通信.实际应用适用于使用broker,如RabbitMQ,ZeroMQ. B.通过Json,Pickle,利用文件的写 ...

  10. 15个 MySQL 基础面试题,DBA 们准备好了吗?

    此前我们已经有发表过Linux 面试基础问答之一.二和三共3篇文章,获得读者的好评,同时我们得到反馈,有些读者希望这种交互式学习方法能够做得更加灵活.心动不如行动,我们这就为您奉上 15个 MySQL ...