<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理

    sicp 2.3小結習題嘗試解答

    Posted on 2007-07-03 17:04 dennis 閱讀(599) 評論(1)  編輯  收藏 所屬分類: 計算機科學與基礎
     習題2.2沒有全部做,我讀書的速度遠遠超過做習題的進度,沒辦法,時間有限,晚上的時間基本用來看書了,習題也都是在工作間隙做的,慢慢來了,前兩章讀完再總結下。回到2.3節(jié),這一節(jié)在前幾節(jié)介紹數值型符號數據的基礎上引入了符號數據,將任意符號作為數據的能力非常有趣,并給出了一個符號求導的例子,實在是太漂亮了。

    習題2.53,直接看結果:
    > (list '''c)
    (a b c)
    > (list (list 'george))
    ((george))
    > (cdr '((x1 x2) (y1 y2)))
    ((y1 y2))
    > (cadr '((x1 x2) (y1 y2)))
    (y1 y2)
    > (pair? (car '(a short list)))
    #f
    > (memq? 'red '((red shoes) (blue socks)))
    #f
    > (memq? 'red '(red shoes blue socks))
    (red shoes blue socks)

    習題2.54,equal?過程的定義,遞歸定義,很容易
    (define (equal? a b)
      (cond ((
    and (not (pair? a)) (not (pair? b)) (eq? a b)) #t)
            ((and (pair? a) (pair? b))
             (
    and (equal? (car a) (car b)) (equal? (cdr a) (cdr b))))
            (
    else
              (display 
    "a and b are not equal"))))
    注意,在DrScheme實現中,eq?可以用于比較數值,比如(eq? 1 1)也是返回真

    習題2.55,表達式(car ''abracadabra)其實就是
    (car (quote (quote abracadabra))),也就是(car '(quote abracadabra)),顯然將返回quote

    習題2.56,求冪表達式的導數,學著書中的代碼寫,也很容易了,先寫出constructor和selector:
    (define (make-exponentiation base e)
      (cond ((
    = e 0) 1)
            ((
    = e 1) base)
            (
    else
              (list 
    '** base e))))
    (define (base x) (cadr x))
    (define (exponent x) (caddr x))
    (define (exponentiation? x)
      (
    and (pair? x) (eq? (car x) '**)))
    用**表示冪運算,因此(make-exponentiation x 3)表示的就是x的3次方。
    修改deriv過程,增加一個條件分支:
    (define (deriv exp var)
      (cond ((number? exp) 0)
            ((variable? exp)
             (
    if (same-variable? exp var) 1 0))
            ((sum? exp)
             (make
    -sum (deriv (addend exp) var)
                       (deriv (augend exp) var)))
            ((product? exp)
             (make
    -sum
                (make
    -product (multiplier exp)
                              (deriv (multiplicand exp) var))
                (make
    -product (multiplicand exp)
                              (deriv (multiplier exp) var))))
            ((exponentiation? exp)
             (let ((n (exponent exp)))
             (make
    -product (make-product n (make-exponentiation (base exp) (- n 1))) (deriv (base exp) var))))
            (
    else
               error 
    "unknown expression type -- Deriv" exp)))
    粗體的就是我們增加的部分,兩次運用make-product做乘法。
    測試下:
    > (deriv '(** x 3) 'x)
    (
    * 3 (** x 2))
    > (deriv '(** (+ x 1) 5) 'x)
    (
    * 5 (** (+ x 14))

    習題2.57,只要修改selector函數就夠了,如果是多項的和或者積,那么被乘數和被加數也是列表,可以直接表示為符號表達式而不求值
     (define (augend s)
     (let ((rest (cddr s)))
        (
    if (null? (cdr rest))
            (car rest) 
            (cons 
    '+ rest))))
    (define (multiplicand p)
      (let ((rest (cddr p)))
        (
    if (null? (cdr rest))
            (car rest) 
            (cons 
    '* rest))))

    習題2.58,分為a和b,a倒是很容易解答,修改下謂詞、選擇函數和構造函數就可以了,將運算符號放在列表中間,注意,題目已經提示,假設+和*的參數都是兩個,因此
    (a)題目:
    (define (=number? x y)
      (
    and (number? x) (= x y)))
    (define (variable? x) (symbol? x))
    (define (same
    -variable? v1 v2) (and (variable? v1) (variable? v2) (eq? v1 v2)))
    (define (sum? x)
      (let ((op (cadr x)))
        (
    and (symbol? op) (eq? op '+))))
    (define (addend s) (car s))
    (define (augend s) (caddr s))
    (define (make
    -sum a1 a2)
      (cond ((
    =number? a1 0) a2)
            ((
    =number? a2 0) a1)
            ((
    and (number? a1) (number? a2)) (+ a1 a2))
            (
    else
             (list a1 
    '+ a2))))
    (define (product? x)
      (let ((op (cadr x)))
        (
    and (symbol? op) (eq? op '*))))
    (define (multiplier x) (car x))
    (define (multiplicand x) (caddr x))
    (define (make
    -product a1 a2)
      (cond ((
    or (=number? a1 0) (=number? a2 0)) 0)
            ((
    =number? a1 1) a2)
            ((
    =number? a2 1) a1)
            ((
    and (number? a1) (number? a2)) (* a1 a2))
            (
    else
              (list a1 
    '* a2))))
    測試下:
    > (deriv '(x + (3 * (x + (y + 2)))) 'x)
    4
    > (deriv '(x + 3) 'x)
    1
    > (deriv '((2 * x) + 3) 'x)
    2
    > (deriv '((2 * x) + (3 * x)) 'x)
    5

    習題2.59,求集合的交集,遍歷集合set1,如果(car set1)不在集合set2中,就將它加入set2,否則繼續(xù),當集合set1為空時返回set2。
    (define (union-set set1 set2)
      (cond ((null? set1) set2)
            ((null? set2) set1)
            ((element
    -of-set? (car set1) set2) set2)
            (
    else
              (union
    -set set1 (cons (car set1) set2))))) 

    習題2.60,需要修改的僅僅是adjoin-set:
    (define (adjoin-set x set)
      (cons x set))
    效率由原來的n變成常量。其他操作的效率與原來的一樣。有重復元素的集合,比如成績單、錢幣等等。


    習題2.61,關鍵點就是在于插入元素后要保持集合仍然是排序的,如果x小于(car set),那么最小的就應該排在前面了,如果大于(car set),那么將(car set)保留下來,繼續(xù)往下找:
    (define (adjoin-set x set)
      (cond ((null
    ? set) (list x))
            ((
    = x (car set)) set)
            ((
    < x (car set)) (cons x set))
            (
    else
               (cons (car set) (adjoin
    -set x (cdr set))))))

    習題2.62,與求交集類似:
    (define (union-set set1 set2)
      (cond ((null
    ? set1) set2)
            ((null
    ? set2) set1)
            (
    else
             (let ((x1 (car set1))
                   (x2 (car set2)))
               (cond ((
    = x1 x2)
                      (cons x1
                            (union
    -set (cdr set1) (cdr set2))))
                     ((
    < x1 x2)
                      (cons x1
                            (union
    -set (cdr set1) set2)))
                     ((
    > x1 x2)
                      (cons x2
                            (union
    -set set1 (cdr set2)))))))))

    測試下:
    > (define set1 (list 2 3 4 5 9 20))
    > (define set2 (list 1 2 3 5 6 8))
    > (union-set set1 set2)
    (
    1 2 3 4 5 6 8 9 20)

    習題2.63,其實兩個變換過程都可以看成是對樹的遍歷
    a)通過測試可以得知,產生一樣的結果,兩者都是中序遍歷二叉樹,書中圖的那些樹結果都是(1 3 5 7 9 11)
    b)對于tree->list-1過程來說,考慮append過程,并且每一步并沒有改變搜索規(guī)模,而append的增長階是O(n),因此tree->list-1的增長階應該是O(n2),n的二次方
    而對于tree-list-2過程,增長階顯然是O(n)

    習題2.64,這題非常有趣,用一個數組構造一棵平衡的樹,顯然,方法就是將數組對半拆分,并分別對兩個部分進行構造,這兩個部分還可以拆分直到遇到數組元素(左右子樹都是'()),中間元素作為entry。這個過程可以一直遞歸下去。這里采用的正是這種方式
    a)解釋如上,(1 3 5 7 9 11)將形成下列的二叉樹:
            5
           /  \
          1    9
           \  /  \
            3 7   11
    顯然,列表的對半拆分,以5作為根節(jié)點,然后左列表是(1 3),右列表是(7 9 11),左列表拆分就以1為節(jié)點,右列表拆分以9為節(jié)點,其他兩個為子樹。

    b)仍然是O(n)

    習題2.65,很簡單了,轉過來轉過去就是了:
    (define (union-set-1 tree1 tree2)
      (list->tree (union-set (tree->list-2 tree1)
                             (tree->list-2 tree2))))
    (define (intersection-set-1 tree1 tree2)
      (list->tree (intersection-set (tree->list-2 tree1)
                                    (tree->list-2 tree2))))

     習題2.66,與element-of-set?類似:
    (define (lookup given-key set-of-records)
      (cond ((null? set-of-records) #f)
            ((= given-key (key (entry set-of-records))) (entry set-of-records))
            ((
    < given-key (key (entry set-of-records))) 
               (lookup given-key (left-branch set-of-records)))
            ((
    > given-key (key (entry set-of-records))) 
               (lookup given-key (right-branch set-of-records)))))

    習題2.67,結果是(a d a b b c a) ,DrScheme字母符號是小寫
    習題2.68,使用到memq過程用于判斷符號是否在列表中:
    (define (encode-symbol symbol tree)
      (define (iter branch)
        (if (leaf? branch)
            '()
            (if (memq symbol (symbols (left-branch branch)))
                (cons 0 (iter (left-branch branch)))
                (cons 1 (iter (right-branch branch))))
            ))
      (if (memq symbol (symbols tree))
          (iter tree)
          (display "bad symbol -- UNKNOWN SYMBOL")))
    習題2.69,因為make-leaf-set產生的已經排序的集合,因此從小到大兩兩合并即可:
    (define (generate-huffman-tree pairs)
      (successive
    -merge (make-leaf-set pairs)))
    (define (successive-merge set)
      (if (= 1 (length set))
    (car set)
    (successive-merge
    (adjoin-set (make-code-tree (car set) (cadr set)) (cddr set)))))

    習題2.70,利用generate-huffman-tree和encode過程得到消息,使用length測量下消息長度就知道多少位了:
    (define roll-tree (generate-huffman-tree '((A 2) (NA 16) (BOOM 1) (SHA 3) (GET 2) (YIP 9) (JOB 2) (WAH 1))))
    (define message (encode
             
    '(Get a job Sha na na na na na na na na Get a job Sha na na na na na na na na Wah yip yip yip yip yip yip yip yip yip Sha boom)
             roll
    -tree))

    > (length message)
    84
      通過huffman編碼后的位數是84位,如果采用定長編碼,因為需要表示8個不同符號,因此需要log2(8)=3位二進制,總位數至少是36*3=108位,壓縮比為22.22%

    習題2.71,很顯然,最頻繁出現的符號肯定在根節(jié)點下來的子樹,位數是1,而最不頻繁的符號是n-1位





    評論

    # re: sicp 2.3小結習題嘗試解答  回復  更多評論   

    2009-10-21 18:33 by just a look
    2.63題,append是n/2因此總的來說還是n
    主站蜘蛛池模板: 男女作爱免费网站| 99久在线国内在线播放免费观看| 久久精品国产精品亚洲人人 | 亚洲AV永久无码天堂影院| 日韩午夜免费视频| 中国好声音第二季免费播放| 亚洲国产高清在线精品一区| 日韩精品亚洲专区在线观看| 久爱免费观看在线网站| 亚洲欧美国产日韩av野草社区| 久久亚洲国产精品123区| 欧美a级在线现免费观看| 国产综合免费精品久久久| 色噜噜亚洲男人的天堂| 亚洲欧洲美洲无码精品VA| 国产精品成人免费视频网站京东| 一个人看www免费高清字幕| 亚洲国产中文在线视频| a级亚洲片精品久久久久久久 | 国产黄色免费网站| 好男人看视频免费2019中文| 精品人妻系列无码人妻免费视频| 亚洲欧洲国产成人精品| 亚洲一区二区三区偷拍女厕| 成人免费无码大片A毛片抽搐色欲| 日本道免费精品一区二区| 国产精品手机在线亚洲| 亚洲国产av一区二区三区丶| 久久亚洲综合色一区二区三区| www国产亚洲精品久久久| 成人性生活免费视频| 无码国产精品一区二区免费16| 亚洲成人在线免费观看| 国产亚洲av片在线观看18女人| 最新69国产成人精品免费视频动漫| 亚洲综合色区中文字幕| 亚洲精品夜夜夜妓女网| 免费一级毛片在线播放不收费| 97无码免费人妻超级碰碰夜夜| 伊人久久免费视频| 成人精品视频99在线观看免费|