1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Tài liệu Kiểu dữ liệu phức hợp_chương 3 doc

90 293 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 90
Dung lượng 1,11 MB

Nội dung

CHNG III. KIU D LIU PHC HP If worms have the power of acquiring some notion, however rude, of the shape of an object and of their burrows, as seems to be the case, they deserve to be called intelligent. Charle R. Darwin (Vegetable Mould, 1881) iu d liu phc hp trong Scheme gm kiu chui (string), kiu vect (vector), kiu b đôi (doublet), kiu danh sách. Ngoài ra, Scheme còn mt s kiu d liu phc hp khác. Kiu d liu th tc (procedure) ch đnh các bin cha giá tr tr v ca hàm. Kiu d liu cng (port) ch đnh các cng vào-ra tng ng vi các tp và các thit b vào-ra (bàn phím, màn hình). Cui cùng, tt c các kiu d liu va xét trên đây, k c kiu đn gin, đu đc Scheme gom li thành mt giuc đc gi là kiu s-biu thc. K Sau đây, ta s ln lt trình bày các kiu d liu chui, vect, b đôi và danh sách. Trong phn trình bày kiu d liu b đôi, chúng ta s nghiên cu khái nim tru tng hoá d liu (data abstraction). III.1 Kiu chui Chui là mt dãy các ký t bt k đc vit gia mt cp du nháy đôi (double-quotes). Giá tr ca chui chính là bn thân nó. Ví d sau đây là mt chui : ”Cha`o ba.n !” --> ”Cha`o ba.n !” Có th đa vào trong chui du nháy đôi, hay du \ (reverse solidus), bng cách đt mt du \ phía trc, chng hn : (display ”two \”quotes\” within.”) --> two ”quotes” within. Th vin Scheme có hàm string cho phép ghép liên tip các ký t thành mt chui : (string #\S #\c #\h #\e #\m #\e) --> ”Scheme” Ta có th đnh ngha mt bin nhn giá tr kiu chui : (define greeting ”Scheme ; cha`o ba.n !”) ; Chú ý du ; trong mt chui không có vai trò là du chú thích.  tip cn đn mt ký t ca chui  mt v trí bt k, cn s dng hàm string-ref. Ch s ch v trí ký t là mt s nguyên dng, tính t 0. Ch s hp l ln nht ca chui đã cho là chiu dài ca chui tr đi 1 : (string-length greeting) --> 21 61 62 LP TRÌNH HÀM (string-ref greeting 0) --> #\S (string-ref greeting 20) --> #\! (define Str ; s dng hàm ghép liên tip các chui (string-append ”Chuoi \”” greeting ” \” co do dai 21.”)) (display Str) --> Chuoi ”Scheme ; cha`o ba.n ! ” co do dai 21. V t string? dùng đ kim tra kiu chui : (string? greeting) --> #t S dng hàm make-string, ta có th to ra mt chui có đ dài bt k và cha các ký t bt k : (define a-5-long-string (make-string 5)) a-5-long-string --> ”?????” (define a-5-asterisk-string (make-string 5 #\*)) a-5-asterisk-string --> ”*****” Hàm string-set! dùng đ thay th mt ký t trong chui đã cho ti mt v trí bt k cho bi ch s : (string-set! a-5-long-string 0 #\c) a-5-long-string --> ”c????” Trên đây ta đã s dng các hàm x lý chui : (string? Str) Tr v #t nu str là mt chui, nu không tr v #f. (string-append str 1 str 2 .) Tr v chui ghép liên tip các chui str 1 , str 2 . (make-string k [char]) Tr v mt chui mi có đ dài k. Nu có tham bin char, thì tt c các ký t ca chui s là char, nu không ni dung ca chui s không đc xác đnh. (string-length str) Tr v đ dài ca chui str. (string-ref str k) Tr v ký t th k ca chui str. Giá tr ca k phi hp l. (string-set! string k char) t giá tr ký t th k ca chui str bi char. Giá tr ca k phi hp l. Sau đây là mt s hàm x lý chui khác ca Scheme : Các v t so sánh chui : (string=? str 1 str 2 ) KIU D LIU PHC HP 63 (string<? str 1 str 2 ) (string>? str 1 str 2 ) (string<=? str 1 str 2 ) (string>=? str 1 str 2 ) tr v #t nu tha mãn quan h th t t vng =, <, >, <=, >= gia các chui (có phân bit ch hoa ch thng), tr v #f nu không tha mãn. Phép so sánh da trên các v t so sánh ký t char=?, char<?, char>?, char<=?, và char>=?. Hai chui đc xem nh tng đng v mt t vng nu chúng có cùng chiu dài và bao gm dãy các ký t ging nhau tng ng vi char=?. Các v t sau đây cng cho kt qu tng t nhng phép so sánh chui không phân bit ch hoa ch thng : (string-ci=? str 1 str 2 ) (string-ci<? str 1 str 2 ) (string-ci>? str 1 str 2 ) (string-ci<=? str 1 str 2 ) (string-ci>=? str 1 str 2 ) Phép so sánh đc da trên các v t so sánh ký t char-ci=?, char-ci<?, char- ci>?, char-ci<=?, và char-ci>=?. Hàm : (string-copy str) tr v chui mi là bn sao (copy) ca str : (string-copy ”abc”) --> ”abc” Hàm : (substring str k l) tr v bn sao ca str k t ký t có ch s k (k c k) đn ký t có ch s l (không k l). Các giá tr ca k và l phi hp l. (substring "Hello, World!" 0 1) --> ”H” (substring "Hello, World!" 7 12) --> ”World” Hàm substring có th đnh ngha li nh sau : (define my-substring (s1 m n) (let ((s2 (make-string (- n m)))) (do ((j 0 (+ j 1)) (i m (+ i 1))) ((= i n) s2) (string-set! s2 j (string-ref s1 i))))) (my-substring "Hello, World!" 7 12) --> ”World” Trong hàm my-substring s dng cu trúc lp do có cú pháp nh sau : (do ((var 1 init 1 step 1 ) . ) (test expr .) command . ) 64 LP TRÌNH HÀM Cu trúc lp do hot đng tng t nh lnh do trong các ngôn ng mnh lnh : bin điu khin var 1 nhn giá tr khi đng init 1 có bc thay đi step 1 (nu có) cho mi ln lp. Khi điu kin lp test cha đc tho mãn (false), biu thc command (nu có) đc thc hin. Khi test đc tho mãn (true), các biu thc expr đc tính (t trái qua phi) đng thi là giá tr tr v. (define L '(1 3 5 7 9)) (do ((L L (cdr L)) (sum 0 (+ sum (car L)))) ((null? L) sum)) --> 25 III.2 Kiu d liu vect Vect là kiu d liu gm mt dãy các phn t tng t kiu chui, nhng mi phn t có th có kiu bt k, không hoàn toàn ký t. Mi phn t ca vect li có th là mt vect, t đó to thành vect có nhiu chiu (multidimensional vector). Trong Scheme, các phn t ca vect đc đt trong mt cp du ngoc (), ngay sát trc cp du ngoc có đt mt du # (number sign). ’#(999 #\a ”Kiki” (1 2 3) ’x) --> ’#(999 #\a ”Kiki” (1 2 3) ’x) S dng hàm vector đ to ra mt vect các s nguyên nh sau : (vector 1 2 3 4 5) --> ’#(1 2 3 4 5) (vector ’x ’y ’z) --> ’#(x y z) Hàm make-vector đ to ra mt vect có đ dài n đnh trc : (make-vector 3) --> ’#(#{Unspecific} #{Unspecific} #{Unspecific}) (make-vector 3 ”Kiki”) --> ’#(”Kiki” ”Kiki” ”Kiki”) Tng t kiu chui, các hàm vector-ref và vector-set! dùng đ tip cn và thay đi tng ng tng phn t ca vect. V t vector? dùng đ kim tra kiu vect : (vector? ’#(x y z)) --> #t S dng cu trúc do, ta to ra mt vect các s t nhiên nh sau : (do ((v (make-vector 5)) (i 0 (+ i 1))) ((= i 5) v) (vector-set! vec i i)) --> ’#(0 1 2 3 4) KIU D LIU PHC HP 65 III.3 Kiu d liu b đôi III.3.1. Khái nim tru tng hoá d liu Tru tng hoá th tc (procedure abstraction) là xây dng các ng dng phc tp t nhng thao tác đn gin, bng cách che du trong chng mc có th nhng chi tit x lý. Tru tng hoá d liu cng nhm mc đích đnh ngha mt lp d liu phc tp và cách thao tác trên các d liu đó mà không quan tâm đn cách biu din và cài đt chúng trong máy vt lý nh th nào. Phng pháp tru tng hoá d liu đc ng dng rng rãi trong lp trình hng đi tng. Mt cu trúc d liu tru tng hay kiu d liu tru tng đc đnh ngha, hay đc đc t (specification) bi 4 thành phn : tên kiu d liu tru tng (types), các đnh ngha hàm (functions), các điu kin đu (preconditions) nu có và các tiên đ (axioms). Hai thành phn đu mô t cú pháp v mt cu trúc thuc tính ca kiu d liu tru tng, hai thành phn sau mô t ng ngha. Thành phn functions lit kê các khuôn mu hàm (function pattern). Mi khuôn mu hàm, còn đc gi là mt ký pháp (signature), có dng mt ánh x cho bit kiu ca các tham đi và ca kt qu nh sau : Tên-hàm : min-xác-đnh − > min-tr Ngi ta thng phân bit ba loi hàm là hàm kin to (constructor) đ to ra kiu d liu mi, hàm tip nhn (accessor) đ trích ra các thuc tính và hàm bin đi (transformator) đ chuyn kiu d liu. Do các hàm không phi luôn luôn xác đnh vi mi d liu nên ngi ta cng phân bit các hàm toàn phn (total functions) và các hàm b phn (partial functions). Trong trng hp các hàm là b phn, ngi ta cn cung cp các điu kin đu là các ràng buc trên min xác đnh ca hàm. Mt li gi hàm không tuân theo điu kin đu đu dn đn sai sót (chia cho 0, tính cn bc hai ca mt s âm, v.v .). Chng hn, điu kin đu ca hàm to s hu t (create-rat n d) là mu s d≠0. Thành phn preconditions có th vng mt nu không có điu kin đu. Thành phn axioms mô t các chc nng vn dng hàm, phi đc khai báo rõ ràng, đy đ và d hiu. Mi vn dng hàm có dng mt mnh đ lôgích hp thc luôn có giá tr true, ngha là mt hng đúng (tautology). Khi cn s dng các bin, ngi ta s dng t khoá var đ khai báo trc tên các bin, tng t trong các ngôn ng lp trình mnh lnh nh C, Pascal . Chú ý rng kiu tin đnh number cng là mt kiu tru tng : bi vì ta có th bit các phép toán s hc trên các s nh +, −, *, . nhng ta li không bit cách biu din chúng trong b nh. Chng hn sau đây là đc t kiu s t nhiên Ν (natual number) : types nat functions 0 : -> nat ; 0 là s t nhiên đu tiên, là mt hng (constant) succ : nat -> nat ; hàm successor ly phn t k tip + : nat × nat -> nat – : nat × nat -> nat * : nat × nat -> nat ^ : nat × nat -> nat = : nat × nat -> boolean 66 LP TRÌNH HÀM axioms var X, Y : nat X + 0 == X X + succ(Y) == succ(X + Y) 0 – X ⇔ 0 ; ch làm vic vi các s t nhiên X – 0 ⇔ X succ(X) – succ(Y) ⇔ X – Y X * 0 ⇔ 0 X * succ(Y) ⇔ X + (X * Y) X ^ 0 ⇔ succ(0) X ^ succ(Y) ⇔ X * (X ^ Y) 0 = 0 ⇔ true succ(X) = 0 ⇔ false 0 = succ(X) ⇔ false succ(X) = succ(Y) ⇔ X = Y III.3.2. nh ngha b đôi Trong ngôn ng Scheme, mt b đôi, hay còn đc gi là cp có du chm (dotted pair), là kiu d liu phc hp tng t bn ghi gm mt cp giá tr nào đó có th t. Có mt du chm đ phân cách hai giá tr lu gi trong b đôi và các du cách đ phân cách gia du chm và các giá tr. Phn t (trng) th nht đc gi là car, phn t th hai cdr. Các tên car và cdr 1 xut hin khi John Mc. Carthy đ xut ngôn ng Lisp chy trên IBM-704 nm 1956 và đc gi li theo truyn thng. Gi s any là mt kiu d liu nào đó ca Scheme, ký pháp ca cu trúc b đôi doublet đc đc t nh sau : types doublet functions cons : any × any -> doublet car : doublet -> any cdr : doublet -> any pair? : any -> boolean axioms var a, y : any car(cons(x, y)) = x cdr(cons(x, y)) = y T kiu tru tng b đôi, đ to ra b đôi, ngi ta s dng cons : (cons s 1 s 2 ) --> (<giá tr ca s 1 > . <giá tr ca s 2 >) Sau đây là mt ví d v mt b đôi : : (cons ’year 2004) ; gm mt ký hiu và mt s −-> (year . 2004) (cons 29 #t) ; gm mt s và mt tr lôgích −-> (29 . #t) nh ngha bin có giá tr là mt b đôi : 1 car = content of the address register, cdr = content of the decrement register. KIU D LIU PHC HP 67 (define x (cons 1 2)) x --> (1 . 2) (car x) --> 1 (cdr x) --> 2 Trong máy, b đôi đc biên dch nh mt cp con tr tr đn car và cdr. x car cdr 1 2 Hình III.1. Biu din các b đôi nh con tr. Các thành phn car và cdr ca b đôi có vai trò đi xng nhau : hàm car tng ng vi thành phn đu tiên và hàm cdr tng ng vi thành phn th hai. Ta có quan h tng quát nh sau : (car (cons a b)) = <giá tr ca a> (cdr (cons a b)) = <giá tr ca b> (car x) --> 1 x = (1 . 2) (cdr x) --> 2 (cdr (car y)) --> 2 V t pair? dùng đ kim tra s-biu thc có phi là mt b đôi hay không ? (define x ’(1 . 2)) (pair? x) --> #t ; x = (1 . 2) là mt b đôi (pair? (cdr x)) --> #f ;(cdr x) = 2 không phi là mt b đôi V t eq? hay đc dùng đ kim tra hai b đôi có đng nht vi nhau không. Thc cht, eq? kim tra tính đng nht ca hai con tr. Ng ngha ca hàm này nh sau : axioms var x, y : doublet ; a, b : any (x = cons(a, b)) ∧ (y = x) ⇒ (eq?(x) = eq?(y)) Ví d : (define x (cons 1 2)) (define y x) ; c x và y cùng tr đn mt b đôi (eq? x y) --> #t Tuy nhiên : 68 LP TRÌNH HÀM (eq? x (cons 1 2)) --> #f bi vì x không tr đn b đôi mi đc to ra bi cons ! III.3.3. t bin trên các b đôi Nh cons, car, cdr, ta đã đnh ngha các b đôi nh là d liu s cp. T đó, ta có th thay đi b đôi nh các hàm đt bin set-car! và set-cdr!. Các hàm này không to ra b đôi mi, nhng làm thay đi b đôi đang tn ti. Scheme quy c các hàm làm thay đi trng thái mt đi tng có tên gi kt thúc bi du chm than !. Ngi ta gi đó là nhng hàm đt bin (mutator functions). Gi s kiu b đôi đc to ra t hai kiu d liu nào đó ca Scheme là T1 và T2, ta vit quy c doublet(T1, T2), khi đó các hàm set-car! và set-cdr! đc b sung vào phn đc t hàm nh sau : functions set-car! : doublet(T1, T2) × T1 → any set-cdr! : doublet(T1, T2) × T2 → any Ng ngha ca các hàm này nh sau : axioms var x : doublet(T1, T2) ; a, a1 : T1, b, b1 : T2 (x = cons(a, b)) ∧ (set-car!(x, a1)) ⇒ (car(x) = a1) (x = cons(a, b)) ∧ (set-cdr!(x, b1)) ⇒ (cdr(x) = b1) Gi s ta có b đôi : (define x (cons 1 2)) x --> (1 . 2) 1 x 2 1 2 x 4 3 (a) (b) Hnh III.3.1. Biu din các b đôi đt bin. Trc (a) và sau khi (b) thay đi b đôi Khi đó nu thc hin : (set-car! x 3) (set-cdr! x 4) thì giá tr ca con tr x không thay đi, c hai trng hp đu cùng tr đn mt b đôi. Tuy nhiên trong trng hp sau, ni dung ca b đôi đã thay đi, lúc này b đôi cha hai con tr tr đn hai v trí biu din ln lt 3 và 4. Riêng hai v trí cha ln lt 1 và 2 vn nh c. Kim tra giá tr ca con tr x : x --> (3 . 4) [...]... (primes ’(2 3 5 7 11 71 73 79 83 149 151 157 227 229 233 30 7 31 1 31 3 38 9 39 7 401 467 479 487 III.4.2.5 K thu t 13 17 19 23 29 31 37 41 43 47 53 59 61 67 89 97 101 1 03 107 109 1 13 127 131 137 139 1 63 167 1 73 179 181 191 1 93 197 199 211 2 23 239 241 251 257 2 63 269 271 277 281 2 83 2 93 317 33 1 33 7 34 7 34 9 35 3 35 9 36 7 37 3 37 9 38 3 409 419 421 431 433 439 4 43 449 457 461 4 63 491 499) quy x lý danh... #\A #\a) > #f (string=? "1 23" "1 23" ) > #t (eqv? #\A #\A) > #t (eqv? 'toto 'toto) > #t (eqv? "1 23" "1 23" ) > #t (equal? "1 23" "1 23" ) > #t V t eqv?, hay eq?, dùng so sánh các ki u d li u b t k , k t qu s là #t n u chúng cùng m t i t ng Riêng ki u d li u danh sách nên s d ng v t so sánh string=? (eq? 1 23 1 23) > #t 92 L P TRÌNH HÀM (eq? 1 234 5678901 234 5678901 1 234 5678901 234 5678901) > #f (eq? ’(1 ... ’a ’(b c a d e)) > (a d e) (memq ’a ’(b c d e g)) > #f (memq ’a ’(b a c a d a)) > (a c a d a) (memv 3. 4 ’(1.2 2 .3 3.4 4.5)) > (3. 4 4.5) (memv 3. 4 ’(1 .3 2.5 3. 7 4.9)) > #f (member ’(b) ’((a) (b) (c))) > ((b) (c)) (member ’(d) ’((a) (b) (c))) > #f (member ”b” ’("a" "b" "c")) > (”b” ”c”) III.4.2 .3 D ng case x lý danh sách D ng case t ng t cond nh ng th pháp c a d ng case nh sau : (case s (L1 body1)... (cons (cons ’()) )) Ví d : (list (cons 1 2) (cons 3 4)) > ((1 2) (3 4)) ; (1 2) và (3 4) là các b Hàm list nh n m t s tham i tùy ý là các s-bi u th c h p t các giá tr c a các tham i ó Ví d : ôi tr v m t danh sách m i t (list 1 2 3) > (1 2 3) (list ’(a b) ’(c d) ’(c d) ’() ’((e))) > ((ab) (cd) () (e)) Danh sách sau ây g m 3 ph n t , ph n t th nh t là d u + : ’(+ 1 2) > (+ 1 2) Chú... V1) (car V2)) (equal? (cdr V1) (cdr V2)))) (else #f))) ; các i t ng có b n ch t khác nhau (equal? > #t (equal? > #t (equal? > #t (equal? > #t #\a #\a) "1 23" "1 23" ) '(1 2) '(1 2)) '(1 2 3 4 5) '(1 2 3 4 5) ) III.4 .3 Bi u di n danh sách III.4 .3. 1 Bi u di n danh sách b i ki u b ôi M t danh sách khác r ng là m t b ôi c bi t : ch ng h n danh sách có m t ph n t (a) chính là b ôi ’(a ()) có ph n t th... ’(a > ’() (list-tail ’(a > ’(c d) (list-tail ’(a > d b c) 0) b c) 2) b c) 3) b c d) 2) b c d) 3) (define week-end (list-tail week-list 5)) week-end > (samedi dimanche) V t (list? L) ki m tra L có ph i là m t danh sách không : (list? > #t (list? > #t (list? > #f (list? > #f (list? > #f ’()) ’(a b c)) ’a) ’ (3 4)) 3) 3 Các hàm chuy n i ki u (string->list str) (list->string L) (string->number... 2 1 3 5 Hình III.8 t bi n c a C c ng là t bi n c a D Ng i ta c ng có th ti t ki m c nhi u b nh b ng cách bi u di n m i b ôi trong m t n v nh Sau ây ta xét m t ví d v kh n ng x y ra hi u ng ph khi th c hi n các phép t bi n trên các danh sách (define X (list 1 2 3 4)) (define Y (cdr X)) ; X và Y có cùng danh sách con (2 3 4) (set-car! X 5) ; thay i X mà không nh h ng n Y X > (5 2 3 4) Y > (2 3 4)... (define (value-y R) (cdr (car (define (value-L R) (car (cdr (define (value-H R) (cdr (cdr Ví d : (define R (cons-rectangle 1 2 R > '((1 2) 3 4) ; t ng c xây d ng nh sau : H) H))) R))) R))) R))) R))) 3 4)) ng v i '((1 2) (3 4)) 74 L P TRÌNH HÀM (value-L R) > 3 (value-H R) > 4 III.4 Ki u d li u danh sách III.4.1 Khái ni m danh sách Khi gi i m t s bài toán, ng i ta th ng ph i nhóm nhi u d li u thành... (null? L) 0 (+ 1 (length (cdr L))))) Hàm length có chi phí tuy n tính Ví d : (length (list 1 2 3) ) > 3 (= (length (list 1 2 3 4)) 0) > #f Các danh sách r ng có th d ng tr c ki n ’() Ví d : c t o ra b i hàm (list) không có tham i, ho c s (= (length (list)) 0) > #t (= (length ’()) 0) > #t (null? (list 1 2 3 4)) > #f (null? (list)) > #t (null? ’()) > #t Scheme không th a nh n d ng ’() là m t bi u... L-congviec-10-10-2000 ’(thu-hai (sang (9h doc- thu) (9h -30 chuan-bi-len-lop) (10h len-lop) (12h an-trua)) (chieu (14h tham-gia-chuyen-de) (16h den-cuoc-hen)))) Ki u d li u danh sách c n có th thu t có th c vào và in ra Scheme cho phép xây d ng các danh sách không thu n nh t (heterogeneous list) v ki u Ch ng h n : (define L ’(1 (2 3) x "bonjour")) (list-ref L 0) > 1 (list-ref L 3) > "bonjour" Tr tr ng h p ng . (1 2 3) ’x) --> ’#(999 #a ”Kiki” (1 2 3) ’x) S dng hàm vector đ to ra mt vect các s nguyên nh sau : (vector 1 2 3 4 5) --> ’#(1 2 3 4 5). (cons-rectangle 1 2 3 4)) R --> '((1 . 2) 3 . 4) ; tng đng vi '((1 . 2) . (3 . 4)) b V y 0 x a L H 74 LP TRÌNH HÀM (value-L R) --> 3 (value-H

Ngày đăng: 15/12/2013, 16:15

TỪ KHÓA LIÊN QUAN