複習一下插入排序:git
def insert_sort(li): for i in range(1, len(li)): j = i - 1 # j 爲手裏最大的牌 tmp = li[i] while j >= 0 and li[j] > tmp: # 只要手裏最大的牌比摸回來的牌大就一致往右移動 # j >= 0 ,說明全部數都比摸到的牌要大,直接退出循環 li[j+1] = li[j] # 右移 j -= 1 li[j+1] = tmp # 肯定要插入的時候,是必須插到j的前一個位置
def insert_sort(li, gap): for i in range(gap, len(li)): j = i - gap tmp = li[i] # 摸回來的牌的值 while j >= 0 and li[j] > tmp: # 在有序區裏面,摸回來的牌比有序區的牌(從右到左)的值小,有序區的牌就向右移動一個位置 li[j+gap] = li[j] j -= gap li[j+gap] = tmp def shell_sort(li): d = len(li) // 2 while d >= 1: insert_sort(li, d) d = d // 2 li = list(range(1000)) import random random.shuffle(li) shell_sort(li) print(li)
希爾排序的時間複雜度比較複雜,且和選區的grap序列有關。算法
如今有一個列表,已知列表中的數範圍都在0到100之間。設計算法在O(n)時間複雜度內將列表進行排序。shell
建立一個列表,用來統計每一個數出現的次數。(index存數字大小,value存出現次數)app
def count_sort(li, max_num): # 建立一個max_num長的列表 count = [0 for i in range(max_num + 1)] for num in li: count[num] += 1 li.clear() for ind, val in enumerate(count): for i in range(val): li.append(ind) import random li = [random.randint(0,100) for _ in range(1000)] count_sort(li, len(li)) print(li)
計數排序的缺點:dom
若是列表只有5個數,數字範圍是1到1億,就須要開一個一億長度的列表,嚴重浪費空間和資源不合理使用。spa
在計數排序中,若是元素的範圍比較大(好比在1到1億之間), 如何改造算法?設計
桶排序(Bucket Sort):首先將元素分在不一樣的桶中,再對每一個桶中元素排序。code
def bucket_sort(li, n=100, max_num=10000): buckets = [[] for i in range(n)] # 建立通 for var in li: i = min(var//(max_num//n), n-1) # i表示var放到幾號桶裏 buckets[i].append(var) # 把var加到桶裏 # 保持桶內的順序 for j in range(len(buckets[i])-1, 0, -1): if buckets[i][j] < buckets[i][j-1]: # 必須是升序 降序的話[9,8,7,6] [99,87,55,22], 合併以後並非有序 buckets[i][j], buckets[i][j-1] = buckets[i][j-1], buckets[i][j] else: break sorted_li = [] for buc in buckets: sorted_li.extend(buc) return sorted_li import random li = [random.randint(0,99999) for i in range(100)] li = bucket_sort(li) print(li)
基數排序是按照低位先排序,而後收集;再按照高位排序,而後再收集;依次類推,直到最高位。blog
def radix_sort(li): max_num = max(li) # 最大值 9->1, 99->2, 888->3, 10000->5 it = 0 while 10 ** it <= max_num: buckets = [[] for _ in range(10)] for var in li: # 987 it=1 987//10->98 98%10->8; it=2 987//100->9 9%10=9 digit = (var // 10 ** it) % 10 buckets[digit].append(var) # 分桶完成 li.clear() for buc in buckets: li.extend(buc) # 把數從新寫回li it += 1