Typescript实现哈夫曼树 + 编码

778 阅读2分钟

最近的大三Java实验课,老师让我们用Java语言来完成文件内容的压缩,不使用Gzip和ZIP的方式来实现,作为一个前端开发,当然要试试用前端的语言的来实现此作业的要求,我选择使用Typescript来完成代码的实现,也试试学了这么久,Typescript掌握了多少。

TS源码

//规定树节点的内容对象
interface keyobj {
    key: string,
    val: number
}

//映射表的类型接口约定
interface kcMap {
    [id: string]: string
}

class Huffman{
    //文本
    public str: string;
    //key值和频率的映射表
    public keyCountMap: any = null;
    //key值和编码的映射表
    public keyCodeMap: kcMap = {};

    //哈夫曼节点列表
    public nodelist: Array<Nodeitem> = [];
    //哈夫曼树根节点
    public root: Nodeitem;
    //哈夫曼编码后的序列
    public code: any = null;

    constructor(str: string){
        this.str = str;
    }
    
    //计算文本每个字母元素出现的频率
    public cal(): void{
        let map: {} = {};
        let i: number = 0;

        while(this.str[i]){
            map[this.str[i]] ? map[this.str[i]] ++ : (map[this.str[i]] = 1);
            i ++;
        }

        this.keyCountMap = map
        console.log(this.keyCountMap);
    };
    
    //对于字母频率,规定成节点,并排序
    public sort(): void{
        //类型声明为对象的数组集合
        let result: Array<Nodeitem> = [];

        for(let key in this.keyCountMap){
            if(this.keyCountMap.hasOwnProperty(key)){
                let obj: keyobj = {
                    key: key,
                    val: this.keyCountMap[key]
                };
                console.log(obj);

                result.push(new Nodeitem(null,null,obj));
            }
        }

        result.sort(function(x,y){
            return x.data.val - y.data.val;
        })

        this.nodelist = result;
        
    }
    
    //制作哈夫曼树
    public makeTree(): Nodeitem{
        let i: number = 0;
        let parentNode: Nodeitem;

        let table: Array<Nodeitem> = this.nodelist;

        //将数组合并成哈夫曼树
        while(table.length > 1){
            parentNode = new Nodeitem(table[i],table[i+1],{
                key: null,
                val: table[i].data.val + table[i + 1].data.val
            })
            table.splice(i,2);
            table.push(parentNode);
            table.sort(function(x,y) {
                return x.data.val - y.data.val
            })
        }

        this.root = table[0] || new Nodeitem(null,null,{key: null,val: 0});

        return this.root;
    }
    
    //将每个字母通过哈夫曼树转换为二进制编码
    public traversal(tree: Nodeitem,code: string): void{
        if(tree.left !== null){
            this.traversal.call(this,tree.left,code + '0');
        }
        else{
            this.keyCodeMap[tree.data.key] = code;
        }

        if(tree.right !== null){
            this.traversal.call(this,tree.right,code + '1');
        }
        else{
            this.keyCodeMap[tree.data.key] = code;
        }

    }
    
    //将文本字符串进行编码
    public encode(): string{

        this.cal();
        this.sort();
        let root: Nodeitem = this.makeTree();

        console.log(root);
        this.traversal(root,'');

        console.log(this.keyCodeMap);

        let i: number = 0;
        let result: string = '';
        
        while(this.str[i]){
            
            result += this.keyCodeMap[this.str[i ++]];
        }

        this.code = result;
        console.log(result);

        return result;
    }
}

class Nodeitem{

    public left: any;
    public right: any;
    public data: keyobj;
    
    constructor(left: any,right: any,data: keyobj){
        this.left = left;
        this.right = right;
        this.data = data;
    }
}

//测试代码(demo)
const str1: string = "dasjfhpasujdhfu;h4wpoiufjhapwoivnowuihvno;awjcoi;wejfoiawejfpiuowefjhijwhvniu";
const huffmanDemo: Huffman = new Huffman(str1);
huffmanDemo.encode();

显示结果