樹的概念
樹是一種數據結構 比如:目錄結構
樹是一種可以遞歸定義的數據結構
樹是由n個節點組成的集合:
- 如果n=0,那這是一棵空樹
- 如果n>0,那存在1個節點作爲樹的根節點,其他節點可以分爲m個集合,每個集合本身又是一顆樹
- 一些概念
- 根節點
- 樹的深度(高度)
- 樹的度
- 孩子節點/父節點
- 子樹
二叉樹–度不超過2的樹
二叉樹 度不超過2的樹
每個節點最多有兩個孩子節點
兩個孩子節點被區分爲左孩子節點和右孩子節點
滿二叉樹
- 一個二叉樹,如果每一層的結點數都達到最大值,則這個二叉樹就是滿二叉樹
完全二叉樹
- 葉節點只能出現在最下層和次下層,並且最下面一層的結點都集中在該層最左邊的若干位置的二叉樹
二叉樹的存儲方式(表示方式)
鏈式存儲方式
順序存儲方式(用列表存取)
堆是一個特殊的完全二叉樹
因爲是堆排序,所以先了解一下順序存儲方式
### 堆排序–什麼是堆
堆:一種特殊的完全二叉樹
- 大根堆:一棵完全二叉樹,滿足任一節點都比其他孩子節點大
- 小根堆:一棵完全二叉樹,滿足任一節點都比其他孩子節點小
堆的向下調整
假設:節點的左右子樹都是堆,但自身不是堆
當根節點的左右子樹都是堆時,可以通過一次向下的調整來將其變換成一個堆
堆排序過程
- 建立堆
- 得到堆頂元素,爲最大元素
- 去掉堆頂,將堆最後一個元素放到堆頂,此時可通過一次調整重新使堆有序
- 堆頂元素爲第二大元素
- 重複步驟3,直到堆變空
構造堆
從最後面的小節點調整,慢慢構造成整個堆
堆實現代碼
def sift(li, low, high):
"""
:param li: 列表
:param low: 堆的根節點位置
:param high: 堆的最後一個元素的位置
:return:
"""
i = low # i最開始指向根節點
j = 2 * i + 1 # j開始是左孩子
tmp = li[low] # 把堆頂存起來
while j <= high: # 只要j位置有數
if j+1<= high and li[j+1] > li[j]: # 如果右孩子有並且比較大
j = j + 1 # j指向右孩子節點,不能互換
if li[j] > tmp:
li[i] = li[j]
i = j # 往下看一層
j = 2 * i + 1
else: #tmp更大,把tmp放到i的位置上
# li[i] = tmp # 把tmp放到某一級領導那兒
break
li[i] = tmp # 把tmp放到葉子節點上
def head_sort(li):
n = len(li)
for i in range((n-2)//2, -1, -1):
# i 表示建堆的時候調整的部分的根的下標
sift(li, i, n-1)
# 建堆完成了
for i in range(n-1, -1, -1):
# i 指向當前堆的最後一個元素
li[0], li[i] = li[i], li[0]
sift(li, 0, i-1) # i-1是新的high
li = [i for i in range(100)]
import random
random.shuffle(li)
print(li)
head_sort(li)
print(li)
堆排序時間複雜度
sift函數–>logn,走樹的高度(深度)
head_sort函數–>nlogn
堆排序的時間複雜度:nlogn