1. 程式人生 > >Python中樹的遍歷-堆排序

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)