冒泡排||快排||选择排||插入排python


python冒泡排序
说实话,做过快排后比较起冒泡排理解起来容易很多。。
冒泡排每次都会遍历都会找出一个最大值。
代码来源菜鸟教程,不是懒得写代码,是因为人家写的标准

递增式冒泡排

def bubbleSort(arr):
    n=len(arr)
	for i in range(n):
	 for j in range(0,n-i-1):
	   if arr[j]>arr[j+1]:
	    arr[j],arr[j+1]=arr[j+1],arr[j]
arr=[64, 34, 25, 12, 22, 11, 90]
bubbleSort(arr)

这里j的最后遍历到的位置: n-i-1 ,我理解是i=0时,遍历到n-1,排好一个数,排好的数下次不需要遍历
先遍历第i个元素,在嵌套for遍历做AB BC CD形式的比较。

递减式冒泡排

看某佬哥做了一道蓝桥杯的冒泡排,写了种逆向排
在这里插入图片描述
佬哥的代码

def bubble_sort(arr):
    num = 0
    for i in range(len(arr)-1,0,-1):
        for j in range(i):
            if arr[j] > arr[j+1]:
                num += 1
                arr[j],arr[j+1] = arr[j+1],arr[j]
    return num
print(bubble_sort(list('jonmlkihgfedcba')))

代码审计: 这里的for里的i遍历从 len(arr)-1 开始,排好一个数,下次不需要遍历。
字符串的长度为15,首次遍历就是 range(14,0,-1),从后遍历;第二个j从0开始遍历到14,递减式的冒泡排。

分区间式快排

python 快排
这段快排是从菜鸟教程摘过来的。觉得写的很不错,仅仅为了学习排序,并没想过实用,因为效率比不上sort

def partition(arr,low,high):
 i=(low-1)        
 pivot=arr[high]
 for j in range(low , high):
    if   arr[j] <= pivot: 
		i = i+1 
		arr[i],arr[j] = arr[j],arr[i] 
arr[i+1],arr[high] = arr[high],arr[i+1] 
return ( i+1 ) 

def quickSort(arr,low,high): 
    if low < high: 
  		pi=partition(arr,low,high)
        quickSort(arr,low,pi-1)
        quickSort(arr, pi+1, high) 

假设数组为

arr = [10, 7, 8, 9, 1, 5] 
n = len(arr) 
quickSort(arr,0,n-1) 

我比较无脑,看到上面的算法没有头脑,就把他列了一遍

low=0=j,high=5
	
arr[4]<high : arr[0],arr[4]=arr[4],arr[0]
	1,7,8,9,10,5

low=1=j,high=5:  arr[1],arr[5]=arr[5],arr[1]
	1,5,8,9,10,7     

low=2=j.high=5:  arr[2],arr[5]=arr[5],arr[2]
	1,5,7,9,10,8

low=3=j.high=5:  arr[3],arr[5]=arr[5],arr[3]
	1,5,7,8,10,9
low=4=j.high=5:  arr[4],arr[5]=arr[5],arr[4]
	1,5,7,8,9,10

这段代码是我吧上面的

arr[i+1],arr[high] = arr[high],arr[i+1] 
return ( i+1 ) 

放到那个for里跑,后面发现不在循环里。但观察了下值,问题不大。。
观察了一晚上和一早上,按我的理解,这个过程是这样的。
第一次比较,high=5,这个值在循环是一个定值,不变的,arr[4]<5,所以和arr[0]换位置,这里换位置只是模糊换,不代表arr[0]>arr[4]…

arr[4]<high : arr[0],arr[4]=arr[4],arr[0]
	1,7,8,9,10,5

然后 i的值是一直加的,在def函数里面。所以在不满足 if arr[j] <= pivot:
他的区间就限制的很小,这里就有点精准排序了,这个我找到的快排的最重要的点。

arr[i+1],arr[high] = arr[high],arr[i+1] 
return ( i+1 )

看这里,排序后的值为1,7,8,9,10,5

arr[4]<high :   i=0 ,arr[0],arr[4]=arr[4],arr[0]
	1,7,8,9,10,5
	return (i+1)

但你在7开始后找不到比5小的数,所以5肯定最小,但7可能不是最大。

low=1=j,high=5:  arr[1],arr[5]=arr[5],arr[1]
	1,5,8,9,10,7     
	return (i+1)

所以接着来
i++,你在8后找不到比7小的数,所以7最小,但8可能不是最大,最后缩小区间排满。

low=2=j.high=5:  arr[2],arr[5]=arr[5],arr[2]
	1,5,7,9,10,8
	return (i+1)

他这里原代码是通过不满足if后通过i的值分段

 quickSort(arr, low, pi-1) 
 quickSort(arr, pi+1, high) 

但说实话有点思路有点乱,小结就是
1.if函数做模糊排序,大致排序。
2.不满足if,通过缩小区间做精准排序。

当然还有C++的写法,但那个是比较两个值,左一个i,右一个j,写起来更复杂,会python快排应该够用了。

**

无脑之选择排序

菜鸟教程的代码

假设数组A=[22,25,23,21,11] 
for i in range(len(A)): 
    min_idx = i 
    for j in range(i+1, len(A)): 
        if A[min_idx] > A[j]: 
            min_idx = j 
    A[i], A[min_idx] = A[min_idx], A[i] 

我这只需要知道他的遍历到时候就能写出来:
首先遍历第一个元素

A=[22,25,23,21,11]
i=0  
min_idx=0  
  21<22
  min_idx=3
  11<21
  min_idx=4  
arr[0],arr[4]=arr[4],arr[0]
A=[11,25,23,21,22]
思路就是:21肯定比22小,但1121还小,结果肯定最小
#遍历第二个元素
i=1,min_idx=1
  23<25
  min_idx=2
21<23
i=2,min_idx=3
 arr[1],arr[3]=arr[3],arr[1]
A=[11,21,23,25,22]

这个遍历很容易,思路参考上面快排

22向后找到21,22>21,不着急换位置,用21和剩下的比较,找到最小的数,这个数在这个位置上就是最小(这个位置是我摸索出来的重点 ),
遍历一次出现一个最小数,(比后面的都小)。遍历结果结果就出来了,唯一注意的一个点就是 上面代码min_idx = j ,arr[j]是原数列的值,并没有做替换,

无脑之插入排序

def insertionSort(arr): 
    for i in range(1, len(arr)): 
        key = arr[i] 
        j = i-1
        while j >=0 and key < arr[j] : 
                arr[j+1] = arr[j] 
                j -= 1
        arr[j+1] = key 
arr = [12, 11, 13, 5, 6] 
insertionSort(arr) 

这里主要看while这里 , key<arr[j],j用来遍历前面的值,key表当前遍历的元素值
如果key和前面的值比较,比前面的值小替换,通过每执行一次while就会有j–,比如这里这个key为5时,这就是这个排序就重要的一点。
谈若不满足while ,key>=arr[j],那arr[j+1]=key这个位置就没要替换。

  12,11,13,5,6
  key=11 ;j=0 
  12>11;arr[1]=arr[0];j=-1
   arr[0]=11  
11,12,13,5,6

 key=13,j=12
 arr[2]=13

key=5,j=13
  13>5 ;arr[3]=arr[2],11,12,5,13,6
  12>5,arr[2]=arr[1].11,5,12,13,6
  11>5,arr[1]=arr[0] 5,11,12,13,6	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ECHO::

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值