C#非託管資源釋放(Finalize&Dispose)方法
阿新 • • 發佈:2022-03-08
【理論知識可以參考】
# 哈夫曼編解碼過程要依賴一棵最優二叉樹,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 = self22 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 = HuffmanTree3 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)