- 课本上给出了合并有序序列的代码,思路简单,直接看课本,上代码:
#coding=utf-8
from collections import namedtuple
import heapq
def mergeKSortedArrays(alist):
h = list() # 最小堆
res= list() # 合并后的输出
heapContent = namedtuple('contents', ('elem', 'array_idx', 'array_elem_idx'))
# 每一个序列k的第一个元素按照堆结构组织
for i, k in enumerate(alist):
heapq.heappush(h, heapContent(k[0],i,1))
total_elems = len(alist)* len(alist[0])
for _ in range(0, total_elems):
popped = heapq.heappop(h)
if popped.elem == float("inf"):
continue
res.append(popped.elem) # 将堆中最小元素弹出并加入到res中
next_array = popped.array_idx
next_elem_idx = popped.array_elem_idx
if next_elem_idx < len(alist[next_array]):
# 将被移除出堆所属的序列的下一个元素插入到当前堆中
heapq.heappush(h, heapContent(alist[next_array][next_elem_idx], \
next_array, next_elem_idx+1))
else:
# 如果没有元素在当前序列中,则插入一个最大整数
heapq.heappush(h, heapContent(float("inf"),next_array, float("inf")))
return res
if __name__ == "__main__":
#A = [ [1, 3, 5, 7],[2, 4, 6, 8],[0, 9, 10, 11],]
A = [[5, 10, 13, 17], [2, 4, 7, 8], [3, 6, 11, 15]]
print(A)
print(mergeKSortedArrays(A))
- 但是没发现这种超级啰嗦吗?我们来个简单的:
from __future__ import print_function
import heapq
import random
data = [[5, 10, 13, 17], [2, 4, 7, 8], [3, 6, 11, 15]]
for i,d in enumerate(data):
print('{}:{}'.format(i,d))
print('\nMerged:')
for i in heapq.merge(*data): #Merge multiple sorted inputs into a single sorted output
print(i,end=' ')
print()
- 复杂的课本上有讲解,我们按照课本的思路分析下这个简单的代码。可以看到主要使用了heapq.merge函数,这个函数的输入是可迭代对象。
- 接下来琢磨下里边的思路:我们使用了教材上的数据,所以将3个数组中的第一个元素取出来,分别是:
[[5, 0, ], [2, 1, ], [3, 2, ]]
,应该能看懂吧?5是第0个序列中的第1个元素,2是第1个序列中的第1个元素,3是第2个序列中的第2个元素,后面的是迭代器中的信息,可以忽略。
- 接下来将这3个元素存入堆中,使用了heapify函数,类似于我们前面的buildheap函数。但这里是小根堆呀,所以输出根节点2;
- 将根节点2对应的下一个元素插入堆的根位置,找呀找,是4;根据小根堆性质,输出根节点3;
- 将根节点3对应的下一个元素插入堆的根位置是6;根据小根堆性质,输出根节点4;
- 将根节点4对应的下一个元素插入堆的根位置是7;根据小根堆性质,输出根节点5;
- 将根节点5对应的下一个元素插入堆的根位置是10;根据小根堆性质,输出根节点6;
- 将根节点6对应的下一个元素插入堆的根位置是11;根据小根堆性质,输出根节点7;
- blablabal…后面的就不废话了!看结果 :
0:[5, 10, 13, 17]
1:[2, 4, 7, 8]
2:[3, 6, 11, 15]
Merged:
2 3 4 5 6 7 8 10 11 13 15 17
- 总结:库函数非常?啊!