python选择排序算法图解,快速排序算法python代码
排名算法是《数据结构与算法》中最基础的算法之一,也是面试中最常被考察的知识点。在本文中,我将详细介绍10种常见的内部排序算法,以及如何用Python实现它们。记得收藏,关注,喜欢。
注意:代码、数据和技术交流的完整版本可在最后获得。
排序算法可以分为内部排序和外部排序。内部排序是指数据记录在内存中排序,外部排序是指排序后的数据太大,无法一次性容纳所有排序后的记录,排序过程中需要访问外部存储。
常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。
用一张图总结一下:
时间复杂度:
平方顺序(O(n2))排序:各种简单排序、直接插入、直接选择、冒泡排序;线性对数序(O(nlog2n))排序:快速排序、堆排序、归并排序;Hill排序:O (n1))排序,其中(是0到1之间的常数;线性顺序(O(n))排序:基数排序,此外还有桶和箱排序。关于稳定性:
排序后两个相等键值的顺序与排序前相同。稳定排序算法:冒泡排序、插入排序、合并排序和基数排序。不是一个稳定的排序算法:选择排序,快速排序,希尔排序和堆排序。名词解释:
n:数据规模。k:“桶”的数量。就地:占用常量内存,不占用额外内存。错位:占用额外的内存。01冒泡排序
冒泡排序也是一种简单直观的排序算法。它反复访问要排序的序列,一次比较两个元素,如果它们的顺序不对,就切换它们。访问序列的工作一直重复到不需要交换为止,也就是说序列已经排序了。这种算法的名字来源于较小的元素会通过交换慢慢“浮”到序列的顶端。
冒泡排序作为一种最简单的排序算法,给我的感觉和单词书里的嫌弃的出现一样,每次都是第一页第一,所以我最熟悉。冒泡排序还有一个优化算法,就是设置一个标志。当元素在一个序列遍历中没有交换时,就证明这个序列是有序的。但是这种改进对提高性能并没有太大的作用。
1.算法步骤比较相邻的元素。如果第一个比第二个大,两个都换。对每一对相邻的元素做同样的工作,从开始的第一对到结束的最后一对。在这一步之后,最后一个元素将是最大的数字。对除最后一个元素之外的所有元素重复上述步骤。每次对越来越少的元素重复上述步骤,直到没有要比较的数字对。2.动画演示
3.Python代码
def bubbleSort(数组):
对于范围内的I(1,len(arr)):
对于范围(0,len(arr)-i)中的j:
if arr[j] arr[j 1]:
数组[j],数组[j 1]=数组[j 1],数组[j]
返回arr02选择排序
排序是一种简单直观的排序算法。不管什么数据进去,都是O (n)的时间复杂度。所以在使用的时候,数据量越小越好。唯一的好处可能就是不占用额外的内存空间。
1.算法步骤首先找到未排序序列中最小(最大)的元素,并将其存储在排序序列的开头。然后继续从剩余的未排序元素中寻找最小(最大)的元素,然后放在排序后的序列的末尾。重复第二步,直到所有元素都排序完毕。2.动画演示
3.Python代码
定义选择排序(arr):
对于范围内的I(len(arr)-1):
#记录最小数量的索引
minIndex=i
对于范围内的j(I ^ 1,len(arr)):
if arr[j] arr[minIndex]:
minIndex=j
当# i不是最小数时,用最小数交换I。
如果我!=minIndex:
arr[i],arr[minIndex]=arr[minIndex],arr[i]
Return arr03插入排序
虽然插入排序的代码实现没有冒泡排序和选择性排序那么简单粗暴,但是它的原理应该是最容易理解的,因为玩过扑克的人应该都能秒懂。插入是最简单、最直观的排序算法。它的工作原理是在排序后的序列中从后向前扫描未排序的数据,找到对应的位置并插入。
和冒泡排序一样,插入排序也有一个优化算法,叫做对半插入。
1.该算法步骤将待排序的第一序列的第一个元素视为有序序列,并将第二个元素至最后一个元素视为未排序序列。从头到尾扫描无序序列,将每个扫描的元素插入有序序列的适当位置。(如果要插入的元素等于有序序列中的一个元素,则将要插入的元素插入到等于的元素之后。) 2.动画演示
3.Python代码
定义插入排序(arr):
对于范围内的I(len(arr)):
preIndex=i-1
current=arr[i]
preIndex=0且arr[preIndex] current:
arr[preIndex 1]=arr[preIndex]
preIndex-=1
arr[preIndex 1]=当前
返回arr04 hill排序
Hill排序,也称为降序增量排序算法,是插入排序的一个更高效的改进版本。然而,希尔排序算法是不稳定的。
希尔排序基于插入排序的以下两个属性:
在对几乎排序的数据进行操作时,插入排序是高效的,即可以达到线性排序的效率;但是插入排序一般效率很低,因为插入排序一次只能移动一位数据。Hill排序的基本思路是:首先,将待排序的整个记录序列分成若干子序列进行直接插入排序。当整个序列中的记录都是“基本有序”时,直接插入所有记录并依次排序。
1.算法步骤选择增量序列t1、t2,tk,其中ti tj,tk=1;根据增量序列的个数k,对序列进行k次排序;每次排序时,根据对应的增量ti,将待排序的列分成若干个长度为m的子序列,每个子表直接插入排序。当增量因子只有1时,整个序列被当作一个表,表的长度就是整个序列的长度。2.Python代码
定义外壳排序(arr):
导入数学
差距=1
while(gap len(arr)/3):
差距=差距*3 1
而间隙0:
对于范围内的I(gap,len(arr)):
临时=数组[i]
j=i-gap
当j=0且arr[j] temp:
arr[j缺口]
间隙
arr[j gap]=温度
gap=math.floor(gap/3)
返回arr
}05合并排序
归并排序是一种基于归并操作的有效排序算法。这个算法是分而治之的典型应用。
作为分治思想的典型算法应用,归并排序通过两种方法实现:
自顶向下递归(所有递归方法都可以通过迭代重写,所以有第二种方法);自底向上迭代。与选择性排序一样,合并排序的性能不受输入数据的影响,但它比选择性排序好得多,因为它总是O(nlogn)的时间复杂度。代价是额外的存储空间。
1.算法步骤申请一个空间,使其大小为两个排序后的序列之和,空间用于存储合并后的序列;设置两个指针,其初始位置分别为两个排序序列的初始位置;比较两个指针指向的元素,选择一个相对较小的元素放入归并空间,将指针移动到下一个位置;重复步骤3,直到指针到达序列的末尾;将另一个序列的所有剩余元素直接复制到合并序列的末尾。2.动画演示
3.Python代码
定义合并排序(arr):
导入数学
if(len(arr) 2):
返回arr
middle=math.floor(len(arr)/2)
left,right=arr[0:middle],arr[middle:]
返回merge(mergeSort(左),mergeSort(右))
定义合并(左、右):
结果=[]
而左和右:
如果left[0]=right[0]:
result . append(left . pop(0));
否则:
result . append(right . pop(0));
离开时:
result . append(left . pop(0));
右侧:
result . append(right . pop(0));
返回06快速排序
快速排序是由Tony Hall开发的一种排序算法。平均来说,对N个项目进行排序需要 (nlogn)次比较。在最坏的情况下,需要进行 (N2)比较,但这种情况并不常见。事实上,快速排序通常比其他 (NLOGN)算法快得多,因为它的内循环可以在大多数架构中高效实现。
快速排序使用分治策略将一个列表分成两个子列表。
快速排序是分治思想在排序算法中的典型应用。本质上,快速排序应该看作是一种基于冒泡排序的递归分治法。
快速排序这个名字简单粗暴,因为只要一听到这个名字,你就会知道它存在的意义,那就是快速高效!是处理大数据最快的排序算法之一。
虽然最坏情况的时间复杂度达到O (n),但人是优秀的,在大多数情况下,比平均时间复杂度为O(n logn)的排序算法表现更好,但不知道为什么。还好我的强迫症又犯了。查了更多的资料,终于在《算法艺术与信息学竞赛》上找到了满意的答案:
快速排序最差的情况是O (n),比如顺序数列的快速排序。但其共享的期望时间为O(nlogn),O(nlogn)标记中隐含的常数因子很小,远小于稳定复杂度等于O(nlogn)的归并排序。所以对于大部分弱序列的随机序列,快速排序总是比归并排序好。
1.算法步骤从序列中挑出一个元素,称为“pivot”;对数列重新排序,所有小于参考值的元素放在参考值的前面,所有大于参考值的元素放在参考值的后面(相同的数字可以在两边)。在这个分区退出后,基准位于系列的中间。这称为分区操作;递归排序小于参考值的元素子系列和大于参考值的元素子系列。在递归的最底层,序列的大小是零或一,也就是一直排序下去。虽然它一直在递归,但这种算法总是会退出,因为在每次迭代中,它至少会将一个元素放到最后一个位置。
2.动画演示
3.Python代码
def快速排序(arr,left=None,right=None):
如果不是isinstance,left=0(left,(int,float))否则向左
right=len(arr)-1 if not is instance(right,(int,float)) else right
如果向左向右:
partitionIndex=partition(arr,left,right)
快速排序(数组,左,分区索引-1)
快速排序(arr,partitionIndex 1,右)
返回arrdef分区(arr,left,right):
枢轴=向左
索引=透视1
i=指数
而我=右:
if arr[i] arr[pivot]:
交换(arr,I,index)
指数=1
i=1
交换(数组,透视,索引-1)
回报指数-1
def swap(arr,I,j):
Arr[i],arr[j]=arr[j],arr[i]07堆排序
堆排序是指利用堆的数据结构设计的一种排序算法。Heap是一种类似于完全二叉树的结构,同时满足heap的性质:即子节点的键值或索引总是小于(或大于)其父节点。堆排序可以说是利用堆的概念进行的一种选择性排序。有两种方法:
Top heap:每个节点的值大于等于其子节点的值,用于堆排序算法中的升序;Top heap:每个节点的值小于或等于其子节点的值,用于堆排序算法中的降序。堆排序的平均时间复杂度为 (nlogn)。
1.算法步骤创建一个堆H[0…n-1];交换反应器头部(最大)和反应器尾部;将堆的大小减少1,调用shift_down(0)以便将新数组顶部的数据调整到相应的位置;重复步骤2,直到堆栈的大小为1。2.动画演示
3.Python代码
def buildMaxHeap(arr):
导入数学
对于范围内的I(math . floor(len(arr)/2),-1,-1):
heapify(arr,I)
def heapify(arr,I):
左=2*i 1
右=2*i 2
最大=i
if left arrLen和arr[left]arr[large]:
最大=左侧
如果右arrLen和arr[右]arr[最大]:
最大=右侧
如果最大!=我:
交换(arr,I,最大)
heapify(arr,maximum)def swap(arr,I,j):
arr[i],arr[j]=arr[j],arr[i]
定义堆排序(arr):
全球arrLen
arrLen=len(arr)
buildMaxHeap(arr)
对于范围内的I(len(arr)-1,0,-1):
swap(arr,0,I)
arrLen -=1
heapify(arr,0)
返回arr08盘点排序
计数排序的核心是将输入的数据值转换成键,存储在额外的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入数据必须是一定范围内的整数。
1.动画演示
2.Python代码
def countingSort(arr,maxValue):
bucketLen=maxValue 1
bucket=[0]*bucketLen
sortedIndex=0
arrLen=len(arr)
对于范围内的I(arr len):
如果不是bucket[arr[i]]:
bucket[arr[i]]=0
bucket[arr[i]]=1
对于范围内的j(bucket len):
while桶[j] 0:
arr[sortedIndex]=j
sortedIndex=1
桶[j]-=1
Return arr09桶排序
桶排序是计数排序的升级版本。它利用了函数的映射关系,高效的关键在于这个映射函数的确定。为了提高桶排序的效率,我们需要做两件事:
当有足够的额外空间时,尽量增加桶数。的映射函数可以将输入的N个数据均匀分布到K个桶中。同时,为了对桶中的元素进行排序,选择一个性能比较排序算法是非常重要的。
输入数据能平均分配到每个桶最快是什么时候?
最慢的时间是什么时候?当输入数据被分配到相同的桶时。
代码Python def bucket_sort:
桶排序
min_num=分钟
最大数量=最大数量
#水桶的大小
bucket_range=(最大数量-最小数量)/长度
#桶阵列
count _ list=[[]for I in range(len(s)1)]
#用数字填充桶数组
对于s中的I:
count _ list[int((I-min _ num)//bucket _ range)]。追加(一)
透明玻璃()
# Backfill,其中sorted是通过桶内排序直接调用的。
对于count_list中的I:
对于排序后的j(I):
追加(j)
if _ _ name _ _==_ _ main _ _:
a=[3.2,6,8,4,2,6,7,3]
bucket_sort(a)
Print(a) # [2,3,3.2,4,6,6,7,8]10基数排序
基数排序是一种非比较整数排序算法。它的原理是把整数按照位数切割成不同的数,然后按照每个位数进行比较。由于整数也可以用特定格式表示字符串(如姓名或日期)和浮点数,所以基数排序不仅可以用于整数。
1.基数排序与计数排序与桶排序基数排序有两种方法:
所有三种排序算法都利用了桶的概念,但是桶的用法有明显的不同:
基数:根据键值的每一位分配桶;计数排序:每个桶只存储一个键值;桶排序:每个桶存储一定范围的值。2.动画演示
3.Python代码
定义半径排序(列表):
I=0 #最初按位排序。
N=1 #最小位数设置为1(包括0)
Max_num=max(list) #获取排序数组中的最大值。
而max_num 10**n: #得到的最大数是多少位?
n=1
当我在:
Bucket={} #用字典构建Bucket
对于范围(10)中的x:
Bucket.setdefault(x,[]) #清空每个桶
列表中的x:#对每个位进行排序。
Radix=int((x/(10**i))% 10) #获取每个位的基数
桶[基数]。append(x) #将对应于
组被添加到阶段#对应基的桶中。
j=0
对于范围(10)中的k:
if len(bucket[k])!=0: #如果桶不为空
对于桶[k]中的y:#将每个元素放入桶中
List[j]=y #并将它放回数组中
j=1
i=1
返回列表
技术交流欢迎转载,收藏,有所收获,喜欢,支持!数据和代码可以从我这里获得。
目前已开通技术交流群,群友2000多人。最好的添加笔记的方法是:兴趣来源,这样才能找到志同道合的朋友。
方式,微信搜索微信官方账号:Python学习与数据挖掘,后台回复:加群
转载请联系作者授权,否则将追究法律责任。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。