資料結構與演算法基礎 樹的應用

2021-08-19 11:42:03 字數 3554 閱讀 9873

樹這一資料結構學的差不多了,該拉出來練練了。本節學習幾個樹的應用,包括優先佇列、huffman編碼等。

優先佇列是特殊的「佇列」,取出元素的順序是依照元素的優先權大小,而不是元素進入佇列的順序。優先佇列要求保證「最優先元素先出」的原則。優先佇列支援兩種操作:刪除最大元素(或最小元素)和插入元素。我們將看到,刪除最大元素的方法可以很簡單地轉換成刪除最小元素。

優先佇列的簡單實現

操作描述

複雜度插入

元素總是插入尾部

o(1)

刪除查詢最大(最小)關鍵字

從陣列中刪去需要移動元素

o(n)

操作描述

複雜度插入

元素總是插入鍊錶的頭部

o(1)

刪除查詢最大(最小)關鍵字

從陣列中刪去需要移動元素

o(n)

o(1)

操作描述

複雜度插入

找到合適的位置

移動元素並插入

o(n)或o(log n)

o(n)

刪除刪去最後乙個元素

o(1)

操作描述

複雜度插入

找到合適的位置

插入o(n)

o(1)

刪除刪除首元素或最後元素

o(1)

從上述優先佇列的實現可以看出,最壞情況下他們的複雜度都會達到o(n)。為了優化效能,考慮到前面學過的二叉樹的資料結構,利用堆實現優先佇列。堆實質上是滿足如下性質的完全二叉樹:樹中任一非葉結點的關鍵字均不大於(或不小於)其左右孩子(若存在)結點的關鍵字。

對於任意位置i,其左兒子在陣列中位置為2i,其右兒子在陣列中位置為2i+1,其父親位置在floor(i/2)。 

主要有兩種不同的基本堆:最大堆和最小堆。

在最大堆中,任一結點的值小於或等於其子節點的值;最小堆則反之。

2.1 最小堆的操作

型別名稱:最小堆(minheap)

資料物件集:乙個有n>0個元素的最大堆h是一顆完全二叉樹,每個結點上的元素值不小於其子節點元素的值。

操作集

build_min_heap

建立最小堆

insert

插入乙個值,並且調整使滿足堆結構

delect

刪除min_heapify

最小堆化:使以i為根的子樹成為最小堆

下面具體看看幾個重要的操作。

2.2 最小堆的插入

如下是**實現

def insert(self, val):

# 插入乙個值val,並且調整使滿足堆結構

idx = len(self.items) - 1

paridx = self.parent(idx)

while paridx >= 0:

if self.items[paridx] > self.items[idx]:

self.items[paridx], self.items[idx] = self.items[idx], self.items[paridx]

idx = paridx

paridx = self.parent(paridx)

else:

break

self.heapsize += 1

2.3 最小堆的刪除

取出根結點元素,同時刪除堆的乙個結點。

# 堆為空

return none

# else:

self.items[0], self.items[last] = self.items[last], self.items[0]

val = self.items.pop()

self.heapsize -= 1

self.min_heapify(0)

return val

2.4 最小堆的建立

將已經存在的n個元素按最小堆的要求存放在乙個一維陣列中。

以上操作的python實現已上傳至github:data_structure/tree

先了解哈夫曼樹的一些基本術語

3.1 哈夫曼樹的構造

根據哈弗曼樹的定義,一棵二叉樹要使其wpl值最小,必須使權值越大的葉子結點越靠近根結點,而權值越小的葉子結點越遠離根結點。

3.2 哈夫曼樹的特點

3.3哈夫曼編碼

哈夫曼編碼主要用於資料壓縮。哈夫曼編碼是一種可變長編碼。該編碼將出現頻率高的字元,使用短編碼;將出現頻率低的字元,使用長編碼。變長編碼的主要問題是,必須實現非字首編碼,即在乙個字符集中,任何乙個字元的編碼都不是另乙個字元編碼的字首。如:0、10就是非字首編碼,而0、01不是非字首編碼。

問題:給定一段字串,如何對字元進行編碼,可以使得該字串的編碼儲存空間最小?

解決

1. 利用字符集中每個字元的使用頻率作為權值構造乙個哈夫曼樹; 

2. 從根結點開始,為到每個葉子結點路徑上的左分支賦予0,右分支賦予1,並從根到葉子方向形成該葉子結點的編碼.

例項:假設乙個文字檔案tfile中只包含7個字元,這7個字元在文字中出現的次數為 

通過哈夫曼樹來構造的編碼稱為哈弗曼編碼(huffman code)

所以:a 的編碼為:00 

b 的編碼為:01 

c 的編碼為:100 

d 的編碼為:1010 

e 的編碼為:1011 

f 的編碼為:11

3.4 哈夫曼樹及編碼的python實現

**實現已上傳至github:data_structure/tree/huffman tree

以上~2018.04.29

資料結構與演算法 樹的應用

1 以二叉鍊錶作儲存結構,設計求二叉樹高度的演算法。2 一棵 n 個結點的完全二叉樹用向量作儲存結構,用非遞迴演算法實現對該 二叉樹進行前序遍歷。3 以二叉鍊錶作儲存結構,編寫非遞迴的前序 中序 後序遍歷演算法。include include define maxsize 100 using nam...

演算法基礎 資料結構 樹

我們就先從樹的儲存看起吧。以字母為例,先建立乙個根節點,然後向右建立子節點,並在最後的字串的結尾處進行標記。好了,上模板 取自acwing int son n 26 cnt n idx 0號點既是根節點,又是空節點 son儲存樹中每個節點的子節點 cnt儲存以每個節點結尾的單詞數量 插入乙個字串 v...

資料結構與演算法 樹

後序遍歷 已知前序和中序求後序 設計 的原則 1 有且僅有乙個根節點 2 所有的子樹也滿足該要求 子樹之間不能有交集 單個節點也是一棵樹 空樹 啥資料都沒有,沒有任何節點 根節點 父節點,子節點,兄弟節點 如果兩個節點的父節點雖不相同,但是它們的父節點處在同一層次上,那麼這兩個節點是兄弟節點 葉子節...