欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > python >内容正文

python

python programming training(二): 排序算法

发布时间:2025/4/5 python 54 豆豆
生活随笔 收集整理的这篇文章主要介绍了 python programming training(二): 排序算法 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

目录

1. 冒泡排序(Bubble Sort)

2. 快速排序(Quick Sort)

参考:


github:https://github.com/yuyongsheng1990/python_training/tree/master/training_002_Ranking_Algorithms

联系:冒泡排序和快速排序都属于交换排序,就是利用交换数据元素的位置进行排序的方法

区别:冒泡排序一次只能消除一个逆序,而快速排序能一次消除多个逆序。

1. 冒泡排序(Bubble Sort)

  • 时间复杂度: -->意味着双层循环
  • 空间复杂度:O(1)
  • 核心双层循环 + 两两比较
  • 特点:冒泡排序,最大的元素会优先排到顶端

两两比较,若list[j]>list[j+1],则交换,否则继续 

-->这意味着包含n个元素的序列中任意一个元素都要和剩余的n-1个元素进行一次比较,即

-->因为这是顺序比较,list[j]和list[j+1],所以1st: n-1; 2ed: n-1,即

-->优化:因为每次冒泡排序,都是先排最大的元素,其次是第二大元素,也就是说,第一轮后,最大的元素排到最后,后面也不用再参与比较了,以此类推,第二轮后,第二大元素也不用再参与比较了,需要比较的次数:(n-1)+(n-2)+(n-3)+...+1,即n(n-1)/2。

这反映到编程中,即i代表冒泡排序轮数,j表示指针索引,j in range(0, len(list) - i)。

# 冒泡排序函数,两层循环 + 两两比较 def BubbleSort(list):# i控制冒泡轮数for i in range(0, len(list)-1):# 因为第一轮,最大的元素通过两两比较排到最后,第二轮,第二大的元素排到倒数第二的位置,# 所以,第一轮后最后一个元素不用再参与比较了,第二轮后,倒数第二个元素不用再参与比较了,j只需要比较到len(list)-i的索引位置就行了for j in range(0, len(list) - i - 1):if list[j] > list[j+1]:list[j], list[j+1] = list[j+1], list[j]# 如果为方便好看的话,i和j化简 def BubbleSort_Simplify(list):# i控制冒泡轮数for i in range(1, len(list)):# 因为第一轮,最大的元素通过两两比较排到最后,第二轮,第二大的元素排到倒数第二的位置,# 所以,第一轮后最后一个元素不用再参与比较了,第二轮后,倒数第二个元素不用再参与比较了,j只需要比较到len(list)-i的索引位置就行了for j in range(0, len(list) - i):if list[j] > list[j+1]:list[j], list[j+1] = list[j+1], list[j]if __name__ == "__main__":# num_list = [12, 9, 12, 23, 93, 88, 45, 60]num_list = [9, 8, 7, 6, 5, 4, 3, 3, 1]BubbleSort_Simplify(num_list)print num_list

2. 快速排序(Quick Sort)

  • 时间复杂度: -->n意味着一层循环​​​​​​​
  • 空间复杂度:
  • 核心基准。通常取第一个元素作为基准,temp;分而治之(Divide and  Conquer)策略把一个序列(list)分为两个子序列(sub-lists),称为partition递归,接下来对左子序列和右子序列分别重复上述步骤,知道快排结束。

最开始学习编程,遇到排序问题,一般都是用冒泡法,因为冒泡法好理解,代码量少。但是这种算法时间复杂度高,当需要排序的元素较多时,程序运行时间很长,因此产生了快速排序算法。该算法的实现可分为以下几步:

1. 在数组中选一个基准数(通常为数组第一个);

2. 将数组中小于基准数的数据移到基准数左边,大于基准数的移到右边;

3. 对于基准数左、右两边的数组,不断重复以上两个过程,直到每个子集只有一个元素,即为全部有序。

例如有一需要排序的数组为:23,45,17,11,13,89,72,26,3,17,11,13(从小到大排序):

选取数组第一个数23为基准数,存入temp变量中,从数组的左右两边界向中间进行遍历,定义两个指针 i 和 j,i 最开始指向数组的第一个元素,j 最开始指向数组的最后一个元素。指针 i 从左向右移动,指针 j 从右向左移动。先移动 j 指针(从右忘左移),当 j 指向的数大于基准数时,略过,j 继续往左移动,直到遇到小于等于基准数的数arr[j],将arr[j]填入arr[i]中;再移动 i 指针,当 i 指向的数小于等于基准数时,略过,i 继续往右移动,直到遇到不比基准数小的数arr[i],将arr[i]填入arr[j]中;再移动 i 指针,再移动 j 指针...(轮换移动),直到 i 和 j 指针相遇,此时将temp(基准数)填入arr[i]中即完成算法的第2个步骤。接下来分别将基准数左边和右边的数组按照以上方法进行聚合,直到每个子集只有一个元素,即排序完成。

可能描述得有些抽象,接下来用图一步一步的示意:

将数组第一个数23赋给temp变量,指针 i 指向数组第一个元素,指针 j 指向数组最后一个元素

  

从 j 开始遍历(从右往左),遇到13时,因为13<=temp,因此将arr[j]填入arr[i]中,即此时指针 i 指向的数为13;

再从 i 遍历(从左往右),遇到45时,因为45>temp,因此将arr[i]填入arr[j]中,此时指针 j 指向的数为45;

继续从 j 遍历,遇到11时,因为11<=temp,因此将arr[j]填入arr[i]中,即此时指针 i 指向的数为11;

从 i 遍历,遇到89时,因为89>temp,因此将arr[i]填入arr[j]中,此时指针 j 指向的数为89;

从 j 遍历,遇到17时,因为17<=temp,因此将arr[j]填入arr[i]中,即此时指针 i 指向的数为17;

从 i 遍历,遇到72时,因为72>temp,因此将arr[i]填入arr[j]中,此时指针 j 指向的数为72;

从 j 遍历,遇到3时,因为3<=temp,因此将arr[j]填入arr[i]中,即此时指针 i 指向的数为3;

  

从 i 遍历,遇到26时,因为26>temp,因此将arr[i]填入arr[j]中,此时指针 j 指向的数为26;

  

从 j 遍历,和 i 重合;

​​​​​​​ 

将 temp(基准数23)填入arr[i]中。

此时完成算法的第2个步骤,接下来将23左边和右边的子区间分别用以上方法进行排序,直到区间只有一个元素即排序完成。
————————————————
版权声明:本文为CSDN博主「elma_tww」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/elma_tww/article/details/86164674

Attention:python实现的快排采用的是覆盖的方法,而不是传统意义上C语言实现的左右位置调换list[left], list[right] = list[right], list[left],而这种覆盖+temp存储对比基准元素的做法更简便一些。

# 定义快排函数 def QuickSort(list, left, right):if left < right:pivot = partition(list, left, right)# 递归,先一直按着一边排序完成,这就像左侧深度遍历QuickSort(list, left, pivot - 1)QuickSort(list, pivot + 1, right)# 基准,分区partition def partition(list, left, right):temp = list[left]while left < right:# 如果单纯判断list[right] > temp,则可能因为指针位置无法变动陷入死循环while left < right and list[right] >= temp:right -= 1list[left] = list[right]# 元素调换覆盖后,虽然一定是小于或大于基准元素temp的,指针left或right似乎可以直接-1或+1,但在python中left=0,right=0时,两次right-1会出现right=-1,造成排序出错。while left < right and list[left] <= temp:left += 1list[right] = list[left]# 因为这种覆盖调换位置的方法因为占用了left指针的位置会出现两个相同的元素,temp还原的时候要放在left指针位置list[left] = tempreturn leftif __name__ == "__main__":num_list = [3, 2, 1]QuickSort(num_list, 0, len(num_list) - 1)print num_list

参考:

[1] 快速排序算法​​​​​​​

[2] Python冒泡排序算法

《新程序员》:云原生和全面数字化实践50位技术专家共同创作,文字、视频、音频交互阅读

总结

以上是生活随笔为你收集整理的python programming training(二): 排序算法的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。