Python实现十大常用排序算法
Python实现十大常用排序算法
一、冒泡排序
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的元素列,依次比较两个相邻的元素,一层一层的将较大的元素往后移动,其现象和气泡在上升过程中慢慢变大类似,故成为冒泡排序。
1.过程图解
2.算法思想
从第一个和第二个开始比较,如果第一个比第二个大,则交换位置,然后比较第二个和第三个,逐渐往后
经过第一轮后最大的元素已经排在最后,所以重复上述操作的话第二大的则会排在倒数第二的位置。
那重复上述操作n-1次即可完成排序,因为最后一次只有一个元素所以不需要比较
3.代码实现
#冒泡排序
arr = [1,23,3,36,4,5,1.5]
#第一层for表示循环的遍数
for i in range(len(arr) - 1 ):
#第二层for表示具体比较哪两个元素
for j in range(len(arr) -1 ):
if arr[j] > arr[j+1]:
arr[j],arr[j+1] = arr[j+1],arr[j]
print(arr) #[1, 1.5, 3, 4, 5, 23, 36]
4.算法分析**
冒泡排序是一种简单直接暴力的排序算法,为什么说它暴力?因为每一轮比较可能多个元素移动位置,而元素位置的互换是需要消耗资源的,所以这是一种偏慢的排序算法,仅适用于对于含有较少元素的数列进行排序。
稳定性:我们从代码中可以看出只有前一个元素大于后一个元素才可能交换位置,所以相同元素的相对顺序不可能改变,所以它是稳定排序
比较性:因为排序时元素之间需要比较,所以是比较排序
时间复杂度:因为它需要双层循环n*(n-1)),所以平均时间复杂度为O(n^2)
空间复杂度:只需要常数个辅助单元,所以空间复杂度为O(1),我们把空间复杂度为O(1)的排序成为原地排序(in-place)
记忆方法:想象成气泡,一层一层的往上变大
二、选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,所以称为:选择排序
1.过程图解
2.算法思想
设第一个元素为比较元素,依次和后面的元素比较,比较完所有元素找到最小的元素,将它和第一个元素互换
重复上述操作,我们找出第二小的元素和第二个位置的元素互换,以此类推找出剩余最小元素将它换到前面,即完成排序
3.代码实现
#选择排序
for i in range(len(arr) -1 ):
#将起始元素设为最小元素
min_index = i
#第二层for循环表示最小原色和后面的元素逐个比较
for j in range(i+1 ,len(arr)):
if arr[j] < arr[min_index]:
min_index = j
arr[min_index],arr[i] = arr[i],arr[min_index]
print(arr)
4.算法分析**
选择排序和冒泡排序很类似,但是选择排序每轮比较只会有一次交换,而冒泡排序会有多次交换,交换次数比冒泡排序少,就减少cpu的消耗,所以在数据量小的时候可以用选择排序,实际适用的场合非常少。
比较性:因为排序时元素之间需要比较,所以是比较排序
稳定性:因为存在任意位置的两个元素交换,比如[5, 8, 5, 2],第一个5会和2交换位置,所以改变了两个5原来的相对顺序,所以为不稳定排序。
时间复杂度:我们看到选择排序同样是双层循环n*(n-1)),所以时间复杂度也为:O(n^2)
空间复杂度:只需要常数个辅助单元,所以空间复杂度也为O(1)
记忆方法:选择对象要先选最小的,因为嫩,哈哈
三、插入排序
插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
1.过程图解
2.算法思想
从第二个元素开始和前面的元素进行比较,如果前面的元素比当前元素大,则将前面元素 后移,当前元素依次往前,直到找到比它小或等于它的元素插入在其后面
然后选择第三个元素,重复上述操作,进行插入
依次选择到最后一个元素,插入后即完成所有排序
3.代码实现
4.算法分析
插入排序的适用场景:一个新元素需要插入到一组已经是有序的数组中,或者是一组基本有序的数组排序。
比较性:排序时元素之间需要比较,所以为比较排序
稳定性:从代码我们可以看出只有比较元素大于当前元素,比较元素才会往后移动,所以相同元素是不会改变相对顺序
时间复杂度:插入排序同样需要两次循坏一个一个比较,故时间复杂度也为O(n^2)
空间复杂度:只需要常数个辅助单元,所以空间复杂度也为O(1)
记忆方法:想象成在书架中插书:先找到相应位置,将后面的书往后推,再将书插入
四、希尔排序
希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本,它与插入排序的不同之处在于,它会优先比较距离较远的元素,该方法因D.L.Shell于1959年提出而得名。
1.过程图解
2.算法思想
希尔排序的整体思想是将固定间隔的几个元素之间排序,然后再缩小这个间隔。这样到最后数列就成为了基本有序数列,而前面我们讲过插入排序对基本有序数列排序效果较好。
计算一个增量(间隔)值
对元素进行增量元素进行比较,比如增量值为7,那么就对0,7,14,21…个元素进行插入排序
然后对1,8,15…进行排序,依次递增进行排序
所有元素排序完后,缩小增量比如为3,然后又重复上述第2,3步
最后缩小增量至1时,数列已经基本有序,最后一遍普通插入即可
已知的最增量式是由 Sedgewick 提出的 (1, 5, 19, 41, 109,…),该步长的项来自 9 4^i - 9 2^i + 1 和 4^i - 3 2^i + 1 这两个算式。这项研究也表明 “比较在希尔排序中是最主要的操作,而不是交换。 用这样增量式的希尔排序比插入排序和堆排序都要快,甚至在小数组中比快速排序还快,但是在涉及大量数据时希尔排序还是比*快速排序慢。
3.代码实现
4.算法分析
比较性:排序时元素之间需要比较,所以为比较排序
稳定性:因为希尔排序是间隔的插入,所以存在相同元素相对顺序被打乱,所以是不稳定排序
时间复杂度: 最坏时间复杂度O(n2)平均复杂度为O(n1.3)
空间复杂度:只需要常数个辅助单元,所以空间复杂度也为O(1)
记忆方法:插入排序是每轮都是一小步,希尔排序是先大步后小步,它第一个突破O(n2)的排序算法。联想起阿姆斯特朗登月之后说:这是我个人一小步,却是人类迈出的一大步。
五、归并排序
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序适用于子序列有序的数据排序。
1.过程图解
2.算法思想
归并排序是分治法的典型应用。分治法(Divide-and-Conquer):将原问题划分成 n 个规模较小而结构与原问题相似的子问题;递归地解决这些问题,然后再合并其结果,就得到原问题的解。从上图看分解后的数列很像一个二叉树。
使用递归将源数列使用二分法分成多个子列
申请空间将两个子列排序合并然后返回
将所有子列一步一步合并最后完成排序
3.代码实现
4.算法分析
比较性:排序时元素之间需要比较,所以为比较排序
稳定性:我们从代码中可以看到当左边的元素小于等于右边的元素就把左边的排前面,而原本左边的就是在前面,所以相同元素的相对顺序不变,故为稳定排序
时间复杂度: 复杂度为O(nlog^n)
空间复杂度:在合并子列时需要申请临时空间,而且空间大小随数列的大小而变化,所以空间复杂度为O(n)
记忆方法:所谓归并肯定是要先分解,再合并
总结
今天给大家介绍的五种排序是比较简单的排序,建议大家自己动手敲几遍代码,书读百遍,其义自现。要求大家必须理解&记住它们的算法原理,因为代码是永远记不住的,只要记住原理你就能用伪代码实现。返回搜狐,查看更多
六、快速排序
def quick_sort(b):
"""快速排序"""
if len(b) < 2:
return arr
# 选取基准,随便选哪个都可以,选中间的便于理解
mid = arr[len(b) // 2]
# 定义基准值左右两个数列
left, right = [], []
# 从原始数组中移除基准值
b.remove(mid)
for item in b:
# 大于基准值放右边
if item >= mid:
right.append(item)
else:
# 小于基准值放左边
left.append(item)
# 使用迭代进行比较
return quick_sort(left) + [mid] + quick_sort(right)