堆排序
个人总结:
1)你需要确定你要使用堆排序得到顺序数组(小到大),还是逆序数组(大到小):
若是顺序数组:你需要编写一个函数得到大顶堆,也就是,把二叉树中最大的元素调换到根节点位置。
若是逆序数组:则相反,将二叉树调整为小顶堆,即最小元素在根节点。
2)堆排序最复杂的部分就是如何将二叉树调整为大顶堆和小顶堆。使用3,1,2这三个数来解释一下,假设3为二叉树的根节点,1为左子树,2为右子树。调整步骤为:
- 先比较左子树和右子树的大小,记录较大元素的下标。
- 再比较子树较大元素和根节点元素,若根节点小于它,则交换两者位置。
注:其次是如何处理更为复杂的二叉树,其实就是循环的找出所有非叶子节点。这里有个公式可以计算非叶子节点的下标,index=2*i+1。
3)最后就是再找出最大值和最小值后,与二叉树的最后一个位置进行交换,然后再它的基础上重复进行寻找最大值和最小值的操作,并进行交换。
import time
import random
arr = [0 for i in range(800000)]
for i in range(800000):
arr[i]=random.randint(0,800000)
def heapSort(arr):
print("堆排序")
i = int(len(arr)/2)-1
while i>=0:
adjustHeap(arr,i,len(arr))
i-=1
#print(arr)
#处理大顶堆的子树
j=len(arr)-1
while j>0:
#交换
temp=arr[j]
arr[j]=arr[0]
arr[0]=temp
adjustHeap(arr,0,j)
j-=1
print(arr)
#功能:将非叶子节点调整为大顶堆
#arr为数组,i为父节点索引,length为长度
def adjustHeap(arr,i,length):
temp = arr[i]#存储父节点
k=i*2+1
while k<length:
#说明左子节点小于右子节点
if k+1<length and arr[k]<arr[k+1]:
k+=1
#如果子节点大于父节点
if arr[k]>temp:
arr[i]=arr[k]#将父节点换成三个数中最大的那个
i=k#i指向子节点中刚刚交换的那个位置
else:
break
k=k*2+1
arr[i]=temp#把父节点的值放进子节点
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
heapSort(arr)
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))