十大经典排序(下)——Python3实现
看星河璀璨,听风起云涌,这里是轨物Fan世
十大经典算法包括:插入排序、选择排序、冒泡排序、快速排序、堆排序、基数排序、桶排序、归并算法、希尔算法、计数算法。。
本期内容:基数排序、桶排序、归并算法、希尔算法、计数算法
下面讲到的算法全由Python3实现,因此你只需要一个python环境就行;但重要的是要明白算法本身的思想。
希尔排序,也称递减增量排序算法,是非稳定排序算法,是插入排序高效改进版
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位
希尔排序的思想是将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。
#希尔算法def shellSort(num):import mathgap=1< len(num)/3):gap = gap*3+1while gap > 0:for i in range(gap,len(num)):temp = num[i]j = i-gapwhile j >=0 and num[j] > temp:=num[j]=gap= tempgap = math.floor(gap/3)return num
归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,是采用分治法非常典型的应用
可以有自上而下的递归和自下而上的迭代两种方法
步骤:
申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
设定两个指针,最初位置分别为两个已经排序序列的起始位置;
比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
重复步骤 3 直到某一指针达到序列尾;
将另一序列剩下的所有元素直接复制到合并序列尾。
#归并排序def mergeSort(num):import mathif(len(num)<2):return nummiddle = math.floor(len(num)/2)left, right = num[0:middle], num[middle:]return merge(mergeSort(left), mergeSort(right))def merge(left,right):result = []while left and right:if left[0] <= right[0]:result.append(left.pop(0));else:result.append(right.pop(0));while left:result.append(left.pop(0));while right:result.append(right.pop(0));return result
计数排序的核心思想在于将输入的数据值转化为键存储在额外开辟的空间中。计数排序不是比较排序,排序的速度快于任何比较排序算法。但有一定的局限性,计数排序要求输入的数据必须是有确定范围的整数。
#计数排序def countingSort(num, maxValue):bucketLen = maxValue+1bucket = [0]*bucketLensortedIndex =0numLen = len(num)for i in range(numLen):if not bucket[num[i]]:bucket[num[i]]=0bucket[num[i]]+=1for j in range(bucketLen):while bucket[j]>0:num[sortedIndex] = jsortedIndex+=1bucket[j]-=1return num
桶排序就是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效,我们需要做到这两点:
-  
    
在额外空间充足的情况下,尽量增大桶的数量
 -  
    
使用的映射函数能够将输入的 N 个数据均匀的分配到K 个桶中
 
同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。
# 桶排序def bucketSort(num):# 选最大的数max_num = max(num)# 选一个元素全是0的列表做桶bucket = [0] * (max_num + 1)# 把所有元素放入桶中, 即把对应元素个数加 1for i in num:bucket[i] += 1# 存储排序好的元素sort_nums = []# 取出桶中的元素for j in range(len(bucket)):if bucket[j] != 0:for y in range(bucket[j]):sort_nums.append(j)return sort_nums
基数排序是一种非比较型整数排序算法。其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。
# 基数排序def radix_sort(num):i = 0 #记录max_num = max(num) # 最大值j = len(str(max_num)) # 记录最大值的位数while i < j:bucket_list =[[] for _ in range(10)] #初始化桶数组for x in num:bucket_list[int(x / (10**i)) % 10].append(x)num.clear()for x in bucket_list:for y in x:num.append(y)i += 1return num
完整代码
#作者轨物Fan世#希尔算法def shellSort(num):import mathgap=1while(gap < len(num)/3):gap = gap*3+1while gap > 0:for i in range(gap,len(num)):temp = num[i]j = i-gapwhile j >=0 and num[j] > temp:num[j+gap]=num[j]j-=gapnum[j+gap] = tempgap = math.floor(gap/3)return num#归并排序def mergeSort(num):import mathif(len(num)<2):return nummiddle = math.floor(len(num)/2)left, right = num[0:middle], num[middle:]return merge(mergeSort(left), mergeSort(right))def merge(left,right):result = []while left and right:if left[0] <= right[0]:result.append(left.pop(0));else:result.append(right.pop(0));while left:result.append(left.pop(0));while right:result.append(right.pop(0));return result#计数排序def countingSort(num, maxValue):bucketLen = maxValue+1bucket = [0]*bucketLensortedIndex =0numLen = len(num)for i in range(numLen):if not bucket[num[i]]:bucket[num[i]]=0bucket[num[i]]+=1for j in range(bucketLen):while bucket[j]>0:num[sortedIndex] = jsortedIndex+=1bucket[j]-=1return num# 基数排序def radix_sort(num):i = 0max_num = max(num)j = len(str(max_num))while i < j:bucket_list =[[] for _ in range(10)]for x in num:bucket_list[int(x / (10**i)) % 10].append(x)num.clear()for x in bucket_list:for y in x:num.append(y)i += 1return num# 桶排序def bucketSort(num):max_num = max(num)bucket = [0] * (max_num + 1)for i in num:bucket[i] += 1sort_nums = []for j in range(len(bucket)):if bucket[j] != 0:for y in range(bucket[j]):sort_nums.append(j)return sort_numsif __name__ == '__main__':num = [1, 6, 7, 13, 22, 54, 7, 99, 333, 777]print("排序元素:", num)result_shell = shellSort(num)result_merge = mergeSort(num)result_counting = countingSort(num,max(num))result_radix = radix_sort(num)result_bucket = bucketSort(num)print("希尔排序:", result_shell)print("归并排序:", result_merge)print("计数排序:", result_counting)print("基数排序:", result_radix)print("桶 排 序:", result_bucket)
