Tải bản đầy đủ (.doc) (40 trang)

tai lieu quy bo di thi tiec 2

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (284.37 KB, 40 trang )

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
+ 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 = ^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
Chơng iII. Danh sách liên kết đơn
(Linked List)
*K/n danh sách liên kết
Danh sách liên kết là danh sách trong đó các phần tử đợc kết nối với nhau bởi vùng liên
kết của chúng. Đây là loại cấu trúc dữ liệu thích hợp cho các phép thêm vào, loại bỏ hoặc
ghép nối các phần tử của danh sách.
I. Danh sách liên kết đơn theo cấu trúc FIFO (First In First
Out) (~Quece hàng đợi)
Nguyên tắc tổ chức danh sách liên kết nh sau:

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 (i = 1..n-1), vùng liên
kết của phần tử cuối cùng n mang giá trị NIL.
Mỗi phần tử trong danh sách liên kết FIFO gồm 2 vùng chính:
Vùng chứa dữ liệu (Data).
Vùng chứa địa chỉ của phần tử khác (ký hiệu: Link / Next).
Ngoài ra còn có các biến chỉ điểm First, Last (kiểu Pointer) để chứa địa chỉ của phần
tử đầu, cuối.
Minh hoạ cách tổ chức danh sách liên kết:
(Việc đa thêm Last thuận lợi cho việc bổ sung thêm phần tử mới)
1. Khai báo kiểu dữ liệu
Mỗi phần tử đợc khai báo kiểu dữ liệu nh sau:
Type
DataType = <Kiểu dữ liệu> ;
Ptr = Item ;
Item = Record
Data : DataType;
Next : Ptr ;
End ;
Var First, Last, P : Ptr ;
Ví dụ 1: Viết khai báo cho 1 danh sách liên kết FIFO mà mỗi phần tử dùng để chứa 1 số
nguyên.
C1 : Type Nguyen = Integer;
Ptr = ^Item ;
Item = Record
Data : Nguyen;
Next : Ptr ;
End;
Var First, Last, P : Ptr ;
11
Data Link Data Link Data Link Data




First
NIL
Last
A
1
A
i
A
i+1
A
n
C2 : Do kiểu dữ liệu là kiểu chuẩn nên
ta có thể viết:
Type Ptr = ^Item ;
Item = Record
Data : Integer ;
Next : Ptr ;
End;
Var First, Last, P : Ptr ;
2. Khởi tạo danh sách liên kết
- Danh sách rỗng First = Nil;
- Các bớc khởi tạo :
Bớc 1 : First = Nil;
Bớc 2 : Tạo 1 biến động mới và gán dữ liệu cho nó (sử dụng New(P)).
Bớc 3 : Nếu First = Nil thì First := P ;
Ngợc lại Last^.Next := P ;
Bớc 4 : Last := P ;

Bớc 5 : Quay lại bớc 2 cho đến khi thoả mãn điều kiện kết thúc.
Ví dụ 2 : Lập chơng trình nhập vào một danh sách các số nguyên cho đến khi số nguyên đợc
nhập bằng 0.
Program Vidu2;
Type
Pt = ^Item;
Item = Record
Sn : Integer;
Next : Pt;
End;
Var First, Last, P : Pt; m : Integer;
BEGIN First := Nil;
Repeat Write(' Nhap so nguyen : '); Readln(m);
If m <> 0 then
Begin New(P); P^.Sn := m;
P^.Next := Nil;
If First = Nil then First:=P
Else Last^.Next := P;
Last := P;
End;
Until m = 0;
END.
3. In danh sách liên kết ra màn hình
B1 : Gán P := First;
B2 : Trong khi cha hết danh sách (P< >Nil) thì
- In ra P^.Data
- P := P^.Next;
Ví dụ 3 : Lập thủ tục in các số nguyên đợc nhập ở ví dụ 2.
Procedure Inds (F : Pt);
Begin

If F=nil then Writeln('Danh sach rong')
Else
Begin P:=F;
While P<>Nil do
Begin Write(P^.Sn,' ');
P:=P^.Next;
End;
End;
End;
Ví dụ 4 : Lập chơng trình tạo danh sách kết nối kiểu FIFO và lần lợt in ra từng bản ghi gồm
2 trờng Họ tên và Tuổi.
Program TaoFIFO;
Uses Crt;
12
Type NS = ^Nhansu;
Nhansu = Record;
Hoten : String[30];
Tuoi : Integer;
Next : Ns;
End;
Var Last, First, P : NS;
Name : String[30];
BEGIN Clrscr;
First := Nil;
Repeat Write(' Ho va ten : '); Readln(Name);
If Name <> '' then
Begin New(P); P^.Next := Nil;
P^.Hoten := Name;
Write('Tuoi : '); Readln(P^.Tuoi);
If First = Nil then First := P

Else Last^.Next := P;
Last := P;
End;
Until Name = '';
{In danh sach}
P := First;
While P<> Nil do
Begin Writeln(P^.Hoten : 30, P^.Tuoi:4);
P := P^.Next;
End;
Readln;
END.
VÝ dô 5 : LËp ch¬ng tr×nh:
- NhËp vµo danh s¸ch c¸c sè nguyªn cho ®Õn khi sè nguyªn ®îc nhËp b»ng 0.
- In ra mµn h×nh c¸c sè nguyªn d¬ng cã trong danh s¸ch.
Program Vidu5;
Type
Pt = ^Item;
Item = Record
Sn : Integer;
Next : Pt;
End;
Var First, Last, P : Pt;
(
**************
)
Procedure Nhap;
Var m : Integer;
Begin First := Nil;
Repeat Write(' Nhap so nguyen : '); Readln(m);

If m <> 0 then
Begin New(P); P^.Sn := m;
P^.Next := Nil;
If First = Nil then First:=P
Else Last^.Next := P;
Last := P;
End;
Until m = 0;
End;
(
**************
)
13
Procedure Inds (F : Pt);
Begin
If F=nil then Writeln('Danh sach rong')
Else
Begin P:=F;
While P<>Nil do
Begin If P^.Sn > 0 then Write(P^.Sn:5);
P:=P^.Next;
End;
End;
End;
(
**************
)
BEGIN
Nhap ; Inds (First);
Readln;

END.
4. Tìm kiếm một phần tử trong danh sách.
- Giả sử phần tử cần tìm kiếm có vùng dữ liệu Data là X. Phép tìm kiếm đợc thực hiện từ
phần tử đầu tiên cho đến khi tìm thấy phần tử có vùng dữ liệu X hoặc đến cuối danh sách
(không tìm thấy).
- Hàm Tim (X) trả về địa chỉ của phần tử đầu tiên hoặc trả về giá trị Nil nếu không tìm thấy.
- Phân biệt hai trờng hợp:
+ Danh sách cha đợc sắp xếp.
+ Danh sách đợc sắp xếp tăng dần.
a) Danh sách cha đợc sắp xếp.
Phép tìm kiếm chỉ kết thúc khi tìm thấy phần tử đầu tiên hoặc hết danh sách.
Function Tim(X: Kieu_Dl): Point;
Var P: Point;
Begin P := First;
While (P < > NIL) and (P^.Data < > X) do P := P^.Link;
Tim:= P;
End;
Ví dụ 6: Chơng trình nhập các số nguyên vào một danh sách liên kết FIFO và lập hàm tìm
kiếm phần tử có vùng dữ liệu là X.
Program VD;
Type
Pt=^Item;
Item=record
Sn : Integer;
Next : Pt;
End;
Var First, Last, P, kq : Pt;
M : Integer;
(
****************

)
Procedure Nhap;
Var ch:char;
Begin First := Nil;
Repeat New(P);
Write(' Nhap so nguyen :'); Readln(P^.Sn);
P^.Next := Nil;
If First=nil then First:=P
Else Last^.Next:=P;
Last:=P;
Write('Co tiep tuc khong (c/k) ? '); Readln(ch);
14
Until Upcase(ch)='K';
End;
(
****************
)
Function Tim(X : Integer) : Pt;
Begin P:=first;
While(P<>nil) and (P^.Sn<>X) do P:=P^.Next;
Tim:=P;
End;
(
****************
)
Procedure Inds(F:Pt);
Begin
If F= Nil then Writeln(' Danh sach rong!')
Else Begin P:=f;
While P<> Nil do

Begin Write(P^.Sn,' ');
P:=P^.Next;
End;
End;
End;
(
****************
)
BEGIN
Nhap; Inds(First);
Write(' Nhap so nguyen can tim : '); Readln(M);
If Tim(M)<> Nil then Writeln (' Tim thay ')
Else Writeln(' Khong tim thay');
Readln;
END.
b) Danh sách đợc sắp xếp tăng dần.
Chỉ cần tìm cho đến khi gặp phần tử đầu tiên hoặc khoá của phần tử hiện tại lớn hơn X.
Function Tim(X : Kieu_Dl) : Point;
Var P : Point;
Begin P := First;
While (P<> Nil) and (P^.Data <> X) do P := P^.Link;
If (P<>Nil) and (P^.Data >X) then P:= Nil
Tim := P;
End;
5. Bổ sung một phần tử vào danh sách
a) Bổ sung vào đầu danh sách
Giả sử phần tử cần bổ sung vào danh sách do con trỏ P quản lí.
Cần thực hiện các bớc sau:
B1) Cho vùng liên kết của P trỏ vào First (P^.Link := First;)
B2) Cho First trỏ vào P (First := P;)

Thủ tục :
Procedure BSd;
Var P: Point;
Begin New (P);
P^.Data := gia_tri;
P^.Link := First;
First := P;
End;
15
New
(1)
(2)
P
First
...
b) Bổ sung vào sau phần tử trỏ bởi q cho trớc:
Gọi P là phần tử có nội dung New cần chèn vào danh sách, Q là phần tử đứng ngay trớc P.





B1) Cho vùng liên kết của P trỏ vào vùng liên kết của Q. (P^.Link := Q^.Link;)
B2) Cho vùng liên kết của Q trỏ vào P. (Q^.Link := P;)
- Nếu Q là phần tử cuối cùng thì Last trỏ vào P (Last := P;)
Thủ tục chèn
Procedure BS2 (Q : Point);
Var P: Point;
Begin New(P);
P^.Data := gia_tri;

P^.Link := Q^.Link;
Q^.Link := P;
If Q = Last then Last := P; {q là phần tử cuối cùng}
End;
Ví dụ 7: Lập thủ tục bổ sung thêm một số nguyên vào danh sách số nguyên đã đợc sắp xếp
theo đúng vị trí của nó.
Procedure Chen(F : Pt);
Var P, Q, R : Pt;
Begin New(R);
Write('Nhap gia tri can chen : '); Readln (R^.Sn);
P := F; Q := Nil;
While (P<>Nil) and (P^.Sn < R^.Sn) do
Begin Q := P;
P := P^.Next;
End;
If (Q=Nil) and (P=F) then
Begin R^.Next := F;
F:= F;
End
Else Begin R^.Next := Q^.Next;
Q^.Next:=R;
If Q = Last then Last:=R;
End;
End;
6. Loại bỏ một phần tử khỏi danh sách
a. Loại bỏ phần tử P ở đầu danh sách
Chỉ cần cho con trỏ First trỏ vào vùng liên kết của P.
B1 : P := First;
B2 : First := First^.Next;
B3 : Dispose (P);


16
P
New
......
(1)(2)
Q

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×