排序算法之堆排序

  堆排序是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
  堆排序的思路:
1、将原始数据按照完全二叉树的形式排列
2、按照堆积的性质,使子节点的键值总是小于它的父节点;即从下到上,从右到左,将所有非叶子节点的值与其叶子节点的值作比较,将较大值放在父节点
3、排列完成后,就是一个有序的堆,然后将堆顶元素R[0]与堆尾元素R[n-1]调换位置,之后将新的R[0]到R[n-2]的元素回到第二步,R[n-1]元素则是已经排列好的。

这里引用了百度百科中python的代码,之后补上自己的python版本和java版本
big_endian是将arr的前end+1个元素,从start开始进行排序。
在第一次初始化排序的时候,是big_endian(arr, 4, 9),big_endian(arr, 3, 9),big_endian(arr, 2, 9),big_endian(arr, 1, 9),big_endian(arr, 0, 9)。
为什么是倒序?如果从堆顶开始,那么某元素R[x],因为比其子节点小而与子节点交换值之后,就有可能比其父节点大了。
heap_sort中,first = len(arr)//2 - 1 直接确定了第一个非叶子节点的位置。第一个循环是将初始列表按照堆积的性质排列;第二个循环,是先将堆顶元素与堆尾元素交换位置,然后再将除堆尾元素之外的元素进行排序。

def big_endian(arr,start,end):    
    root=start    
    child=root*2+1 #左孩子    
    while child<=end:
    #孩子比最后一个节点还大,也就意味着最后一个叶子节点了,就得跳出去一次循环,已经调整完毕     
        if child+1<=end and arr[child]<arr[child+1]:
        #为了始终让其跟子元素的较大值比较,如果右边大就左换右,左边大的话就默认           
            child+=1            
        if arr[root]<arr[child]:
        #父节点小于子节点直接交换位置,同时坐标也得换,这样下次循环可以准确判断:是否为最底层,
        #是不是调整完毕                
            arr[root],arr[child]=arr[child],arr[root]                
            root=child                
            child=root*2+1            
        else:               
        break
         
def heap_sort(arr): #无序区大根堆排序    
    first=len(arr)//2 - 1    
    for start in range(first,-1,-1):
    #从下到上,从左到右对每个节点进行调整,循环得到非叶子节点        
        big_endian(arr,start,len(arr)-1) #去调整所有的节点    
    for end in range(len(arr)-1,0,-1):        
        arr[0],arr[end]=arr[end],arr[0] #顶部尾部互换位置        
        big_endian(arr,0,end-1) #重新调整子节点的顺序,从顶开始调整    
    return arr
     
def main():    
    l=[3,1,4,9,6,7,5,8,2,10]    
    print(heap_sort(l))
 
if __name__=="__main__":    
    main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值