UNPKG

ts-ds-tool

Version:

Data structure and algorithm of TypeScript

112 lines (103 loc) 3.22 kB
import { Heap } from "../../heap/Heap"; import { MinHeap } from "../../heap/MinHeap"; import { HuffmanTreeNode } from "./HuffmanTreeNode"; export class HuffmanTree{ private root: HuffmanTreeNode; private traversalFlag = 0; private pathCache: {[index: string]: string} = {}; public get Root(){ return this.root; } constructor(private array: Array<[string, number]>|{[index: string]: number}){ this.buildTree(); } private buildTree(){ const heap: Heap<HuffmanTreeNode> = new MinHeap<HuffmanTreeNode>("Weight"); const arr: Array<{value: string, weight: number}> = []; if (this.array instanceof Array){ this.array.forEach(item => { arr.push({value: item[0], weight: item[1]}); }); }else{ // tslint:disable-next-line:forin for (const key in this.array) { const element = this.array[key]; arr.push({value: key, weight: element}); } } arr.forEach(item => { heap.add(new HuffmanTreeNode(item.value, item.weight)); }); let parent = null; for (let i = 0; i < arr.length - 1; i++){ const last = heap.poll(); const lastSecond = heap.poll(); parent = new HuffmanTreeNode(null, last.Weight + lastSecond.Weight); parent.Left = last; parent.Right = lastSecond; heap.add(parent); } heap.clear(); this.root = parent; this.createPath(); } public getPath(value: string){ const path = this.pathCache[value]; if (!path){ throw new Error(`Not Found '${value}' path`); } return path; } public getText(codes: string){ const strArr: Array<string> = []; let node = this.root; for (const element of codes) { if (element === "0") { // 左走 node = node.Left; }else { // 右走 node = node.Right; } if (node.isLeaf()) { strArr.push(node.Value); node = this.root; } } return strArr.join(""); } private createPath(node = this.root , path = ""){ if (!node){ return; } if (node.isLeaf()){ this.pathCache[node.Value] = path; }else{ this.createPath(node.Left , path + "0"); this.createPath(node.Right , path + "1"); } } public getWPL(){ if (!this.root){ return 0; } this.traversalFlag = 0; let sum = 0; this.traversal(this.root, item => { if (!item.Left && !item.Right){ sum += item.Weight * this.traversalFlag; } }); return sum; } private traversal(tree: HuffmanTreeNode, fn: (value: HuffmanTreeNode) => void){ if (!tree){ return; } fn(tree); this.traversalFlag ++; this.traversal(tree.Left, fn); this.traversal(tree.Right, fn); this.traversalFlag --; } }