桶排序和計數排序
桶排序
在說計數排序之前需要先提一下桶排序,因為計數排序實際上可以被認為是一種特殊的桶排序。
桶排序,顧名思義,需要準備很多桶,比如在一次數學考試過后,需要給同學們按成績高低排個序,學生人數是56,成績最低為0分,滿分為120。
我們就可以準備6個桶:A、B、C、D、E、F,每個桶存放不同區段的成績。
F桶:0~20
E桶:21~40
D桶:41~60
C桶:61~80
B桶:81~100
A桶:101~120
遍歷一遍數據將成績放入不同的桶里面之后,再對每個桶里面的數據進行快速排序,然后將排好序的數據按FEDCBA的順序合在一起。
桶排序時間復雜度分析
- 遍歷一次,將數據放入對應的桶中,
- 假設數據分散比較均勻,被分到k個桶中,每個桶中數據大概是
- 每個桶內的快速排序為
- 綜合一下,桶排序的時間復雜度是
- 當k無限趨近與n的時候,
無限等于1,此時桶排序的時間復雜度是O(n)
計數排序
計數排序可以認為就是一種特殊的桶排序,特殊在哪兒呢?計數排序的桶個數和要排序的數據的范圍一致,比如上面數據考試成績排序的問題,計數排序的思想就是根據范圍0~120來建立121個桶,將數據分布在121個桶。因為每個桶內的數據是相等的,這樣就不用再進行桶內排序了,直接按桶順序合起來就可以了。
計數排序代碼實現
"""
計數排序
Author: xingrui
"""
# 最大值
def maxNum(nums: list):
maxNumber = nums[0]
for number in nums[1:]:
if maxNumber < number:
maxNumber = number
return maxNumber
# 計數排序
def countSort(nums: list):
maxNumber = maxNum(nums)
# 初始化數組大小
countArray = [0] * (maxNumber + 1)
# 將原始數組的每個元素出現次數放到countArray中計數
for number in nums:
countArray[number] += 1
# 累加countArray中的元素,得出在最后結果中的位置關系
for i, item in enumerate(countArray):
if i == 0:
continue
else:
countArray[i] += countArray[i - 1]
result = [0] * len(nums)
for item in nums[::-1]:
countArray[item] -= 1
index = countArray[item]
result[index] = item
return result
if __name__ == "__main__":
nums = [2, 3, 1, 3, 0, 5, 4, 2]
print(countSort(nums))
基數排序
基數排序
基數排序適用的情景比較特殊,需要數據本身是有層次的,比如對單詞進行排序,對手機號進行排序,排序的時候會將每個手機號同一個位置的字符拿出來用計數排序或者桶排序來排序。
代碼實現
"""
基數排序
Author: xingrui
"""
# 最大值
def maxLength(words: list) -> int:
length = len(words[0])
for word in words[1:]:
if length < len(word):
length = len(word)
return length
# 自動補全
def autoComplete(words: list, length: int):
for i, item in enumerate(words):
if len(item) < length:
words[i] = item + "".join(["0"] * (length - len(item)))
# 基數排序
def radixSort(words: list):
length = maxLength(words)
autoComplete(words, length)
for index in range(length - 1, -1, -1):
countSort(words, index)
for i, word in enumerate(words):
words[i] = str(word).strip("0")
# 計數排序
def countSort(words: list, index: int):
# 初始化數組大小,ASCII中小寫字母z對應的數字是122
countArray = [0] * 123
# 將原始數組的每個元素出現次數放到countArray中計數
for word in words:
letter = word[index]
countArray[ord(letter)] += 1
# 累加countArray中的元素,得出在最后結果中的位置關系
for i, item in enumerate(countArray):
if i == 0:
continue
else:
countArray[i] += countArray[i - 1]
result = [0] * len(words)
for item in words[::-1]:
letter = item[index]
ascii = ord(letter)
countArray[ascii] -= 1
result[countArray[ascii]] = item
if __name__ == "__main__":
words = ["admin", "activity", "birdcage", "heel", "cushion", "fruit",
"background", "bride", "horse", "zebra", "juice", "bridegroom"]
radixSort(words)
print(words)
參考
http://www.lxweimin.com/p/28ed6963276c
http://www.lxweimin.com/p/0aff57aa5f8d
http://www.lxweimin.com/p/be8842b1e5dc