Stanford CS106B 2022 Assignment 9. Huffman Coding 解析

这是slidev中关于霍夫曼树的解析,再去b站找几个视频来看就很好理解了,简单来说就是叶子节点代表字符,根节点什么都不是

Part One: Build the Huffman Tree 

这里用到了assignment6的最小堆,挺好理解的

EncodingTreeNode* huffmanTreeFor(const string& str) {
    /* TODO: Delete this comment and the next few lines, then implement this. */
    Map<char,int> hashmap;
    for(char x:str){
        hashmap[x]++;
    }
    if (hashmap.size()<=1){
        error("Less than two char");
    }
    //直接存储 EncodingTreeNode 对象而不是指针,会导致对象被复制,而不是通过引用存储在队列中
    PriorityQueue<EncodingTreeNode*> pq;
    for(char key:hashmap){
        EncodingTreeNode* newNode=new EncodingTreeNode;
        newNode->ch=key;
        newNode->zero=nullptr;
        newNode->one=nullptr;
        pq.enqueue(newNode,hashmap[key]);
    }
    while(pq.size()!=1){
        int zeroPriority=pq.peekPriority();
        EncodingTreeNode* zeroNode=pq.dequeue();
        int onePriority=pq.peekPriority();
        EncodingTreeNode* oneNode=pq.dequeue();
        EncodingTreeNode* newCode=new EncodingTreeNode;
        newCode->one=oneNode;
        newCode->zero=zeroNode;
        pq.enqueue(newCode,zeroPriority+onePriority);
    }
    return pq.dequeue();
}

Part Two: Implement Text Encoding and Decoding

思路也比较容易理解,在注释里 ,建议用笔在图上画一个树,然后让代码跟着纸上的逻辑来演示,笔者就是在这里出现逻辑错误,在纸上用代码的思路带入数据画一次就行

string decodeText(Queue<Bit>& bits, EncodingTreeNode* tree) {
    /* TODO: Delete this comment and the next few lines, then implement this. */
    //从bits中取出比特位,遍历tree,0往左走,1往右走,当tree为叶子节点时候,把字符添加到string
    if(bits.size()==0){
        return "";
    }
    EncodingTreeNode* Node=tree;
    while(Node->one!=nullptr){
        Bit bit=bits.dequeue();
        if (bit==0){
            Node=Node->zero;
        }
        else{
            Node=Node->one;
        }
    }
    //退出循环时Node已经是叶子节点
    string res="";
    char ch=Node->ch;
    res+=ch;
    res+=decodeText(bits,tree);
    return res;
}





Queue<Bit> help(Queue<Bit> bits,char& ch,EncodingTreeNode* tree){
    //当为叶子节点时,判断它的ch是否与传入的ch相等,相等返回队列,否则返回{}
    if(tree->zero==nullptr && tree->one==nullptr){
        if(tree->ch==ch){
            return bits;
        }
        return {};
    }
    //zeroNode左节点,oneNode右节点
    EncodingTreeNode* zeroNode=tree->zero;
    EncodingTreeNode* oneNode=tree->one;
    //当前根节点选择往zero分支走时,队列加元素0
    Queue<Bit> zeroRoad;
    zeroRoad=bits;
    zeroRoad.enqueue(0);
    zeroRoad=help(zeroRoad,ch,zeroNode);
    //当前根节点选择往one分支走时,队列加元素1
    Queue<Bit> oneRoad;
    oneRoad=bits;
    oneRoad.enqueue(1);
    oneRoad=help(oneRoad,ch,oneNode);
    //走得通返回正确队列,走不通返回{},我们只要返回正确队列就行
    if(zeroRoad.size()!=0){
        return zeroRoad;
    }
    return oneRoad;
}

Queue<Bit> encodeText(const string& str, EncodingTreeNode* tree) {
    /* TODO: Delete this comment and the next few lines, then implement this. */
    Queue<Bit> res;
    string str1=str;
    while(str1.size()!=0){
        char ch=str1[0];
        Queue<Bit> bits=help({},ch,tree);
        while(bits.size()!=0){
            Bit bit=bits.dequeue();
            res.enqueue(bit);
        }
        str1=str1.substr(1);
    }
    return res;
}

Part Three: Implement Tree Encoding and Decoding 

这部分较比上部分简单

EncodingTreeNode* decodeTree(Queue<Bit>& bits, Queue<char>& leaves) {
    EncodingTreeNode* Node=new EncodingTreeNode;
    //叶子节点时
    if(bits.dequeue()==0){
        Node->ch=leaves.dequeue();
        Node->one=nullptr;
        Node->zero=nullptr;
    }
    //树节点时(bits.dequeue()==1)
    else{
        Node->zero=decodeTree(bits,leaves);
        Node->one=decodeTree(bits,leaves);
    }
    return Node;

}



void encodeTree(EncodingTreeNode* tree, Queue<Bit>& bits, Queue<char>& leaves) {
    //叶子节点时
    if(tree->one==nullptr && tree->zero==nullptr){
        bits.enqueue(0);
        leaves.enqueue(tree->ch);
    }
    //树节点时
    else{
        bits.enqueue(1);
        //先对左节点处理,加入队列
        encodeTree(tree->zero,bits,leaves);
        //对右节点处理
        encodeTree(tree->one,bits,leaves);
    }
}

Part Four: Put It All Together 

 

HuffmanResult compress(const string& text) {
    /* TODO: Delete this comment and the next few lines, then implement this. */
    auto tree = huffmanTreeFor(text);
    Queue<Bit>Bits; Queue<char>Leaves; Queue<Bit>messageBits;
    HuffmanResult res;
    encodeTree(tree , Bits , Leaves);
    messageBits = encodeText(text, tree);
    deleteTree(tree);
    res.messageBits = messageBits; res.treeBits = Bits; res.treeLeaves = Leaves;
    return res;
}


string decompress(HuffmanResult& file) {
    /* TODO: Delete this comment and the next few lines, then implement this. */
    EncodingTreeNode* tree = decodeTree(file.treeBits, file.treeLeaves);
    string str = decodeText(file.messageBits, tree);
    deleteTree(tree);
    return str;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

idMiFeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值