排序---堆排序的非递归实现

堆排序需要解决两个问题: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)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值