標籤:局限性 return 覆蓋 排序 div 重寫 class 需要 演算法實現
參考部落格:常用排序演算法總結(二)
計數排序 counting sort
1.計數排序是一種非常快捷的穩定性強的排序方法,時間複雜度O(n+k),其中n為要排序的數的個數,k為要排序的數的組大值。計數排序對一定量的整數排序時候的速度非常快,一般快於其他排序演算法。但計數排序局限性比較大,只限於對整數進行排序。計數排序是消耗空間發雜度來擷取快捷的排序方法,其空間發展度為O(K)同理K為要排序的最大值。
2.計數排序的基本思想為一組數在排序之前先統計這組數中其他數小於這個數的個數,則可以確定這個數的位置。例如要排序的數為 7 4 2 1 5 3 1 5;則比7小的有7個數,所有7應該在排序好的數列的第八位,同理3在第四位,對於重複的數字,1在1位和2位(暫且認為第一個1比第二個1小),5和1一樣位於6位和7位。
計數排序非常基礎,他的主要目的是對整數排序並且會比普通的排序演算法效能更好。例如,輸入{1, 3, 5, 2, 1, 4}給計數排序,會輸出{1, 1, 2, 3, 4, 5}。這個演算法由以下步驟組成:
初始化一個計數數組,大小是輸入數組中的最大的數。
遍曆輸入數組,遇到一個數就在計數數組對應的位置上加一。例如:遇到5,就將計數數組第五個位置的數加一。
把計數數組直接覆蓋到輸出數組(節約空間)。
時間複雜度:O(n)
統計一個列表內每個元素出現的個數。用於小規模範圍內計算!
弊端:
有限定!為排序需要建立一個列表,開闢一塊記憶體空間,而且這個空間的大小取決於排序列表的最大值。
如果一個要排序的列表中僅有,【1,10000】這兩個數,那麼我們統計的話,建立的用於計數的列表就要開一一個可以存放10000個數的記憶體空間。這樣導致的結果就是,其他的數無用並且損耗效能,時間複雜度沒變但是空間複雜度增加了!這也間接的暴露了範圍取值的弊端。
演算法實現:
def count_sort(li, maxnum=100): """ 建立一個列表,往列表內寫值 :param li: :param maxnum: :return: """ count = [0 for i in range(maxnum+1)] #建立用以計數的所有元素都是0的列表, result = [] for i in li: #遍曆要計數的列表,每個元素對應的索引位置的數加1 count[i] += 1 for num, count in enumerate(count): #對已經完成計數的列表進行枚舉列印,格式(數字,次數) for i in range(count): #再通過次數建立一個迴圈,出現多少次就把對應的數寫入列表多少次 result.append(num)def count_sorts(li, max_num): """ 僅在當前列表下操作,按照次數重寫列表 :param li: :param max_num: :return: """ count = [0 for i in range(max_num + 1)] for num in li: count[num] += 1 i = 0 for num,m in enumerate(count): for j in range(m): li[i] = num i += 1 return lili = [3,4,1,2,5,6,6,5,4,3,3]print(count_sorts(li,max(li)))
應用:
有一個數組[3,4,1,2,5,6,6,5,4,3,3]請寫一個函數,找出該數組中沒有重複的數的總和(上面的沒有重複數的總和為 1+2=3)。
def count_sorts(li, max_num): """ 計數排序引申,求和 :param li: 傳入的列表 :param max_num:列表中最大值 :return:和 sums """ counts = [0 for i in range(max_num + 1)] for num in li: counts[num] += 1 sums = 0 for num,count in enumerate(counts): # print(num,count) #列印列表內對應數字出現的次數 if count == 1: sums += num return sumsli = [3,4,1,2,5,6,6,5,4,3,3]print(count_sorts(li,max(li)))
演算法 計數排序