假設,有20個隨機整數,取值範圍是0到10,需要對其排序。可能第一反應是使用快速排序啊,快排的時間複雜度是o(nlog n)!但是,可不可以比o(nlog n)更快呢?這就是這篇文章要介紹的計數排序(從名字上來看,就是計算數字出現頻次的排序方法,非常的見名知意)。
因為取值範圍是0到10(整數的值在0,1,2,3,4,5,6,7,8,9,10裡),共有11個數值,所以需要11個坑,我們定義乙個長度是12的陣列array,每個元素的初始值是0,然後對20個隨機整數進行迴圈,對應的元素值加1。最後,輸出array,就是排好序的。
比如有20個整數,分別是 9,2,8,5,1,8,6,9,5,8,1,5,8,3,4,7,0,6,2,10
初始化陣列array
陣列下標01
2345
6789
10頻率00
0000
0000
0要排序的隨機整數,第乙個值是9,那陣列下標是9的分布值加1,所以array變成
陣列下標01
2345
6789
10頻率00
0000
0001
0第二個值是2,陣列下標是2的分布值加1
陣列下標01
2345
6789
10頻率00
1000
0001
0後面的以此類推。最終輸出array,元素的值是幾,就輸出幾次。這個陣列顯然是有序的了。
陣列下標01
2345
6789
10頻率12
2113
2142
1**如下
def sort(array):
# 1.獲取陣列內的最大值和最小值,來確定陣列的size
max = array[0]
min = array[0]
for i in array:
if i > max:
max = i
if i < min:
min = i
# 2.定義定長陣列,陣列的元素初始值是0(這裡偷懶使用了列表生成式)
sort_array = [0 for i in range(max - min + 1)]
# 3.計數
for i in array:
sort_array[i - min] = sort_array[i - min] + 1
# 4.獲得排序後的陣列
sortarray = [0 for i in array]
index = 0
for i, value in enumerate(countarray):
for j in range(1, value + 1):
sortarray[index] = i + min
index = index + 1
return sortarray
if __name__ == "__main__":
array = [9, 2, 8, 5, 1, 8, 6, 9, 5, 8, 1, 5, 8, 3, 4, 7, 0, 6, 2, 10]
sort_array = sort(array)
print(sort_array)
下面是輸出結果
[0, 1, 1, 2, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 8, 8, 9, 9, 10]
process finished with exit code 0
從**實現來看,也不複雜,甚至很簡單。
上面的演算法,因為有乙個雙重fou迴圈,還可以在優化下。
假設考試是十分制的,共有20個同學,同學的考試成績是上面的那20個數(9, 2, 8, 5, 1, 8, 6, 9, 5, 8, 1, 5, 8, 3, 4, 7, 0, 6, 2, 10),考試獲得9分的有兩個同學,那到底誰是第
二、誰是第三呢?
上面的**,需要公升級一下,頻率一欄,需要變成「分布值」了,它的值是上一格的值和自身的值之和
陣列下標01
2345
6789
10分布值
13(1+2)
5(3+2)
6(5+1)
7(6+1)
10(7+3)
12(10+2)
13(12+1)
17(13+4)
19(17+2)
20(19+1)
然後對分布值陣列輸出,第乙個是下標10的,遍歷之後分布值**的下標10的分布值就減1,它是第一名(總人數-分布值+1)
陣列下標01
2345
6789
10分布值13
56710
1213
1719
19(20-1)
假如獲得9分的是張三和李四,遍歷張三之後,**下標9的值減1,它是第二名(2 = 20-19 +1)
陣列下標01
2345
6789
10分布值13
56710
1213
1718(19-1)
19李四是第三名(3 = 20 -18 + 1)
陣列下標01
2345
6789
10分布值13
56710
1213
1717(18-1)
19這樣的話,相同分數的同學,就分出分數排名了。
def sort2(array):
# 1.獲取陣列內的最大值和最小值,來確定陣列的size
max = array[0]
min = array[0]
for i in array:
if i > max:
max = i
if i < min:
min = i
# 2.定義定長陣列,陣列的元素初始值是0(這裡偷懶使用了列表生成式)
countarray = [0 for i in range(max - min + 1)]
# 3.計數
for i in array:
countarray[i - min] = countarray[i - min] + 1
# 4.計數的陣列變形
sum = 0
for i,value in enumerate(countarray):
sum = sum + value
countarray[i] = sum
# 5.獲得排序後的陣列
sortarray = [0 for i in array]
for i in array:
sortarray[countarray[i - min] - 1] = i
countarray[i - min] = countarray[i - min] - 1
return sortarray
if __name__ == "__main__":
array = [9, 2, 8, 5, 1, 8, 6, 9, 5, 8, 1, 5, 8, 3, 4, 7, 0, 6, 2, 10]
sort_array = sort2(array)
print(sort_array)
假設array元素有n個,取值範圍是m。
時間複雜度:3n(步驟1、步驟3、步驟5) + m(步驟4),去掉係數,時間複雜度是o(n+m)
空間複雜度:只考慮統計陣列,那就是m
陣列的元素有小數。比如有乙個元素是1.001,這種建立統計陣列的話,那代價就太大太大了。
陣列內的元素跨度大。假如有十個數,最大是1000,最小是1,使用計排的話,得建立1000個長度的陣列,這顯然也不合適的。
排序演算法之計數排序
今在學習中,遇到計數排序演算法,雖然其對待排序的序列要求嚴格,但對於符合條件的序列來說,其時間複雜度很小。故列於此,僅為學習記憶。參考資料 對於僅由大寫字母 或小寫字母 構成的無序序列,可採用下面演算法進行排序。該演算法不在序列的每個元素間進行比較,而是使用了乙個額外的help整型字串來記錄每個元素...
線性排序之 計數排序
counting sort適用於排列分布比較集中的資料,即最大值和最小值相差不會太大,具體這個差在多少合適,還是以後值得我思考的問題?計數排序的演算法思想是需要分配3個陣列,original,counter original counter i counter i counter i 1 即計數為小...
演算法 排序之計數排序
最近想到演算法導論中的計數排序,看看理解的怎麼樣試著講講自己的理解。1 思想 計數排序 是 線性時間的 排序演算法,時間複雜度為o n 雖然有一定的侷限性。但是還是很好的一種演算法。用2個陣列進行額外的儲存資訊,陣列 c 是對 資料中值相同的 記錄下來,以便後面查閱 b 是輸出的有序陣列,再將有序的...