文章目录
前言
以下是十种经典排序算法的python代码展示,现已将代码封装为类,有错误的地方希望大家批评指正呀,大家共同探讨共同成长,加油加油!!
一、涉及的排序算法
十种经典的排序算法分别是:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序和基数排序。(具体的介绍就不详细说明了,这位博主有很详细的介绍排序算法详细介绍
二、代码
代码如下(示例):
主代码
class sort:
def swap(self,nums,m,n):
tmp=nums[m]
nums[m]=nums[n]
nums[n]=tmp
'''
bubble是冒泡排序,针对数组里的元素进行n-1轮排序
每轮会把最大/小的元素移动到数组末尾
'''
def bubble(self,nums):
Len=len(nums)
if Len==1:
return nums
for i in range(Len-1,-1,-1):
for j in range(i):
if nums[j]>nums[j+1]:
sort.swap(self,nums,j,j+1) #类中调用其他方法,要带类名
return nums
'''
select选择排序
内层循环应该是无序区,实际操作的是无序区
'''
def select(self,nums):
Len = len(nums)
if Len==1:
return nums
for i in range(Len-1):
Min = nums[Len - 1]
Min_pos = Len - 1
for j in range(i,Len-1):
# print('i={},j={}'.format(i,j))
if nums[j]<Min:
Min=nums[j]
Min_pos = j #找到无序区最小的数
# print('i={},Min_pos={}'.format(i,Min_pos))
sort.swap(self, nums, i, Min_pos) #交换最小序号和新的最小值的序号
# print('nums={}'.format(nums))
# print('Min={},Min_pos={}'.format(Min,Min_pos))
'''
错误:这种只是把最小的放在了第一个,要正着来
for i in range(Len - 2,-1,-1):
Min = nums[Len - 1]
Min_pos = Len - 1
for j in range(i, Len - 1):
print('i={},j={}'.format(i,j))
if nums[j] < Min:
Min = nums[j]
Min_pos = j # 找到无序区最小的数
print('i={},Min_pos={}'.format(i,Min_pos))
sort.swap(self, nums, i, Min_pos) # 交换最小序号和新的最小值的序号
print('nums={}'.format(nums))
# print('Min={},Min_pos={}'.format(Min,Min_pos))
'''
return nums
'''
插入排序:insert
内层循环应该是有序区,因为是从无序区插入有序区,实际需要操作的是有序区
'''
def insert(self,nums):
Len = len(nums)
if Len==1:
return nums
for i in range(1,Len):
for j in range(Len-1):
if nums[i]<nums[j]:
nums.insert(j,nums.pop(i))
break
return nums
'''
希尔排序:shell
关键在于间隔序列的选择!!!(提前设定好间隔序列,动态定义间隔序列)
'''
def shell(self,nums):
Len = len(nums)
if Len==1:
return nums
gap=Len
while gap>1:
gap=gap//2
for pos in range(gap,Len,gap):
while pos:
if nums[pos] < nums[pos-gap]:
tmp=nums[pos]
nums[pos]=nums[pos-gap]
nums[pos-gap]=tmp
pos = pos - gap
else:
'''
关注跳出条件,不要浪费计算资源
因为是从头到尾排序,之前的已经是排好的,所以后面的只需要从前面的序列里面最大
'''
break
return nums
'''
归并排序:merge
n路归并
'''
def merge(self,nums,l,mid,r):
# print('before sort:{}'.format(nums))
if l==r:
return nums
else:
tmp=[]
i = l
j = mid + 1
while i<=mid and j<=r:
if nums[i]<=nums[j]:
tmp.append(nums[i])
i = i + 1
else:
tmp.append(nums[j])
j = j + 1
'''
在取值的过程中有一个数组取完了,就会把另一个数组剩下的元素全部添加
因为已经排好序
'''
while i <= mid:
tmp.append(nums[i])
i =i + 1
while j <= r:
tmp.append(nums[j])
j = j + 1
'''
把拎出来的临时数组赋值回去,因为每次的标号不一定相同因此得注意!!
'''
for i in range(l, r + 1):
nums[i] = tmp[i - l]
return tmp
def mmerge(self,nums,l,r):
if l>=r:
return nums
mid=(r+l)//2
self.mmerge(nums, l, mid)
self.mmerge(nums, mid + 1, r)
self.merge(nums,l,mid,r)
return nums
'''
快速排序:quick
'''
def quick(self,nums,l,r):
# print('before sort:{}'.format(nums))
# print('l={},r={}'.format(l,r))
stu = l
if l>=r:
return nums,stu
for j in range(l,r):
for i in range(l+1,r):
# print('i={},stu={}'.format(i,stu))
if nums[i]<nums[stu] and i>stu:
self.swap(nums,stu,i)
stu=i
# print('stu={}'.format(stu))
elif nums[i]>nums[stu] and i<stu:
self.swap(nums, stu, i)
stu = i
# print('stu={}'.format(stu))
return stu
def mquick(self,nums,l,r):
if l>=r:
return nums
'''
分区操作,找到每个数组段的区间中点
'''
stu = self.quick(nums,l,r)
'''
每个区分别操作
'''
self.mquick(nums,l,stu)
self.mquick(nums, stu+1, r)
return nums
'''
堆排序:heap
'''
def heap(self,nums,end): #堆操作
pos=(end-1)//2
for i in range(pos,-1,-1):
l = 2 * i + 1
r = 2 * i + 2
# print('i={},l={},r={}'.format(i,l,r))
if nums[i]<nums[l]:
self.swap(nums, i, l)
if r<=end and nums[i]<nums[r]:
self.swap(nums, i, r)
# print('nums:',nums)
return nums
def mheap(self,nums):
print('before sort:{}'.format(nums))
Len=len(nums)
if Len==1:
return nums
for end in range(Len-1,0,-1):
# print('end={}'.format(end))
self.heap(nums,end)
self.swap(nums,0,end)
return nums
'''
计数排序:count
'''
def count(self,nums):
Len=len(nums)
Min=nums[0]
Max=nums[0]
for i in nums:
if i>Max:
Max = i
elif i<Min:
Min = i
count=[0]*(Max-Min+1)
k=0
for i in nums:
count[i-Min]+=1
for i,ele in enumerate(count):
if ele!=0:
for j in range(ele):
nums[k]=i+Min
k=k+1
return nums
'''
桶排序:bucket
'''
def bucket(self,nums):
Len=len(nums)
Min = nums[0]
Max = nums[0]
for i in nums:
if i>Max:
Max = i
elif i<Min:
Min = i
Min=Min//10
Max=Max//10
tmp=[[0 for i in range(Len)] for j in range(Max-Min+1)] #浅拷贝,改变一个复制的数组部分也会变,只适用于一维
stmp = []
for j in range(Max - Min + 1):
k=0
for i in nums:
if (i//10)==j:
tmp[j][k] = i
k=k+1
self.mquick(tmp[j],0,k)
stmp = stmp + tmp[j][0:k]
# stmp = self.cat(tmp[j], k)
nums=stmp
return nums
'''
基数排序:Radix
'''
def radix(self,nums):
Len=len(nums)
'''
找到最大值
判断最高位
'''
Max = nums[0]
for i in nums:
if i > Max:
Max = i
bin=0
z=Max
while z:
z = z// 10
bin = bin + 1
# print('bin={}'.format(bin))
for j in range(0,bin): #bin = bin-1的原因是怕遗漏了最大值是0的数组 取不到bin
Min = (nums[0]%(10*pow(10,j)))//pow(10,j)
Max = (nums[0]%(10*pow(10,j)))//pow(10,j)
# print('before Min={},Max={}'.format(Min,Max))
for i in nums:
i=i%(10*pow(10,j))//pow(10,j)
# print('i={}'.format(i))
if i > Max:
Max = i
elif i < Min:
Min = i
# print('after find Min={},Max={}'.format(Min,Max))
count = [[-1 for i in range(Len)] for k in range(Max - Min + 1)]
x=0
for i in nums:
k=i%(10*pow(10,j))//pow(10,j) #代表每一位数字
# print('k={}'.format(k))
count[k - Min][x] = i
# print('k - Min={},x={},count={}'.format(k - Min,x,count))
x=x+1
k=0
for i in range(Max - Min + 1):
for j in range(Len):
if count[i][j]>=0:
nums[k]=count[i][j]
k=k+1
return nums
调用方式、示例
nums=[2,4,32,66,8,5,1,9,100,23,3291]
sort_ins=sort() #创建一个对象,再调用相关的方法
print('after sort:{}'.format(sort_ins.radix(nums)))
总结
应该是有一些编写不足的方面,希望大家批评指正,但是经过测试,所有代码都是正确的。