1. 程式人生 > >排序演算法之python堆排序

排序演算法之python堆排序

堆排序

介紹:

    堆排序也是一種選擇排序。每趟從待排序的記錄中選出關鍵字最小的記錄,順序放在已排序的記錄序列末尾,直到全部排序結束為止。跟簡單選擇排序不同的是待排序的待排序列是利用二叉樹這種資料結構儲存的。相比之下是更優化的。

思想:

首先,要介紹一下堆。堆是一課順序儲存的完全二叉樹。有大根堆和小根堆。若每個結點的的key不小於其孩子結點的key,此時叫大根堆;若每個結點的的key不大於其孩子結點的key,此時叫小根堆。

比如,序列{k1,k2,...,kn},滿足以下條件:

1.ki <= k2i+1 且 ki <= k2i+2 (小根堆)

2.ki >= k2i+1 且 ki >= k2i+2 (大根堆)

對於一個堆序列,為了方便,我們這裡使用大根堆,可分為兩個步驟,第一先建堆,第二把堆頂元素與最後一個元素互換位置。即最大元素輸出,再把剩下的元素調整成大根堆。直到大根堆為空,則堆排序完成。

這裡我舉一個例子

程式碼:

def HeapSort(input_list):
	
	#調整parent結點為大根堆
	def HeapAdjust(input_list,parent,length):
		
		temp = input_list[parent]
		child = 2*parent+1
		
		while child < length:
			if child+1 <length and input_list[child] < input_list[child+1]:
				child +=1
			
			if temp > input_list[child]:
				break
			input_list[parent] = input_list[child]
			parent = child
			child = 2*child+1
		input_list[parent] = temp
	
	if input_list == []:
		return []
	sorted_list = input_list
	length = len(sorted_list)
	#最後一個結點的下標為length//2
	#建立初始大根堆
	for i in range(0,length // 2 +1)[::-1]:
		HeapAdjust(sorted_list,i,length)
	
	for j in range(1,length)[::-1]:
		#把堆頂元素即第一大的元素與最後一個元素互換位置
		temp = sorted_list[j]
		sorted_list[j] = sorted_list[0]
		sorted_list[0] = temp
		#換完位置之後將剩餘的元素重新調整成大根堆
		HeapAdjust(sorted_list,0,j)
		print('%dth' % (length - j))
		print(sorted_list)
	return sorted_list
	
		
if __name__ == '__main__':
	input_list = [50,123,543,187,49,30,0,2,11,100]
	print("input_list:")
	print(input_list)
	sorted_list = HeapSort(input_list)
	print("sorted_list:")
	print(input_list)

結果:

input_list:
[50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
1th
[187, 123, 50, 49, 100, 30, 0, 2, 11, 543]
2th
[123, 100, 50, 49, 11, 30, 0, 2, 187, 543]
3th
[100, 49, 50, 2, 11, 30, 0, 123, 187, 543]
4th
[50, 49, 30, 2, 11, 0, 100, 123, 187, 543]
5th
[49, 11, 30, 2, 0, 50, 100, 123, 187, 543]
6th
[30, 11, 0, 2, 49, 50, 100, 123, 187, 543]
7th
[11, 2, 0, 30, 49, 50, 100, 123, 187, 543]
8th
[2, 0, 11, 30, 49, 50, 100, 123, 187, 543]
9th
[0, 2, 11, 30, 49, 50, 100, 123, 187, 543]
sorted_list:
[0, 2, 11, 30, 49, 50, 100, 123, 187, 543]

分析:

1.演算法效能

2.時間複雜度

時間複雜度分為兩部分

第一是建立初始堆,建立堆的T(n)=O(n)

	#建立初始大根堆
	for i in range(0,length // 2 +1)[::-1]:
		HeapAdjust(sorted_list,i,length)

第二部分是排序的T(n),因為HeapAdjust()是logn,一共執行n次,故T(n)=O(nlogn)

因此總的時間複雜度為O(nlogn)

	for j in range(1,length)[::-1]:
		#把堆頂元素即第一大的元素與最後一個元素互換位置
		temp = sorted_list[j]
		sorted_list[j] = sorted_list[0]
		sorted_list[0] = temp
		#換完位置之後將剩餘的元素重新調整成大根堆
		HeapAdjust(sorted_list,0,j)

3.演算法穩定性

不穩定,在比較關鍵字和交換時會導致關鍵字的順序改變。但是,堆是一種順序儲存方式,故當想求得序列中第k個最小元素之前的部分排序序列,最好採用堆排序