You are on page 1of 13

1.

M u
i tng c ti liu: Bt k ai mun tm hiu v Free Pascal ni dung nh tiu ch ra. Nhng nu bn l mt hc sinh, sinh vin hay ni chung l nhng ngi ch dng Free Pascal nghin cu thut ton, ti khng ngh rng ti liu ny gip g nhiu. Ni dung ti liu: Gii thiu cu trc mng ng v mt s ng dng. Gii hn trch nhim: Ti khng phi mt Pascal guru th thit trong cng ng nhng ngi s dng Free Pascal, hn th na ti liu ny vit vi mc ch gii tr, v vy khng th m bo ni dung trong ti liu ny chnh xc tuyt i. Ngi c cn t chu trch nhim vi ni dung ca ti liu. Nu lp trnh theo ti liu ny m CPU ca bn bc chy hoc bn thn bn b tu ho nhp ma, y l li ti bn. Bn quyn: Ti liu ny pht hnh theo giy php GNU/FDL, ngha l bn ton quyn s dng, sao chp, sa cha v phn phi li ti liu min sao tn tc gi (nqhien@gmail.com) khng b thay th v khi phn phi li ti liu ny, bn cng phi tun theo giy php GNU/FDL. Mi trng Free Pascal: Chng trnh dch: Free Pascal Compiler 2.6.0, compiler mode: Free Pascal dialect, IDE c khuyn khch s dng l Free Pascal IDE.

2. Mng ng
V d 1:
type AI = array of Integer; var a: AI; i: Integer; BEGIN SetLength(a, 10); for i := Low(a) to High(a) do a[i] := i; for i := Low(a) to High(a) do Write('a[',i,']','=',a[i], ', '); WriteLn; SetLength(a, 5); for i := Low(a) to High(a) do Write('a[',i,']','=',a[i], ', ');

WriteLn; SetLength(a, 10); for i := Low(a) to High(a) do Write('a[',i,']','=',a[i], ', '); WriteLn; END. CTRL+F9
a[0]=0, a[1]=1, a[2]=2, a[3]=3, a[4]=4, a[5]=5, a[6]=6, a[7]=7, a[8]=8, a[9]=9 a[0]=0, a[1]=1, a[2]=2, a[3]=3, a[4]=4, a[0]=0, a[1]=1, a[2]=2, a[3]=3, a[4]=4, a[5]=0, a[6]=0, a[7]=0, a[8]=0, a[9]=0

T v d, ta rt ra cc nhn xt: Mng ng (dynamic array) khng cn khai bo trc min ch s cng nh s lng phn t : AI = array of Integer;. Min ch s ca mng ng a: Low(a)..High(a), trong Low(a) = 0, High(a) = Length(a)-1, Length l hm tr li s phn t ca mt mng ng. Mng ng c cp pht b nh (trong thi gian chy) bng th tc SetLength. o Mng ng khi b SetLength vi s phn t t hn, cc phn t cui mng b xo v cc phn t u c gi tr nh c. o Mng ng khi b SetLength vi s phn t nhiu hn, gi tr cc phn t u cng c gi nguyn v cc phn t mi c tr ngu nhin no (khng c g m bo cc phn t ny l 0 nh v d trn). V d 2:
var a, b: AI; i: Integer; BEGIN SetLength(a, 10); for i := Low(a) to High(a) do a[i] := i; b := a; b[Length(b) shr 1] := -1; for i := Low(a) to High(a) do Write('a[',i,']','=',a[i], ', '); WriteLn; for i := Low(b) to High(b) do Write('b[',i,']','=',b[i], ', '); WriteLn; END. CTRL+F9
a[0]=0, a[1]=1, a[2]=2, a[3]=3, a[4]=4, a[5]=-1, a[6]=6, a[7]=7, a[8]=8, a[9]=9 b[0]=0, b[1]=1, b[2]=2, b[3]=3, b[4]=4, b[5]=-1, b[6]=6, b[7]=7, b[8]=8, b[9]=9

Nhn xt: Php gn hai mng ng khng ging vi gn 2 mng tnh, php gn b := a; cc phn t ca a khng c copy sang b. Hai mng a v b sau php gn ch l mt, vic thay i phn t ca b ng ngha vi vic thay i phn t tng ng ca a. Ni cch khc: sau php gn b := a; th a v b cng tham chiu (reference) n mt vng nh.

Thc cht mng ng l con tr (pointer) v SetLength l th tc cp pht, thu hi vng nh cho con tr , b nh c s dng lu tr mng ng l heap. Tuy nhin mng ng c qun l khc con tr ch: V c php, mng ng cho php dng cc ton t [] v khai bo t nhin, ging nh mng tnh (static array). Vng nh c cp pht cho mng ng c qun l theo c ch m s tham chiu (reference count), ngha l vng nh ny s c t ng gii phng nu s lng tham chiu bng 0. V d 3: Vi a, b l 2 mng ng, xt on lnh:
SetLength(a, 10); b := a; SetLength(a, 0); //1 SetLength(b, 0); //2

Trc lnh 1, s tham chiu n vng nh cp pht cho a l 2. Sau lnh gn 1, s tham chiu n vng nh ny l 1 v a c s phn t bng 0. Sau lnh 2, b cng c s phn t bng 0. Ch rng ta c th vit b := nil; thay cho SetLength(b, 0); im cui cng cp n trong phn ny bn v mng ng nhiu chiu, xem v d sau: V d 4:
type AI = array of Integer; AII = array of AI; // array of array of Integer; var a: AII; i, j: Integer; BEGIN SetLength(a, 10); for i := 0 to High(a) do SetLength(a[i], i+1); END.

Trong v d ny, a: AII l mt mng ng hai chiu, d thy dng 0 c 1 phn t, dng 1 c 2 phn t, dng i c i+1 phn t. y ta thy mi dng ca mng hai chiu c th c s phn t khc nhau. n y ta c th pht biu v mng ng: Mng ng l cu trc d liu kiu mng vi s phn t l ng c th thay i trong thi gian chy (run time). Lm vic vi mng ng ging nh lm vic vi mng tnh nhng mng ng thc cht l con tr, vng nh c cp pht cho mng ng nm trn heap v c Free Pascal qun l theo cch ring.

3. Mt s php ton thng dng trn mng ng


Ngoi High, Low, Length, SetLength cc hm, th tc sau y thng c dng trn mng ng: 1. Copy y l hm ging ht hm copy trn String hay AnsiString. 2. SizeOf Hm SizeOf mt bin mng ng lun tr li gi tr l kch thc (n v byte) ca mt con tr (lun l 4 byte trong mi trng 32 bit). ly kch thc ca mng ng phi kt hp Length v SizeOf kiu phn t ca mng ng . 3. Move Move vn c th dng bnh thng trn mng ng, nhng nh rng bin mng ng l con tr, v vy trong th tc move trnh truy xut n tn mng, chng lnh sau khng c vn g vi mng tnh move(a, a[5], Length(a)*SizeOf(a[0])); v vi mng tnh a v a[0] cng a ch nhng vi mng ng cn sa li: move(a[0], a[5], Length(a)*SizeOf(a[0])); hoc move(a^, a[5], Length(a)*SizeOf(a[0])); 4. Fill Cc th thc FillByte, FillChar, FillDWord, FillQWord, FillWord cng c th dng vi lu nh khi dng move.

4. Kho st tc mng ng
Ta dng chng trnh sau o tc ca mng ng cc thao tc: truy xut n phn t, ly s phn t v SetLength v so snh vi cc thao tc trn mng tnh.
{Mode: Release} uses SysUtils; const MAX COUNT type AI SI TProc var a: AI; b: SI; n: LongInt; procedure SpeedMeasure(Title: string; proc: TProc; count: LongInt); var time: TDateTime; begin time := now; Write(Title,'...'); for count := count downto 1 do proc; time := now - time; = 10000; = 10000000; = array of Integer; = array[0..MAX-1] of Integer; = procedure;

WriteLn(FormatDateTime('nn:ss:zz', time)); end; procedure AIAccess; begin a[0] := a[1]; end; procedure SIAccess; begin b[0] := b[1]; end; procedure AISetLength; begin Inc(n); SetLength(a, n); end; procedure SILength; begin n := MAX; end; procedure AILength; begin n := Length(a); end; BEGIN SetLength(a, MAX); SpeedMeasure('Static SpeedMeasure('Static

array access array Length

', @SIAccess, COUNT); ', @SILength, COUNT);

SpeedMeasure('Dynamic array access ', @AIAccess, COUNT); SpeedMeasure('Dynamic array Length ', @AILength, COUNT); n := 0; SpeedMeasure('Dynamic array SetLength', @AISetLength, COUNT); END. CTRL+F9 Static array access ...00:00:047 Static array Length ...00:00:047 Dynamic array access ...00:00:062 Dynamic array Length ...00:00:078 Dynamic array SetLength...00:05:485

Nhn xt: Tc truy xut phn t trn mng ng chm hn so vi mng tnh mt cht. Vic gi n hm Length ly s phn t ca mng i hi chi ph gi hm. Tng t nh vy khi s dng High v Low. SetLength c tc rt chm v y l th tc cp pht vng nh. Tng t, c th th thy vic gii phng vng nh cng rt chm.

5. G li vi mng ng
Trnh g li c s dng y l GDB trnh g li mc nh, tch hp trong IDE Free Pascal. Vi mng ng, ng tic l ta khng d dng g li nh i vi mng tnh. Khng th theo di (watch) ton b ni dung ca mt mng ng ging nh vi mng tnh, thay vo ch c th theo di gi tr tng phn t. Gi s theo di gi tr ca phn t t i ca mng ng a, cn thm biu thc theo di (add watch CTRL+F7 trong IDE Free Pascal): a^[i]. Mo nh theo di mt on gi tr ca mng ng l dng k thut p kiu trong GDB. Ta s p kiu mng ng v mt mng tnh. Chng hn trong chng trnh phn 4, theo di on MAX phn t u tin ca mng ng a, ta c th thm biu thc theo di: SI(a).

6. Ci t mt s cu trc d liu bng mng ng.


Ta s ci t (implement) mt s cu trc d liu nh stack, queue theo hai cch: truyn thng bng con tr v cch mi: s dng mng ng, qua so snh v rt ra mt s nhn xt. V d 1: Cu trc d liu stack vi TAIStack l stack dng mng ng v TLkStack l stack ci t bng con tr lin kt. Ta s ci t 3 thao tc chnh: push, pop v top cho stack.
uses SysUtils; const COUNT = 10000000;

type TAIStack = array of LongInt; PNode = ^TNode; TNode = record x: LongInt; next: PNode; end; TLkStack = PNode; TProc var a: TAIStack; b: TLkStack; {TAIStack} procedure init(var stack: TAIStack); begin stack := nil; end; procedure push(var stack: TAIStack; x: LongInt); = procedure;

begin SetLength(stack, Length(stack) + 1); stack[High(stack)] := x; end; procedure pop(var stack: TAIStack); begin SetLength(stack, High(stack)); end; function top(var stack: TAIStack): LongInt; begin top := stack[High(stack)] end; {TLkStack} procedure init(var stack: TLkStack); begin stack := nil; end; procedure push(var stack: TLkStack; x: LongInt); var p: PNode; begin p := stack; new(stack); stack^.next := p; stack^.x := x; end; procedure pop(var stack: TLkStack); var p: PNode; begin p := stack; stack := stack^.next; dispose(p); end; function top(var stack: TLkStack): LongInt; begin top := stack^.x; end; {Measure} procedure SpeedMeasure(Title: string; proc: TProc; count: LongInt); var time: TDateTime; begin time := now; Write(Title,'...'); for count := count downto 1 do proc; time := now - time;

WriteLn(FormatDateTime('nn:ss:zz', time)); end; procedure AIPush; begin push(a, 0); end; procedure AIPop; begin pop(a); end;

procedure AITop; var tmp: LongInt; begin tmp := top(a); end; procedure LkPush; begin push(b, 0); end; procedure LkPop; begin pop(b); end;

procedure LkTop; var tmp: LongInt; begin tmp := top(b); end; {main} BEGIN init(a); init(b); SpeedMeasure('AI push', @AIPush, COUNT); SpeedMeasure('AI top ', @AITop, COUNT); SpeedMeasure('AI pop ', @AIPop, COUNT); SpeedMeasure('Lk push', @LkPush, COUNT); SpeedMeasure('Lk top ', @LkTop, COUNT); SpeedMeasure('Lk pop ', @LkPop, COUNT); END. CTRL+F9 AI push...00:20:297 AI top ...00:00:140 AI pop ...00:01:031 Lk push...00:00:781 Lk top ...00:00:094 Lk pop ...00:00:516

Tc ca TAIStack r rng khng c g n tng so vi TLkStack nu khng mun ni l thm hi. Nguyn nhn c th thy l do tc chm chp ca SetLength trong cc thao tc push v pop. khc phc s chm chp ca SetLength ta s c gng ci tin sao cho s ln phi gi n SetLength cng t cng tt.

Trong thao tc push, t lnh SetLength(stack, Length(stack) + 1); ta c mt hng ci tin l mi ln SetLength cho mng ng ta s dng SetLength(stack, Length(stack) + k); vi k > 1. Ta cn dng mt bin n qun l s lng phn t thc t trong stack, v ch SetLength cho mng ng khi n vt qu Length hin ti ca mng ng. S k c chn cng ln cng tt, tuy nhin y ta chn k bng 2 ln Length hin ti ca mng ng m bo b nh khng qu lng ph. i vi thao tc pop, tng t nh push, nu nh cn tit kim b nh ta c th SetLength li mi khi n nh hn hai ln Length hin ti ca mng ng, nhng nu u tin cho tc ta c th b qua vic gii phng vng nh. Vi cch lm nh trn, ti u chi ph thi gian ta tn gp 2 ln chi ph b nh. nh ngha li kiu d liu TAIStack:
TAIStack = record n: LongInt; x: array of LongInt; end;

Ci t cc thao tc trn TAIStack:


{TAIStack} procedure init(var stack: TAIStack); begin stack.n := 0; stack.x := nil; end; procedure push(var stack: TAIStack; x: LongInt); begin Inc(stack.n); if stack.n > Length(stack.x) then SetLength(stack.x, stack.n shl 1); stack.x[stack.n-1] := x; end; procedure pop(var stack: TAIStack); begin Dec(stack.n); //if stack.n < Length(stack.x) shr 1 then //SetLength(stack.x, Length(stack.x) shr 1); end; function top(var stack: TAIStack): LongInt; begin top := stack.x[stack.n - 1] end;

Kt qu sau khi ci tin:


AI push...00:00:360 AI top ...00:00:109

AI Lk Lk Lk

pop ...00:00:109 push...00:00:735 top ...00:00:094 pop ...00:00:515

Tc t c rt ng khch l . Tuy nhin ta cng c th on c l TAIStack khng th t c tc nh stack s dng mng tnh. Lu rng ti liu ny khng khuyn khch ngi lp trnh chn cch ci t nhng cu trc d liu nh stack ni trn bng mng ng thay cho cch dng con tr lin kt truyn thng. Khi lp trnh, ngi lp trnh phi tu c ng bin tu theo bi ton c th. V d 2: Cu trc d liu queue: TAIQueue ci t bng mng ng.
type AI = array of LongInt; TAIQueue = record first, last: LongInt; x: AI; end; TProc var a: TAIQueue; procedure init(var queue: TAIQueue); begin queue.x := nil; queue.first := 0; queue.last := -1; end; procedure push(var queue: TAIQueue; x: LongInt); var tmp: AI; begin Inc(queue.last); if queue.last = Length(queue.x) then SetLength(queue.x, (queue.last+1) shl 1); queue.x[queue.last] := x; end; procedure pop(var queue: TAIQueue); begin Inc(queue.first); if queue.first > Length(queue.x) shr 1 then begin Dec(queue.last, queue.first); Move(queue.x[queue.first], queue.x[0], (queue.last+1)*SizeOf(queue.x[0]) ); queue.first := 0; end; end; = procedure;

function top(var queue: TAIQueue): LongInt; begin top := queue.x[queue.first]; end; procedure SpeedMeasure(Title: string; proc: TProc; count: LongInt); var time: TDateTime; begin time := now; Write(Title,'...'); for count := count downto 1 do proc; time := now - time; WriteLn(FormatDateTime('nn:ss:zz', time)); end; procedure AIPush; begin push(a, 0); end; procedure AIPop; begin pop(a); end;

procedure AITop; var tmp: LongInt; begin tmp := top(a); end; BEGIN init(a); SpeedMeasure('AI push', @AIPush, COUNT); SpeedMeasure('AI top ', @AITop, COUNT); SpeedMeasure('AI pop ', @AIPop, COUNT); END. CTRL+F9 AI push...00:00:360 AI top ...00:00:109 AI pop ...00:00:172

Queue trong v d ny c ci t tng t stack. Thao tc pop chm hn trn stack v phi x l thm trng hp: khi first qu ln ta dch li first v v tr u mng.

7. Bi tp
Bi tp 1: Nu a v b l hai bin mng cng kiu, cn hon v a v b, khi nu a v b l mng ng th php hon v s nhanh hn hay mng tnh s nhanh hn? Bi tp 2: Cho bn ghi c nh ngha:
record n: Integer; a: array of Integer;

end;

Vi hai bin a v b thuc kiu bn ghi ni trn, hy ch ra trng hp m lnh gn a := b tr nn nguy him. Bi tp 2: Cn ci t cu trc d liu stack, heap vi cc phn t ca stack c kch thc rt ln, khi nn chn cch ci t bng con tr lin kt hay dng mng ng? Bi tp 3: Ci t cu trc d liu deque bng mng ng, vit li cc thao tc push_back, pop_back, push_front, pop_front, back, front v ton t [] tng t nh kiu d liu deque trong th vin STL ca C++. Bi tp 4: Th nghim chng trnh sau v rt ra nhn xt:
type AI = array of Integer; var a: array[1..10] of Integer; procedure foo(a: AI); begin for i := Low(a) to High(a) do Write(a[i]); end; BEGIN Foo(a); END.

Bi tp 5: c chng trnh di y v tr li: Sau khi gi foo, phn t a[0] ca bin ton cc (global variable) a c thay i khng? Sau khi gi foo, bin ton cc a c b thay i khng? Khi gi n chng trnh con foo, h thng s cp pht stack lu tr nhng g?
type AI = array of Integer; var a: AI; procedure foo(a: AI); var b: AI; begin a[0] := -1; SetLength(b, 10); a := b; end; BEGIN SetLength(a, 10); foo(a); END.

8. Li kt
Trc khi Free Pascal h tr mng ng, nh ngha ra cu trc mng ng thng thng ngi lp trnh phi t ch ly mng ng bng con tr. Rt may Free Pascal nh ngha sn kiu d liu mng ng v che du bn cht con tr ca mng ng, t ngi lp trnh c th s dng mt cch d dng v thn thin ging nh mng tnh. Mng ng cng c h tr trong nhiu ngn ng lp trnh hin i khc nh C++ vi con tr hoc cu trc d liu vector (th vin STL), Java v cc ngn ng .NET vi kiu d liu ArrayList... S dng mng ng khng em li li th v tc khi so snh vi mng tnh nhng b li mng ng c kh nng thay i s phn t mt cch linh hot. Nu trong mt bi ton c th cn s dng mng vi s lng phn t ti a xc nh th hn nhin u tin tc ta s chn mng tnh, nhng trong trng hp tng qut, chng hn khi vit mt th vin nh ngha cc kiu d liu nh stack, queue, v mun ci t chng da trn cu trc mng, khi mng tnh khng p ng c yu cu, thay vo ta cn n s linh hot ca mng ng. Ti liu ny gii thiu cu trc d liu mng ng trong Free Pascal v minh ho cch s dng cng nh mt s ng dng ca mng ng. Ton b ni dung ca ti liu, ngi c c tm thy trong phn ti liu tham kho hoc google, ngi vit ti liu ny thng dng cch tm hiu ch khng c nhng ti liu nh ti liu ny

9. Ti liu tham kho


1. http://www.freepascal.org/docs-html/ref/ref.html 1.1. http://www.freepascal.org/docs-html/ref/refsu15.html 1.2. http://www.freepascal.org/docs-html/ref/refse15.html#x43-500003.4 2. http://wiki.freepascal.org/GDB_Debugger_Tips 3. http://en.wikipedia.org/wiki/Dynamic_array 4. http://www.cplusplus.com/reference/stl/deque/ 5. http://www.gnu.org/copyleft/fdl.html

You might also like