其他算法(希尔排序,计数排序,桶排序,基数排序)
1.希尔排序
属于一种插入分组排序算法
首先取一个整数d1=n/2,将元素分为d1个组,每组相邻量元素之间距离为d1,在各组内进行直接插入排序;
取第二个整数d2=d1/2,重复上述分组排序过程,直到di=1,即所有元素在同一组内进行直接插入排序。
希尔排序每趟并不使某些元素有序,而是使整体数据越来越接近有序;最后一趟排序使得所有数据有序。
例:
对于如下数列,第一次d=4
我们可以做如下变换
归位
第二次d=2,我们在做交换
归位
第三次d=1,我们在做交换,此时是相邻元素间做交换,这步还不是太直观
代码
def insert_sort_d(li, d): for i in range(d, len(li)): # i表示摸到牌的位置 j = i - d tmp = li[i] while j >= 0 and li[j] > tmp: li[j+d] = li[j] j -= d li[j+d] = tmp def shell_sort(li): d = len(li) // 2 while d > 0: insert_sort_d(li, d) d //= 2 li = [5,7,4,6,3,1,2,9,8] shell_sort(li) print(li)
2.计数排序
现在有一个列表,已知列表中的数范围都在0到100之间。设计算法在O(n)时间复杂度内将列表进行排序
创建一个列表,统计每个数出现次数
import random def count_sort(li, max_val=100): count = [0 for i in range(max_val+1)] for v in li: count[v] += 1 li.clear() for a,b in enumerate(count): for i in range(b): li.append(a) li = [random.randint(0,100) for i in range(100)] count_sort(li) print(li)
3.桶排序(最快最简单的排序)
基本思想是将一个数据表分割成许多个buckets,每个buckets在各自排序
代码
def bucket_sort(lis): max_num = max(lis) # 创建一个元素全是0的列表当作桶 bucket = [0] * (max_num + 1) # [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # 把所有元素放入桶内,即对应元素+1,桶内没有就是0 for i in lis: bucket[i] += 1 # [0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1] # 存储排序好的元素 sort_num = [] # 取出桶内元素 for j in range(len(bucket)): if bucket[j] != 0: # 这步用于保证不去重操作 for k in range(bucket[j]): sort_num.append(j) return sort_num lis = [10, 5, 2, 7, 6, 8, 3, 1, 4] print(bucket_sort(lis))
说明:
桶排序是稳定的,它是常见排序中最快的一种,通常情况下比快排还要快
桶排序最大的问题就是消耗的内存比较大,算是牺牲了空间,换取了时间
4.基数排序(时间复杂度O(kn),空间复杂度O(k+n),k代表数字位数)
多关键字排序:假如现在有一个员工表,要求按照薪资排序,年龄相同的员工按照年龄排序
关键点,我们可以对个位和个位比较,十位和十位比较
import math import random def list_to_buckets(li, i): # i 表示按哪一位装桶 0表示个位 1表示十位 buckets = [[] for _ in range(10)] for val in li: digit = val // (10 ** i) % 10 buckets[digit].append(val) return buckets def buckets_to_list(buckets): return [val for bucket in buckets for val in bucket] # li = [] # for bucket in buckets: # for val in bucket: # li.append(val) # return li def radix_sort(li): max_val = max(li) k = math.floor(math.log10(max_val)) + 1 # n表示需要装拆桶多少次 for i in range(k): li = buckets_to_list(list_to_buckets(li, i)) return li li = list(range(100)) random.shuffle(li) print(radix_sort(li))