堆排序需要解决两个问题:1.如何由一个无序序列建成一个堆 2.如何在输出堆顶元素后调整剩余元素成为一个新的堆。
其实两个问题就是一个问题,就是如何调整剩余元素成为一个新的堆。
筛选:筛选是从第n/2向下取整个元素开始的,如果看成是完全二叉树,那么肯定是第n/2向下取整的非终端结点。
堆排序:一个无序序列建堆的过程就是一个反复筛选的过程。
def heapsort(data):
###建立小根堆
data.insert(0,0)
print('创建小根堆之前的数组:', data)
data = buildMinHeap(data)
return data
def buildMinHeap(data):
data_l = len(data)
for j in range(int(data_l/2),0,-1):
data[0] = data[j]
t = j
i = t * 2
while i < data_l:
if i+1 < data_l:###右子树存在
if data[i] < data[t] and data[i] < data[i+1]: ###如果左子树最小
tmp = data[i]
data[i] = data[t]
data[t] = tmp
t = i
i = t*2
elif data[i] < data[t] and data[i] > data[i+1]: ###如果右子树最小 左子树次之 右子树和根交换
tmp = data[i+1]
data[i+1] = data[t]
data[t] = tmp
t = i + 1
i = t * 2
elif data[i+1] < data[t] and data[i] > data[t]:#右子树最小
tmp = data[i + 1]
data[i + 1] = data[t]
data[t] = tmp
t = i + 1
i = t * 2
else:
break
else:
if data[i] < data[0]:##如果左子树小于根
tmp = data[t]
data[t] = data[i]
data[i] = tmp
t = i
i = t * 2
else:
break
#print(data[1:])
return data[1:]
if __name__ == '__main__':
#data= [49,38,65,97,76,13,27,49]
data = [0,23,12,34,23,124]
data_l = len(data)
num = []
for m in range(data_l):
if m==0:
data = data[m:]
else:
data = data[1:]
data = heapsort(data)
print('删除根元素的数组', data)
num.append(data[0])
print(num)
def sort(arr):
###1 构建大顶堆
n = len(arr)
for i in range(n//2-1,-1,-1):
##从第一个非叶子节点从下至上从右至左调整结构
adjustHeap(arr,i,n)
###2 调整堆结构 + 交换堆顶和堆尾堆元素 注意第一次交换时是
for j in range(n-1,-1,-1):
swap(arr, 0, j) # 将堆顶元素与末尾元素进行交换
adjustHeap(arr,0,j)
print(arr)
###t表示第t个元素,保证第t个元素之前是有序的
def adjustHeap(arr,t,n):
##取出当前元素,父节点元素
tmp = arr[t]
k = 2 * t +1
while k < n :
if k + 1 < n and arr[k] < arr[k+1]: ##如果左节点小于右节点,指向右节点
k += 1
if arr[k] > tmp:#如果右节点大于父节点,右节点覆盖父节点不交换
arr[t] = arr[k]
t = k
else:
break
k = k * 2 + 1 ###如果
arr[t] = tmp
def swap(arr, i, j):
t = arr[i]
arr[i] = arr[j]
arr[j] = t
arr = [93,2,78,62,5,4,32,12,10]
sort(arr)