1. 程式人生 > 其它 >C#非託管資源釋放(Finalize&Dispose)方法

C#非託管資源釋放(Finalize&Dispose)方法

【理論知識可以參考】

資料結構:哈夫曼樹和哈夫曼編碼

 

# 哈夫曼編解碼過程要依賴一棵最優二叉樹,ta具有最小帶權路徑長度wpl,所以首先需要生成這個最優二叉樹 

# 這棵最優二叉樹也叫哈夫曼樹

 1 local HuffmanTreeNode = {}
 2 HuffmanTreeNode.__index = HuffmanTreeNode
 3 
 4 function HuffmanTreeNode.new(w, v)
 5     local obj = {}
 6     setmetatable(obj, HuffmanTreeNode)
 7     obj:ctor(w, v)
8 return obj 9 end 10 11 function HuffmanTreeNode:ctor(w, v) 12 self.weight = w 13 self.value = v or w---元素值 14 self.left = nil ---左子節點 15 self.right = nil ---右子節點 16 self.parent = nil ---父節點 17 end 18 19 function HuffmanTreeNode:SetLeft(l) 20 self.left = l 21 l.parent = self
22 end 23 24 function HuffmanTreeNode:SetRight(r) 25 self.right = r 26 r.parent = self 27 end 28 29 function HuffmanTreeNode:IsLeaf() 30 return nil == self.left and nil == self.right 31 end

 

# 構建的過程就是不斷的取2個權值最小的節點組成新節點,直到取完

# 如果遇到新組成的節點權值和已有節點相同的,優先用已有節點

 1 local HuffmanTree = {}
 2 HuffmanTree.__index = HuffmanTree
3 4 function HuffmanTree.new() 5 local obj = {} 6 setmetatable(obj, HuffmanTree) 7 obj:ctor() 8 return obj 9 end 10 11 function HuffmanTree:ctor() 12 self.root = nil ---根節點 13 self.codesQueryDict = nil ---編碼查詢表 14 end 15 16 function HuffmanTree:Build(nodeArr) 17 local ct = #nodeArr 18 19 local minHeap = {} --這邊暫時用陣列模擬最小堆 20 for i=1,ct do 21 minHeap[i] = nodeArr[i] 22 end 23 local sortFunc = function(a, b) 24 if a.weight == b.weight then 25 local aNoParent = (nil == a.parent) 26 local bNoParent = (nil == b.parent) 27 if aNoParent ~= bNoParent then 28 return aNoParent 29 end 30 end 31 return a.weight < b.weight --小的排前面 32 end 33 table.sort(minHeap, sortFunc) 34 35 local parent = nil 36 while #minHeap > 1 do 37 local node1 = minHeap[1] 38 local node2 = minHeap[2] 39 table.remove(minHeap, 1) 40 table.remove(minHeap, 1) 41 42 parent = HuffmanTreeNode.new(node1.weight + node2.weight, nil) 43 parent:SetLeft(node1) 44 parent:SetRight(node2) 45 46 table.insert(minHeap, parent) 47 table.sort(minHeap, sortFunc) 48 end 49 50 self.root = parent 51 end 52 53 function HuffmanTree:__tostring() 54 if nil == self.root then return end 55 56 local levelStr = {} 57 local function preOrder(level, node) 58 if nil == node then return end 59 60 local str = levelStr[level] 61 if nil == str then 62 str = {} 63 levelStr[level] = str 64 end 65 table.insert(str, node.weight) 66 67 preOrder(level+1, node.left) 68 preOrder(level+1, node.right) 69 end 70 preOrder(1, self.root) 71 end

 

用20, 50, 10, 100構建的哈夫曼樹:

 1 function Test1()
 2     local hf = HuffmanTree.new()
 3     local nodeArr = {
 4         HuffmanTreeNode.new(20),
 5         HuffmanTreeNode.new(50),
 6         HuffmanTreeNode.new(10),
 7         HuffmanTreeNode.new(100),
 8     }
 9     hf:Build(nodeArr)
10     tostring(hf)
11 end
12 Test1()

 

# 編碼,先生成編碼查詢表,一般給左子樹分配0,右子樹分配1,所以編碼後的查詢表:

20 -> 001
50 -> 01
100 -> 1
10 -> 000

# 然後編碼,就直接從這種查詢表直接取編碼值,查不到的就是沒法編碼的

 1 function HuffmanTree:BuildCodes()
 2     self.codesQueryDict = {}
 3     local stack = {}
 4 
 5     local function preOrder(node)
 6         if nil == node then return end
 7 
 8         if node:IsLeaf() then
 9             self.codesQueryDict[node.value] = table.concat(stack)
10             return
11         end
12 
13         table.insert(stack, 0)
14         preOrder(node.left)
15         table.remove(stack, #stack)
16 
17         table.insert(stack, 1)
18         preOrder(node.right)
19         table.remove(stack, #stack)
20     end
21     preOrder(self.root)
22 end
23 
24 function HuffmanTree:Encode(arr)
25     local encodeBuilder = {}
26     for i=1,#arr do
27         local item = arr[i]
28         local codes = self.codesQueryDict[item]
29         if nil == codes then return nil end --編碼失敗
30         table.insert(encodeBuilder, codes)
31     end
32     local byteStr = table.concat(encodeBuilder)
33     return byteStr
34 end

 

# 解碼,根據0為左子樹,1為右子樹,從根開始往下找,直到找到葉子節點;然後再從根往下找,不斷重複。

 1 function HuffmanTree:DecodeByString(byteStr)
 2     local decodeBuilder = {}
 3     local node = self.root
 4     local i = 1
 5     while true do
 6         local nodeIsLeaf = node:IsLeaf()
 7         if nodeIsLeaf then
 8             table.insert(decodeBuilder, node.value)
 9             node = self.root
10         end
11 
12         if i > string.len(byteStr) then
13             if not nodeIsLeaf then return end --解碼錯誤
14             break
15         end
16 
17         local b = string.sub(byteStr, i, i)
18         if "0" == b then node = node.left
19         elseif "1" == b then node = node.right end
20         i = i + 1
21     end
22 
23     return table.concat(decodeBuilder)
24 end

 

# 測試程式碼

 1 function Test1()
 2     local hf = HuffmanTree.new()
 3     local nodeArr = {
 4         HuffmanTreeNode.new(20),
 5         HuffmanTreeNode.new(50),
 6         HuffmanTreeNode.new(10),
 7         HuffmanTreeNode.new(100),
 8     }
 9     hf:Build(nodeArr)
10     tostring(hf)
11 
12     hf:BuildCodes()
13     local encodeStr = hf:Encode({10, 50})
14     print(encodeStr)
15     print(hf:DecodeByString(encodeStr))
16 end
17 Test1()

 

【其他參考】

資料結構——哈夫曼樹(Huffman Tree) - 知乎 (zhihu.com)

詳細圖解哈夫曼Huffman編碼樹_無鞋童鞋的部落格-CSDN部落格_huffman編碼樹

Java 哈夫曼編碼與解碼_m0_38036210的部落格-CSDN部落格_java 哈夫曼解碼

哈夫曼樹以及哈夫曼編碼和解碼-Java實現 | 一個程式設計師的簡單生活 (ddkiss.com)