-
Notifications
You must be signed in to change notification settings - Fork 1
/
heap.py
126 lines (109 loc) · 3.65 KB
/
heap.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# coding=utf-8
"""
用python自己实现heap
"""
class Heap(object):
def __init__(self):
# 数据从索引1开始,第0个位置存放0
self.heap_list = [0]
self.current_size = 0
def insert(self, k):
# 把元素k插入最小堆
self.heap_list.append(k)
self.current_size += 1
self.per_up(self.current_size)
def perc_up(self, i):
# 调整第i个元素,使heap_list成为最小堆
self.heap_list[0] = self.heap_list[i]
while i//2 > 0 and self.heap_list[0] < self.heap_list[i//2]:
self.heap_list[i] = self.heap_list[i//2]
i = i//2
self.heap_list[i] = self.heap_list[0]
def del_min(self):
# 删除最小堆的元素,使剩下的元素还是最小堆
if self.current_size < 1:
return
del_item = self.heap_list[1]
self.heap_list[1] = self.heap_list[self.current_size]
self.current_size -= 1
self.heap_list.pop()
self.perc_down(1)
return del_item
def perc_down(self, i):
# 删除元素之后,调整元素,使成为最小堆
while i <= self.current_size//2:
# 找到左右两个孩子中较小那一个的索引
if 2*i+1 > self.current_size:
min_index = 2*i
else:
if self.heap_list[2*i] < self.heap_list[2*i+1]:
min_index = 2*i
else:
min_index = 2*i+1
# 从根节点开始调整元素
if self.heap_list[i] > self.heap_list[min_index]:
self.heap_list[i], self.heap_list[min_index] = self.heap_list[min_index], self.heap_list[i]
i = min_index
else:
break
def build_heap(self, alist):
"""
利用数组alist里的多个元素,组成一个最小堆
从第一个非叶子节点开始,也就是i//2, 每个节点下沉,把最小值往上浮,直到根节点为止
:param alist:
:return:
"""
self.current_size = len(alist)
self.heap_list = [0] + alist[:]
i = len(alist)//2
while i > 0:
self.perc_down(i)
i -= 1
"""
下面的堆索引从0开始
iparent = index
i_left = index*2+1
i_right = index*2+2
"""
def swap(array, i, j):
array[i], array[j] = array[j], array[i]
def build_max_heapify(array):
# 把一个数组变成最大堆
# 按照数组原样画一个完全二叉树出来,从第一个非叶子节点i开始,以i为根节点,构建max_heap
n = len(array)
# 第一个非叶子节点
i_parent = n//2-1
while i_parent >= 0:
max_heapify(array, i_parent, n)
i_parent -= 1
def max_heapify(array, index, heapsize):
# 把节点index为根的堆变成最大堆
while 2*index+1 < heapsize:
i_left = 2*index+1
i_right = i_left+1
if i_right >= heapsize:
max_index = i_left
else:
if array[i_left] < array[i_right]:
max_index = i_right
else:
max_index = i_left
if array[index] < array[max_index]:
swap(array, index, max_index)
index = max_index
else:
break
def heap_sort(alist):
heapsize = len(alist)
build_max_heapify(alist)
# 再把alist最后一个元素之外的列表设为最大堆
for i in range(heapsize-1, 0, -1):
# 把最大堆的最大值放到alist末尾
swap(alist, 0, i)
max_heapify(alist, 0, i)
if __name__ == '__main__':
alist = [2,3,10,4,20,21,0,-1]
heap_sort(alist)
print alist
import heapq
print heapq.nlargest(2, alist)