Nhằm xây dựng cây nhị phân tìm kiếm có gốc được trỏ bởi Goc; tương ứng với một hoán vị nào đó của các phần tử trong danh sách sao cho độ cao của cây nhận được là nhỏ nhất. Giải:[r]
(1)DANH SÁCH MÓC NỐI
Biến động (Nút) Cấu trúc nhị phân:
Đối với có ba phép duyệt: - Gốc – Trái – Phải
- Trái – Gốc – Phải - Trái – Phải – Gốc Ví dụ:
A BDE CFGH Cây nhị phân tìm kiếm:
Là nhị phân chứa dãy khóa thỏa mãn điều kiện khóa gốc lớn khóa nút trái nhỏ khóa nút phải
Ví dụ:
Nhận xét:
Duyệt theo phương án: Trái – Gốc – Phải : 11 15 16 17 19 25 cho dãy khóa theo thứ tự tăng dần Như việc tìm kiếm nút chứa khóa k Nếu tìm có cho địa nút đó, khơng cho địa NULL
Function Timnut(T: Tro; K: Integer): Tro; Var p: Tro;
Begin
P:= T;
While (p<> Nil) and (p^.Giatri <> k) If (p^.Giatri < k then p:= p^.Phai Else
P:= p^.Trai; Timnut:= p;
End;
Tìm theo đệ quy:
Function Timnut(T: Tro; k: Integer):Tro; Begin
If (T=NIL) or (T^.Giatri= k) Then Timnut:= T
Else
If (T^.Giatri > k) Then
Timnut: = Timnut(T^.Phai, k) x
A
E
C B
F D
G H
Trái Phải
15
11
25 9
17 5
(2)Else
Timnut:= Timnut(T^.Trai, k); End;
2.1 Bổ sung thêm khóa K vào T (nếu chưa có nút chứa K): Procedure Bosung(T: Tro; K: Integer);
Var p,r : Tro; OK: Boolean; Begin
If (T=NIL) Then Begin
New(T);
T^.Giatri: = k; T^.Trai:= NIL;
T^.Phai:= NIL; End Else Begin
P:= T; OK:= True;
While (p^.Giatri <> k) and OK If (p^.Giatri > k) Then
If (p^.Trai <> NIL) Then p:= p^.Trai else OK:= False Else
If (p^.Phai <> NIL) Then p:= p^.Phai else OK:= False If (p^.Giatri = k) Then Write(“Gia tri da ton tai”)
Else Begin
New(r); R^.Giatri:= k;
R^.Phai:= NIL; R^.Trai:= NIL;
If (p^.Giatri > k) Then p^.Trai := r Else p^.Phai:= r; End;
End; End;
Đề thi năm 2003:
Câu 2: Người ta biểu diễn thông tin câu lạc bóng đá chuyên nghiệp quốc gia dạng nhị phân tìm kiếm có khóa TenCLB (Tên câu lạc bộ) Mỗi nút ghi gồm trường: TenCLB trường trỏ Left, Right, First Hai trỏ Left Right lần lượt trỏ tới nút trái phải nút Con trỏ First trỏ phần tử đầu danh sách liên kết đơn chứa thông tin cầu thủ thuộc câu lạc (danh sách có 11 phần tử) Mỗi phần tử danh sách ghi gồm trường: TenCT (Tên cầu thủ), SoAo (số áo), Tuoi (tuổi), Next (lưu địa phần tử danh sách) Danh sách theo thứ tự tăng dần SoAo Người ta cho khai báo cấu trúc liệu nói sau:
Type st25 = string[25]; TroCT = ^Cauthu; Cauthu = Record
TenCT: St25; SoAo, Tuoi: Byte; Next: TroCT; End;
TroCLB = ^Nut; Nut = Record
TenCLB: St25; First: TroCT; L,R: TroCLB; End;
Var Top: TroCLB;
TenCLB
First R
L
TenCLB R
L TenCT L TenCLB R
SoAo Tuoi Next
(3)a Viết thủ tục in danh sách cầu thủ câu lạc có tên club Procedure List(Club: st25);
Var P: TroCLB; r: TroCT; Begin
P:= Top;
While (p<> Nil) and (p^.TenCLB <> Club)
If (p^.TenCLB > Club) Then p:= p^.L else p:= p^.R; If p= Nil Then Write(“Khơng có câu lạc này”)
Else Begin
r:= p^.First;
Writeln(“Danh sách cầu thủ”); While r<> Nil
Begin
Writeln(p^.TenCT); r:= r^.next;
End; End; End;
2 Viết thủ tục Procedure Bosung(Top: TroCLB; Name: st25; m,k: byte) bổ sung cầu thủ tên Name, tuổi k, số áo m vào câu lạc có tên Club> Việc bổ sung thực trường hợp câu lạc Club có chưa có cầu thủ câu lạc có số áo
Procedure Bosung(Top: TroCLB; Name: st25; m,k: byte); Var p: TroCLB; q, r: TroCT;
Begin
p:= Top;
While (p<> Nil) and (p^.TenCLB <> Club)
If (p^.TenCLB > Club) Then p:= p^.L Else p:= p^.R; If (p = Nil) Then Write (“Khơng có Câu lạc này”)
Else
Begin
R:= p^.First;
{Con trỏ r dùng để duyệt nút cho r dừng lại nút thỏa mãn điều kiện sau:
Số áo m
Số áo < m số áo nút > m Hoặc nút cuối
}
If (r^.SoAo > m) or (p^.First = Nil) then Begin
New(q); q^.TenCT = Name;
q^.Tuoi:= k; q^.SoAo:= m;
q^.Next: = p^.First; p^.First:= q;
End Else Begin
While (r^.Next <> Nil) and ((r^.Next)^.SoAo <= m ) r:= r^.Next;
If r^.SoAo = m then Write (“Đã có”) Else
Begin
New(q);
q^.TenCT:= Name; q^.Tuoi:= k; q^.SoAo:= m; q^.Next:= r^.Next; r^.Next:= q; End;
(4)(5)c Xóa tên cầu thủ mang số áo m câu lạc Club Procedure Xoa(Club: st25; m: byte);
Begin p:= Top;
While (p<> Nil) and (p^.TenCLB <> Club)
If (p^.TenCLB > Club) Then p:= p^.L Else p:= p^.R; If (p = Nil) Then Write (“Khơng có Câu lạc này”)
Else
Begin
R:= p^.First;
While (r<> Nil) and (r^.SoAo <> m) r:= r^.Next; If (r=Nil) Then Write(“Khơng có nút chứa số áo này!”)
Else
Begin
If (r=p^.First) Then p^.First:= r^.Next Else
Begin
q:= p^.First;
While (q^.Next <> r) q:= q^.Next; q^.Next:= r^.Next;
End; Dispose(r); End;
End; End;
d Viết hàm Function TuoiMin(Club: st25): byte cho biết tuổi cầu thủ trẻ câu lạc có tên Club {Tìm giá trị nút}
Function TuoiMin(Club: st25): byte; Var k: byte;
Begin p:= Top;
While (p<> Nil) and (p^.TenCLB <> Club)
If (p^.TenCLB > Club) Then p:= p^.L Else p:= p^.R; If (p = Nil) Then Write (“Khơng có Câu lạc này”)
Else
Begin
r:= p^.First;
If (r=Nil) Then Write (“Câu lạc khơng có cầu thủ nào!”) Else
Begin
k:= r^.Tuoi; r:= r^.Next;
While (r<> Nil) Begin
If (r^.Tuoi < k) Then k:= r^.Tuoi; R:= r^.Next;
End; TuoiMin:= k; End;
End; End;
- Nếu tình tìm tên s cầu thủ có tuổi < I { Phải tìm nút có điều kiện }
- Nếu Câu lạc chưa có => phải bổ sung thêm câu lạc cầu thủ nút câu lạc
Bài 1: (Đề 2003) Type Link= ^Node; Node = Record
Key: Integer; Next: Link; End;
Var i, M,N: integer; t, x: Link; Begin
(6)New(t); t^.key:= 1; x:= t; For i:= to N
Begin New(t^.Next); T:= t^.Next; T^.Key:= i; End; t^.Next:= x;
While (t<> t^.Next) Do Begin
For i:= to M-1 Do t:= t^.Next; Write(t^.Next^.Key);
x:= x^.Next;
t^.Next:= t^.Next^.Next; Dispose(x);
End; Writeln(t^.Key); End
a Cho biết kết với N=5; M= 3;
Kết quả: 3, 1, 5, 2,
b Chương trình thực cơng việc gì?
Đầu tiên tạo danh sách nối vòng gồm n nút, chứa dãy số 1,2,3,…,n Và có nút trỏ x, nút cuối trỏ t
Nếu chừng t <> t^.next đồng nghĩa với danh sách có nút (từ nút trở lên)
nó thực hiện:
- Chuyển t sang quản lí nút sau t M-1 vị trí - Sau viết giá trị key nút sau t - Loại bỏ nút sau t
Cuối viết giá trị nút trỏ t hình
Bài 3: (Đề thi 1996A)
Trong hệ soạn thảo văn soạn lưu nhớ dạng danh sách nối kép sau:
1 1 1 1 1
(7)Khai báo danh sách (Đầu, Cuối) sau: Type str80 = string[80];
Tro = ^DongVB; DongVB = Record
Truoc: Tro; Dong: Str80; Sau: Tro; End;
Var Dau, Cuoi: Tro; {Dau = Nil văn rỗng} a Viết thủ tục dạng
Procedure Xemtruoc(Var d: Tro; p: Tro; S: str80);
Cho phép xen dòng với nội dung cho s vào trước phần trỏ p danh sách có đầu d
Giải:
// Trong thủ tục cần thêm c cuối danh sách để thủ tục hoàn chỉnh Procedure Xemtruoc(Var c,d: Tro; p: Tro; s: str80); Var r: Tro;
Begin
New®; r^.dong:= s;
r^.Truoc:= Nil; r^.Sau:= Nil; If (d= Nil) Then
Begin d:= r; c:= r;
End Else
If (p = d) Then Begin
r^.Sau:= p; p^.Truoc:= r; d:= r;
End Else
Begin
r^.Truoc:= p^.Truoc; r^.Sau:= p;
p^.Truoc^.Sau:= r; p^.Truoc:= r; End;
End;
c Gọi Blốc(db,cb) khối liền dòng kể từ dòng trỏ db đến dòng cb Hãy viết thủ tục chuyển dời Blốc(dc,cb) tới trước dòng trỏ Noiden danh sách (d,c) Giả sử nơi đến không Blốc
Giải:
Procedure ChuyenBL(Var d,c: Tro; db, cb, Noiden: Tro);
// Nơi đến có trường hợp: đến đầu văn văn
// Khi xây dựng thủ tục cần ý đến trường hợp đặc biệt sau: Trong Blốc có chứa dịng // trỏ đầu thay đổi
// Trong Blốc có chứa dòng cuối => trỏ cuối thay đổi
// Trong Blốc khơng chứa dịng dòng cuối Noiden: dòng địa //chỉ đầu thay đổi
// Nơi đến: khơng phải dịng địa đầu không thay đổi Var
Begin
If (db= d) then Begin
dd:= d; // Con trỏ dd quản lí đầu block, block dịng đầu văn d:= cb^.Sau; //trở thành dòng
cb^.sau:= Nil; d^.Truoc:= Nil;
(8)cb^.Sau:= Noiden; Noiden^.Truoc:= cb; End
Else
Begin
db^.Truoc^.Sau:= cb^.Sau; cb^.Sau^.Truoc:= db^.Truoc; db^.Truoc:= Nil;
cb^.Sau:= Nil; End;
/* Ba trường hợp nằm chung nhiệm vụ cắt Block khỏi danh sách chứa văn Nhiệm vụ sau chèn Block vào trước dòng nơi đến */
Noiden^.Truoc^.Sau:= db; Db^.Truoc:= Noiden^.Truoc; Cb^.Sau:= Noiden;
Noiden^.Truoc:= cb;
c Viết thủ tục cho phép chép (mà không hủy) Block tới trước dòng trỏ Noiden danh sách đầu trỏ d Giả sử Noiden không Block
Giải:
Procedure ChepBL(Var d: Tro; db, cb, Noiden: Tro); /* Đối với thủ tục ta cần giải công việc sau:
+ Tạo danh sách độc lập ds,cs quản lí nút đầu cuối danh sách để chép nội dung Block:
- Chèn ds, cs vào trước dòng trỏ nơi đến */ Var
Begin
ds:= Nil; // Danh sách rỗng cs:= Nil;
// Trường hợp dừng p=Nil p^.Truoc = cb While (p <> Nil) and (p^.Truoc <> cb)
Begin
New(r); r^.dong:= p^.dong; r^.Truoc:= Nil;
r^.sau:= Nil; If (ds = Nil) Then
Begin
ds:= r; cs:= r;
End
Else begin
r^.Truoc:= cs; cs^.Truoc:= r; cs:= r;
End;
p:= p^.Sau; End;
// Chèn danh sách ds, cs vào trước nơi đến If (Noiden = d) then
Begin
cs^.Sau:= d; d^.Truoc:= cs; d:= ds;
End
Else Begin
Noiden^.Truoc^.Sau:= ds; //Noiden dịng văn
Ds^.Truoc:= Noiden^.Truoc; Cs^.Sau:= Noiden;
Noiden^.Truoc:= cs; ds
(9)End; End;
Đề 1997:
Bài 3: Kết thi đại học lớp lưu lại danh sách tuyến tính móc nối nút khai báo sau:
Type Tro = ^Nut; Nut = Record
Sohieu: integer; Tin: Alpha;
Toan, Ly, Hoa: Real; Tiep: Tro;
End;
Đầu danh sách trỏ biến Dau Var dau: Tro;
Hãy viết chương trình
1 Procedure Nhap(Var Dau: Tro; sh: Integer; Name: Alpha; t,l, h: real) cho phép nhập số hiệu sh, tên học sinh name điểm tốn, lý, hóa cho t, l, h tương ứng với nút đặt cuối danh sách lớp cho trỏ dau
Giải:
Procedure Nhap(Var Dau: Tro; sh: Integer; Name: Alpha; t,l, h: real) Var hs: Tro;
Begin
//Bổ sung nút vào cuối danh sách New(hs);
Hs^.sohieu:= sh; Hs^.ten:= Name; Hs^.Toan:= t; Hs^.Ly:= l; Hs^.Hoa:= h; Hs^.Tiep:= Nil;
If dau = Nil then Dau:= hs Else
Begin P:= Dau;
While p^.Tiep <> Nil Do p:= p^.Tiep; P^.Tiep:= Hs;
End; End;
2 Procedure Ketqua(Dchuan: real; Dau: Tro; Var Do, Truot: Tro);
Cho phép thơng báo danh sách học sinh đỗ (có trường điểm Tốn, Lý, Hóa lớn điểm chuẩn Dchuan) Danh sách trỏ trỏ Do danh sách học sinh bị trượt trỏ trỏ Truot
Yêu cầu: Không chép lại phần tử danh sách lớp học sang vùng nhớ danh sách cho
Giải:
Ý tưởng:
+ Dùng biến trỏ p để duyệt danh sách trỏ Dau + Tại vị trí p ta làm:
- Cắt p khỏi danh sách Dau
- Xem nút p đỗ hay trượt Nếu đậu bổ sung vào sau danh sách Đỗ (trỏ trỏ Do) Nếu trượt bổ sung vào danh sách trượt (trỏ trỏ Truot)
(10)Procedure Ketqua(Dchuan: real; Dau: Tro; Var Do, Truot: Tro); Var p, r1,r2: Tro;
Begin
Do:= Nil; Truot: Nil; {2 danh sách rỗng chưa có nút nào} While (Dau <> Nil) Do
Begin
// Cắt p khỏi danh sách
P:= Dau;
Dau:= Dau^.Tiep; P^.Tiep:= Nil;
If (p^.Toan+ p^.Ly+p^.Hoa >= Dchuan) then //Nếu thi đậu
Begin
If (Do = Nil) Then Do:= p Else
r1^.Tiep:= p; r1:= p;
End Else
Begin
If (Truot = Nil) Then Truot:= p Else
r2^.Tiep:= p; r2:= p; End;
End; End;
Đề 1995 – B
Bài 1: Cho khai báo kiểu danh sách tuyến tính móc nối Type Tro = ^KieuPT;
KieuPT = Record
Giatri: Integer; Tiep: Tro;
End;
1. Cho Var ds, q: Tro; ds rtỏ tới đầu danh sách tuyến tính Hãy viết thư mục Procedure LayMax(Var ds, q: Tro)
cho phép lấy phần tử lớn khỏi danh sách ds, phần tử trỏ q Giải:
Procedure LayMax(Var ds, q: Tro) Var r: Tro;
Begin
q:= ds; r:= q^.Tiep; While (r <> Nil) Do
Begin
If (r^.Giatri > q^.Giatri) Then q:= r; r:= r^.Tiep;
End;
If (q = ds) then ds:= ds^.Tiep Else
Begin
r:= ds;
While r^.Tiep <> q r:= r^.Tiep; r^.Tiep:= q^.Tiep;
End; q^.Tiep:= Nil; End;
2 1 7 3
r = Nil r
ds
(11)2 Cho Var ds1, ds2: Tro;
Trong ds1, ds2 trỏ đầu danh sách tuyến tính chưa xếp theo trường Giatri cịn ds2 gán Nil Viết thủ tục:
Procedure Sapchon(Var ds1, ds2: Tro);
Cho phép chọn dần phần tử ds1 từ giá trị lớn đến bé, đưa vào ds2 để cuối ds1 = Nil ds2 trỏ tới danh sách tuyến tính gồm phần tử ds1, xếp theo thứ tự tăng dần trường Giatri
Giải:
Procedure Sapchon(Var ds1, ds2: Tro); Var
Begin
While (ds1 <> Nil) Do Begin
LayMax(ds1, q);
If ds2 = Nil Then ds2:= q
Else //Bổ sung q vào đầu danh sách d2 để theo thứ tự tăng dần
Begin
LayMax(ds, q); q^.Tiep:= ds2; ds2:= q;
End; End;
End; Đề 1997:
Bài 3: Cây nhị phân kiểu Min – Max có tổ chức sau:
- Mỗi nút chứa trường giá trị khóa, có kiểu liệu Integer; Type Nut = Record
Giatri : Integer; Kieu: Boolean; Trai, Phai: ^Nut; End;
TroNut = ^Nut; Quy ước:
Kiểu = T nút thuộc loại MAX
F nút thuộc loại MIN
a Viết thủ tục đệ quy để tính giá trị nút nhị phân trỏ trỏ gốc, dựa khóa nút
Function TinhGiaTri (Goc: TroNut): Integer; Function Min(a,b: Integer): Integer;
Function Max(a,b: Integer): Integer; Begin
If (Goc^.Trai = Nil) and (Goc^.Phai = Nil) Then TinhGiaTri:= Goc^.Giatri;
Else
If (Goc^.Kieu = T) Then //Nút có kiểu MAX 10
7 6 10 12
6 10
(12)TinhGiaTri:= Max(TinhGiaTri(Goc^.Trai), TinhGiaTri(Goc^.Phai))
Else
TinhGiaTri:= Min(TinhGiaTri(Goc^.Trai), TinhGiaTri(Goc^.Phai))
End;
Procedure TaoCayB(Goc: TroNut); Begin
If (Goc^.Trai = Nil) and (Goc^.Phai <> Nil) then Begin
Goc^.Giatri:= TinhGiaTri(Goc); TaoCayB(Goc^.Trai);
TaoCayB(Goc^.Phai); End;
End;
b Viết thủ tục tính giá trị trung bình giá trị Khóa nút Procedure TimTong(Var S, SoNut: Integer; Goc: TroNut); Begin
S:= S+ Goc^.Giatri; SoNut:= SoNut + 1;
If (Goc^.Trai <> Nil) and (Goc^.Phai <> Nil) Then Begin
TimTong(s, SoNut, Goc^.Trai); TimTong(s, SoNut, Goc^.Phai); End;
End;
Procedure TrungBinh(Goc: TroNut); Var S, SoNut: Integer; p: TroNut; Begin
S:= 0; SoNut:= 0; p:= Goc; TimTong(S, SoNut, p);
Write(“Trung bình là: “, S/SoNut); End;
Xây dựng phương án không đệ quy cho câu 1: + Duyệt theo thứ tự sau (Trái phải gốc)
+ Mỗi lần thăm nút: Tùy theo nút MIN hay MAX mà chọn giá trị cho nó, lấy trái phải(Nếu nút thăm nút lá)
Nhắc lại duyệt không đệ quy nhị phân: Duyệt trước: (Gốc – trái - Phải)
- Nộp Goc vào Stack - REPEAT
o Lấy nút p từ Stack o Thăm p
o Nếu có phải nạp vào Stack o Nếu p có trái nạp vào Stack UNTIL Stack rỗng
A C B
E
D F G
K H I
(13)A B D E K C F H I G
Duyệt giữa: (Trái - Gốc - Phải) + p:= Goc;
+ REPEAT
- Nộp p nhánh lệch trái vào Stack - Lấy p từ Stack
- Thăm p
- Chuyển p sang gốc phải p (có thể Nil) UNTIL (Stack rỗng) and (P = NIL)
Procedure DuyetGiua(Goc: TroNut) Var
Begin
//Khởi tạo Stack S = 0;
p:= Goc; Repeat
While (p<> Nil) Begin
Push(S, p); p:= p^.Trai; End;
p:= Pop(S);
Write(p^.GiaTri,” “); p:= p^.Phai;
Until (S =0) and (p = Nil); Return ;
End;
Duyệt sau: (Trái - Phải - Gốc) Procedure TaoCay(Goc: TroNut);
Type MangTro = Array[1 100] of Integer; Var S: MangTro; R: Mang;
N, TS, TR: Integer; P: TroNut;
Procedure SPUSH(S: MangTro; Var TS: Integer; P: TroNut); Begin
TS:= TS + 1; S[TS] := p; End;
Function SPOP(S: MangTro; Var TS: Integer): TroNut; Begin
TS:= TS -1 ; SPOP:= S[TS+1]; End;
Procedure RPUSH(R: Mang; Var TR: Integer; n: Integer); Begin
TR:= TR + 1; R[TR]:= n; End;
Function RPOP(S: Mang; Var TS: Integer): Integer; Begin
TR= TR-1 ;
RPOP:= R[TR + 1];
G I H
(14)End; BEGIN
TS:= 0; TR:= 0; p:= Goc; Repeat
While (p<> Nil) Begin
SPUSH(S, TS, p); RPUSH(R, TR, 1); p:= p^.Trai; End;
p:= SPOP(S, TS); n:= RPOP(R,TR);
If (n=1) and (p^.Phai <> Nil) then Begin
SPUSH(S, TS, p); RPUSH(R,TR,2); P:= p^.Phai; End;
Else
//Thăm nút tính giá trị Min, Max Begin
If (p^.Trai <> Nil) and (p^.Phai <> Nil) Then If (p^.Kieu = T) Then
p^.GiaTri:= Max(p^.Trai^.GiaTri, p^.Phai^.GiaTri)
Else
p^.GiaTri:= Min(p^.Trai^.GiaTri, p^.Phai^.GiaTri);
p:= Nil; End;
Until (TS =0) and (p = Nil); END;
Đề 1993:
Cho nhị phân với khai báo sau: Type Tro = ^Nut;
Nut = Record
Giatri: Integer; Trai, Phai: Tro; End;
Var T: Tro;
Hãy lập hàm Function Copy(T: Tro): Tro; cho phép chép với gốc trỏ T Function Copy(T: Tro): Tro;
Begin
If (T = Nil) Then Begin
New(p);
P^.GiaTri:= T^.GiaTri; P^.Trai:= Copy(T^.Trai); P^.Phai:= Copy(T^.Phai); Copy:= p;
End; End;
Bài 4:
Với nhị phân khai báo 3, ta tiến hành duyệt theo giải thuật không đệ quy theo sơ đồ sau, có danh sách tuyến tính để lưu (các trỏ tới) nút cần ghi nhớ
(15)Begin
- Lấy nút từ danh sách, gọi N - Thăm N (chẳng hạn in giá trị
- Nạp trỏ trái N vào danh sách (nếu có) - Nạp trỏ phải N vào danh sách (nếu có) End;
Giải thuật S (Dùng Stack) (lấy nút (nạp muộn nhất)) Giải thuật Q (dùng Queue) lấy nút cũ (nạp sớm nhất) a Hãy cho biết giải thuật S, Q duyệt theo thứ tự nào? Giải:
Giải thuật S:
Stack: Kết quả: Giải thuật Queue: Queue: Kết quả:
Duyệt ưu tiên theo mức, mức ưu tiên từ trái sang phải
b Từ gợi ý sơ đồ trên, viết thủ tục duyệt nhị phân theo thứ tự (gốc- trái – phải) Chú ý không phá hoại cho cố gắng loại động tác thừa Thăm nút thể in giá trị nút
Giải:
Gốc – Trái – Phải:
S: ->
Procedure PreOrder(Goc: Tro); Var p: Tro; TS: Integer;
Procedure PUSH(S: MangTro; Var TS: Integer; p: Tro); Function POP(S: MangTro; Var TS: Integer): Tro; Begin
TS:= 0; //Khởi tạo danh sách rỗng PUSH(S, TS, Goc);
While (TS >0) Begin
p:= POP(S, TS); Write(p^.Giatri);
If p^.Phai <> Nil Then PUSH(S, TS, p^.Phai); If p^.Trai <> Nil Then PUSH(S, TS, p^.Trai); End;
End;
ĐỀ IFI 09/96 Bài 3:
Người ta biểu diễn thông tin thư viện dạng nhị phân tìm kiếm với khóa TenTG (tên tác giả) Mỗi nút ghi gồm trường TenTG trường trỏ: trỏ Trai Phai trỏ tới nút trái phải Hai trỏ Dau va Cuoi trỏ tới phần tử đầu cuối danh sách tuyến tính móc nối dùng để ghi nhận sách có thư viện tác giả Mỗi phần tử danh sách ghi gồm có trường: Tensach Tieptheo Có thể hình dung:
1 3 2
5
4 6
7 8 9
(16)Người ta khai báo: Type Str25 = string[25];
Trosach = ^Record
Tensach: String; Tieptheo: TroSach; End;
TroTG = ^Tacgia; Tacgia = Record
Trai: TroTG; TenTG: str25; Dau, Cuoi: TroSach; Phai: TroTG; End;
Var Goc: TroTG;
a Hãy viết hàm Function Nut(Goc: TroTG; Ten: str25): TroTG; cho kết trỏ: - Bằng NIL Goc = Nil khơng thì:
- Trỏ tới nút có TenTG = Ten nút tồn tại, khơng thì:
- Trỏ tới nút Ten < TenTG Trai = Nil Trỏ tới nút Ten > TenTG Phai = Nil
Cây bên trái < bên phải tên xếp theo thứ tự Giải:
Function Nut(Goc: TroTG; Ten: str25): TroTG; Var p: TroTG;
Begin
If (Goc = Nil) Then Nut:= Nil Else
Begin
p:= Goc;
While ((Ten< p^.Tentg)and(p^.Trai <> Nil))or((Ten>p^.TenTG)and(p^.Phai<> Nil))
If (Ten < p^.TenTG) Then p:= p^.Trai Else p:= p^.Phai;
Nut:= p; End;
End;
b Hãy viết hàm cho ta địa (con trỏ kiểu TroTG) nút thành lập, chưa gắn vào cây, TenTG = Ten phần tử danh sách tương ứng TenSach = Tuade
Function NutMoi(Ten: str25; Tuade: string): TroTG; Var p: TroTG; r: TroSach;
Begin
New(p);
p^.TenTG:= Ten; p^.Trai:= Nil; p^.Phai:= Nil; New(r);
r^.TenSach:= Tuade; r^.Tieptheo:= Nil;
p^.Dau:= r; p^.Cuoi:= r; End;
c Hãy viết thủ tục cho phép bổ sung tên tác giả (Ten) với sách (Tuade) vào thư viện trỏ Goc theo cách sau:
- Nếu Ten TuaDe có thư viện khơng phải làm
Đầu
Trái Cuối Phải
x x p
Trái
(17)- Nếu Ten có Tuade chưa có bổ sung Tuade vào cuối danh sách tương ứng với nút có tên TenTG = Ten
- Nếu Ten TuaDe chưa có bổ sung nút vào thư viện, với TenTG = Ten TenSach = TuaDe
Giải:
Procedure Bosung(Var Goc: TroTG; Ten: str25; TuaDe: String); Var p: TroTG; r: TroSach;
Begin
p:= Nut(Goc, Ten);
If (p= Nil) Then Goc:= NutMoi(Ten, TuaDe) Else
If ((Ten < p^.TenTG) Then p^.Trai:= NutMoi(Ten, TuaDe) Else
If (Tem > p^.TenTG) Then p^.Phai:= NutMoi(Ten, TuaDe) Else
Begin
r:= p^.Dau;
While (r<> Nil) and (r^.TenSach<> TuaDe) Do r:= r^.TiepTheo;
If (r=Nil) Then Begin
New(r);
r^.TenSach:= TuaDe; r^.TiepTheo:= Nil;
If (p^.Dau = Nil) Then p^.Dau:= r Else
p^.Cuoi^.TiepTheo:= r; p^.Cuoi:= r;
End; End;
End; Đề 02/1998
Bài 2: Khai báo kiểu danh sách tuyến tính móc nối nhị phân sau: Type Tro = ^Ptu;
Ptu = Record
GiaTri: Integer; Tiep: Tro; End;
Pointer = ^Nut; Nut = Record
Value: Integer; Trai, Phai: Pointer; End;
Var ds: Tro;
Goc: Pointer;
Viết chương trình thực công việc sau:
1 Procedure Dungcay(ds:Tro; Var Goc: Pointer) nhằm xây dựng nhị phân tìm kiếm có gốc trỏ gốc sở phần tử danh sách ds cho Giả thiết phần tử danh sách có giá trị khác đơi
Ví dụ:
8 10
Ta xây dựng nhị phân tìm kiếm sau:
8
3 9
(18)Giải:
Procedure Dungcay(ds: Tro; Var Goc: Pointer); Var
Procedure BosungNut(Var Goc: Pointer; n: Integer); Var r, p: Pointer;
Begin
New(r);
r^.Value:= n;
r^.Trai:= nil; r^.Phai:= Nil; If (Goc = nil) Then Goc:= r Else
Begin
p:= Goc;
While ((p^.Value < n)and(p^.Phai <>Nil)) OR ((p^.Value > n) and (p^.Trai <> Nil)) Do
If p^.Value < n Then p:= p^.Phai Else p:= p^.Trai If (p^.Value < n) Then p^.Phai:= r Else p^.Trai:= r; End;
End; BEGIN
q:= ds;
While (q <> Nil) Do Begin
BosungNut(Goc, q^.Giatri); q:= q^.Tiep;
End; END:
2 Nhằm xây dựng nhị phân tìm kiếm có gốc trỏ Goc; tương ứng với hoán vị phần tử danh sách cho độ cao nhận nhỏ
Giải:
Procedure Cay_NP_Min(Ds: Tro; Var Goc: Pointer); /*
+ Đầu tiên xếp dãy theo thứ tự tăng dần
+ Xóa đệ quy: Lấy giá trị đưa vào gốc sau gọi đệ quy dựng trái với dãy phía trước dựng phải với dãy phía sau:
*/ Type
Mang = Array[1 1000] ò Integer; Var A: Mang; n: Integer;
Procedure DocRaMang(Var A: Mang; Var n: Integer; Ds: Tro); /*
Đọc dãy số từ danh sách lưu vào mảng A Số phần tử dãy lưu vào n Sau xếp thứ tự tăng dần mảng A
*/
Procedure Dung(A: Mang; Dau, Cuoi: Integer; Var Goc: Pointer); Var Giua: Integer;
Begin
New(Goc);
Giua:= (Dau+Cuoi) Div 2; Goc^.Giatri:= A[Giua]; Goc^.Trai:= Nil;
1 10
T1 T1
Cuối
(19)Goc^.Phai:= Nil;
If (Dau< Giua) Then Dung(A, Dau, Giua-1, Goc^.Trai); If (Giua <Cuoi) Then Dung(A, Giua + 1, Cuoi, Goc^.Phai); End;
BEGIN
DocRaMang(A, n, DS); Dung(A, 1, n, Goc); END; Bài 3: (Đề 1999-2000)
Cho khai báo nhị phân sau: Type Tro = ^Nut;
Nut = Record
GiaTri: Integer; Trai, Phai: Tro; End;
Var Goc: Tro;
Hãy lập chương trình thực cơng việc sau:
1 Hàm cho phép Kiểm tra xem có gốc trỏ trỏ gốc có phải nhị phân tìm kiếm hay khơng?
Chú ý: Cây rỗng coi tìm kiếm Viết theo phương án đệ quy không đệ quy Giải:
Đệ quy:
Function CayTK(Goc: Tro):Boolean; Begin
If ((Goc = Nil) Or ((Goc^.Trai = Nil) and (Goc^.Phai = Nil))) Then CayTK:= True
Else
Begin
If (Goc^.Trai = Nil) Then
If (Goc^.Giatri <Goc^.Phai^.Giatri) Then CayTK:= True
Else CayTK:= False Else
If (Goc^.Phai = Nil) Then
If (Goc^.Giatri > Goc^.Trai^.Giatri) Then CayTK:= True
Else CayTK:= False Else
CayTK:= CayTK(Goc^.Trai) and CayTK(Goc^.Phai) and
(Goc^.Giatri > Max(Goc^.Trai) and
(Goc^.Giatri < Min(Goc^.Phai) End;
End;
Function Max(Goc: Tro): Integer; Function Min(Goc: Tro): Integer;
Với giá trị trả hàm nút lớn nhỏ
2 Trường hợp ban đầu khơng phải tìm kiếm, viết thủ tục cho phép tráo đổi nội dung nút cây, không thay đổi cấu trúc cây, để nhận nhị phân tìm kiếm Giải:
Đọc vào mảng phải đọc theo thứ tự 8
7 6
4
3 1
9
4 8 3
6
1 9
7
3
1
(20)Procedure SapLai(Goc: Tro);
Type Mang = Array[1 100] of Integer; Var n: Integer;
Procedure DocVaoMang(Goc: Tro; Var A: Mang; Var n: Integer); // n phần tử đưa vào có số thứ tự n mang thông tin
Begin
If Goc <> Nil) Then Begin
DocVaoMang(Goc^.Trai, A, n); n:= n + 1;
A[n]:= Goc^.GiaTri;
DocVaoMang(Goc^.Phai, A, n); End;
End;
Procedure XepThuTuTrenMang(Var A: Mang; n: Integer); Procedure DuaVaoCay(Goc: Tro; A: Mang);
Var i: Integer; Begin
If (Goc <> Nil) Then Begin
DuaVaoCay(Goc^.Trai, A, i); Goc^.GiaTri:= A[i];
i:= i + 1;
DuaVaoCay(Goc^.Phai, A, i); End;
End; BEGIN
N:= 0;
DocVaoMang(Goc, A, n); XepThuTuTrenMang(A, n); N:= 1;
DuaVaoCay(Goc, A, n); END;
TỔNG KẾT:
* Đối với nhị phân nói chung có phương án duyệt đệ quy không đệ quy - Gốc Trái Phải
- Trái Gốc Phải - Trái Phải Gốc
Thăm gốc: Có nghĩa ta quản lí địa nút hay gốc ta làm việc với nút tùy toán cụ thể
Cây nhị phân tìm kiếm: - Có giải thuật bản:
+ Tìm kiếm nút thỏa mãn điều kiện (dù nút gì) cho nút có, khơng cho địa Nil
+ Tìm nút có giá trị Khóa cho trước, có cho địa nút đó, cịn khơng bổ sung vào nút cuối cho địa nút
+ Loại bỏ nút:
10 7 15
4
(21) p khơng có trái p có trái
Procedure LoaiBo(Var Goc: Tro; p: Tro); Begin
If (p=Goc) Then Begin
If (p^.Trai = Nil) Then Goc:= Goc^.Phai Else
Begin
r:= Goc^.Trai;
While r^.Phai <> Nil Do r:= r^.Phai R^.Phai:= Goc^.Phai;
Goc:= Goc^.Trai; End;
Dispose(p); End
Else // Khi gốc không trùng p
If (p^.GiaTri < Goc^.GiaTri) Then LoaiBo(Goc^.Trai, p) Else LoaiBo(Goc^.Phai, p);
End;
- Phải xác định trỏ quản lí p (trong nút đó) đóng vai trị quản lí gốc - Khi Goc = p: Có trái -> Loại bỏ gốc
Nếu khơng có -> Loại bỏ Khơng đệ quy:
+ Tìm nút q mà trỏ phải trái quản lí p: Procedure LoaiBo(Var Goc: Tro; p: Tro); Var q, r: Tro;
Begin
// Tìm nút q nhận p làm nút q:= Goc;
While (q^.Trai <> p) and (q^.Phai <> p) Do
If (q^.GiaTri <p^.GiaTri) Then q:= q^.Phai Else q:= q^.Trai; //Điều chỉnh lại trỏ
If (p^.Trai = Nil) Then
If q^.Trai = p Then q^.Trai:= p^.Phai Else q^.Phai:= p^.Phai Else
Begin
If (q^.Trai = p) Then q^.Trai:= p^.Trai Else q^.Phai:= p^.Trai;
//Nếu trỏ trái q = p -> Con trỏ trái q quản lí trỏ trái p ngược lại trỏ phải q quản lí trỏ trái p
r:= p^.Trai;
While (r^.Phai <> Nil) Do r:= r^.Phai; r^.Phai:= p^.Phai;
End; Dispose(p); End;
* Bổ sung thêm trường hợp p = Goc (p gốc) If (p= Goc) Then
If (p^.Trai = Nil) Then Goc:= p^.Phai Else
Begin
r:= p^.Trai;
While (r^.Phai <> Nil) Do r:= r^.Phai; r^.Phai:= Goc^.Phai;
Goc:= p^.Trai; End;
(22)ĐỀ IFI 1997: Bài 4:
Người ta biểu diễn biểu thức số học với toán tử +, -, *, / hai +, - Trong với tốn tử chứa nút biến chứa Chẳng hạn: (((a+b)*c)-(((-c)/d/e)) biểu diễn sau:
Viết khai báo nhị phân nói Giả sử với biến có giá trị cho trước Hãy viết chương trình cho phép từ thành lập nhớ trên, tính giá trị biểu thức toán học liên quan
Giải: Type
Str25 = String[25]; Tro = ^Nut; Nut = Record
Giatri: Str25; Trai, Phai: Tro End;
Function Value(S: Str25): Integer; Var k, n: Integer;
Begin
Val(S, n, k); //Đổi chuỗi S thành số n, thành công k =0, có lỗi k<>
Value:= n; End;
Function GTBT(Goc: Tro): Real; Begin
If (Goc^.Trai = Nil) and (Goc^.Phai =Nil) Then GTBT:= Value(Goc^.GiaTri)
Else
Case Goc^.GiaTri Of
“*”:
GTBT:= GTBT(Goc^.Trai) * GTBT(Goc^.Phai);
“/” :
GTBT:= GTBT(Goc^.Trai) / GTBT(Goc^.Phai);
“+”:
If (Goc^.Trai = Nil) Then GTBT:= GTBT(Goc^.Phai) Else
GTBT:= GTBT(Goc^.Trai) + GTBT(Goc^.Phai);
“-“ :
If (Goc^.Trai = Nil) Then
GTBT:= - GTBT(Goc^.Phai) Else
-* /
+ c e
a b
/
- d
(23)GTBT:= GTBT(Goc^.Trai) - GTBT(Goc^.Phai);
End; End;
2 Giả sử biểu thức số học với ngoặc đơn đầy đủ đọc sẵn vào biến lưu kiểu String Hãy viết chương trình thành lập biểu diễn biểu thức Cây lưu nhớ máy tính
Giải: Ý tưởng:
- Xác định toán tử với biểu thức nằm trước sau toán tử
- Tạo với gốc chứa tốn tử này, sau gọi đệ quy để tạo phải chứa biểu thức phía sau Nếu có biểu thức phía trước tạo trái chứa biểu thức
- Ngược lại tốn tử ngơi trái rỗng
Tình suy biến đệ quy: Khi xâu St khơng có dấu ngoặc (chỉ chứa biến) Procedure DungCay(Var Goc: Tro; St: String);
Var Begin
If (KiemTra(St)) Then
/* KiemTra(St) = T St khơng có dấu ngoặc
F St có chứa dấu ngoặc */ Begin
New(Goc);
Goc^.GiaTri:= St;
Goc^.Trai:= Nil; Goc^.Phai:= Nil; End
Else
Begin
If ((St[2] = “+”) or (St[2]= “-“)) Then Begin
New(Goc);
Goc^.GiaTri:= St[2];
Goc^.Trai:= Nil; //Vì biểu thức
Delete(St, 1, 2);
Delete(S, Length(St),1); DungCay(Goc^.Phai, St); End;
Else
Begin
n:= VitriToanTu(St); S1:= XauPhiaTruoc(St, n); S2:= XauPhiaSau(St, n); New(Goc);
Goc^.GiaTri:= St[n]; DungCay(Goc^.Trai, S1); DungCay(Goc^.Phai, S2); End;
End; End;
Function ViTriToanTu(St: String): Integer;
// Đếm vị trí tốn tử mà tốn tử tách biểu thức cho thành biểu thức trước //sau // Xác định xâu S1: For i:= to n -1
// Xác định xâu S2: For j:= n +1 to (length(S) -1) Do ĐỀ SỐ 2/1996
Bài 1:
Dãy Morse vô hạn xác định sau:
m = x0, x1, …, xn - Ban đầu: Viết phần tử x0 =
(24)n = n-1 , n-1 dãy n-1 xây dựng từ dãy n-1 cách thay thành 1, thay thành
0 = 0; 1 = ,1 2 = 0, 1, 1,
1 Viết hàm đệ quy xây dựng giá trị phần tử thứ k dãy Morse Ví dụ; k = 0: x0 = 0;
k = 7; x7 = 1; …
Giải:
Suy biến đệ quy: k = 0; Nếu k >
0 = x5 phủ định x1 = 1; = x1 phủ định x0 = 0;
Function Phudinh(a: Integer): Integer; Begin
If (a = 0) Then PhuDinh:= Else
Begin
S:= 1;
// Số lượng phần tử k chạy từ Ví dụ k =6 -> có phần tử
While S < k+1 Do Begin
S:= S*2; M:= S div 2; End;
Xacdinh:= PhuDinh(Xacdinh(k-m)); End;
End;
2 Đưa phương án không dùng đệ quy: Giải:
Function Xacdinh(k: Integer): Integer; Var kk, i, Dem, a, m, S: Integer; Begin
kk:= k; Dem:= 0; While (kk > 0) Do
Begin
S:= 1;
While S < kk + Do S:= S*2; M:= S div 2;
Kk:= kk – m; Dem:= Dem + 1; End;
A:= 0;
For i:= to Dem Do a:= PhuDinh(a); Xacdinh:= a;
End;
Nếu không sử dụng (1) ta phải bỏ (3) (2) thay a:= Phudinh(a), thêm phép gán a:= 0; từ đầu
ĐỀ NĂM 1998 Bài 2:
Khai báo kiểu danh sách tuyến tính móc nối sau: Type Tro=^Nut;
Nut = Record
(25)End; Var ds: Tro;
Viết chương trình thực công việc sau:
1 Function Doixung(ds: Tro): Boolean; nhằm kiểm tra xem danh sách ds có phải đối xứng hay không? Viết hai phương án lặp đệ quy
Đệ quy:
- Suy biến đệ quy: Danh sách rỗng -> Đối xứng
Danh sách có nút -> Đối xứng Function Doixung(ds: Tro): Boolean;
Var Begin
//Xét suy biến đệ quy
If (ds = Nil) or (ds^.Tiep = Nil) Then Doixung:= True Else
Begin
d:= ds; r:= ds; c:= r^.Tiep;
While c^.Tiep <> Nil Do Begin
r:= c;
c:= c^.Tiep; End;
If (d^.GiaTri <> c^.GiaTri) Then DoiXung:= False Else
Begin
r^.Tiep:= Nil;
Doixung:= Doixung(ds^.Tiep); End;
End; End;
Phương án lặp:
Function Doixung(Ds: Tro): Boolean; Var d, c, r: Tro; OK: Boolean; Begin
OK:= True; d:= Ds;
While ((d <> Nil) and (d^.Tiep <> Nil) and OK ) Do Begin
r:= d; c:= r^.Tiep;
While (c^.Tiep <> Nil) Do Begin
R:= c;
C:= c^.Tiep; End;
If (d^.Giatri <> c^.GiaTri) Then OK:= False Else
Begin
r^.Tiep:= Nil; d:= d^.Tiep; End;
End;
(26)2 Xây dựng hàm Function KiemTra_DX(ds: Tro): Boolean; nhằm kiểm tra xem danh sách ds cho, có tồn cách xếp lại phần tử để cuối nhận danh sách đối xứng hay không? Viết phương án đệ quy lặp
Giải:
- Quản lí nút Tìm danh sách có nút chứa số giống - Nếu có: Loại cặp nút Lặp lại
(27)ĐỀ 2006:
Type TroNut =^Nut;
Nut = Record
GiaTri: Integer;
Left, Right: TroNut; End;
Var T: Tro;
a.Tính chiều cao
Function ChieuCao(T: TroNut): Byte; Begin
If (T = Nil) Then ChieuCao:= Else
ChieuCao:= Max(ChieuCao(T^.Left), ChieuCao(T^.Right)) + 1; End;
b
Type TroNutDS = ^NutDS; NutDS = Record
GiaTri: Integer;
Muc: Byte; {lưu mức tương ứng} Next: TroNutDS;
End; Var F: TroNutDS;
Procedure Ghi(T: TroNut; Var F: TroNutDS; Level: Byte); Var
Begin
If (T <> Nil) Then Begin
New(p); p^.GiaTri:= T^.GiaTri; P^.Muc:= level;
P^.Next: = F; F:= p;
Ghi(T^.Left, F, Level + 1); Ghi(T^.Right, F, Level + 1); End;
End;
c Viết hàm đếm số nút DemSoNut(F: TroNutDS; Level: Byte): Integer; Function DemSoNut(F: TroNutDS; Level: Byte): Integer; Var p: TroNutDS; Dem: Integer;
Begin
p:= F;
While (p<> Nil) Begin
If (p^.Muc = level) Then Dem:= Dem + 1; P:= p^.Next;
End; DemSoNut:= Dem; End;
d Kiểm tra xem có phải nhị phân đầy đủ: Function LaCayNPDD(T: TroNut): Boolean;
Var Begin
H:= ChieuCao(T); SoNut:= 1;
For i:= to h –
SoNut:= SoNut*2; // Số nút tối đa mức Ghi(T, F, 1);
If (SoNut = DemSoNut(F,h) Then LaCayNPDD:= True Else
(28)/* Bai tap 3_52 - In bieu thuc dang hau to cua mot bieu thuc trung to */ #include <stdio.h>
#include <conio.h> #define MAX 100
#define PLUS /* Dau cong */ #define MINUS /* Dau tru */ #define MULTIPLE /* Dau nhan */ #define DIVIDE /* Dau chia */
#define LPAREN /* Dau mo ngoac don */ #define RPAREN /* Dau dong ngoac don */ int top;
struct { int toantu; } stack[MAX]; void push (int tt) {
if (top < MAX-1)
stack[++top].toantu = tt; }
int isempty() {
return top == -1; }
int pop (int *tt) {
if (!isempty()) {
*tt = stack[top ].toantu; return 1;
}
return 0; }
int get (int *tt) {
if (!isempty()) {
*tt = stack[top].toantu; return 1;
}
return 0; }
void xet(int tt) {
char chuoi[] = "+-*/";
int uutien[] = {0,0,1,1,-1,-1}; int toantu, done = 0, val; if (isempty())
push(tt); else
{ {
if (get(&toantu)) {
(29){
pop(&toantu);
printf("%c ", chuoi[toantu]); }
else {
push(tt); done = 1; }
} else {
done = 1; push(tt); }
} while (!done); }
}
void in_hauto(char *expr) {
int len, i=0, ttu, done; char c, chuoi[]="+-*/"; top = -1;
len = strlen(expr); {
c = expr[i++];
while (c == ' ' && i < len-1) c = expr[i++];
switch (c) {
case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' :
case '9' : printf("%c ", c); break; case '+' : xet(PLUS); break;
case '-' : xet(MINUS); break; case '*' : xet(MULTIPLE); break; case '/' : xet(DIVIDE); break; case '(' : push(LPAREN); break; case ')' : done = 0;
{
if (isempty()) {
done = 1;
printf("\n\nError\n"); }
else {
pop(&ttu);
if (ttu != LPAREN)
printf("%c ", chuoi[ttu]); else
done = 1; }
} while (!done); break;
(30)} while (i < len); while (!isempty()) {
pop(&ttu);
printf("%c ", chuoi[ttu]); }
}
void main() {
char expr[50]; int done = 0;
printf("\nChuong trinh in bieu thuc hau to tuong ung voi mot bieu thuc" "trung to hop le"
"\nChu y :"
"\nCac toan hang chi tu den 9"
"\nCac toan tu chi gom + - * / ( )\n"); {
printf("\nNhap mot bieu thuc trung to hop le (trong de thoat): "); gets(expr);
if (strlen(expr) > 0) in_hauto(expr); else
done = 1; } while (!done); }
//Dem tong so nut la cua cay #include <stdio.h>
#include <alloc.h>
typedef int element_type; typedef struct node { element_type element; struct node *left, *right; } NODE;
NODE *root;
void khoi_tao_cay(NODE ** root) {
*root = NULL; }
void insert(NODE *tmp, NODE **root) {
if (tmp->element < (*root)->element) if ((*root)->left)
insert(tmp, &(*root)->left); else
(*root)->left = tmp; else
if ((*root)->right)
insert(tmp, &(*root)->right); else
(*root)->right = tmp; }
void insert_node(element_type e, NODE **root) {
(31)tmp = (NODE *)malloc(sizeof(NODE)); tmp->element = e;
tmp->left = NULL; tmp->right = NULL; if (*root == NULL) *root = tmp; else
insert(tmp, root); }
void nhap_cay(NODE **root) {
element_type e; {
printf("\nNhap element (-1 de ket thuc) : "); scanf("%d", &e);
if (e != -1)
insert_node(e, root); } while (e != -1);
}
int dem_nut_la(NODE *root) {
if (root == NULL) return 0;
else
if (root->left != NULL || root->right != NULL)
return dem_nut_la(root->left) + dem_nut_la(root->right); else
return 1; }
void main() {
int tong_nut_la; khoi_tao_cay(&root); nhap_cay(&root);
tong_nut_la = dem_nut_la(root);
printf("\nTong so nut la = %d", tong_nut_la); getch();
(32)Uses crt; Type
DS1 =^SN; SN = Record
info:integer; next:DS1; end;
DS2 =^TEN; TEN = Record
ten:string; dau:DS1; down:DS2; end;
Var
index:DS2; st,ten1:string; so:integer;
{****************************************************} Procedure Bosung(var index:ds2;so:integer;ten:string); Var p,q,tempo:DS2;
tam,tmp:DS1; Begin
new(tam); tam^.info:=so; tam^.next:=nil; p:=index;
while (p<>nil) and (p^.ten<ten) do begin
q:=p;
p:=p^.down; end;
if (p<>nil) and (p^.ten=ten) then begin
tmp:=p^.dau;
while tmp^.next<>nil do tmp:=tmp^.next; tmp^.next:=tam;
end else begin
new(tempo); tempộten:=ten; tempộdau:=tam; if p=index then begin
tempộdown:=index; index:=tempo;
end else begin
tempộdown:=p; q^.down:=tempo; end;
end; end;
{***********************************************} Procedure Inbang(index:ds2);
var p:ds2;tam:ds1; aa: string[10]; begin
writeln;
(33)while p<>nil do begin
write(' ',p^.ten,' ':35-length(p^.ten)); tam:=p^.dau;
while tam<>nil do begin
str(tam^.info,aa);
write(tam^.info,' ': 5- length(aa)); tam:=tam^.next;
end;
p:=p^.down; writeln; end;
end;
(* - *) //Xoá tên học viên danh sách
Procedure Xoaten(var index: ds2;st: string); Var p,q: ds2;
Begin
p:= index;
While (p<> nil)and(p^.ten< st) do Begin
q:= p;
p:= p^.down; end;
If p = nil then Writeln('Khong co ten danh sach') else
if p= index then index:= index^.down else
q^.down:= p^.down; end;
(* - *) Procedure Xoa(var index: ds2; st: string;so: integer);
Var tam,p1: ds1; p,q: ds2; Begin
p:= index;
While (p <> nil) and (p^.ten < st ) do Begin
q:= p;
p:= p^.down; end;
If p = nil then Writeln('Khong co ten danh sach') else
begin
tam:= p^.dau;
While (tam <> nil)and( tam^.info <> so) do Begin
p1:= tam;
tam:= tam^.next; end;
If tam = nil then writeln('Khong co so trang ten nay') else
if tam= p^.dau then p^.dau:= p^.dau^.next else
p1^.next:= tam^.next; end;
end;
(34)Procedure Sapxep(var index: ds2); Var p1,q1: ds1;
tam: integer; p: ds2;
Begin
p:= index;
While p<> nil do Begin
p1:= p^.dau;
While p1^.next <> nil do Begin
q1:= p1^.next; While q1 <> nil do
Begin
If p1^.info > q1^.info then Begin
tam:= p1^.info; p1^.info:= q1^.info; q1^.info:= tam; end;
q1:= q1^.next; end;
p1:= p1^.next; end;
p:= p^.down; end;
end;
(* -*) { Thu tuc dem xem co bao nhieu trang xuat hien cua ten: '}
Procedure Demst(var index: ds2); Var dem: byte;
p,q: ds2; p1: ds1; Begin
Writeln(' TEN SO LAN XUAT HIEN '); p:= index;
While p<> nil do Begin
p1:= p^.dau; Dem:= 1;
While p1^.next <> nil do Begin
dem:= dem+ 1; p1:= p1^.next; end;
Writeln(' ', p^.ten,' ':35-length(p^.ten),dem); p:= p^.down;
end; end;
BEGIN {CHUONG TRINH CHINH} Repeat
write('Nhap ten :');readln(st); if st<>'' then
begin repeat
write('Nhap so trang :');readln(so); if so>0 then bosung(index,so,st); until so<=0;
end; until st='';