1. Trang chủ
  2. » Giáo án - Bài giảng

de va dap an de thi cao hoc mon ct du lieu

34 25 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 34
Dung lượng 86,54 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

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]

Trang 1

DANH SÁCH MÓC NỐI

Biến động (Nút)

Cấu trúc cây nhị phân:

Đối với cây có ba phép duyệt:

2 Cây nhị phân tìm kiếm:

Là cây nhị phân chứa dãy khóa thỏa mãn điều kiện tại mỗi cây con thì khóa ở gốc lớn hơn khóa tại cácnút của cây con trái của nó và nhỏ hơn khóa tại các nút của cây con phải của nó

Ví dụ:

Nhận xét:

Duyệt cây theo phương án: Trái – Gốc – Phải : 5 9 11 15 16 17 19 25 cho dãy khóa theo thứ tự tăngdần Như vậy việc tìm kiếm nút chứa khóa k Nếu tìm có thì cho ra địa chỉ nút đó, nếu không thì cho rađịa chỉ NULL

Function Timnut(T: Tro; K: Integer): Tro;

Var p: Tro;

Begin

P:= T;

While (p<> Nil) and (p^.Giatri <> k) do

If (p^.Giatri < k then p:= p^.Phai

F D

17 5

Trang 2

Else

Timnut:= Timnut(T^.Trai, k);

End;

2.1 Bổ sung thêm khóa K vào cây T (nếu chưa có nút nào chứa K):

Procedure Bosung(T: Tro; K: Integer);

Var p,r : Tro; OK: Boolean;

If (p^.Phai <> NIL) Then p:= p^.Phai else OK:= False

If (p^.Giatri = k) Then Write(“Gia tri nay da ton tai”)

4 trường: TenCLB và 3 trường con trỏ Left, Right, First Hai con trỏ Left và Right lần lượt trỏ tới 2

nút con trái và con phải của nút đó Con trỏ First trỏ bởi phần tử đầu của một danh sách liên kết đơnchứa thông tin các cầu thủ thuộc câu lạc bộ (danh sách này có ít nhất 11 phần tử) Mỗi phần tử condanh sách này là một bản ghi gồm 4 trường: TenCT (Tên cầu thủ), SoAo (số áo), Tuoi (tuổi), và Next(lưu địa chỉ của phần tử tiếp theo trong danh sách) Danh sách này được sắp theo thứ tự tăng dần củaSoAo Người ta cho khai báo cấu trúc dữ liệu nói trên như sau:

x

Trang 3

a Viết thủ tục in danh sách các cầu thủ trong câu lạc bộ có tên club.

Procedure List(Club: st25);

Var P: TroCLB; r: TroCT;

Begin

P:= Top;

While (p<> Nil) and (p^.TenCLB <> Club) do

If (p^.TenCLB > Club) Then p:= p^.L else p:= p^.R;

If p= Nil Then Write(“Không có câu lạc bộ này”)

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) do

If (p^.TenCLB > Club) Then p:= p^.L Else p:= p^.R;

If (p = Nil) Then Write (“Không có Câu lạc bộ này”)

While (r^.Next <> Nil) and ((r^.Next)^.SoAo <= m ) do r:=r^.Next;

If r^.SoAo = m then Write (“Đã có”)Else

Begin New(q);

Trang 4

End;

Trang 5

c Xóa tên cầu thủ mang số áo m trong câu lạc bộ Club.

Procedure Xoa(Club: st25; m: byte);

Begin

p:= Top;

While (p<> Nil) and (p^.TenCLB <> Club) do

If (p^.TenCLB > Club) Then p:= p^.L Else p:= p^.R;

If (p = Nil) Then Write (“Không có Câu lạc bộ này”)

Else

Begin

R:= p^.First;

While (r<> Nil) and (r^.SoAo <> m) do r:= r^.Next;

If (r=Nil) Then Write(“Không có nút chứa số áo này!”)Else

While (p<> Nil) and (p^.TenCLB <> Club) do

If (p^.TenCLB > Club) Then p:= p^.L Else p:= p^.R;

If (p = Nil) Then Write (“Không có Câu lạc bộ này”)

If (r^.Tuoi < k) Then k:= r^.Tuoi;

- Nếu trong tình huống tìm tên s của cầu thủ có tuổi < I { Phải tìm nút có điều kiện }

- Nếu Câu lạc bộ chưa có trong cây => phải bổ sung thêm câu lạc bộ và cầu thủ sẽ là nút đầu tiên củacâu lạc bộ

Trang 6

b Chương trình trên thực hiện công việc gì?

 Đầu tiên tạo một danh sách nối vòng gồm n nút, lần lượt chứa dãy số 1,2,3,…,n

 Và có nút đầu tiên trỏ bởi x, nút cuối cùng trỏ bởi t

 Nếu như chừng nào t <> t^.next đồng nghĩa với danh sách có hơn một nút (từ 2 nút trở lên) thì

nó sẽ 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 của nút sau t.

- Loại bỏ nút sau t

 Cuối cùng viết giá trị của nút trỏ bởi t ra màn hình

Bài 3: (Đề thi 1996A)

Trong một hệ soạn thảo văn bản đang soạn được lưu ở bộ nhớ trong dưới dạng một danh sách nối képnhư sau:

t x

Trang 7

Khai báo của danh sách (Đầu, Cuối) như sau:

Procedure Xemtruoc(Var d: Tro; p: Tro; S: str80);

Cho phép xen một dòng mới với nội dung cho bởi s vào trước phần được trỏ bởi p trong danh sách có đầu d

Giải:

// Trong thủ tục này cần thêm c là cuối danh sách để thủ tục hoàn chỉnh hơn

Procedure Xemtruoc(Var c,d: Tro; p: Tro; s: str80);

c:= r;

End Else

Giải:

Procedure ChuyenBL(Var d,c: Tro; db, cb, Noiden: Tro);

// Nơi đến có 2 trường hợp: chỉ đến đầu văn bản hoặc giữa của văn bản

// Khi xây dựng thủ tục cần chú ý đến các trường hợp đặc biệt sau: Trong Blốc có chứa dòng // đầu tiên khi đó con trỏ đầu sẽ thay đổi

// Trong Blốc có chứa dòng cuối cùng => con trỏ cuối sẽ thay đổi

// Trong Blốc không chứa dòng đầu tiên và dòng cuối cùng Noiden: là dòng đầu tiên thì địa //chỉ của đầu sẽ thay đổi

// Nơi đến: không phải dòng đầu tiên thì địa chỉ của đầu không thay đổi

cb^.sau:= Nil; d^.Truoc:= Nil;

Noiden^.Truoc^.Sau:= dd; // Móc block vào trước noiden

dd^.Truoc:= Noiden^.Truoc;

Trang 8

Procedure ChepBL(Var d: Tro; db, cb, Noiden: Tro);

/* Đối với thủ tục này ta cần giải quyết các công việc sau:

+ Tạo một danh sách độc lập ds,cs quản lí nút đầu và cuối của danh sách để sao chép nội dung của Block:

- Chèn ds, cs vào trước dòng trỏ bởi nơi đến */

Var

Begin

ds:= Nil; // Danh sách rỗng

cs:= Nil;

// Trường hợp dừng sẽ là p=Nil và p^.Truoc = cb

While (p <> Nil) and (p^.Truoc <> cb) do

Trang 9

Đầu của danh sách được trỏ bởi biến Dau

Var dau: Tro;

Hãy viết chương trình con

1 Procedure Nhap(Var Dau: Tro; sh: Integer; Name: Alpha; t,l, h: real) cho phép nhập số hiệu sh, têncủa học sinh là name và các điểm toán, lý, hóa được cho bởi t, l, h tương ứng với một nút mới sẽ đặt ởcuối danh sách của lớp được cho bởi con trỏ dau

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 Toán, Lý, Hóa lớn hơn hoặc bằng điểmchuẩn Dchuan) Danh sách này được trỏ bởi con trỏ Do và danh sách các học sinh bị trượt được trỏ bởicon trỏ Truot

Yêu cầu: Không chép lại các phần tử của danh sách lớp học sang một vùng nhớ ngoài danh sách đãcho

Giải:

Ý tưởng:

+ Dùng một biến con trỏ p để duyệt danh sách trỏ bởi Dau

+ Tại mỗi vị trí của p ta làm:

- Cắt p khỏi danh sách Dau.

- Xem nút p đỗ hay trượt Nếu đậu thì bổ sung vào sau danh sách Đỗ (trỏ bởi con trỏ Do) Nếu trượt

thì bổ sung vào danh sách trượt (trỏ bởi con trỏ Truot)

(Luôn dùng con trỏ phụ là tốt nhất: dùng r1 để quản lí cuối danh sách Do và r2 để quản lí nút cuối danh sách Truot)

Trang 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 này rỗng chưa có nút nào}

While (Dau <> Nil) Do

Bài 1: Cho khai báo kiểu của một 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; trong đó ds rtỏ tới đầu của một 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 nhất ra khỏi danh sách ds, phần tử đó sẽ được trỏ bởi q

q p

Trang 11

2 Cho Var ds1, ds2: Tro;

Trong đó ds1, ds2 trỏ đầu của một danh sách tuyến tính chưa được sắp xếp theo trường Giatri còn ds2

thì được gán bằng Nil Viết thủ tục:

Procedure Sapchon(Var ds1, ds2: Tro);

Cho phép chọn dần các phần tử trong ds1 từ giá trị lớn đến bé, đưa vào ds2

để cuối cùng ds1 = Nil còn ds2 trỏ tới một danh sách tuyến tính gồm mọi phần tử của ds1, nhưng đã được sắp xếp theo thứ tự tăng dần của trường Giatri

Bài 3: Cây nhị phân kiểu Min – Max có tổ chức như sau:

- Mỗi nút chứa một trường giá trị khóa, có kiểu dữ liệu Integer;

Type Nut = Record

Kiểu = T nếu nút thuộc loại MAX

F nếu nút thuộc loại MIN

a Viết thủ tục đệ quy để tính giá trị của các nút của cây nhị phân được trỏ bởi con trỏ gốc, dựa trênkhóa của nút lá

Function TinhGiaTri (Goc: TroNut): Integer;

Function Min(a,b: Integer): Integer;

Function Max(a,b: Integer): Integer;

Trang 12

TinhGiaTri:= Max(TinhGiaTri(Goc^.Trai), TinhGiaTri(Goc^.Phai))

Else

TinhGiaTri:= Min(TinhGiaTri(Goc^.Trai), TinhGiaTri(Goc^.Phai))

b Viết thủ tục tính giá trị trung bình của các giá trị Khóa của nút trong cây

Procedure TimTong(Var S, SoNut: Integer; Goc: TroNut);

TimTong(s, SoNut, Goc^.Trai);

TimTong(s, SoNut, Goc^.Phai);

End;

End;

Procedure TrungBinh(Goc: TroNut);

Var S, SoNut: Integer; p: TroNut;

Xây dựng phương án không đệ quy cho câu 1:

+ Duyệt cây theo thứ tự sau (Trái phải gốc)

+ Mỗi lần thăm nút: Tùy theo nút đó là MIN hay MAX mà chọn giá trị cho nó, lấy cây con trái hoặcphải(Nếu nút được thăm không phải là nút lá)

Nhắc lại duyệt không đệ quy của cây nhị phân:

Duyệt trước: (Gốc – trái - Phải)

- Nộp Goc vào Stack

- REPEAT

o Lấy một nút p từ Stack

o Thăm p

o Nếu có con phải thì nạp vào Stack

o Nếu p có con trái thì nạp vào Stack

UNTIL Stack rỗng

A C B

E

HIFGDKEBCA

Trang 13

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;

Trang 14

p^.GiaTri:= Min(p^.Trai^.GiaTri, p^.Phai^.GiaTri);

Cho cây nhị phân với khai báo như sau:

Type Tro = ^Nut;

Hãy lập hàm Function Copy(T: Tro): Tro; cho phép sao chép cây với gốc trỏ bởi T

Function Copy(T: Tro): Tro;

Nạp (con trỏ) gốc vào danh sách

While Danh sách không rỗng Do

Trang 15

- Lấy một nút từ danh sách, gọi đó là N

- Thăm N (chẳng hạn in giá trị của nó

- Nạp con trỏ trái của N vào danh sách (nếu có)

- Nạp con trỏ phải của N vào danh sách (nếu có)End;

Giải thuật S (Dùng Stack) (lấy nút mới nhất (nạp muộn nhất))

Giải thuật Q (dùng Queue) lấy nút cũ nhất (nạp sớm nhất)

a Hãy cho biết các giải thuật S, Q duyệt cây theo thứ tự nào?

Duyệt ưu tiên theo mức, cùng mức thì ưu tiên từ trái sang phải

b Từ sự gợi ý của sơ đồ trên, hãy viết 1 thủ tục duyệt cây nhị phân theo thứ tự (gốc- trái – phải) Chú

ý không được phá hoại cây đã cho và cố gắng loại các động tác thừa Thăm một nút được thể hiện bởi

in giá trị của nút đó ra

Giải:

Gốc – Trái – Phải:

S: 1 3 2 5 4 7 9 8 6 -> 1 2 4 7 5 8 9 3 6

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;

Write(p^.Giatri);

If p^.Phai <> Nil Then PUSH(S, TS, p^.Phai);

If p^.Trai <> Nil Then PUSH(S, TS, p^.Trai);

tử đầu và cuối của một danh sách tuyến tính móc nối dùng để ghi nhận các sách có trong thư viện củatác giả đó Mỗi phần tử của danh sách này một bản ghi gồm có 2 trường: Tensach và Tieptheo Có thểhình dung:

1 3 2

5

Trang 16

Người ta khai báo:

Var Goc: TroTG;

a Hãy viết một hàm Function Nut(Goc: TroTG; Ten: str25): TroTG; cho kết quả là một 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 một nút trong đó Ten < TenTG và Trai = Nil hoặc là Trỏ tới một nút trong đóTen > TenTG và Phai = Nil

Cây bên trái < cây bên phải vì tên được sắp xếp theo thứ tự

Function NutMoi(Ten: str25; Tuade: string): TroTG;

Var p: TroTG; r: TroSach;

Trang 17

- 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ó tênTenTG = Ten.

- Nếu Ten và TuaDe đều chưa có thì bổ sung một nút mới vào thư viện, với TenTG = Ten và TenSach

= TuaDe

Giải:

Procedure Bosung(Var Goc: TroTG; Ten: str25; TuaDe: String);

Var p: TroTG; r: TroSach;

Bài 2: Khai báo kiểu của một danh sách tuyến tính móc nối và một cây nhị phân như sau:

Type Tro = ^Ptu;

Viết các chương trình con thực hiện công việc sau:

1 Procedure Dungcay(ds:Tro; Var Goc: Pointer) nhằm xây dựng cây nhị phân tìm kiếm có gốc đượctrỏ bởi gốc trên cơ sở các phần tử của danh sách ds đã cho Giả thiết rằng các phần tử của danh sách cógiá trị khác nhau từng đôi một

Trang 18

r^.Trai:= nil; r^.Phai:= Nil;

If (Goc = nil) Then Goc:= r

If p^.Value < n Then p:= p^.Phai Else p:= p^.Trai

If (p^.Value < n) Then p^.Phai:= r Else p^.Trai:= r;

+ Đầu tiên xếp dãy theo thứ tự tăng dần

+ Xóa đệ quy: Lấy giá trị ở giữa đưa vào gốc sau đó gọi đệ quy dựng cây con trái với dãy phía trước

và dựng cây con 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ử của dãy lưu vào n Sau đó xếp thứ tự tăng dầntrên mảng A

*/

Procedure Dung(A: Mang; Dau, Cuoi: Integer; Var Goc: Pointer);

Var Giua: Integer;

Trang 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 của một cây nhị phân như sau:

Type Tro = ^Nut;

Nut = Record

GiaTri: Integer;

Trai, Phai: Tro;

End;

Var Goc: Tro;

Hãy lập các chương trình con thực hiện công việc sau:

1 Hàm cho phép Kiểm tra xem cây có gốc được trỏ bởi con trỏ gốc có phải là cây nhị phân tìm kiếmhay không?

Chú ý: Cây rỗng cũng được coi là cây tìm kiếm Viết theo 2 phương án đệ quy và không đệ quy.Giải:

Begin

If (Goc^.Trai = Nil) Then

If (Goc^.Giatri <Goc^.Phai^.Giatri) Then CayTK:= True

Else CayTK:= FalseElse

If (Goc^.Phai = Nil) Then

If (Goc^.Giatri > Goc^.Trai^.Giatri) Then CayTK:= True

Else CayTK:= FalseElse

CayTK:= CayTK(Goc^.Trai) and CayTK(Goc^.Phai) and

(Goc^.Giatri < Min(Goc^.Phai)

End;

End;

Function Max(Goc: Tro): Integer;

Function Min(Goc: Tro): Integer;

Với giá trị trả về của hàm là nút lớn nhất hoặc nhỏ nhất của cây

2 Trường hợp cây ban đầu không phải là cây tìm kiếm, hãy viết thủ tục cho phép tráo đổi nội dungcủa các nút trong cây, nhưng không thay đổi cấu trúc cây, để nhận được cây nhị phân tìm kiếm.Giải:

Đọc cây vào mảng phải đọc theo thứ tự giữa

Procedure SapLai(Goc: Tro);

8 7 6

4

9

4 8 3

Duyệt giữa cây

lần lượt đưa vào

Trang 20

Type Mang = Array[1 100] of Integer;

Var n: Integer;

Procedure DocVaoMang(Goc: Tro; Var A: Mang; Var n: Integer);

// n là phần tử đưa vào có số thứ tự n mang thông tin ra

Procedure XepThuTuTrenMang(Var A: Mang; n: Integer);

Procedure DuaVaoCay(Goc: Tro; A: Mang);

Cây nhị phân tìm kiếm:

- Có 3 giải thuật cơ bản:

+ Tìm kiếm một nút thỏa mãn điều kiện (dù nút đó là gì) và cho ra nút đó nếu có, nếu khôngcho ra địa chỉ Nil

+ Tìm nút có giá trị Khóa cho trước, nếu có thì cho ra địa chỉ của nút đó, còn không thì bổsung vào nút mới và cuối cùng cho ra địa chỉ nút đó

+ Loại bỏ một nút:

10 7 15

4

9

Trang 21

 p không có con trái

If (p^.GiaTri < Goc^.GiaTri) Then LoaiBo(Goc^.Trai, p)Else LoaiBo(Goc^.Phai, p);

End;

- Phải xác định được con trỏ quản lí p (trong cây và ở một nút nào đó) đóng vai trò quản lí gốc

- Khi Goc = p: Có cây con 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 hoặc trái của nó 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 con

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 các con trỏ trên cây

If (p^.Trai = Nil) Then

If q^.Trai = p Then q^.Trai:= p^.Phai Else q^.Phai:= p^.PhaiElse

Trang 22

ĐỀ IFI 1997:

Bài 4:

Người ta biểu diễn một biểu thức số học với các toán tử +, -, *, / hai ngôi và +, - một ngôi bằng mộtcây Trong đó với mọi toán tử được chứa ở một nút trong và mỗi biến được chứa ở một lá của cây.Chẳng hạn: (((a+b)*c)-(((-c)/d/e)) được biểu diễn bởi cây sau:

Viết khai báo của cây nhị phân nói trên Giả sử rằng với mọi biến có một giá trị cho trước Hãy viếtmột chương trình con cho phép từ một cây đã thành lập ở bộ nhớ trong như trên, tính giá trị của biểuthức toán học liên quan

“/” :

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

Ngày đăng: 23/05/2021, 11:09

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w