You are on page 1of 54

DANH SÁCH ĐA LIÊN KẾT

Bài 1. Để quản lý những tên riêng cùng số trang mà nó xuất hiện trong một
cuốn sách, người ta sử dụng một danh sách liên kết (phần tử cơ bản của nó
được gọi là dòng). Mỗi dòng trong danh sách là một bản ghi gồm 4 trường:
trường Ten để lưu tên riêng, trường Dau, Cuoi là hai con trỏ trỏ vào nút đầu
và nút cuối của một danh sách liên kết (ta gọi là danh sách số trang) dùng để
ghi nhận các số trang trong cuốn sách có tên riêng đó xuất hiện, trường
Dongktiep lưu địa chỉ dòng kế tiếp. Mỗi nút của danh sách số trang gồm 2
trường: Sotrang và con trỏ Trangtiep trỏ đến số trang tiếp theo có chứa tên
riêng. Giả thiết danh sách số trang được sắp xếp theo thứ tự tăng của
Sotrang. Khai báo cấu trúc dữ liệu trên như sau:
Type
St25 = string[25];
TroSotrang=^so;
So = record
Sotrang : Integer;
Trangtiep: TroSotrang;
end;
TroDong = ^dong;
dong = record
Ten : St25; {Tên riêng}
dau, cuoi : TroSotrang;
Dongktiep : TroDong;
end;
Var first : TroDong;
1. Viết hàm: Function taoptutrang(Trang : Integer):TroSotrang;
cho kết quả là con trỏ trỏ vào phần tử mới thuộc kiểu TroSotrang, chứa số
trang (Trang).
2. Viết thủ tục:
Procedure chentrang(Var p:TroDong;Trang:Integer);
để chèn số trang (Trang) vào cuối danh sách các số trang với dòng có địa chỉ
p. Giả thiết danh sách số trang đã chứa ít nhất một số.
3. Viết thủ tục: Procedure indong(k : TroDong);
để in thông tin của dòng: tên riêng, theo sau là số các trang của dòng có địa
chỉ k.
4. Viết thủ tục:
Procedure chentendau(Var k : TroDong; Ten : St25; Trang : Integer);
để chèn dòng mới vào đầu danh sách k với tên riêng (Ten) và số trang
(trang).
5. Viết thủ tục:
Procedure bosung(Var First : TroDong; Ten : St25; Trang : Integer);
cho phép bổ sung tên riêng (Ten) và số trang (Trang) vào danh sách trỏ bởi
First theo cách sau:
Nếu tên riêng (Ten) không xuất hiện trong danh sách được sắp, thủ tục
thực hiện việc chèn tên riêng trong danh sách, kết hợp với số trang (Trang).
Nếu Ten đã có trong danh sách, thủ tục kiểm tra số sau cùng trong danh sách
các số đi kèm kết hợp với Ten có bằng Trang hay không. Nếu bằng thì thôi,
nếu không sẽ chèn Trang vào cuối danh sách các số đó.

1.
Function taoptutrang(Trang : Integer):TroSotrang;
Var q : TroSotrang;
Begin
New(q);
q^.Sotrang := trang;
q^.trangtiep := Nil;
taoptutrang := q;
end;
2.
Procedure chentrang(Var p : TroDong; Trang : Integer);
Var q : TroSotrang;
Begin
q := taoptutrang(trang);
p^.cuoi^.trangtiep :=q;
p^.cuoi :=q;
end;
3.
Procedure indong(k : TroDong);
Var p : TroSotrang;
Begin
Write(k^.Ten, ‘:’);
p:= k^.dau;
while (p < > p^.cuoi) do
Begin
Write(k^.Sotrang, ‘,’);
P:=p^.Trangtiep;
End;
Writeln(p^.Sotrang);
End;
4.
Procedure chentendau(Var k : TroDong; Ten : st25; trang : Integer);
Var p : Trodong; q : TroSotrang;
Begin
New(p);
p^.Ten := Ten;
q :=taoptutrang(trang);
p^.dau :=q;
p^.cuoi :=q;
p^.Dongktiep := k;
k := p;
End;
5.
Procedure bosung(Var First : TroDong; Ten : st25; Trang : Integer);
Begin
If First = nil Then chentendau(first,Ten,Trang)
Else
If First^.Ten < > Ten Then
chentendau(First,Ten,Trang)
else
If First^.Ten < Ten Then
bosung(First^.Dongktiep,Ten,Trang)
Else
If First^.cuoi^.Sotrang < > Trang Then
chentrang(First,Trang)

End;
Bài 2. Trong một hệ soạn thảo văn bản, văn bản được tổ chức lưu trữ trong
bộ nhớ dưới dạng một danh sách liên kết kép, mỗi nút trong danh sách (gọi
là dòng) là một bản ghi gồm trường Dong (dòng văn bản) và hai con trỏ, một
con trỏ hướng về dòng trước và con trỏ khác hướng về dòng tiếp theo. Ta sẽ
dùng hai con trỏ Dau và Cuoi lần lượt trỏ vào phần tử đầu và phần tử cuối
của văn bản. Khai báo cấu trúc dữ liệu này như sau:
Type
St80 = String[80];
Tro=^dongvanban;
dongvanban = record
Truoc : Tro;
Dong: St80; {dòng văn bản}
Sau: Tro;
end;
Var Dau, Cuoi : Tro;
1. Viết thủ tục Procedure Khoitao(Var Dau, Cuoi: Tro);
để khởi đầu việc soạn thảo bằng cách tạo ra những con trỏ Dau và Cuoi
cho văn bản rỗng.
2. Viết thủ tục
Procedure Chencuoi(Var Dau, Cuoi: Tro; dong : St80);
cho phép chèn một dòng mới với nội dung là dong vào cuối văn bản được
trỏ bởi Dau và Cuoi.
3. Viết thủ tục
Procedure Xoadong(Var Dau, Cuoi : Tro; Vitri : Tro) ;
cho phép xóa một dòng có địa chỉ là Vitri trong văn bản được trỏ bởi
Dau, Cuoi.
4. Ta định nghĩa khối là một dãy liên tiếp các dòng trong văn bản. Ký
hiệu (db,cb) là khối được xác định vị trí bởi địa chỉ dòng đầu db và của
dòng cuối cb. Viết thủ tục
Procedure Xoakhoi(Var Dau, Cuoi : Tro; db, cb : Tro);
cho phép xóa khối (db,cb) khỏi văn bản được trỏ bởi Dau và Cuoi.

1.
Procedure Khoitao(Var Dau, Cuoi: Tro);
Begin
Dau := Nil;
Cuoi := Nil;
End;
2.
Procedure Chencuoi(Var Dau, Cuoi: Tro; dong : St80);
Var p : Tro;
Begin
New(p);
p^.dong := dong;
p^.truoc := cuoi;
p^.sau := nil;
if dau = nil Then dau =p
else
cuoi^.sau := p;
cuoi = p;
End;
3.
Procedure Xoadong(Var Dau, Cuoi : Tro; Vitri : Tro) ;
Begin
If dau = cuoi Then khoitao(dau,cuoi)
Else
If vitri = dau Then {xoa o dau }
begin
Dau = vitri^.sau;
Dau^.truoc : = nil;
End
Else
If vitri = cuoi Then {xoa o dau }
begin
cuoi = vitri^.truoc;
cuoi^.sau : = nil;
End
Else {truong hop tong quat}
Begin
Vitri^.truoc^.sau := vitri^.sau;
Vitri^.sau^.truoc := vitri^.truoc;
End;
Dispose(vitri);
End;
4.
Procedure Xoakhoi(Var Dau, Cuoi : Tro; db, cb : Tro);
Var p : Tro;
Begin
If (dau = db) and (cuoi = cb) Then
khoitao(dau,cuoi)
Else
If db = dau Then
Begin {cb<>nil va cb <> cuoi}
Dau := cb^.sau;
Dau^.truoc := nil;
End;
Else
If cb = cuoi Then
Begin {db <>nil và db <> dau}
cuoi := db^.truoc;
cuoi^.sau := nil;
End;
Else {trường hợp tổng quát}
Begin
db^.truoc^.sau := cb^.sau;
cb^.sau^.truoc := db^.truoc;
End;
While (db < > cb^.sau) Do
Begin
p := db;
db := db^.sau;
dispose(p);
end;
End;
Bài 3. Người ta tổ chức lưu trữ trong bộ nhớ các dòng của một văn bản dưới
dạng một danh sách liên kết kép mà mỗi nút của nó gọi là dòng. Ta sẽ dùng
hai con trỏ là Dau và Cuoi lần lượt trỏ vào dòng đầu và dòng cuối của văn
bản. Cho khai báo cấu trúc dữ liệu này như sau:
Type
St80 = String[80];
Tro=^dongvb;
dongvb = record
Truoc : Tro;
Dong: St80; {dòng văn bản}
Sau: Tro;
end;
Var Dau, Cuoi : Tro;
Giả sử văn bản khác rỗng.
1. Viết thủ tục
Procedure Chentruoc(Var Dau : Tro; Vitri : Tro; dong : St80);
cho phép chèn một dòng với nội dung là dong vào trước dòng có địa chỉ
là Vitri trong văn bản được trỏ bởi Dau.
2. Viết thủ tục
Procedure Chensau(Var Cuoi : Tro; Vitri : Tro; dong : St80);
cho phép chèn một dòng với nội dung là dong vào sau dòng có địa chỉ là
Vitri trong văn bản được trỏ bởi Cuoi.
3. Ta định nghĩa khối là một dãy liên tiếp các dòng trong văn bản. Ký
hiệu (db,cb) là khối được xác định vị trí bởi địa chỉ dòng đầu db và của
dòng cuối cb. Viết thủ tục:
Procedure Chepkhoi(Var Dau : Tro; db, cb, Noiden : Tro);
cho phép sao chép khối (db,cb) tới trước dòng trỏ bởi Noiden trong danh
sách trỏ bởi Dau. Giả sử Noiden không ở trong khối (db,cb).

1.
Procedure Chentruoc(Var Dau : Tro; Vitri : Tro; dong : St80);
Var p : Tro;
Begin
New(p);
p^.dong := dong;
p^.sau := vitri;
p^.truoc := vitri^.truoc;
vitri^.truoc := p;
if vitri = dau then dau:=p
else
p^.truoc^.sau := p;
End;
2.
Procedure Chensau(Var Cuoi : Tro; Vitri : Tro; dong : St80);
Var p : Tro;
Begin
New(p);
p^.dong := dong;
p^.truoc := vitri;
p^.sau := vitri^.sau;
vitri^.sau := p;
if vitri = cuoi then cuoi :=p
else
p^.sau^.truoc := p;
End;
3.
Procedure Chepkhoi(Var Dau : Tro; db, cb, Noiden : Tro);
Begin
While (db < > cb^.sau) do
Begin
Chentruoc(dau, noiden, db^.dong);
db := db^.sau;
End;
End;
Bài 4. Trong một hệ soạn thảo văn bản, văn bản được lưu trữ trong bộ nhớ
dưới dạng một danh sách liên kết kép quay vòng như hình vẽ:
Danhsach

Lính canh
Danhsach

Dòng 1

Dòng 2 Lính canh

Trường hợp văn bản rỗng

Dòng n

Trường hợp tổng quát văn bản khác rỗng

Các phần tử được nối kép bởi hai con trỏ ngược nhau và tạo thành hai vòng
kín. Để tránh phức tạp khi cần xử lý ở đầu hay cuối văn bản, người ta đưa
thêm vào trước dòng thứ nhất một phần tử giả không chứa văn bản (gọi là
lính canh). Khai báo cấu trúc dữ liệu này như sau:
Type
St80 = String[80];
Tro=^dongvb;
dongvb = record
Truoc : Tro;
Dong: St80; {dòng văn bản}
Sau: Tro;
end;
Var Danhsach : Tro;
Giả sử danh sách đã được khởi tạo với một văn bản rỗng, nghĩa là chỉ gồm
một phần tử là lính canh và con trỏ danhsach trỏ vào lính canh đó.
1. Viết thủ tục
Procedure Chencuoi( Danhsach : Tro; dong : St80);
cho phép chèn một dòng mới với nội dung là dong vào cuối văn bản được
trỏ bởi Danhsach.
2. Viết thủ tục
Procedure Chentruoc(Danhsach,Vitri : Tro; dong : St80);
cho phép chèn một dòng với nội dung là dong vào trước dòng có địa chỉ là
Vitri trong văn bản được trỏ bởi Danhsach. Giả sử văn bản khác rỗng.
3. Viết thủ tục
Procedure Chensau(Danhsach,Vitri : Tro; dong : St80);
cho phép chèn một dòng với nội dung là dong vào sau dòng có địa chỉ là
Vitri trong văn bản được trỏ bởi Danhsach. Giả sử văn bản khác rỗng.
4. Ta gọi khối là dãy liên tiếp các dòng trong văn bản. Ký hiệu (db,cb) là
khối được xác định vị trí bởi địa chỉ dòng đầu db và của dòng cuối cb, khối
không chứa phần tử lính canh. Viết thủ tục
Procedure Chuyenkhoi(Danhsach,db, cb, noiden : Tro);
cho phép trong danh sách trỏ bởi ds, chuyển dời khối (db,cb) không rỗng tới
trước phần tử trỏ bởi noiden (noiden không ở trong khối). Giả sử văn bản
khác rỗng.

1.
Procedure Chencuoi( Danhsach : Tro; dong : St80);
Var p : Tro;
Begin
New(p);
p^.dong := dong;
p^.sau := danhsach;
p^.truoc := danhsach^.truoc;
danhsach^.truoc^.sau := p;
danhsach^.truoc := p;
End;
2.
Procedure Chentruoc(Danhsach,Vitri : Tro; dong : St80);
Var p : Tro;
Begin
New(p);
p^.dong := dong;
p^.sau := vitri;
p^.truoc := vitri^.truoc;
vitri^.truoc := p;
p^.truoc^.sau := p;
End;
3.
Procedure Chensau(Danhsach,Vitri : Tro; dong : St80);
Var p : Tro;
Begin
New(p);
p^.dong := dong;
p^.truoc := vitri;
p^.sau := vitri^.sau;
vitri^.sau := p;
p^.sau^.truoc := p;
End;
4.
Procedure Chuyenkhoi(Danhsach, db, cb, noiden : Tro);
Begin
{cắt khối}
db^.truoc^.sau := cb^.sau;
cb^.sau^.truoc := db^.truoc;
{dán lại trước noiden}
cb^.sau :=noiden;
db^.truoc := noiden^.truoc;
noiden^.truoc :=cb;
db^.truoc^.sau := db;
End;
Bài 5. Trong một hệ soạn thảo văn bản, văn bản được lưu trữ trong bộ nhớ
dưới dạng một danh sách liên kết kép và quay vòng như hình vẽ:

Danhsach

Lính canh
Danhsach

Dòng 1

Dòng 2 Lính canh

Trường hợp văn bản rỗng

Dòng n

Trường hợp tổng quát văn bản khác rỗng

Các phần tử được nối kép bởi hai con trỏ ngược nhau và tạo thành hai vòng
kín. Để tránh phức tạp khi cần xử lý ở đầu hay cuối văn bản, người ta đưa
thêm vào trước dòng thứ nhất một phần tử giả không chứa văn bản (gọi là
lính canh) và con trỏ danhsach trỏ vào lính canh. Khai báo cấu trúc dữ liệu
này như sau:
Type
St80 = String[80];
Tro=^dongvb;
dongvb = record
Truoc : Tro;
Dong: St80; {dòng văn bản}
Sau: Tro;
end;
Var Danhsach : Tro;
1. Viết thủ tục Procedure Khoitao(Var Danhsach: Tro);
để khởi đầu việc soạn thảo bằng cách tạo ra con trỏ Danhsach cho văn bản
rỗng.
2. Viết thủ tục
Procedure Xoadong(Danhsach, Vitri : Tro);
cho phép xóa dòng có địa chỉ là Vitri trong văn bản được trỏ bởi Danhsach.
Giả sử văn bản khác rỗng.
3. Ta gọi khối là dãy liên tiếp các dòng trong văn bản. Ký hiệu (db,cb) là
khối được xác định vị trí bởi địa chỉ dòng đầu db và của dòng cuối cb, khối
không chứa phần tử lính canh. Viết thủ tục
Procedure Xoakhoi(Danhsach, db, cb : Tro);
cho phép xóa khối (db,cb) trong văn bản (khác rỗng) được trỏ bởi Danhsach.
4. Viết thủ tục
Procedure Saokhoi(Danhsach, db, cb, noiden : Tro);
cho phép trong danh sách trỏ bởi Danhsach, sao chép khối khối (db,cb)
không rỗng tới trước phần tử trỏ bởi noiden (noiden không ở trong khối).

1.
Procedure Khoitao(Var Danhsach: Tro);
Begin
New(danhsach);
Danhsach^.truoc :=danhsach;
Danhsach^.sau :=danhsach;
End;
2.
Procedure Xoadong( Danhsach,Vitri : Tro);
Begin
Vitri^.truoc^.sau := vitri^.sau;
Vitri^.sau^.truoc := vitri^.truoc;
Dispose(p);
End;
3.
Procedure Xoakhoi(Danhsach, db, cb : Tro);
Begin
{cắt khối}
db^.truoc^.sau := cb^.sau;
cb^.sau^.truoc := db^.truoc;
{giải phóng bộ nhớ}
While (db < > cb^.sau) do
Begin
db := db^.sau;
dispose(db^.truoc);
end;
End;
4.
Procedure Chentruoc(Danhsach, Vitri : Tro; dong : St80);
Var p : Tro;
Begin
New(p);
p^.dong := dong;
p^.sau := vitri;
p^.truoc := vitri^.truoc;
vitri^.truoc := p;
p^.truoc^.sau := p;
End;

Procedure Saokhoi(Danhsach, db, cb, noiden : Tro);


Begin
While (db< > cb^.sau) do
Begin
chentruoc(noiden,db^.dong);
db :=db^.sau;
end;
end;
Bài 6.
1. Viết chương trình đổi một số nguyên dương hệ 10 sang số hệ 2 theo 3
phương án sau:
a. Dùng mảng để lưu giá trị trung gian trước khi in.
b. Dùng một danh sách liên kết đơn để lưu giá trị trung gian trước khi
in.
c. Dùng kỹ thuật đệ qui.
2. Cho một danh sách liên kết đơn List có nút đầu được trỏ bởi con trỏ Dau
và có khai báo cấu trúc như sau:
Type
List=^Pt;
Pt=record
Data:integer;
Next:List;
end;
Var Dau : List;
Viết thủ tục Procedure daods(Var dau:List);
để đão ngược danh sách được trỏ bởi dau bằng cách thay đổi các liên kết
(không được sao chép vào một danh sách khác).

1.
a. Dùng mảng:
Procedure HenhiPhan(n:Integer);
Var a:Array[1..10] of integer;
i,j:Integer;
Begin
i:=0;
While n<>0 do
Begin
inc(i);
a[i]:=n mod 2;
n:=n div 2;
End;
For j:=i downto 1 do Write(a[j]);
Writeln;
End;
b. Dùng danh sách liên kết đơn:
Type DanhSach=^DS;
DS= Record
x:Integer;
next:DanhSach;
End;

Procedure HenhiPhan(n:Integer);
Var Head,p,q:DanhSach;
Begin
Head:=nil;
While n<>0 do
Begin
new(p);
p^.x:=n mod 2;
p^.next:=nil;
If Head=nil then Head:=p
else
Begin
p^.next:=Head;
Head:=p;
End;
n:=n div 2;
End;
q:=Head;
While q<>nil do
Begin
Write(q^.x);
q:=q^.next;
end;
Writeln;
End;
c. Dùng đệ qui

Procedure Henhiphan(n:Integer);
Begin
if n<>0 then
Begin
DeQui(n div 2);
Write(n mod 2);
End;
End;
2.
Procedure daods(Var dau:List);
Var p1,p2:List;
Begin
If dau < > nil then
Begin
P2 := nil;
While dau^.next < > nil do
Begin
P1 := p2;
P2 := dau;
Dau := dau^.next;
P2^.next :=p1;
End;
Dau^.next := p2;
End ;
End;
Bài 7.
Cho khai báo cấu trúc dữ liệu sau:
Type Danhsach=^DS;
DS=Record
Data:Integer;
Next:Danhsach;
End;
Var Head : DanhSach; {Head trỏ vào đầu danh sách}
1. Viết thủ tục:
Procedure Laymin(Var Head, q : Danhsach);
cho phép lấy phần tử có giá trị nhỏ nhất ra khỏi danh sách liên kết trỏ bởi
Dau, phần tử đó sẽ được trỏ bởi q.
2. Cho khai báo: Var ds1, ds2 : Tro;
Trong đó ds1 trỏ tới đầu của một danh sách liên kết đơn chưa được sắp theo
trường Data, còn ds2 thì đã được khởi gán ds2 := Nil. Hãy viết một thủ tục:
Procedure Sapchon( Var ds1, ds2 : Danhsach);
cho phép chọn dần các giá trị trong ds1 từ giá trị bé đến lớn, đưa vào ds2 để
kết quả ta được ds1 = Nil, còn ds2 trỏ tới một danh sách liên kết gồm mọi
phần tử cũ của ds1 nhưng đã được sắp theo thứ tự của trường Data.

1.
Procedure LayMin(Var Head,q:DanhSach);
Var p,pp:DanhSach;
Begin
New(q);
p:=Head; q^.Data:=p^.Data; q^.next:=nil;
While (p< >nil) do
Begin
if p^.Data < q^.Data then q^.Data:=p^.Data;
p:=p^.next;
End;
q^.next:=nil;
(*Xoa nut vua tim duoc*)
if q^.Data=Head^.Data then Head:=Head^.next
else
Begin
pp:=Head; p:=Head^.next;
While (p^.Data< >q^.Data) do
Begin
pp:=pp^.next;
p:=p^.next;
end;
pp^.next:=p^.next;
Dispose(p);
End;
End;
2. {them vao dau danh sach}
Procedure InsertHead(p:Danhsach;Var Head:Danhsach);
Var q:Danhsach;
Begin
p^.Next:=Head;
Head:=p;
End;
{Thu tuc sap chon}
Procedure SapChon(Var ds1,ds2:DanhSach);
Var p,q:DanhSach;
Begin
While ds1<>nil do
Begin
LayMin(ds1,p);
InsertHead(p,ds2);
End;
End;
Bài 8.
1. Cho danh sách liên kết đơn có khai báo cấu trúc dữ liệu sau:
Type Tropt=^pt;
pt = Record
Data : Integer;
Next : Tropt;
End;
Var dau : Tropt ; {dau trỏ vào đầu danh sách}
a. Viết thủ tục Procedure Bosung(Var dau : Tropt; q : Tropt);
cho phép nối nút q vào cuối danh sách trỏ bởi dau.
b. Viết hàm Function DSTangdan(dau: Tropt):Boolean;
xác định xem danh sách có sắp theo thứ tự tăng của trường Data hay không?
2. Ta gọi từ điển là một mảng một chiều đánh chỉ số theo chữ hoa của chữ
cái, gồm những con trỏ trỏ tới các danh sách liên kết đơn. Mỗi nút trong
danh sách là một bản ghi gồm hai trường: Trường Tu để ghi nhận chuỗi ký
tự (ta gọi là từ) và trường con trỏ trỏ tới nút kế tiếp. Giả sử mỗi danh sách
liên kết này đều đã được sắp theo thứ tự tăng của từ, các từ trong mỗi danh
sách có cùng chữ cái đầu, đều bắt đầu bằng ký tự trong tập [’A’..’Z’] và
phân biệt nhau. Cho khai báo cấu trúc dữ liệu của từ điển như sau:
Type
St10 = string[10];
Danhsach = ^kieupt;
kieupt = record
Tu : st10;
tiep : Danhsach;
end;
Tudien = array[’A’..’Z’] of Danhsach;
Var T : Tudien;
1. Viết hàm
Function Kiemtra(Var T : Tudien; Mtu : st10):Boolean;
cho phép kiểm tra xem từ Mtu có trong từ điển hay không?
2. Viết thủ tục:
Procedure Bosung( Var T: Tudien; Mtu : St10);
cho phép bổ sung một từ mới Mtu vào từ điển:
- Nếu tìm thấy, hiển thị thông báo “Đã có trong từ điển”
- Nếu không tìm thấy, chèn nó vào trong từ điển ở vị trí thích hợp.
1.
a.
Procedure Bosung(Var dau : Tropt; q : Tropt);
Var p:Tropt;
Begin
If dau = nil then
Begin
Dau:=q;
Dau^.next := nil;
End
Else
Begin
p := dau;
While (p^.next < > nil) do p:= p^.next;
p^.next := q;
q^.next := nil;
end;
b.
Function DSTangdan(dau: Tropt):Boolean;
Var p1, p2 : Topt; tangdan:Boolean;
Begin
If (dau < > nil) then
Begin
P1 := dau;
P2 := dau^.next;
Tangdan := true;
While tangdan and (p2 < > nil) do
Begin
If p1^.data <= p2^.data then
Begin
P1 := p2;
P2 := p2^.next;
End;
Else
Tangdan := false;
End;
End;
2.
a.
Function Kiemtra(Var T : Tudien; Mtu : st10):Boolean;
Var p:Danhsach; found : Boolean;
Begin
P := T[Mtu[1]];
Found := false;
While (p< >nil) and (not found) do
If p^.Tu = Mtu then found :=true
Else
P := p^.next;
Kiemtra := true;
End;

b.
Procedure Chentu(Var DS:DanhSach; Mtu : st10);
Var p,q,before:DanhSach;
Begin
New(p);
p^.tu :=Mtu;
q:=DS;
While (q < > nil) and (q^.Tu < Mtu) do
Begin
Before := q;
q:=q^.next;
end;
if q = dau then DS :=p
Else
Begin
before^.next := p;
p^.next := q;
End;
End;

Procedure BoSung(Var T:Tudien; Mtu:st10);


Var c:Char;
Begin
If kiemtra(T,Mtu) then
Writeln(‘Da co trong tu dien’)
else
Chentu(T[Mtu[1],Mtu);
End;
Bài 9.
Xét một cụm dân cư nhỏ gồm nhiều gia đình. Giả sử mỗi gia đình:
- Có một họ riêng biệt
- Chỉ bao gồm bố, mẹ,
- Có thể có con hoặc không,
- Có thể có nhiều xe.
Mỗi người trong cụm dân cư (cha, mẹ hoặc con) chỉ thuộc một gia đình. Tất
cả các gia đình có họ khác nhau, tên các thành viên của gia đình khác nhau,
số cha mẹ không quá hai, số con hạn chế, dân cư sắp xếp theo thứ tự tăng
của họ.
Cho khai báo cấu trúc dữ liệu trên sau:
Type
St10 = string[10];
Trogdinh = ^giadinh;
Tronguoi = ^nguoi;
Troxe = ^xe;
giadinh = record
Ho : st10;
chame : Tronguoi;
con : Tronguoi;
xe : Troxe;
Tiep : Trogdinh;
end;
nguoi = record
ten : st10;
namnu : Boolean;
tieptheo : Tronguoi;
end;
xe = record
kieu : st10;
soxe : st10;
tieptheo : Troxe;
end;
Var dancu:Trogdinh;

1. Viết hàm Function Sogdkcm(dancu : Trogdinh):Integer;


theo hai phương pháp: đệ qui và không đệ qui; để đếm số gia đình không
còn cha mẹ (nghĩa là danh sách cha mẹ bằng rỗng) trong danh sách trỏ bởi
dancu.
2. Viết hàm Function Socon(dancu : Trogdinh):Integer;
để đếm số con trong các gia đình trong danh sách trỏ bởi dancu.
3. Viết hàm
Function Chuxe(dancu : Trogdinh ; Msoxe : st10):Trogdinh;
trả về địa chỉ của gia đình có số xe là Msoxe, hàm trả về nil nếu không
tìm thấy số xe trong danh sách trỏ bởi dancu.
4. Viết hàm
Function Loaixe( dancu: Trogdinh; Msoxe : st10):Boolean;
cho phép loại bỏ một chiếc xe có số xe Msoxe trong danh sách trỏ bởi
dancu. Nếu việc lại bỏ thành công thì hàm trả về giá trị True, ngược lại hàm
trả về giá trị false.

1. {không đệ qui}
Sogdkcm(dancu : Trogdinh):Integer;
Var dem: integer;
Begin
Dem := 0 ;
While (dancu < > nil) do
Begin
If dancu^.chame = nil then
Dem := dem+1;
End;
Sogdkcm := dem;
End;

{đệ qui}
Sogdkcm(dancu : Trogdinh):Integer;
Var dem: integer;
Begin
If dancu = nil then Sogdkcm := 0;
Else
If dancu^.chame < > nil then
Sogdkcm := Sogdkcm(dancu^.tieptheo)
Else
Sogdkcm := 1 + Sogdkcm(dancu^.tieptheo)
End;
2.
Socon(dancu : Trogdinh):Integer;
Var concai : Tronguoi; dem : integer;
Begin
Dem := 0;
While (dancu < > nil) do
Begin
Concai := dancu^.con;
While (concai < > nil) do
Begin
Dem := dem+1;
Dancu^.con := dancu^.con^.tieptheo;
End;
Dancu := dancu^.tieptheo;
End;
Socon := dem;
End;
3.
Function Coxe(xe : Troxe; Msoxe : st10):Boolean;
Begin
If xe = nil then Coxe :=false
Else
If xe^.soxe = Msoxe then Coxe := True
Else
Coxe := coxe(xe^.tieptheo, Msoxe);
End;
Function Chuxe(dancu : Trogdinh ; Msoxe : st10):Trogdinh;
Begin
If dancu = nil then chuxe := nil;
Else
If coxe(dancu^.xe,Msoxe) then
chuxe:= dancu
Else
Chuxe := chuxe(dancu^.tieptheo,Msoxe);
End;
4.
Procedure loaixedau(xe:Troxe);
Var p:Troxe;
Begin
P := xe;
Xe := xe^.tieptheo;
Dispose(p);
End;
Function Loaixe1( xe: Troxe; Msoxe : st10):Boolean;
Begin
If xe = nil then loaixe1 := false
Else
If xe^.soxe = Msoxe then
Begin
Loaixedau(xe);
loaixe1 := true;
end
else
loaixe1 : loaixe1(xe^.tieptheo,Msoxe);
end;

Function Loaixe( dancu: Trogdinh; xe: Troxe; Msoxe : st10):Boolean;


Begin
If dancu = nil then loaixe = false
Else
If loaixe1(dancu^.xe,Msoxe) then loaixe := true;
Else
Loaixe := loaixe(dancu^.tieptheo,Msoxe);
End;
Bài 10.
Để quản lý một danh sách học viên đồng thời theo 3 thứ tự (tăng): thứ tự họ
tên, thứ tự tuổi và thứ tự điểm, người ta dùng một danh sách liên kết với khai
báo như sau:
Type
Datatype = record
Hoten : string[30];
Tuoi: integer;
Điem: real;
end;
Trods = ^phantu
Phantu = record
Data: Datatype;
Next : array[1..3] of Trods;
End;
Var first : array[1..3] of Trods;
{3 biến con trỏ first[i] ( i=1,2,3) quản lý ba phần tử đầu tiên của danh sách
theo các thứ tự tương ứng : Hoten, tuoi, diem.
1. Viết thủ tục: Procedure InsertOrder(X : Datatype);
cho phép bổ sung phần tử X vào danh sách.
2. Viết thủ tục: Procedure Duyetds(key : integer);
cho phép duyệt danh sách theo key (giá trị key =1 sẽ duyệt theo họ tên, key
= 2 duyệt theo tuổi, key = 3 duyệt theo điểm).
3. Viết thủ tục: Procedure Delete(X : Datatype);
cho phép xóa phần tử X trong danh sách.

1.
Procedure InsertOrder(X : Datatype);
Var px, p, prev : Trods;
i : integer;
ss : Boolean;
Begin
New(px);
Px^.data := X;
If first[1] = nil then
For i:=1 to 3 do
Begin
First[i] := px;
Px^.next[i] := nil;
End;
Else
For i := 1 to 3 do
Begin
p:=first[i];
if i = 1 then ss = (p^.data.hoten < X.hoten)
else
if i = 2 then ss = (p^.data.tuoi < X.tuoi)
else
ss = (p^.data.diem < X.diem);
While ss and (p < >nil) do
Begin
Prev := p;
P := p^.next[i];
End;
If p = first[i] then
Begin
Px^.next[i] := first[i];
First[i] := px;
End
Else
Begin
Prev^next[i] :=px;
Px^.next[i] := p;
End;
End;
End;
2.
Procedure Duyetds(key : integer);
Var p : Trods;
Begin
If first[1] = nil then halt
P := first[key];
While p < > nil do
Begin
With p^.data do
Writeln(hoten, ‘ ‘, tuoi,’ ‘,diem:0:2);
P :=p^next[key];
End;
End;
3.
Procedure Delete(X : Datatype);
Var prev, p, q : Trods;
Found : Boolean;
i : integer;
Begin
q := first[1];
found := false;
while (q < > nil) and (not found) do
if q^.data.hoten = X.hoten then found = true
else
q := q^next[1];
If found then
Begin
For i := 1 to 3 do
Begin
p := first[i];
While (p < >q) do
Begin
Prev := p;
P := p^.next[i];
End;
If p = q then prev^.next[i] := q^.next[i];
End;
Dispose(q);
End;
End;
CÂY NHỊ PHÂN
Bài 1. Trong một thư viện, người ta biễu diễn thông tin về tác giả và các
cuốn sách của tác giả đó bởi một cây tìm kiếm nhị phân với khóa là TênTG
(tên tác giả). Mỗi nút của cây là một bản ghi gồm trường TenTG và 4
trường con trỏ: hai con trỏ Trai va Phai lần lượt trỏ tới nút con trái và nút
con phải, hai con trỏ Dau và Cuoi lần lượt trỏ tới nút đầu và nút cuối của
một danh sách liên kết dùng ghi nhận các sách có trong thư viện của tác giả
đó. Mỗi nút của danh sách này là một bản ghi gồm 2 trường: trường Tensach
và trường Tieptheo.
Khai báo cấu trúc dữ liệu trên như sau:
Type
St25 = string[25];
TroSach=^Sach;
Sach = record
TenSach:String;
Tieptheo: TroSach;
end;
TroTG = ^Tacgia;
Tacgia = record
Trai: TroTG;
TenTG:st25;
dau, cuoi:TroSach;
phai: TroTG;
end;
Var Goc : TroTG; {Goc trỏ đến nút gốc của cây}
1. Viết hàm Function Vitri(Goc : TroTG; Ten : St25 ):TroTG;
cho kết quả là con trỏ:
- bằng Nil khi Goc = Nil, nếu không thì :
- trỏ tới nút có TenTG = Ten nếu nút đó tồn tại, nếu không thì :
- trỏ tới nút trong đó Ten < TenTG và Trai = Nil, hoặc là :
- trỏ tới nút trong đó Ten > TenTG và Phai = Nil.
2. Viết hàm
Function NutMoi(Ten : St25; Tuade : String):TroTG;
cho kết quả là địa chỉ của nút mới thành lập (có kiểu TroTG) nhưng chưa
được gắn vào cây, trong đó TenTG =Ten và Tensach = Tuade.
3. Viết thủ tục
Procedure Bosung(Var Goc : TroTG; Ten : St25; Tuade: String );
cho phép bổ sung tên một tác giả (Ten) với một cuốn sách (Tuade) vào
thư viện trỏ bởi Goc theo cách sau:
- Nếu Ten và Tuade đều đã có thì không làm gì nữa,
- Nếu Ten đã có và Tuade chưa có thì bổ sung Tuade đó vào cuối
danh sách tương ứng với nút có TenTG = Ten,
- Nếu Ten và Tuade đều chưa có thì bổ sung một nút mới vào cây
với TenTG = Ten, Tensach = Tuade.

1.
Function Vitri(Goc : TroTG; Ten : St25 ):TroTG;
Var tieptuc: Boolean;
Begin
If goc = nil then vitri := nil;
Else
Begin
Tieptuc := true;
While tieptuc do
If (Ten <Goc^.ten) and (goc^.trai < >nil) then
Goc = goc^.trai;
Else
If (Ten > Goc^.ten) and (goc^.phai < >nil) then
Goc = goc^.phai;
Else
Tieptuc := false;
Vitri := goc;
End;
End;

Viết dưới dạng đệ qui:


Function Vitri(Goc : TroTG; Ten : St25 ):TroTG;
Begin
If goc = nil then vitri := nil;
Else
Begin
If (Ten <Goc^.ten) and (goc^.trai < >nil) do
Vitri := vitri(goc^.trai,ten);
Else
If (Ten > Goc^.ten) and (goc^.phai < >nil) do
Vitri := vitri(goc^.phai,ten);
Else
Vitri := goc;
End;
2.
Function TaoptuSach(Tuade : string):TroSach;
Var q : TroSach;
Begin
New(q);
q^.Tensach := Tuade;
q^.tieptheo := Nil;
taoptuSach := q;
end;

Function TaoNutMoi(Ten : St25; Tuade : String):TroTG;


Var p : TroTG; q : TroSach;
Begin
New(p);
P^.ten := ten;
p := TaoptuSach(Tuade);
p^.dau := q;
p^.cuoi := q;
p^.trai:= nil;
p^.phai:= nil;
TaoNutMoi := p;
End;

3.
Procedure chensach(p : TroTG; Tuade : String);
Var q : TroSach;
Begin
q := taoptsach(Tuade);
p^.cuoi^.tieptheo :=q;
p^.cuoi :=q;
End;

Procedure Bosung(Var Goc : TroTG; Ten : St25; Tuade: String );


Var p : TroTG;
Begin
If goc = nil then
Goc := TaoNutMoi(Ten,Tuade)
Else
Begin
p := vitri(goc,ten);
if p^.ten > ten then
p^.trai := TaoNutMoi(Ten,Tuade)
else
if p^.ten < ten then
p^.phai := TaoNutMoi(Ten,Tuade)
else
if p^.cuoi^.Tuade < > Tuade then
chensach(p,tuade);
End;
End;
Bài 2. Cho khai báo cây nhị phân như sau:
Tro = ^Nut;
Nut = Record
Giatri: integer;
Trai, Phai: Tro;
End;
Var T : Tro; {T trỏ đến nút gốc của cây}
Với cây nhị phân này ta có thể tiến hành duyệt cây theo giải thuật sau, trong
đó có dùng một danh sách liên kết để chứa các nút cần ghi nhớ trong cây:
- Nạp (con trỏ) gốc cây vào danh sách
- While danh sách không rỗng Do
Begin
Lấy một nút từ danh sách, gọi đó là N;
Thăm N (in ra giá trị của nó);
Nạp con trái của N vào danh sách (nếu có);
Nạp con phải của N vào danh sách (nếu có);
End;
Dựa vào giải thuật trên, hãy viết hai thủ tục duyệt cây:
1. Giải thuật S (dùng stack): Lấy nút mới nhất (được nạp muộn nhất)
trong danh sách.
2. Giải thuật Q (dùng queue): Lấy nút cũ nhất (được nạp sớm nhất)
trong danh sách.

1.
Type TRO=^NUT;
NUT=Record
giatri:Integer;
Trai,Phai:TRO;
End;
DanhSach=^Phantu;
Phantu=Record
pt:Tro;
next:DanhSach;
End;
List=^StackType;
StackType=Record
Data:tro;
Next:List;
End;

Var Goc :TRO;


{1. Duyet cay dung Stack}
Procedure InPut(pt:Tro; Var First,Last:DanhSach);
Var p:DanhSach;
Begin
New(p); p^.pt:=pt; p^.next:=nil;
if First=nil then Begin First:=p; Last:=p; end
else Begin
p^.next:=First; First:=p;
End;
End;

Function OutPutStack(Var First,Last:DanhSach):DanhSach;


Begin
if First=nil then OutPutStack:=nil
else Begin
OutPutStack:=First;
if First=Last then
Begin
First:=nil; Last:=nil;
End
else Begin
First:=First^.next;
End;
End;

Procedure DuyetCayS(Root:Tro);
Var First,Last,N:DanhSach;
p:Tro;
Begin
First:=nil; Last:=nil;
Input(Root,First,Last);
While First<>nil do
Begin
N:=OutPutStack(First,Last);
p:=N^.pt;
if p<>nil then
Begin
Write(p^.giatri:5);
if p^.Trai<>nil then Input(p^.Trai,First,Last);
if p^.Phai<>nil then Input(p^.Phai,First,Last);
End;
End;
End;

{2. Duyet cay dung Queue}

Function OutPutQueue(Var First,Last:DanhSach):DanhSach;


Var p:DanhSach;
Begin
if First=nil then OutPutQueue:=nil
else if First=Last then
Begin OutPutQueue:=First; First:=nil; Last:=nil; end
else Begin
p:=First;
While p^.next<>Last do p:=p^.next;
OutPutQueue:=Last;
p^.next:=nil;
Last:=p;
End;
End;
Procedure DuyetCayQ(Root:Tro);
Var First,Last,N:DanhSach;
p:Tro;
Begin
First:=nil; Last:=nil;
Input(Root,First,Last);
While First<>nil do
Begin
N:=OutPutQueue(First,Last);
p:=N^.pt;
if p<>nil then
Begin
Write(p^.giatri:5);
if p^.Trai<>nil then Input(p^.Trai,First,Last);
if p^.Phai<>nil then Input(p^.Phai,First,Last);
End;
End;
End;
Bài 3. Cho khai báo cây nhị phân như sau:
Tro = ^Nut;
Nut = record
Giatri: integer;
Trai, Phai: Tro;
end;
Var T : Tro; {T trỏ đến nút gốc của cây}
1. Viết hàm Function Hoanvi(T:Tro):Tro;
để hoán vị thứ tự trái phải của các con của mỗi nút trên cây nhị phân.
2. Viết thủ tục đệ qui Procedure Insert(X:DataType;var Root:Tro);
để chèn thêm một nút có giá trị X vào cây tìm kiếm nhị phân có cấu trúc như
ở trên.
3. Viết một thủ tục không đệ qui Procedure NLR_Stack(Root:Tro);
cho phép duyệt cây tìm kiếm nhị phân theo thứ tự giữa.

1.
Function Hoanvi(T:Tro):Tro;
Var TT:tro;
Begin
if T< >nil then
begin
new(TT);
TT^.giatri:=T^.giatri;
TT^.Phai:=Hoanvi(T^.Trai);
TT^.Trai:=Hoanvi(T^.Phai);
end
else
TT:=nil;
Hoanvi:=TT;
End;
2.
Procedure Insert_dq(X:DataType;var Root:Tro);
Var pX,p,Before:Tro;
Begin
If Root=nil then
Begin
New(Root);Root^.giatri:=X;Root^.Trai:=nil;Root^.Phai:=nil;
End
Else
if X<Root^.giatri then Insert_dq(X,Root^.Trai)
else if X>Root^.giatri then Insert_dq(X,Root^.Phai);
End;
3.
{ Chen phan tu vao Stack }
Procedure PushStack(X:Tro; Var Stack:List);
Var p:List;
Begin
New(p);
p^.giatri:=X;
p^.next:=Stack;
Stack:=p;
End;
{Loai bo 1 phan tu khoi Stack }
Procedure PopStack(Var X:Tro; Var Stack:List);
Var p:List;
Begin
If Stack<>nil then
Begin
p:=Stack;
Stack:=p^.next;
X:=p^.giatri;
Dispose(p);
end;
End;

Procedure NLR_Stack(Root:Tro);
Var p:Tro;
S:List;
cont:Boolean;
Begin
InitStack(S);p:=Root;cont:=True;
While (p< >nil) and Cont do
Begin
write(p^.giatri:5);
if p^.phai<>nil then PushStack(p^.phai,S);
if p^.trai<>nil then p:=p^.Trai
else
if StackEmpty(S) then cont:=false
else PopStack(p,S);
end;
End;
Bài 4. Cho khai báo cây nhị phân như sau:
Tro = ^Nut;
Nut = record
Giatri: integer;
Trai, Phai: Tro;
end;
Var Goc : Tro; {Goc trỏ đến nút gốc của cây}
1. Viết thủ tục xóa một nút khỏi cây tìm kiếm nhị phân có cấu trúc như trên.
2. Viết hàm : Function copy(Goc : Tro):Tro;
cho phép trả lại địa chỉ gốc một cây mới, cây này được thành lập như một
bản sao của cây đã cho (trỏ bởi Goc).

1.
Procedure Del(Var p:Tro);
Var q,q1 : Tro;
Begin
If p^.phai = nil then
Begin
q := p;
p:=p^.trai;
end
else
If p^.left = nil then
Begin
q := p;
p:=p^.phai;
end
else
begin
q := p^.trai;
if q^.phai = nil then
begin
p^.giatri := q^.giatri;
p^.trai := q^.trai
end;
else
begin
repeat
q1 := q;
q :=q^.phai;
until q^.phai = nil;
p^.giatri = q^.giatri;
q1^.phai = q^.trai;
end;
end;
dispose(q);
end;
Procedure Delete(Var Goc:Tro; X:integer);
Begin
If Goc < > nil then
If X < goc^.giatri then Delete(goc^.trai,X)
Else
If X > goc^.giatri then Delete(goc^.phai,X)
Else
Del(goc);
End;

2.
Function Saochep(T:tro):tro;
Var TT:tro;
Begin
if T<>nil then
begin
new(TT);
TT^.data:=T^.data;
TT^.trai:=Saochep(T^.trai);
TT^.phai:=Saochep(T^.phai);
end
else
TT:=nil;
Saochep:=TT;
End;
Bài 5. Cho khai báo cây nhị phân như sau:
Tro = ^Nut;
Nut = record
Giatri: integer;
Trai, Phai: Tro;
end;
Var T : Tro; {T trỏ đến nút gốc của cây}
1. Viết hàm tính chiều cao của cây nhị phân trỏ bởi T.
2. Viết thủ tục Insert(X:integer; Var T : Tro);
cho phép chèn nút có khóa X vào cây nhị phân tìm kiếm.
3. Giả sử đây là cây tìm kiếm nhị phân.
a. Viết hàm đệ qui: Function find_min(T:Tro):Tro;
cho phép trả về địa chỉ của nút có trường giatri nhỏ nhất.
b. Viết hàm không đệ qui: Function find_max(T:Tro):Tro;
cho phép trả về địa chỉ của nút có trường giatri lớn nhất.

1.
Function chieucao(T:Tro):integer;
var p:tro;
Begin
p:=T;
if p=nil then chieucao:=1
else
chieucao:=1+max(chieucao(p^.left),chieucao(p^.right));
End;
2.
Insert(X:integer; Var T : Tro);
Begin
If T = nil then
Begin
New(T);
T^.giatri := X;
T^.trai := nil;
T^.phai := nil;
End;
Else
Begin
If X < T^.giatri then
Insert(X, T^.trai)
Else
If X < T^.giatri then
Insert(X, T^.trai);
End;
End;

3.
a.
Function find_min(T:Tro):Tro;
Begin
If T = nil then find_min = nil
Else
T^.trai = nil then find_min = T
Else
Find_min = find_min(T^.trai);
End;
b.
Function find_max(T:Tro):Tro;
Begin
If T < > nil then
While T^.phai < > nil do
T := T^.phai;
Find_max := T;
End;
Bài 6. Cho khai báo cây nhị phân như sau:
Tro = ^Nut;
Nut = record
Giatri: integer;
Trai, Phai: Tro;
end;
Var T : Tro; {T trỏ đến nút gốc của cây}
1. Viết hàm tính chiều cao của cây nhị phân trỏ bởi T.
2. Viết thủ tục Insert(X:integer; Var T : Tro);
cho phép chèn nút có khóa X vào cây nhị phân tìm kiếm.
3. Giả sử đây là cây tìm kiếm nhị phân.
a. Viết hàm đệ qui: Function find_min(T:Tro):Tro;
cho phép trả về địa chỉ của nút có trường giatri nhỏ nhất.
b. Viết hàm không đệ qui: Function find_max(T:Tro):Tro;
cho phép trả về địa chỉ của nút có trường giatri lớn nhất.

1.
Function chieucao(T:Tro):integer;
var p:tro;
Begin
p:=T;
if p=nil then chieucao:=1
else
chieucao:=1+max(chieucao(p^.left),chieucao(p^.right));
End;
2.
Insert(X:integer; Var T : Tro);
Begin
If T = nil then
Begin
New(T);
T^.giatri := X;
T^.trai := nil;
T^.phai := nil;
End;
Else
Begin
If X < T^.giatri then
Insert(X, T^.trai)
Else
If X < T^.giatri then
Insert(X, T^.trai);
End;
End;

3.
a.
Function find_min(T:Tro):Tro;
Begin
If T = nil then find_min = nil
Else
T^.trai = nil then find_min = T
Else
Find_min = find_min(T^.trai);
End;
b.
Function find_max(T:Tro):Tro;
Begin
If T < > nil then
While T^.phai < > nil do
T := T^.phai;
Find_max := T;
End;
Bài 7. Một công ty du lịch cần quản lý các xe ô tô của họ bằng một cây nhị
phân có cấu trúc như sau:

Type TroXe=^Xe;
Xe= Record
Taixe:string[6]; {Tài xế}
Bienso:string[4]; {biển số}
sochongoi:byte; {số chỗ ngồi}
left, right:Troxe;
End;
Var Top:Troxe; {Top trỏ đến nút gốc của cây}
Giả thiết cây có tính chất: số chỗ ngồi của mỗi nút nhỏ hơn tất cả số chỗ
ngồi tại mọi nút trên cây con trái của nó và bằng số chỗ ngồi tại mọi nút trên
cây con phải của nó.
top -->
Xung, 2567,4
/ \
An,3234,12 Tran,3456, 4
/ \ \
Chien,4656,35 Binh,4554,12 Anh, 4567, 4
\
Hung,6789,4
1. Vẽ cây nhị phân với tính chất như trên để biểu diễn thông tin về xe ô tô
như sau:
Tài xế Biển số Số chỗ ngồi
Mai 4324 12
Lan 5654 24
Cuc 6767 24
Truc 3454 36
Hong 5465 12
Hoa 5344 50
Hue 6787 12
2. Viết thủ tục: Procedure Print(Top:TroXe; n:byte);
Cho phép in tên tài xế, biển số xe của tất cả xe có n chỗ ngồi được lưu trên
cây nhị phân trỏ bởi Top.
3. Viết hàm Function Max(Top:Troxe):byte;
trả về số chỗ ngồi lớn nhất của xe được lưu trữ trên cây nhị phân trỏ bởi Top
(khác nil).
Type
st6=string[6];
st4=string[4];
TroXe=^Xe;
Xe= record
Taixe:st6;
Bienso:st4;
sochongoi:byte;
left,right:Troxe;
End;

1.
Mai, 4324,12
/ \
Lan, 5654, 24 Hong,5465, 12
/ \ \
Truc,3454, 36 Cuc, 6767, 24 Hue ,6787, 12
/
Hoa ,5344, 50

2.
{1. De qui}
Procedure Print(Root:TroXe; n:Byte);
var p:Troxe;
Begin
p:=Root;
if p = Nil then writeln('NIL')
else
if (p^.sochongoi= n) then
begin
writeln(p^.taixe,’ ’,p^.bienso,’ ’,p^.sochongoi,);
Print(root^.right,n);
end
else
Print(root^.left,n);
End;
{2. Lặp}
Procedure Print2(Root:TroXe; n:Byte);
var p:Troxe;
Begin
p:=Root;
if p = nil then writeln('Nil')
else
while p <> nil do
begin
if (p^.sochongoi =n) then

begin
while p<> nil do
begin
writeln(p^.taixe,’ ’,p^.bienso,’ ’,p^.sochongoi);
p:=p^.right;
end;

end

else
p:=p^.left;
end;
End;
3.
Function Maxn(Root:Troxe):byte;
var n:byte;
p:troXe;
Begin
p:=root;
if p=nil then Maxn:=0
else
while p<>nil do
begin
n:=p^.sochongoi;
p:=p^.left;
end;
Maxn:=n;
End;
Bài 8.
1. Viết thủ tục không đệ qui để duyệt cây nhị phân theo thứ tự trước (NLR).
2. Viết thủ tục không đệ qui để duyệt cây nhị phân theo mức của các nút
trong cây.

Type
DataType=Integer;
Tro=^kieupt;
kieupt=record
Data:DataType;
Trai,Phai:Tro;
end;
List=^StackType;
StackType=Record
Data:tro;
Next:List;
End;
Var Goc:Tro;
{ Chen phan tu vao Stack }
1.
Procedure PushStack(X:Tro; Var Stack:List);
Var p:List;
Begin
New(p);
p^.Data:=X;
p^.next:=Stack;
Stack:=p;
End;
{Loai bo 1 phan tu khoi Stack }
Procedure PopStack(Var X:Tro; Var Stack:List);
Var p:List;
Begin
If Stack<>nil then
Begin
p:=Stack;
Stack:=p^.next;
X:=p^.Data;
Dispose(p);
end;
End;
Function StackEmpty(Stack:List):Boolean;
begin
if Stack=nil then StackEmpty:=True
else StackEmpty:=False;
end;
Procedure NLR_Stack(Root:Tro);
Var p:Tro;
S:List;
cont:Boolean;
Begin
InitStack(S);p:=Root;cont:=True;
While (p<>nil) and Cont do
Begin
write(p^.Data,' ');
if p^.phai<>nil then PushStack(p^.phai,S);
if p^.trai<>nil then p:=p^.Trai
else
if StackEmpty(S) then cont:=false
else PopStack(p,S);
end;
End;
2.
{Them 1 phan tu vao Queue}
Procedure Insert_Queue(X:Tro;var Queue:list);
Var p,q:List;
Begin
New(p);
p^.Data:=X;
p^.Next:=Nil;
If Rear=Nil then Front:=p
Else Rear^.next:=p;
Rear:=p;
End;
{Loai bo phan tu khoi Queue}
Procedure Delete_Queue(var Y:Tro;var Queue:List);
var Succ:Boolean;p:List;
Begin
Succ:=false;
If Front<>nil then
Begin
Succ:=True;
p:=Front;
Front:=p^.next;
Y:=p^.Data;
If Front=Nil then Rear:=nil;
Dispose(p);
End;
End;
{Duyet cay theo muc }
{Giai thuat (dung Hang)}
Procedure LRD_Level(Root:Tro);
Var p:Tro;
Q,Dau,Cuoi:List;
Begin
InitQueue(Q);
If Root<>nil then Insert_Queue(Root,Q);
while front<>nil do
begin
Delete_Queue(p,Q);
write(p^.Data,' ');
if p^.trai<>nil then Insert_Queue(p^.trai,Q);
if p^.phai<>nil then Insert_Queue(p^.phai,Q);
end;
end;
Bài 9. Một biểu thức số học dạng trung tố được biểu diễn bằng cây nhị phân
như sau:
- Các nút trong cây chứa các toán tử + - * / # ^ trong đó # là phép
trừ một ngôi và ^ là phép lũy thừa.
- Các nút lá chứa toán hạng (số thực).
- Mỗi nút chứa các trường: left trỏ tới cây con trái, right trỏ tới cây
con phải, một trường loại nút cho biết nút này ứng với + - * / # hay
toán hạng. Nếu loại nút là # thì chỉ có cây con phải, còn nếu loại
nút là toán hạng thì không có các cây con trái, cây con phải, và nút
có thêm một trường chứa giá trị thực của toán hạng.
Giả sử đã có một cây như trên, gốc được trỏ bởi con trỏ T. Hãy viết thủ tục
khởi tạo cây và viết hàm cho phép tính giá trị của biểu thức tương ứng với
cây đó.

Type INFIX=^CONTRO;
CONTRO=Record
Loainut:Char;
GiaTri:Real;
Left,Right:INFIX;
End;
Var Root:INFIX;
st:String;
i:byte;
Token,ch:Char;
Procedure NextToken;
Begin
i:=i+1;
Token:=st[i];
End;

Procedure KhoiTaoCay(Var p:INFIX);


Begin
NextToken;
New(p); p^.Loainut:=Token;
If Token in ['0'..'9'] then
Begin {cac thao tac luon la la}
p^.Giatri:=Ord(p^.Loainut)-48; {Doi ra gia tri so}
p^.Left:=nil; p^.Right:=nil;
End
else
if token in ['+','-','*','/','^'] then
Begin
KhoiTaoCay(p^.Left);
KhoiTaoCay(p^.Right);
End
else
if token in ['#'] then
begin
p^.left:=nil;
KhoiTaoCay(p^.Right);
end;
End;

Function Valtree(p:INFIX):real;
begin
Case p^.Loainut of
'+':Valtree:=Valtree(p^.Left) + Valtree(p^.Right);
'-':Valtree:=Valtree(p^.Left) - Valtree(p^.Right);
'*':Valtree:=Valtree(p^.Left) * Valtree(p^.Right);
'/':Valtree:=Valtree(p^.Left) / Valtree(p^.Right);
'#':Valtree:=-Valtree(p^.Right);
'^':Valtree:=Exp(Valtree(p^.Right)*Ln(Valtree(p^.Left)));{a luy thua b=
exp(b*lna)}
Else Valtree:=p^.Giatri;
end;
end;

You might also like