Python 堆排序:如何排序?
我试图在Python中实现堆排序,但似乎做得不对。我已经尝试实现了这个,但是我的代码没有排序!它只是筛选到荒谬的效果。我倾向于认为问题在这方面: 将堆的根(最大值)与堆的最后一个元素交换 如何获得最大值 这就是我所拥有的:Python 堆排序:如何排序?,python,sorting,computer-science,heapsort,Python,Sorting,Computer Science,Heapsort,我试图在Python中实现堆排序,但似乎做得不对。我已经尝试实现了这个,但是我的代码没有排序!它只是筛选到荒谬的效果。我倾向于认为问题在这方面: 将堆的根(最大值)与堆的最后一个元素交换 如何获得最大值 这就是我所拥有的: def my_heap_sort(sqc): def heapify(count): start = (count-2)/2 while s
def my_heap_sort(sqc):
def heapify(count):
start = (count-2)/2
while start >= 0:
sift_down(start, count-1)
start -= 1
def swap(i, j):
sqc[i], sqc[j] = sqc[j], sqc[i]
def sift_down(start, end):
root = start
while (root * 2 + 1) <= end:
child = root * 2 + 1
temp = root
if sqc[temp] < sqc[child]:
temp = child+1
if temp != root:
swap(root, temp)
root = temp
else:
return
count = len(sqc)
heapify(count)
end = count-1
while end > 0:
swap(end, 0)
end -= 1
sift_down(0, end)
选择排序是一种相对直接的排序算法: 遍历数组,提取前n个元素的最小值,然后提取下n-1个元素的最小值。。。。。。 这就是O(n^2)算法 由于您总是提取最小值,因此应该考虑使用最小堆。它在O(logn)时间内提取一分钟。提取min n次导致O(n*logn)时间 因此,对于堆排序,只需要构建一个堆(heapifyo(n)),然后遍历数组并提取min n次 您可以使用python构建堆或构建自己的堆
def heapsort(l):
hp = make_heap(l)
for i in range(len(l)):
yield hp.extract_min()
如何获取最大值?您不需要“获取”它。根正好是最大值,这是堆的一个已定义属性 如果您觉得难以理解堆排序,将非常有帮助
我重写了你的代码:
def swap(i, j):
sqc[i], sqc[j] = sqc[j], sqc[i]
def heapify(end,i):
l=2 * i + 1
r=2 * (i + 1)
max=i
if l < end and sqc[i] < sqc[l]:
max = l
if r < end and sqc[max] < sqc[r]:
max = r
if max != i:
swap(i, max)
heapify(end, max)
def heap_sort():
end = len(sqc)
start = end // 2 - 1 # use // instead of /
for i in range(start, -1, -1):
heapify(end, i)
for i in range(end-1, 0, -1):
swap(i, 0)
heapify(i, 0)
sqc = [2, 7, 1, -2, 56, 5, 3]
heap_sort()
print(sqc)
我找到了它,几乎想知道它是如何工作的:
def heapsort(sqc):
def down_heap(sqc, k, n):
parent = sqc[k]
while 2*k+1 < n:
child = 2*k+1
if child+1 < n and sqc[child] < sqc[child+1]:
child += 1
if parent >= sqc[child]:
break
sqc[k] = sqc[child]
k = child
sqc[k] = parent
size = len(sqc)
for i in range(size/2-1, -1, -1):
down_heap(sqc, i, size)
for i in range(size-1, 0, -1):
sqc[0], sqc[i] = sqc[i], sqc[0]
down_heap(sqc, 0, i)
def heapsort(sqc):
def向下堆(sqc、k、n):
父项=sqc[k]
当2*k+1=sqc[子级]:
打破
sqc[k]=sqc[child]
k=儿童
sqc[k]=父级
尺寸=长度(sqc)
对于范围内的i(尺寸/2-1,-1,-1):
下堆(sqc、i、尺寸)
对于范围内的i(尺寸-1,0,-1):
sqc[0],sqc[i]=sqc[i],sqc[0]
向下堆(sqc,0,i)
编辑:
这个实现是基于我自己对算法的理解编写的。它更长,但对我来说,这个算法在这个实现中更清晰。当您需要理解算法时,长名称是有帮助的,所以我保留了所有长名称
def heapsort(sequence):
sequence_length = len(sequence)
def swap_if_greater(parent_index, child_index):
if sequence[parent_index] < sequence[child_index]:
sequence[parent_index], sequence[child_index] =\
sequence[child_index], sequence[parent_index]
def sift(parent_index, unsorted_length):
index_of_greater = lambda a, b: a if sequence[a] > sequence[b] else b
while parent_index*2+2 < unsorted_length:
left_child_index = parent_index*2+1
right_child_index = parent_index*2+2
greater_child_index = index_of_greater(left_child_index,
right_child_index)
swap_if_greater(parent_index, greater_child_index)
parent_index = greater_child_index
def heapify():
for i in range((sequence_length/2)-1, -1, -1):
sift(i, sequence_length)
def sort():
count = sequence_length
while count > 0:
count -= 1
swap_if_greater(count, 0)
sift(0, count)
heapify()
sort()
def heapsort(顺序):
序列长度=len(序列)
def交换如果大于(父索引、子索引):
如果序列[父索引]<序列[子索引]:
序列[父索引],序列[子索引]=\
序列[子索引],序列[父索引]
def sift(父索引,未排序的长度):
大于的索引=λa,b:a如果序列[a]>序列[b]否则b
而父索引*2+2<未排序的长度:
左\子\索引=父\索引*2+1
右\子\索引=父\索引*2+2
更大的子索引=更大的索引(左子索引,
右(子索引)
如果大于,则交换(父索引,子索引)
父索引=更大的子索引
def heapify():
对于范围内的i((序列长度/2)-1,-1,-1):
筛选(i,序列长度)
def sort():
计数=序列长度
当计数>0时:
计数-=1
如果_大于(计数,0),则交换_
筛选(0,计数)
希皮菲()
排序()
编辑:
和优化版本:
def opt_heapsort(s):
sl = len(s)
def swap(pi, ci):
if s[pi] < s[ci]:
s[pi], s[ci] = s[ci], s[pi]
def sift(pi, unsorted):
i_gt = lambda a, b: a if s[a] > s[b] else b
while pi*2+2 < unsorted:
gtci = i_gt(pi*2+1, pi*2+2)
swap(pi, gtci)
pi = gtci
# heapify
for i in range((sl/2)-1, -1, -1):
sift(i, sl)
# sort
for i in range(sl-1, 0, -1):
swap(i, 0)
sift(0, i)
def opt_heapsort(s):
sl=透镜(s)
def交换(pi、ci):
如果s[pi]s[b]否则b
而pi*2+2<未排序:
gtci=i_gt(π*2+1,π*2+2)
交换(pi、gtci)
pi=gtci
#希皮菲
对于范围((sl/2)-1,-1,-1)内的i:
筛选(i,sl)
#分类
对于范围内的i(sl-1,0,-1):
互换(i,0)
筛选(0,i)
我发现heapify(堆排序的“核心”)的不同实现在internetz上并不清楚。下面是我谦虚的尝试,通过添加一个简单但清晰的“heapify”示例来帮助社区。我使用向量来避免数组操作带来的额外混乱
此方法对数组中的1个单元格进行重排序。
使整体健康
def heapsort(sqc):
def down_heap(sqc, k, n):
parent = sqc[k]
while 2*k+1 < n:
child = 2*k+1
if child+1 < n and sqc[child] < sqc[child+1]:
child += 1
if parent >= sqc[child]:
break
sqc[k] = sqc[child]
k = child
sqc[k] = parent
size = len(sqc)
for i in range(size/2-1, -1, -1):
down_heap(sqc, i, size)
for i in range(size-1, 0, -1):
sqc[0], sqc[i] = sqc[i], sqc[0]
down_heap(sqc, 0, i)
def heapsort(sequence):
sequence_length = len(sequence)
def swap_if_greater(parent_index, child_index):
if sequence[parent_index] < sequence[child_index]:
sequence[parent_index], sequence[child_index] =\
sequence[child_index], sequence[parent_index]
def sift(parent_index, unsorted_length):
index_of_greater = lambda a, b: a if sequence[a] > sequence[b] else b
while parent_index*2+2 < unsorted_length:
left_child_index = parent_index*2+1
right_child_index = parent_index*2+2
greater_child_index = index_of_greater(left_child_index,
right_child_index)
swap_if_greater(parent_index, greater_child_index)
parent_index = greater_child_index
def heapify():
for i in range((sequence_length/2)-1, -1, -1):
sift(i, sequence_length)
def sort():
count = sequence_length
while count > 0:
count -= 1
swap_if_greater(count, 0)
sift(0, count)
heapify()
sort()
def opt_heapsort(s):
sl = len(s)
def swap(pi, ci):
if s[pi] < s[ci]:
s[pi], s[ci] = s[ci], s[pi]
def sift(pi, unsorted):
i_gt = lambda a, b: a if s[a] > s[b] else b
while pi*2+2 < unsorted:
gtci = i_gt(pi*2+1, pi*2+2)
swap(pi, gtci)
pi = gtci
# heapify
for i in range((sl/2)-1, -1, -1):
sift(i, sl)
# sort
for i in range(sl-1, 0, -1):
swap(i, 0)
sift(0, i)
for (int i = myvector.size()/2; i >= 0; i--) { in = Heapify(in, i);}
vector_of_int Sort::Heapify(vector_of_int in_vector, int in_index)
{
int min_index = in_index; // Track index of smallest out of parent and two children.
int left_child_index = 0;
int right_child_index = 0;
int vector_size = in_vector.size();
left_child_index = LeftChildIndex(in_index);// index of left child, at position 2*in_index
right_child_index = left_child_index + 1;// index of right child, at position 2*in_index + 1
// If left_child_index is not overflowing, suggest swap...
if ((left_child_index) < vector_size)
{
// If parent larger than left child, min_index remembers left child position
if (in_vector[min_index] > in_vector[left_child_index])
{ min_index = left_child_index; }
}
// If right_child_index is is not overflowing, suggest swap...
if (right_child_index < vector_size)
{
// If parent larger than right child, min_index remembers right child position
if (in_vector[min_index] > in_vector[right_child_index])
{ min_index = right_child_index; }
}
// Now min_index has the index of the smallest out of parent and it's two children.
// If the smallest is not the parent, swap parent and smallest.
if (min_index != in_index)
{
in_vector = swap(in_vector, in_index ,min_index);
in_vector = Heapify(in_vector, min_index); // RECURSION IS HERE
}
return in_vector;
}
// End heapify
def findMin(heapArr,i,firstChildLoc,secondChildLoc):
a = heapArr[i]
b = heapArr[firstChildLoc]
c = heapArr[secondChildLoc]
return i if ((a < b) and (a < c)) else firstChildLoc if (b < c) else secondChildLoc
def prelocateUp(heapArr):
l = len(heapArr)
i = l-1
while True:
parentLoc = (i+1)/2 - 1
if parentLoc >= 0:
if heapArr[parentLoc] > heapArr[i]:
temp = heapArr[parentLoc]
heapArr[parentLoc] = heapArr[i]
heapArr[i] = temp
else :
break
i = parentLoc
return heapArr
def prelocateDown(heapArr):
l = len(heapArr)
i = 0
while True:
firstChildLoc = 2*(i+1) - 1
secondChildLoc = 2*(i+1)
if (firstChildLoc > l-1):
break
elif (secondChildLoc > l-1):
if heapArr[i] > heapArr[firstChildLoc]:
temp = heapArr[i]
heapArr[i] = heapArr[firstChildLoc]
heapArr[firstChildLoc] = temp
break
else :
minLoc = findMin(heapArr,i,firstChildLoc,secondChildLoc)
if minLoc !=i:
temp = heapArr[i]
heapArr[i] = heapArr[minLoc]
heapArr[minLoc] = temp
i = minLoc
else :
break
return heapArr
def heapify(heapArr,op):
if op==1:
heapArr = prelocateUp(heapArr)
else :
heapArr = prelocateDown(heapArr)
return heapArr
def insertHeap(heapArr,num):
heapArr.append(num)
heapArr = heapify(heapArr,1)
return heapArr
def getMin(heapArr):
ele = heapArr[0]
heapArr[0] = heapArr[-1]
heapArr.pop(-1)
heapArr = heapify(heapArr,2)
return ele,heapArr
a=[5,4,8,2,6]
heapArr = []
for i in xrange(0,len(a)):
heapArr = insertHeap(heapArr,a[i])
#No
sortedArr = []
for i in xrange(0,len(a)):
[ele,heapArr] = getMin(heapArr)
sortedArr.append(ele)
print sortedArr
from heapq import heappush, heappop
def heapsort(iterable):
h = []
for value in iterable:
heappush(h, value)
return [heappop(h) for i in range(len(h))]
heapsort([1, 3, 5, 7, 9, 2, 4, 6, 8, 0])
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
**Heap Sorting on any given Number,Below Program will first convert it into binary heap tree and then its performing heap sorting**
class HeapSort():
def __init__(self):
self.hst_list=[None]
self.final_list=[]
def add_element(self,value):
self.hst_list.append(value)
def build_hst(self):
for _ in range((len(self.hst_list)//2)):
self.convert_into_hst()
def get_left_child(self,idx):
for m in range(len(self.hst_list)):
if m==2*idx:
return self.hst_list[2*idx]
return 999
def get_right_child(self,idx):
for m in range(len(self.hst_list)):
if m==2*idx+1:
return self.hst_list[2*idx+1]
return 999
def convert_into_hst(self):
i=1
while i<=len(self.hst_list)//2:
left_child=self.get_left_child(i)
right_child=self.get_right_child(i)
if self.hst_list[i]>=left_child:
p_val=self.hst_list[i]
self.hst_list[i]=left_child
self.hst_list[2*i]=p_val
#print(self.hst_list)
elif self.hst_list[i]>=right_child:
p_val=self.hst_list[i]
self.hst_list[i]=right_child
self.hst_list[2*i+1]=p_val
i=i+1
def print_hst(self):
print(self.hst_list)
print(self.final_list)
def perform_sorting(self):
for i in range(1,len(self.hst_list)):
self.perform_heap_sorting()
def perform_heap_sorting(self):
self.final_list.append(self.hst_list[1])
self.hst_list.pop(1)
self.build_hst()
print(self.final_list)
hst_obj=HeapSort()
hst_obj.add_element(10)
hst_obj.add_element(5)
hst_obj.add_element(5)
hst_obj.add_element(30)
hst_obj.add_element(15)
hst_obj.add_element(50)
hst_obj.add_element(25)
hst_obj.add_element(35)
hst_obj.add_element(1)
hst_obj.add_element(100)
hst_obj.build_hst()
hst_obj.perform_sorting()