哈夫曼编码与解码的JavaScript实现

来源:互联网 发布:淘宝达人直播申请 编辑:程序博客网 时间:2024/05/02 06:07
//计算字符出现频率function frequencies(s) {    var hash = {};    for(var i=0;i<s.length;i++){        var c = s.charAt(i);        if(hash[c]){            hash[c]++;        }        else{            hash[c] = 1;        }    }    return Object.keys(hash).map(function(e){        return [e , hash[e]];    });}//交换数组元素方法function swap(arr,i,j){    var temp = arr[i];    arr[i] = arr[j];    arr[j] = temp;}//冒两次泡,取出权重最小的2个元素function bubbleTwice(array){    for(var i=0;i<2;i++){        for(var j=0;j<array.length-i-1;j++){            if(array[j][1] < array[j+1][1]){                swap(array,j,j+1);            }        }    }}//创建哈夫曼树function createTree(array){//只要列表中还有2个及以上的元素    while(array.length > 1){//冒两次泡        bubbleTwice(array);//取出权重最小的2个元素        var left = array.pop();        var right = array.pop();//左子树分配代码"0"//右子树分配代码"1"        left.code = "0";        right.code = "1";//生成父节点,权重为2个子节点权重之和        var parent = [null,left[1] + right[1]];        parent.left = left;        parent.right = right;//将生成的父节点加入列表        array.push(parent);    }//返回根节点    return array[0];}//深度遍历哈夫曼树,获取字符和哈夫曼编码(路径)的映射function getMapping(root){    var map = {};    var traverse = function(parent,path){        if(parent){            if(parent.left || parent.right){                if(parent.left){                    traverse(parent.left,path + parent.left.code);                }                if(parent.right){                    traverse(parent.right,path + parent.right.code);                }            }//如果是叶子节点            else{                if(path){//映射当前字符和哈夫曼编码                    map[parent[0]] = path;                }            }        }    };    traverse(root,"");    return map;}//编码方法//freqs:字符出现频率映射对象//s:待编码的字符串function encode(freqs,s) {    var root = createTree(freqs);    if(root && (root.left || root.right) && !s){        return "";    }    if(!s){        return null;    }    var map = getMapping(root);    var res = "";    for(var i=0;i<s.length;i++){        if(map[s.charAt(i)]){            res += map[s.charAt(i)];        }        else{            return null;        }    }    return res;}//解码方法//freqs:字符出现频率映射对象//s:待解码的字符串function decode(freqs,s) {    var root = createTree(freqs);    if(root && (root.left || root.right) && !s){        return "";    }    if(!s){        return null;    }    var map = getMapping(root);    var res = "";//对编码内容,一段段匹配,解码,截取    sign:    while(s){        for(var i in map){            var index = s.indexOf(map[i]);            if(index == 0){                res += i;                s = s.slice(map[i].length);                continue sign;            }        }        return null;    }    return res;}//Test1var str = "aaaabcc";var fq = frequencies(str);//[["a",4],["b",1],["c",2]]document.write(JSON.stringify(fq) + "<br>");var encoded = encode(fq,str);//"1111000101"//长度为10document.write(encoded + "<br>");var decoded = decode(fq,encoded);//truedocument.write(decoded === str);//Test2str = "abcdabcaba";fq = frequencies(str);//[["a",4],["b",3],["c",2],["d",1]]document.write(JSON.stringify(fq) + "<br>");encoded = encode(fq,str);//"0111011000111010110"//长度为19document.write(encoded + "<br>");decoded = decode(fq,encoded);//truedocument.write(decoded === str);

原创粉丝点击