Python中树的遍历-堆排序

Posted Python爱好者666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python中树的遍历-堆排序相关的知识,希望对你有一定的参考价值。

1、二叉树的遍历

遍历:迭代所有元素一遍。

树的遍历:对树中所有的元素不重复的访问一遍,也成扫描

广度优先遍历:层序遍历

深度优先遍历:前序、中序、后续遍历。

遍历序列:将树中所有元素遍历一遍后,得到的元素序列。将层次结构转换成了线性结构。

2、层序遍历

按照数的层次,从第一层开始,自左向右遍历元素

遍历顺序ABCDEFGHI

 

3、深度优先遍历

设树的根节点为D,左子树为L。右子树为R,且要求L一定在R之前,有以下几种遍历方式:

前序遍历:DLR  也是先序遍历,也叫做先根遍历。DLR

中序遍历,也叫中根遍历。LDR

后序遍历:也叫做后根遍历。LRD

1)前序遍历DLR

从根结点开始,先从左子树后右子树。

遍历顺序:A BDGH  CEIF

 

2)中序遍历LDR

从根节点的左子树开始遍历,然后是根结点,在右子树。

每个子树内部,也是先左子树,后根结点,在右子树;

 

3)后序遍历

先左子树,后右子树,在根节点。

每个子树内部依然是先左子树,后右子树,在根节点;

 

4、堆排序:Heap

堆是一个完全二叉树。

每个非叶子结点都要大于或者等于其它左右孩子结点的值成为大顶堆。

每个非叶子结点都要小于或者等于其左右孩子结点的值成为小顶堆。

根结点一定是大定对中的最大值,一定是小顶堆中最小的值。

1)     大顶堆,完全二叉树的每个非叶子结点都要大于或者等于其左右孩子结点的值。

根结点一定是大顶堆中最大值。

 

 

2)         小顶堆:

完全二叉树的每个非叶子结点都要小于或者等于其左右孩子结点的值。

根结点一定是小顶堆中最小的值。

3)         构件完全二叉树,

将待排序数字为30,20,80,40,50,10,60,70,90

构件一个完全二叉树存放数据,并根据性质5对元素进行编号。

构造一个列表为[0,30,20,80,40,50,10,60,70,90]

4)     构造大顶堆———核心算法

度数为2的结点A,如果他的左右孩子结点的最大值比他的值大,将这个最大值与该结点交换。

度数为1的节点,如果他的左孩子的值大于他,则交换。

如果结点被交换到新的位置,还需和其它孩子结点重复上面的过程。

5)         起点结点的选择。

从完全二叉树的最后一个结点的双亲结点开始,及最后一层的最后边叶子结点的父结点开始。

结点树为n,则其实结点的编号为n//2

6)         下一个结点的选择:

从其实结点开始向左找其同层结点,到头后在从上一层的最右边结点开始继续向左逐个查找,直至根结点。

7)         大顶堆目标,确保每个结点的值都比左右点的值大。

8)         排序:

将大顶堆根节点 这个最大值和最后一个叶子结点交换,那么最后一个叶子结点就是最大值,将这个叶子节点排除在待排序结点之外。

从根节点开始(新的根节点),重新调整为大顶堆,重复上一步。

 

 

 

 

 

9)大顶堆总结:最大值一定在最顶层。次大值一定在第二层。

堆排序总结:

1、时间复杂度o(nlogn)

2、由于堆排序对原始记录的排序状态并不敏感,因此无论是最好、最坏和平均时间复杂度均为o(nlogn)。时间比较稳定。

3、空间复杂度。只是使用了一个交换用的空间,空间复杂度就是o(1)

4、稳定性,不稳定的排序算法。

熟悉树的概念之上的。

 

堆排序代码:

import math

def print_tree(array):
    index = 1
    depth = math.ceil(math.log2(len(array)))
    sep = ‘ ‘
    for i in range(depth):
        offset = 2 ** i
        print(sep *(2**(depth-i-1)-1), end=‘‘)
        line = array[index:index+offset]
        for j, x in enumerate(line):
            print("{:>{}}".format(x, len(sep)), end=‘‘)
            interval = 0 if i == 0 else 2 ** (depth-i) - 1
            if j < len(line) - 1:
                print(sep * interval, end=‘‘)

        index += offset
        print()


origin = [0, 30, 20, 80, 40, 50, 10, 60, 70, 90]
total = len(origin) - 1
print(origin)
print_tree(origin)
print(‘++++++++‘)


def heap_adjust(n, i, array:list):

    while 2 * i <= n:
        lchile_index = 2 * i
        max_child_index = lchile_index
        if n> lchile_index and array[lchile_index + 1] > array[lchile_index]:
            max_child_index = lchile_index + 1

        if array[max_child_index] > array[i]:
            array[i], array[max_child_index] = array[max_child_index], array[i]
            i = max_child_index
        else:
            break


def max_heap(total, array:list):
    for i in range(total//2, 0, -1):
        heap_adjust(total, i, array)
    return array


print_tree(max_heap(total, origin))
print(‘--------------------‘)
def sort(total, array:list):
    while total > 1:
        array[1], array[total] = array[total], array[1]
        total -= 1
        if total == 2 and array[total] >= array[total-1]:
            break
        heap_adjust(total, 1, array)
    return array

print_tree(sort(total, origin))
print(origin)





























































以上是关于Python中树的遍历-堆排序的主要内容,如果未能解决你的问题,请参考以下文章

排序:Java实现大顶堆和二叉树的广度优先遍历原理及代码注释详解

树,树的遍历和堆排序

入门学算法_堆排序树遍历

python-堆排序

堆排序

07堆排序 python