目录
01冒泡排序
1、比较相邻的元素。如果第一个比第二个大,就交换它们两个;
2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
3、针对所有的元素重复以上的步骤,除了最后一个;
重复步骤1~3,直到排序完成。
class Solution:
def bubble_sort(self,a):
for i in range(len(a)):
for j in range(len(a)-i-1):
if a[j]>a[j+1]:
a[j],a[j+1]=a[j+1],a[j]
a=[1,3,6,5,4,7]
s=Solution()
s.bubble_sort(a)
print(a)
02快速排序
1、从数列中通过partition(arr,left,right)函数,挑出一个元素,称为 “基准”(pivot);
2、重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数
可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
3、递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
class Solution:
def partition(self,a,left,right):
pivot=left # 划分参考数索引,默认为第一个数为基准数,可优化
while (left <right):
while (left<right and a[right]>=a[pivot]):
right-=1
while (left<right and a[left]<=a[pivot]):
left+=1
a[left],a[right]=a[right],a[left]
return left
def quick_sort(self,a,left,right):
if left>=right:
return
mid=self.partition(a,left,right)
self.quick_sort(a,left,mid-1)
self.quick_sort(a,mid+1,right)
a=[1,3,5,6,2,4,7,0]
s=Solution()
left=0
right=len(a)-1
s.quick_sort(a,left,right)
print(a)
03简单插入排序
1、从第一个元素开始,该元素可以认为已经被排序;
2、取出下一个元素,在已经排序的元素序列中从后向前扫描;
3、如果该元素(已排序)大于新元素,将该元素移到下一位置;
4、重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
5、将新元素插入到该位置后;
6、重复2~5。
class Solution:
def insert_sort(self,a):
for i in range(1,len(a)):
j=i
t=a[i]
while j>0 and a[j-1]>t:
a[j]=a[j-1]
j-=1
a[j]=t
s=Solution()
a=[1,3,5,6,2,4,7,0]
s.insert_sort(a)
print(a)
04希尔排序
为减少简单插入排序移动次数提出的排序算法
1、将序列分为间距为d的多个子序列[a[0],a[int(len(a)/2)],,a[int(len(a)-1)]]; [a[1],a[int(len(a)/2)+1]];......
d的一般取值为:d=len(a)/2; d=d/2
2、每个子序列进行插入排序
class Solution:
def shell_sort(self,a):
if (len(a)<1):
return
d=int(len(a)/2)
while(d>=1):
self.insert_sort(a,d)
d=int(d/2)
def insert_sort(self,a,d):
for i in range(d,len(a)):
j=i-d
t=a[i]
while j>=0 and a[j]>t:
a[j+d]=a[j]
j-=d
print(j,i-d)
if (j!=i-d):
a[j+d]=t
s=Solution()
a=[1,3,5,6,2,4,7,0]
s.shell_sort(a)
print(a)
05简单选择排序
1、遍历数组,每次找到数组中最小的元素,每次最小的元素与当前数交换
2、R[1,k]为有序元素, R[k+1,n]为无序元素
class Solution:
def select_sort(self,a):
for i in range(len(a)-1):
min_i=i
for j in range(i+1,len(a)):
if (a[min_i]>a[j]):
min_i=j
if (min_i!=i):
a[i],a[min_i]=a[min_i],a[i]
a=[1,5,2,7,9,3]
s=Solution()
s.select_sort(a)
print(a)
06归并排序
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的
一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列
段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
1、申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
2、设定两个指针,最初位置分别为两个已经排序序列的起始位置;
3、比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
4、重复步骤 3 直到某一指针达到序列尾;
5、将另一序列剩下的所有元素直接复制到合并序列尾。即数组长度小于2
def mergeSort(a):
if len(a)<2:
return a
mid=int(len(a)/2)
left=a[0:mid]
right=a[mid:]
return merge(mergeSort(left),mergeSort(right))
def merge(left,right):
res=[]
while(left and right):
if left[0]<right[0]:
res.append(left.pop(0))
else:
res.append(right.pop(0))
while left:
res.append(left.pop(0))
while right:
res.append(right.pop(0))
return res
a=[3,4,2,1,8,5,6,7]
b=mergeSort(a)
print(b)
07计数排序
计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,
计数排序要求输入的数据必须是有确定范围的整数。
1. 计数排序的特征
当输入的元素是 n 个 0 到 k 之间的整数时,它的运行时间是 Θ(n + k)。计数排序不是比较排序,
排序的速度快于任何比较排序算法。
由于用来计数的数组C的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加上1),
这使得计数排序对于数据范围很大的数组,需要大量时间和内存。例如:计数排序是用来排序0到100之间的
数字的最好的算法,但是它不适合按字母顺序排序人名。但是,计数排序可以用在基数排序中的算法来排序
数据范围很大的数组。
通俗地理解,例如有 10 个年龄不同的人,统计出有 8 个人的年龄比 A 小,那 A 的年龄就排在第9位,
用这个方法可以得到其他每个人的位置,也就排好了序。当然,年龄有重复时需要特殊处理(保证稳定性),
这就是为什么最后要反向填充目标数组,以及将每个数字的统计减去 1 的原因。
算法的步骤如下:
(1)找出待排序的数组中最大和最小的元素
(2)统计数组中每个值为i的元素出现的次数,存入数组C的第i项
(3)对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
(4)反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1
def countSort(a):
maxNum=max(a)
minNum=min(a)
list_count=[0]*(maxNum+1)
for i in a:
list_count[i]+=1
res=[]
for i in range(minNum,maxNum+1):
while list_count[i]>0:
res.append(i)
list_count[i]-=1
return res
a=[3,4,5,6,2,3,4,5,7,8,9,8,0]
b=countSort(a)
print(b)
08桶排序
桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。
为了使桶排序更加高效,我们需要做到这两点:
在额外空间充足的情况下,尽量增大桶的数量
使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中
同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。
当输入的数据可以均匀的分配到每一个桶中,最快
当输入的数据被分配到了同一个桶中,最慢
1、设置桶的容量bucketSize,确定桶的数量int(max(a)/bucketSize)+1
2、定义落入桶中的映射函数int(i/(bucketSize+1)),保证每个桶按顺序有序
3、对每个桶排序,合并桶中的值
def bucketSort(a,bucketSize):
if(len(a)<=1):
return a
#初始化桶
bucketNum=int(max(a)/bucketSize)+1
buckets=[[] for i in range(bucketNum)]
#定义映射函数i/(bucketSize+1)
for i in a:
buckets[int(i/(bucketSize+1))].append(i)
res=[]
for i in buckets:
res+=sorted(i)
return res
a=[1,7,8,11,32,3,67,4,55,6,10]
b=bucketSort(a,10)
print(b)
09基数排序
1、取得数组中的最大数,并取得位数b;
2、声明基数个桶,从0-b位依次对数组进行排序
3、获取第i位的排序结果,对(i+1)位进行基数排序buckets[int(x/radix**i)%radix]
4、重复2-3,直到位数遍历完
def radix_sort(a,radix):
#取数组中的最大数,获取位数
max_bit=len(str(max(a)))
i=0
#按位数排序
while i<max_bit:
#定义桶
buckets=[[] for j in range(radix)]
for x in a:
buckets[int(x/radix**i)%radix].append(x)
a.clear()
#获取第i位排序后的结果
for bucket in buckets:
a+=bucket
i+=1
a=[112,334,55,66,3,67,9,0]
radix_sort(a,10)
print(a)
10堆排序
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,
并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
在python中heapq实现了堆排序,在这里只是简单地使用该函数实现对数据的排序
import heapq
def heap_sort(a):
return heapq.nsmallest(len(a),a)
a=[112,334,55,66,3,67,9,0]
b=heap_sort(a)
print(b)
不调函数实现:
def adjust_heap(a,n,i):
'''
堆调整
a:数组
n:数组长度
i:当前需要被调节的节点
'''
l=2*i+1 #左孩子
r=2*i+2 #右孩子
largest=i #值最大节点编号
if l<n and a[largest]<a[l]:
largest=l
if r<n and a[largest]<a[r]:
largest=r
if largest!=i:
a[largest],a[i]=a[i],a[largest]
adjust_heap(a,n,largest)
def heap_sort(a):
n=len(a)
for i in range((n-1)//2+1,-1,-1):
adjust_heap(a,n,i)
while n>0:
a[n-1],a[0]=a[0],a[n-1]
n-=1
adjust_heap(a,n,0)
print(a)
https://blog.csdn.net/weixin_37621790/article/details/86695537 (堆排序介绍较为详细的网址)
参考网址:
https://blog.csdn.net/weixin_41571493/article/details/81875088