Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 40 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
40
Dung lượng
368 KB
Nội dung
Chơng i. Kiểu con trỏ và biến động 1. Khái niệm - Các biến có kiểu cấu trúc (mảng, tập hợp, bản ghi ) đã nghiên cứu từ tr ớc đến nay đợc gọi là tĩnh vì chúng đợc xác định và cấp phát bộ nhớ khi biên dịch. (Mô tả kiểu và khai báo biến) - Các biến thuộc kiểu dữ liệu đã học nh mảng, tập hợp, bản ghi, đ ợc gọi là biến tĩnh vì chúng đợc xác định rõ ràng khi khai báo và sau đó đợc dùng thông qua tên của chúng. Thời gian tồn tại của các biến tĩnh cũng là thời gian tồn tại của khối chơng trình có chứa khai baó các biến này. (Ví dụ các biến tĩnh đợc khai báo trong chơng trình chính sẽ tồn tại trong suốt thời gian chơng trình chạy, các biến tĩnh đợc khai báo trong chơng trình con sẽ tồn tại mỗi khi chơng trình con đó đợc gọi). Do đó trong nhiều chơng trình, việc sử dụng một số lợng lớn các biến sẽ gây ra hậu quả không đủ bộ nhớ (phạm vi ô nhớ dành cho tất cả các biến tĩnh trên máy vi tính họ IBM PC là 64KB). Ví dụ khi có khai báo Var DS : array [1 Max] of Real; Ta phải xác định số phần tử của mảng, nghĩa là trị số của max phải đợc xác định khi mô tả. Vùng nhớ mà biến DS chiếm là cố định trong thời gian chơng trình làm việc. Do đó ở thời điểm lập trình ta phải hình dung đợc độ lớn của mảng và thờng khai báo d, gây lãng phí bộ nhớ. - Để khắc phục trờng hợp lãng phí bộ nhớ nh trên, Turbo Pascal cho phép dùng biến động đ- ợc lu trữ trong vùng HEAP. Biến động có thể đợc tạo ra khi cần thiết và xoá đi khi không dùng. Do đó số biến này hoàn toàn không xác định trớc. Biến động không có tên và do con trỏ quản lý. (Việc đặt tên thực chất là gán cho nó một địa chỉ xác định) - Việc tạo ra biến động và xoá nó đi nhờ NEW và DISPOSE. - Việc truy nhập các biến động đợc tiến hành nhờ các biến con trỏ. 2. Biến con trỏ (Pointer Variable) - Biến con trỏ là một loại biến đặc biệt có kích thớc 2 byte, không dùng để chứa dữ liệu mà là chứa địa chỉ của các biến động. - Các giá trị của biến con trỏ không thể đọc vào từ bàn phím hay in ra trực tiếp trên màn hình, máy in (không dùng Write/ Read). a. Khai báo biến con trỏ (Pointer) - Để khai báo biến con trỏ P dùng để chứa địa chỉ của các biến động có kiểu dữ liệu T với kiểu con trỏ Tp tơng ứng ta khai báo nh sau : * Khai báo gián tiếp : Type Tp = ^T ; Var P : Tp ; Ví dụ : 1) Type songuyen = ^Integer ; HS = ^BG BG = Record Hoten : String [25] ; Tuoi : Integer ; DTB : Real ; End; 1 Var i , j : songuyen ; P, Q : HS ; Thì i, j, P, Q là các biến con trỏ. 2) Type Point = ^Nhan_Su; Nhan_Su = Record Ten : String [25] ; Tuoi : Integer ; Luong : Real ; End; Var P : Point ; {P là biến kiểu con trỏ chứa địa chỉ của biến động có kiểu là Nhan_Su} Pascal cho phép mô tả con trỏ trớc cả mô tả kiểu của biến động. Viết nh sau cũng đợc: 3) Type Nhan_Su = Record Ten : String [25] ; Tuoi : Integer ; Luong : Real ; End; Point : ^Nhan_Su; Var P : Point; 4) Quản lý sách: Type Sach = Record - Tên sách TenS : String [30] ; - Tên tác giả TenTg : String [25] ; - Mã sách MaS : String [3] ; - Năm xb NamXB : Integer ; End ; Point : ^Sach ; Var P : Point ; 5) Đa thức : - Số mũ - Hệ số Type Dathuc = Record Somu : Byte ; Heso : Integer ; End ; Point = ^Dathuc ; Var P : Point; * Khai báo trực tiếp: Var i,j : ^Integer; P : ^T; Q : ^Real; * Khai báo tổng quát : - Khai báo tổng quát cho phép con trỏ có thể trỏ đến bất kỳ vị trí nào trong bộ nhớ. Để khai báo biến con trỏ mà không nhất thiết chỉ ra kiểu dữ liệu các biến động do nó quản lý, ta khai báo nh sau : Var <Tên Biến> : Pointer; Ví dụ : P : Pointer ; (con trỏ tổng quát) Q : Pointer ; 2 Chú ý : Để truy nhập đến biến động do con trỏ P quản lý, ta viết nh sau: P^. Mô tả: Biến con trỏ P chứa địa chỉ của biến động P^ Trờng hợp P^ chứa nhiều trờng b) Các thao tác đối với con trỏ (1) Phép gán (:=) Phép gán thực hiện khi hai trỏ cùng kiểu Ví dụ : P:=Q; Có nghĩa là cho con trỏ Q trỏ vào vùng biến động mà P đang trỏ. Mô tả : P := Q ; Kết quả: (2) Phép so sánh - Với dữ liệu kiểu con trỏ, ta không thể thực hiện các phép so sánh: < , > , >= , <= mà chỉ có thể so sánh = và < >. - Khi so sánh P, Q : có nghĩa là P và Q cùng trỏ đến (hay không trỏ đến) 1 vùng biến động. (3) Hằng con trỏ NIL - Nil là một giá trị đặc biệt dành cho các biến con trỏ để báo con trỏ không trỏ vào đâu cả. Có thể gán Nil cho bất kỳ biến con trỏ nào. Ví dụ: Gán P := Nil thì P không trỏ đến dữ liệu nào cả. 3. Biến động (Dynamic variable) 3.1. Cấp phát vùng nhớ cho biến động - Để cấp phát vùng nhớ cho các biến động do con trỏ P quản lý, ta dùng thủ tục New(P) ; Khi đó máy sẽ tạo ra một vùng nhớ có kiểu và kích thớc do P qui định, hớng con trỏ P trỏ tới vùng biến động trên. 3 2 byte Chứa dữ liệu P P^ Hoten Tuoi Dtb P P^ Q Q^ Q Q^ P P^ P Vẫn còn P^ = Q^ NIL Vẫn còn P P^ P P:=Nil; - Nếu trong một chơng trình dùng N lần thủ tục New(P); liên tục thì tạo ra n biến động, song con trỏ P sẽ chỉ vào biến động đợc tạo ra lần cuối cùng. Mô tả : Ví dụ 1 : Có đoạn chơng trình sau: New (P) ; P^ := 10 ; New (P) ; P^ := 15 ; Ví dụ 2 : . New (P) ; {tạo ra biến động có địa chỉ trong P} WITH P^ DO {Câu lệnh WITH đợc phép dùng với biến động} Begin Ten := Nguyen An ; Tuoi := 20 ; Dtb := 7.0 ; End; New (P); P^.Ten := Le Binh ; P^.Tuoi:= 21 ; P^.Dtb := 6.5 ; Nh vậy đã tạo ra đợc 2 biến động kiểu HS, sau lần gọi New(P) lần 2, biến động đầu tiên mặc dù vẫn còn nằm trong ô nhớ của nó nhng con trỏ P không chứa địa chỉ của nó nữa mà P sẽ trỏ vào biến động vừa đợc tạo ra. Tóm lại : Sau mỗi lần dùng New(P) thì con trỏ P sẽ chứa địa chỉ của biến động P^ vừa đ- ợc tạo ra, còn các biến động đợc tạo ra bằng New(P) trớc đó sẽ không đợc P trỏ đến. Muốn truy nhập vào các biến động đợc tạo ra trớc đó ta phải có các biện pháp lu trữ địa chỉ chúng lại (phần sau). 3.2. Giải phóng hay thu hồi ô nhớ của biến động * Đối với 1 biến động: Để giải phóng hay thu hồi ô nhớ của biến động con trỏ P quản lí ta thực hiện thủ tục DISPOSE (P); Ví dụ 1 : Var P1, P2 : ^Integer ; Begin New (P1) ; {tạo ra một biến động kiểu nguyên có địa chỉ trong P1} P1^ := 1976 ; P2 := P1 ; Writeln('Nam sinh ',P2^) ; {xuất hiện màn hình Nam sinh 1976} Dispose (P2) ; {giải phóng biến động} End. Ví dụ 2 : Uses Crt ; Var P1, P2 : ^String ; Begin 4 P P 10 P P 15 P^ P^ P^ P^ New(P) lần 1 P^ :=10; New(P) lần 2 P^ :=15 ; Nguyen An 20 7.0 Le Binh 21 6.5 P Biến động được tạo ra lần 1 Biến động được tạo ra lần 2 New (P1) ; P1^ := 'Con duong da qua' ; P2 := P1 ; Writeln('Thich phim ',P2^) ; Dispose (P2) ; Readln ; End. * Đối với nhiều biến động Để giải phóng hay thu hồi ô nhớ của nhiều biến động (có thể tất cả các biến động) ta dùng cặp thủ tục MARK và RELEASE. Thủ tục MARK (Pvar) : trong đó PVar là biến con trỏ. Thủ tục này đánh dấu vị trí đầu tiên của vùng ô nhớ cần giải phóng sau này. Sau thủ tục MARK có thể dùng một loạt thủ tục NEW để tạo ra các biến động khác và chúng sẽ chiếm ô nhớ kể từ vị trí đợc đánh dấu. Thủ tục RELEASE (Pvar) : sẽ xoá tất cả các biến động đã tạo từ khi đánh dấu MARK. Ví dụ : MARK (R) ; NEW (P) ; NEW (Q) ; NEW (K) ; RELEASE (R) ; Ví dụ : Tính tổng 20 số nguyên nhập từ bàn phím. Program Tong ; Var P : Pointer ; Pds : Array[1 20] of ^Integer ; S, i: Integer ; BEGIN Mark(P) ; {Tạo 20 biến động kiểu nguyên để chứa dữ liệu nạp vào từ bàn phím} For i:=1 to 20 do Begin New (Pds[i]) ; Readln (Pds[i]^) ; End; {Tính tổng các số vừa nạp} S:=0 ; For i:=1 to 20 do S:= S + Pds[i]^ ; {Giải phóng 20 biến động} Release (P); {In kết quả} Writeln ('Tong S = ',S); END. 3.3. Phân bổbộ nhớ. HEAP và STACK - HEAP là vùng nhớ mà Turbo Pascal dùng để lu trữ các biến động do NEW tạo ra. Thông thờng Turbo Pascal dùng tất cả vùng nhớ tự do (thờng rất lớn) của máy PC cho HEAP. TP quản lí HEAP thông qua con trỏ của HEAP. Con trỏ của HEAP luôn luôn trỏ vào byte (ô nhớ) tự do đầu tiên của vùng ô nhớ còn tự do của HEAP. Mỗi lần gọi NEW, con trỏ của 5 HEAP đợc dịch chuyển về phía đỉnh của vùng ô nhớ tự do một số byte tơng ứng với kích th- ớc của biến động mới đợc tạo ra. - STACK là vùng nhớ dành cho các biến cục bộ đợc chơng trình con sử dụng. Kích thớc mặc định của nó là 16KB. Tuy vậy có thể dùng mục Memory sizes trên Option menu để thay đổi kích thớc vùng nhớ dành cho STACK. - Cách phân bố chơng trình, STACK, HEAP trong bộ nhớ của PC. MemAvail và MaxAvail là 2 hàm kiểm soát HEAP. - MemAvail cho tổng số byte còn rỗi trên Heap. - MaxAvail cho số byte liên tục lớn nhất còn rỗi trên Heap. Các vùng nhớ còn rỗi trên Heap thờng bị phân thành các khối nhỏ do máy cấp phát và giải toả các vùng nhớ trên Heap không theo một trật tự nào. Khi tạo biến cấp phát động trên Heap thì điều cần quan tâm là kích thớc của khối chứ không phải là tổng số vùng nhớ còn rỗi trên Heap. Để tránh tràn Heap trớc khi cấp phát bộ nhớ cho một đối tợng có kích thớc lớn (nh mảng, bản ghi) ta nên dùng hàm MaxAvail để kiểm tra có đủ bộ nhớ không. 4. Các ví dụ Ví dụ 1: Sử dụng các biến con trỏ có thể để lập chơng trình tính: Program VD1; Uses CRT; Var n, i : Integer; M, T : ^Integer; S : ^Real; BEGIN Clrscr; Repeat Write('Nhap n = '); Readln(n); Until (n>=1); New(M); M^:=0; New(T); T^:=1; New(S); S^:=0; For i:=1 to n do Begin M^ := M^ + sqr(i); T^ := T^ * i; S^ := S^ + M^/T^; End; Writeln('Ket qua la S = ',S:10:4); Readln; END. Ví dụ 2: Lập chơng trình nhập vào 1 danh sách sinh viên (sử dụng các biến con trỏ có thể). Mỗi sinh viên đợc quản lí bởi các trờng: Hoten - Họ và tên DM1 - Điểm môn 1 6 Vùng ô nhớ còn tự do Các biến động đã được tạo ra Vùng bộ nhớ Stack Bộ nhớ chương trình và biến tĩnh Heap : Vùng ô nhớ dành cho biến động Con trỏ của Stack Con trỏ của Heap 1 2 + 22 2! 1 2 + 22 + 3 2 2! 1 2 + 22 + + n 2 2! S = 1 + + + + C¸ch 2: Program VD4; Uses Crt; Type Nguyen = ^Integer; Var A : Array[1 10] of Nguyen; i, S : Integer; Pmark: Pointer; BEGIN Clrscr; Mark (Pmark); For i:=1 to 10 do Begin New(A[i]); Write('Nhap so thu ',i);Readln(A[i]^); S := S + A[i]^; End; Writeln('Tong S = ',S); Release (Pmark); Readln; END. DM2 - §iÓm m«n 2 DT - §iÓm tæng víi DT = DM1+DM2 Program VD2; Uses Crt; Type SV = Record Hoten : String[30]; DM1, DM2, DT : Real; End; Var n,i : Byte; P : ^SV; BEGIN Clrscr; Write('Cho so sinh vien : '); Readln(n); For i:=1 to n do Begin Writeln('Nhap sinh vien thu ',i); New(P); With P^ do Begin Write('Ho va ten :'); Readln(Hoten); Write('Diem mon 1:'); Readln(DM1); Write('Diem mon 2:');Readln(DM2); DT := DM1 + DM2; End; End; Readln; END. VÝ dô 3 : Sö dông biÕn con trá lËp ch¬ng tr×nh tÝnh tæng: S = 1- 2 + 3 - + (-1)… n-1 * n Program VD3; Uses Crt; Var i,n : Integer; S : ^Integer; P : Pointer; BEGIN Clrscr; Write('Cho n = '); Readln(n); New(S); S^:=0; For i:=1 to n do If odd(i) then S^ := S^ + i Else S^ := S^ - i; Writeln('Tong S = ',S^); Readln; END. VÝ dô 4 : TÝnh tæng 10 sè nguyªn nhËp tõ bµn phÝm. C¸ch 1: Program VD4; Uses Crt; Var i : Integer; S,P : ^Integer; Pmark: Pointer; BEGIN Clrscr; Mark (Pmark); New(S); S^:=0; For i:=1 to 10 do Begin New(P); Write('Nhap so thu ',i);Readln(P^); S^ := S^ + P^; End; Writeln('Tong S = ',S^); Release (Pmark); Readln; END. 7 VÝ dô 5 : Sö dông biÕn con trá ®Ó tÝnh tæng: S1 = 1 + 2 + + n; … S2 = 2 + 4 + + 2… * n Program VD5; Uses Crt; Var i,n : Integer; S1,S2 : ^Integer; P : Pointer; BEGIN Clrscr; Write('Cho n = ');Readln(n); Mark(P); New(S1); S1^ := 0; New(S2); S2^ := 0; For i:=1 to n do Begin S1^ := S1^ + i; S2^ := S2^ + i*2; End; Writeln('Tong cac so tu 1 den ',n,' la S1 = ',S1^); Writeln('Tong cac so chan tu 1 den ',n,' la S2 = ',S2^); Release(P); Readln; END. 8 Chơng iv. Tạo th viện các chơng trình con (unit) 1. Cấu trúc chung của một Unit Unit <Tên_Unit>; Interface { Khai báo các Unit khác } { Khai báo các hằng, biến, kiểu } { Khai báo các chơng trình con } Implementation { Khai báo hằng, tên, biến, kiểu cục bộ } { Cài đặt các chơng trình con } BEGIN { Các lệnh khởi tạo } END. Một Unit bao gồm 5 thành phần cơ bản sau: 1) Phần khai báo : Nhằm mục đích khai báo cho chơng trình dịch biết đây là một Unit, nó đợc định nghĩa nh sau : Unit <Tên_Unit> ; Trong đó <Tên_Unit> phải trùng với phần chính của tên tệp chứa Unit. Ví dụ : Tên tệp chứa là MyUnit.Pas thì ta phải định nghĩa là : Unit MyUnit; 2) Phần giao tiếp : Khai báo tất cả những gì mà các chơng trình hoặc các Unit khác có thể sử dụng đợc. Phần này đợc bắt đầu bởi từ khoá Interface. 3) Phần cài đặt : Bao gồm các lệnh cụ thể nhằm định nghĩa các thủ tục và hàm đợc khai báo ở phần giao tiếp. Tất cả các khai báo hằng, biến, kiểu trong phần này chỉ có giới hạn trong Unit mà thôi. Phần cài đặt đợc bắt đầu bởi từ khoá Implementation. 4) Phần khởi tạo : Bao gồm các lệnh mà các lệnh này sẽ đợc thực hiện trớc khi 1 thủ tục hoặc hàm của Unit đợc sử dụng. Phần này có thể có hoặc không trong Unit và nó đợc bắt đầu bởi từ khoá BEGIN. 5) Phần kết thúc : Chỉ bao gồm 1 từ khoá END. nhằm báo cho chơng trình dịch biết vị trí kết thúc của một Unit. Cũng nh tất cả các chơng trình Pascal khác, tất cả những phần nằm sau END. đều không có ý nghĩa. 2. Dịch và sử dụng Unit a. Dịch Unit - Chọn mục Compile trên menu. - ấn Enter tại mục Destination để chuyển sang Memory Disk. - ấn F9. Sau khi dịch xong, tên tệp có chứa Unit sẽ có phần mở rộng ngầm định là TPU. b. Sử dụng Unit - Các chơng trình hoặc Unit muốn sử dụng một Unit nào đó thì phải mở nó bằng lệnh Uses <Tên_Unit> ; - Nếu 2 Unit đợc mở chứa các chơng trình con trùng tên thì khi có lời gọi chơng trình con của Unit đợc mở sau sẽ đợc thực hiện. Nếu muốn thực hiện đợc chơng trình con của Unit đợc mở trớc ta phải viết : TênUnit.TênCTCon; Ví dụ : Uses A, B; Trong đó A và B đều chứa thủ tục có tên là M. 9 Phần khai báo Phần giao tiếp Phần cài đặt Phần khởi tạo Phần kết thúc Khi viÕt M; ⇒ Thùc hiÖn M cña B. A.M; ⇒ Thùc hiÖn M cña A. VÝ dô : LËp Unit chøa c¸c hµm sau : - TÝnh íc s« chung lín nhÊt cña hai sè nguyªn. - TÝnh béi sè chung nhá nhÊt cña hai sè nguyªn. UNIT UC_BC; ( ******** ) INTERFACE Function UCLN (a,b : Integer) : Integer; Function BCNN (a,b : Integer) : Integer; ( ******** ) IMPLEMENTATION Function UCLN ; Begin While a<>b do If a>b then a := a-b Else b := b-a; UCLN := a; End; {--------------------} Function BCNN ; Begin BCNN := (a div UCLN(a,b) ) * b; End; ( ******** ) BEGIN Writeln('Dang thuc hien Unit'); END. Ch¬ng tr×nh chÝnh sö dông Unit Program Tim_UC_BC; Uses UC_BC; Var a,b,UC,BC : Integer; BEGIN Write('Nhap hai so nguyen a,b : '); Readln(a,b); UC := UCLN(a,b); BC := BCNN(a,b); Writeln('Uoc chung lon nhat cua ',a,' va ',b,' la UCLN = ',UC); Writeln('Boi chung lon nhat cua ',a,' va ',b,' la BCNN = ',UC); Readln; END. 10 [...]... hiện tại của con trỏ đến điểm có toạ độ (x,y) Line (x1, y1, x2, y2) : Vẽ đoạn thẳng từ toạ độ (x1,y1) đến toạ độ (x2,y2) LineRel (dx,dy) : Vẽ một đoạn thẳng từ toạ độ hiện tại đến toạ độ (x+dx, y+dy) Ví dụ 3 : Viết chơng trình tạo đờng gấp khúc bằng các đoạn thẳng Đờng gấp khúc đi qua các đỉnh sau : (20 ,20 ), ( 620 ,20 ), ( 620 ,180), (20 ,1800) và ( 320 ,100) Program DuongThang; Uses Crt, Graph; Var Gd, Gm, y,... Program DuongThang; Uses Crt, Graph; Var Gd, Gm, y, size : Integer; Begin Gd := Detect; InitGraph (Gd, Gm, 'C:\TP\BGI'); SetBkColor(Green); SetColor(Yellow); MoveTo( 320 ,100); Line (20 ,20 , 620 ,20 ); LineRel(-300,80); LineTo( 620 ,180); LineTo( 620 ,20 ); Readln; CloseGraph; End Ví dụ 4 : Vẽ 1 hệ trục toạ độ Đecac vuông góc có gốc nằm chính giữa màn hình Program HeToaDo; 36 Uses Crt, Graph; ... liên kết của P B1 : P := First; B2 : First := First^.Next; B3 : Dispose (P); 16 Procedure Xoad; Begin P := First; If P < > Nil then Begin First := P^.Next; Dispose(P); End; End; b Loại bỏ phần tử P đứng ngay sau phần tử trỏ bởi Q Ta cho vùng liên kết của Q trỏ đến vùng liên kết của P P B1 : P := Q^.Next; B2 : Q^.Next := P^.Next; B3 : Dispose (P); Q Procedure Xoa2(Q:PT); Var P : PT; Begin P := Q^.Next;... nguyên, ta khai báo nh sau: 23 Type Point = ^Node; Node = Record Sn: Integer; {Dữ liệu kiểu số nguyên} Prev: Point; End; Var First, P: Point; Ví dụ 2 : Khai báo kiểu dữ liệu cho danh sách sinh viên, ta khai báo nh sau: Type Point = ^Node; Node = Record Hoten : String [25 ]; Tuoi : Byte; Diem: Byte; Prev: Point; End; Var First, P: Point; 2 Khởi tạo danh sách Bớc 1: Gán First:=Nil; Bớc 2: Lặp đi lặp lại các... hình 22 ii Danh sách liên kết đơn theo cấu trúc LIFO ( Last In First Out) # Mô tả: 1 phần tử: 1 danh sách: Chiều nhập : 1 Prev Data NIL Chiều in ra : 4 2 Prev Data 3 3 Prev 2 4 Data Prev Data 1 First #Nguyên tắc tổ chức : First - Vùng liên kết của phần tử thứ i chứa địa chỉ của phần tử thứ i-1 - Vùng liên kết của phần tử đầu tiên đợc nhập mang giá trị Nil Data Prev Nil - Mỗi phần tử của danh sách gồm 2. .. While P Nil do Begin Inc(S); Writeln(S:5, P^.SBD:5, P^.Hoten :25 , P^.TBC:8 :2) ; P:=P^.Prev; End; Write('An ENTER de ket thuc xem.'); Readln; End; (******************* ) Procedure Bosung; Var Tiep : Char; Begin Clrscr; If First = Nil then Begin Write('Danh sach rong! Hay khoi tao danh sach!'); Readln; Exit; End; Repeat Writeln('Moi nhap bo sung sinh vien : '); NhapSBD; If SBDT0 then Begin New(P);... sach!') Else Begin P :=First; While P^.SBD SBDT do P :=P^.Next; Writeln('Thong Tin SBD ', SBDT,' la :'); Writeln('Ho va ten :', P^.Hoten); Writeln('Diem TBC :', P^.TBC :1 :2) ; NhapSBD; P^.SBD := SBDT; 32 Write('Ho va ten moi:');Readln(P^.Hoten); Write('Nhap diem moi:');Readln(P^.TBC); Writeln('Da nhap xong!'); End; Write('Co sua tiep khong ? (C/K) : '); Readln(Tiep); Until Upcase(Tiep)='K'; End; (*******************... Writeln; Writeln(' 1 Khoi tao danh sach.'); Writeln(' 2 Duyet xuoi.'); Writeln(' 3 Duyet nguoc.'); Writeln(' 4 Bo sung vao cuoi danh sach.'); Writeln(' 5 Sua sinh vien.'); Writeln(' 6 Xoa sinh vien.'); Writeln(' 7 Thoat khoi chuong trinh.'); Write(' Moi chon cong viec tu 1-7 : ');Readln(chon); Case chon of 1 : Khoi_Tao; 2 : Duyet_xuoi; 3 : Duyet_nguoc; 4 : Bosung; 5 : SuaSV; 6 : XoaSV Else Exit; End; 33... khỏi danh sách bỏ phần tử sau phần tử trỏ bởi q cho trớc b Loại a Loại bỏ phần tử đầu tiên Procedure Loaibod; Begin P := First; If P < > Nil then Begin 26 Procedure Delsauq(q:PT); Var P: PT; Begin P := Q^.Prev; If P < > Nil then Begin Q^.Prev := P^.Prev; Dispose(P); End; End; First := P^.Prev; Dispose(P); End; End; Ví dụ 6 : Chơng trình loại bỏ tất cả các phần tử chứa số nguyên S trong danh sách LIFO,... nguyen vua nhap :'); Inds(L); Write('Nhap so nguyen can loai bo: X = '); Readln(X); Xoa(L, X); Writeln('Danh sach sau khi loai bo : '); Inds(L); Readln; END 27 Chơng 4: danh sách liên kết đôi 1 Khái niệm: Danh sách liên kết đôi là danh sách liên kết mà mỗi phần tử của nó ngoài vùng chứa thông tin còn có hai vùng liên kết, kí hiệu Prev, Link 2 Mô tả: Mô tả tổ chức của danh sách liên kết đôi : Nil Nil . động Con trỏ của Stack Con trỏ của Heap 1 2 + 2 2 2! 1 2 + 2 2 + 3 2 2! 1 2 + 2 2 + + n 2 2! S = 1 + + + + C¸ch 2: Program VD4; Uses Crt; Type Nguyen =. (P1) ; P1^ := 'Con duong da qua' ; P2 := P1 ; Writeln('Thich phim ',P2^) ; Dispose (P2) ; Readln ; End. * Đối với nhiều biến động Để