`
chiyx
  • 浏览: 274526 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

SICP读书笔记-huffman编码的实现

阅读更多

huffman 编码是一种变长前缀式编码,通过利用被编码消息中符号的出现频率(频率出现越高的用越少的码),可以有效的节约空间。在 SICP 的2.3.4节通过实现一个huffman编码树来阐述通过表和数据抽象去操作集合和数的例子。

 

构建 huffman 编码树


  • huffman 树以表的方式来表示,将树分为 叶子节点*和 *非叶子节点

('leaf symbol weight) : 叶子节点,包含标示叶子的符号'leaf, 实际字符 symbol,权重 weight
(left right symbols weight): 非叶子节点, 包含左子树 left, 右子树 right, 实际字符表(它孩子节点的符号汇总表), 权重 weight (它孩子节点的权重之和).

  • 构建过程

将符号和其对应的频率如 (A 4) (B 2) (C 3) (D 1) *变换为叶子节点的有序表(按权重升序), 然后反复归并集合中具有最小权重的2个元素,直到集合中只剩下一个元素,那么这个元素就是我们所需要的 *huffman 树.

(define (generate-huffman-tree pairs)
 (define (successive-merge entry-set)
  (cond ((null? entry-set) '())
        ((null? (cdr entry-set)) (car entry-set))
        (else
         (successive-merge (adjoin-set
                            (make-code-tree (car entry-set) (cadr entry-set))
                            (cddr entry-set))))))
 (successive-merge (make-leaf-set pairs)))

 


通过huffman编码和解码


  • 编码通过针对消息中的每个字符,遍历 huffman 数,如果往左则增加一个0,往右为1,到达叶子节点时得到的2进制序列就是该字符的编码。以下是针对单个符号的编码算法:
;编码单个字符
(define (encode-symbol symbol tree)
 (if (leaf? tree)
     '()
     (let ((code-br-pair (encode-branch symbol tree)))
          (cons
           (car code-br-pair)
           (encode-symbol symbol (cadr code-br-pair))))))

;根据字符是在左树还是右树进行编码
(define (encode-branch symbol tree)
 (let (
       (left (left-branch tree))
       (right (right-branch tree))
      )
  (cond ((member? symbol (symbols left)) (list 0 left))
        ((member? symbol (symbols right)) (list 1 right))
        (else (error "symbol not int left or right branch - " symbol)))))
解码以一串二进制序列和对应的 huffman 数为参数,逐个根据二进制序列中的值决定遍历树的走向,0向左走,1向右走,到达叶子节点则该叶子节点的symbol即为解码的符号,继续剩下的序列,直到序列为空。
(define (decode bits tree)
 (define (decode-l bits current-branch)
  (if (null? bits)
      '()
      (let ((next-branch (choose-branch (car bits) current-branch)))
       (if (leaf? next-branch)
           (cons (symbol-leaf next-branch)
                 (decode-l (cdr bits) tree))
           (decode-l (cdr bits) next-branch)))))
 (decode-l bits tree))

(define (choose-branch bit branch)
 (cond ((= bit 0) (left-branch branch))
       ((= bit 1) (right-branch branch))
       (else (error "bad bit -- CHOOSE-BRANCH" bit))))

 


完整的代码如下


  • 树的构建 huffman-tree.scm
;构建如((A 4) (B 2) (C 1) (D 1))的符号和权重的序对列表,构建huffman树
(define (generate-huffman-tree pairs)
 (define (successive-merge entry-set)
  (cond ((null? entry-set) '())
        ((null? (cdr entry-set)) (car entry-set))
        (else
         (successive-merge (adjoin-set
                            (make-code-tree (car entry-set) (cadr entry-set))
                            (cddr entry-set))))))
 (successive-merge (make-leaf-set pairs)))

;定义树叶子的表示法
(define (make-leaf symbol weight)
 (list 'leaf symbol weight))
;判断是否是叶子节点
(define (leaf? object)
 (eq? (car object) 'leaf))
;获取叶子节点的符号
(define (symbol-leaf x) (cadr x))
;获取叶子节点的权重
(define (weight-leaf x) (caddr x))
;获取树的符号表
(define (symbols tree)
 (if (leaf? tree)
     (list (symbol-leaf tree))
     (caddr tree)))
;获取树的权重
(define (weight tree)
 (if (leaf? tree)
     (weight-leaf tree)
     (cadddr tree)))
;获取树的左子树
(define (left-branch tree) (car tree))
;获取树的右子树
(define (right-branch tree) (cadr tree))
;树表示为1个具有4个元素的表:左节点,右节点,符号列表,权重
(define (make-code-tree left right)
 (list left
       right
       (append (symbols left) (symbols right))
       (+ (weight left) (weight right))))
;根据权重,构建叶子和树的有序标,方便归并一对最小项
(define (adjoin-set x set)
 (cond ((null? set) (list x))
        ((> (weight x) (weight (car set))) (cons (car set) (adjoin-set x (cdr set))))
        (else (cons x set))))
;构造叶子的初始排序集合
(define (make-leaf-set pairs)
 (if (null? pairs)
     '()
     (let ((pair (car pairs)))
      (adjoin-set (make-leaf (car pair) (cadr pair)) (make-leaf-set (cdr pairs))))))

 

  • 编码和解码 huffman-code.scm
(load "huffman-tree.scm")
;编码消息
(define (encode message tree)
 (if (null? message)
     '()
     (append
      (encode-symbol (car message) tree)
      (encode (cdr message) tree))))

;编码单个字符
(define (encode-symbol symbol tree)
 (if (leaf? tree)
     '()
     (let ((code-br-pair (encode-branch symbol tree)))
          (cons
           (car code-br-pair)
           (encode-symbol symbol (cadr code-br-pair))))))

;根据字符是在左树还是右树进行编码
(define (encode-branch symbol tree)
 (let (
       (left (left-branch tree))
       (right (right-branch tree))
      )
  (cond ((member? symbol (symbols left)) (list 0 left))
        ((member? symbol (symbols right)) (list 1 right))
        (else (error "symbol not int left or right branch - " symbol)))))
;包含关系判断
(define (member? item set)
    (not (equal? (member item set) false)))
;解码消息
(define (decode bits tree)
 (define (decode-l bits current-branch)
  (if (null? bits)
      '()
      (let ((next-branch (choose-branch (car bits) current-branch)))
       (if (leaf? next-branch)
           (cons (symbol-leaf next-branch)
                 (decode-l (cdr bits) tree))
           (decode-l (cdr bits) next-branch)))))
 (decode-l bits tree))

(define (choose-branch bit branch)
 (cond ((= bit 0) (left-branch branch))
       ((= bit 1) (right-branch branch))
       (else (error "bad bit -- CHOOSE-BRANCH" bit))))

 

  • 测试代码 huffman-use.scm
(load "huffman-code.scm")
;定义一个特定的文本串
(define message '(a a b a c a c b b d d d d d d))
;定义初始的叶子节点
(define leaf-set (list '(a 4) '(b 3) '(c 2) '(d 6)))
;根据叶子节点,生成对应的huffman树
(define huffman (generate-huffman-tree leaf-set))
;encode
(define bits (encode message huffman))
(display bits)
;decode
(define msg (decode bits huffman))
(newline)
(display msg)

 

  • 测试结果如下
(1 0 1 0 1 1 1 1 0 1 1 0 1 0 1 1 0 1 1 1 1 1 1 0 0 0 0 0 0)
(a a b a c a c b b d d d d d d)

 

1
0
分享到:
评论

相关推荐

    sicp-py-zh:[译] UCB CS61a SICP Python 描述 中文版

    docker run -tid -p <port>:80 apachecn0/sicp-py-zh # 访问 http://localhost:{port} 查看文档 PYPI pip install sicp-py-zh sicp-py-zh # 访问 http://localhost:{port} 查看文档 NPM npm install -g sicp-py-zh ...

    sicp-in-python(中文版+英文版)PD

    sicp-in-python(中文版+英文版)PDF 背景. SICP 全称Structure and Interpretation of Computer Programs,翻译过来叫《计算机程序的构造和解释》使用python

    Python库 | sicp-0.0.2-py3-none-any.whl

    资源分类:Python库 所属语言:Python 资源全名:sicp-0.0.2-py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    sicp-js-zh:【译】NUS CS1101s SICP JavaScript 描述

    NUS CS1101s SICP JavaScript 描述原文:协议:如果你交给某人一个程序,你将折磨他一整天;如果你教某人如何编写程序,你将折磨他一辈子。...下载Dockerdocker pull apachecn0/sicp-js-zhdocker run -tid

    sicp-memo-ans:SICP笔记和答案

    笔记 如果你想在 gauch 中使用随机函数 (use math.mt-random) (define m (make <mersenne> :seed (sys-time))) (mt-random-integer m 1000) (define (random n) (mt-random-integer m n)) 使用。 另外,如果你想...

    sicp-eg-ex:sicp课程视频示例,自己的笔记,习题题解

    在"Sicp-eg-ex-main"这个文件中,很可能是项目的主要实现代码或者笔记,包含了作者在学习过程中的思考和发现。通过阅读和分析这些代码,我们可以看到如何将SICP的理论知识转化为实际的编程实践,这对于深化理解和...

    CeO2对SiCp/Al-Si复合材料组织及性能的影响 (2015年)

    采用粉末冶金法制备 SiCp/Al-Si复合材料,以 CeO2 为变质剂,制备含 CeO2 的 SiCp/Al-Si 复合材料。研究 CeO2 的添加量(质量分数)对复合材料组织和力学性能的影响,探讨复合材料中 CeO2 在烧结过程中的作用机理。研究...

    sicp-study-group:一个研究计算机程序结构和解释(SICP)的研究小组

    文件名“sicp-study-group-master”暗示这是一个开源项目,很可能包含了学习资源、笔记、代码示例或练习解决方案。通常,这样的项目会包含以下组成部分: 1. **阅读材料**:可能是SICP书的章节摘要、笔记或者补充...

    激光表面熔覆SiCp/Ni-Cr-B-Si-C涂层的组织演化及其相确定

    运用激光熔覆技术在AISI1045钢表面制备了30vol-% SiCp/Ni-Cr-B-Si-C涂层。SEM和TEM观察分析表明:SiCp在熔覆过程中完全溶解;涂层结合区组织为共晶结构;涂层组织由初生石墨球G,分布在γ-Ni固溶体枝晶中的M23(C,B)6...

    sicp-compiler-notes:有关SICP编译器的一些说明和演示

    在SICP上进行试用-> WASM编译演示:SICP如何将机器代码注册为WASM 为阶乘翻译LISP代码(define (factorial n) (define (iter product counter) (if (> counter n) product (iter (* counter product) (+ counter 1)))...

    sicp-py-zh:【译】UCB CS61a SICP Python

    压缩包中的"sicp-py-zh-master"很可能包含了整个项目的源代码、翻译后的文本、示例程序、测试以及其他相关资源。以下是对SICP Python中核心知识点的详细解释: 1. **函数式编程**: - **高阶函数**:函数可以作为...

    SiCp/Al-Fe-V-Si复合材料组织与性能的热稳定性 (2008年)

    为研究SiCP/Al-Fe-V-Si复合材料的热稳定性,对多层喷射沉积技术制备的SiC颗粒增强Al-Fe-V-Si合金经过不同温度下的热稳定性实验后进行了硬度检测,并对其显微组织进行了电镜观察。结果表明:随着基体合金材料中Fe含量的...

    sicp-study-group

    CoRecursive Slack SICP研究小组 章节 1-1-1 ::表达式 1-1-2 ::命名与环境 1-1-3 ::评估组合 1-1-4 ::复合程序 1-1-5 ::程序应用的替代模型 1-1-6 ::条件表达式和谓词 1-1-7 ::例子:牛顿法求平方根 1-1-8 :...

    sicp in python 中文 sicp 中文

    sicp in python 中文版 sicp in python 中文版 sicp in python 中文版 !!!download>>>https://github.com/wizardforcel/sicp-py-zh

    不同冷却条件SiCp/ZA-27复合材料界面的TEM观察 (2001年)

    主要用透射电子显微技术(TEM)、电子探针显微分析(EPMA)和选区电子衍射技术(SAD)分析了不同冷却条件下SiCp/ZA-27复合材料的界面特征和结构,发现冷却速度明显影响复合材料的界面结构、界面相组成和复杂金属氧化物的...

    喷射沉积SiCP/Al-Si复合材料干滑动磨损性能的研究 (2013年)

    采用喷射沉积法制备SiCP体积分数为15%,Si质量分数分别为7%,13%和20%的SiCP/Al-Si复合材料,并经热挤压致密化加工.采用环块式摩擦试验机对复合材料的干滑动摩擦磨损性能进行了测试分析,滑动速度为1 m/s,外加载荷...

    SICP-Python版本

    SICP-Python版本

    sicp-to-z80:一台SICP寄存器机到TI-84 Z80编译器

    最终目标是完全支持SICP指令集,然后使用此编译器将Scheme编译为Z80,或直接将Scheme编写为Z80。 无论哪种方式,该项目对我来说也意味着可以在TI-84(不是最好的语言)上探索Z80装配中的编程。特征显示字符串和数字...

Global site tag (gtag.js) - Google Analytics