Bài tập CTDL

Màu nền
Font chữ
Font size
Chiều cao dòng

1) Trình bày giải thuật tìm tất cả các cách đặt 8 quân hậu vào bàn cờ vua sao cho không quân nào ăn quân nào, bằng cách dùng thủ tục đệ qui quay lui.

Bài làm:

Procedure Dathau(j)

For i:=1 to 8 do

If a[i] and b[i+j] and c[i-j] then

Begin

x[j] := i;

a[i] := False; b[i+j] := False; c[i-j] := False;

If j < 8 then

Dathau(j+1);

Else

//In nghiệm

For k := 1 to 8 do

Write (x[k]);

//Cất hậu để tìm nghiệm tiếp theo

a[i] := True;

b[i+j] := True;

c[i-j] := True;

End;

Program Con_hau;

For i:=1 to 8 do a[i] := True;

For i:=2 to 16 do b[i+j] := True;

For i:= -7 to 7 do c[i-j] := True;

Dathau(1);

End.

2) Trình bày giải thuật đánh giá biểu thức hậu tố bằng cách dùng STACK. Minh họa diễn biến của quá trình đọc biểu thức và sự thay đổi trong STACK với biểu thức: 5 9 – 2 6 / + theo dạng:

Diễn biến đọc biểu thức                                                                                    Diễn biến STACK                                                                                                                        Thực hiện phép toán

9 – 2 6 / +                                                                                                        5                                                                

                                                                                                                        9                                                                

- 2 6 / +                                                                                                           5                                                                

2 6 / +                                                                                                              - 4                                                                                                                        5 – 9

Bài làm:

Procedure Danh_gia;

Repeat

<Đọc phần tử tiếp theo của biểu thức>

If <x là toán hạng> then

Push (S,T,x);

Else

Begin

X:= Pop(S,T);

Y:= Pop(S,T);

Z := Y x X ; //x đang lưu trữ toán tử

Push (S,T,Z) ;

End ;

Until // Gặp dấu kết thúc biểu thức

Write (Pop (S,T))

Return;

Diễn biến đọc biểu thức

Diễn biến STACK

Thực hiện phép toán

9 – 2 6 / +

5

9

- 2 6 / +

5

2 6 / +

- 4

5 – 9

2

6 / +

- 4

6

2

/ +

- 4

1/3

2/6

+

- 4

- 11/3

- 4 + 1/3

3) Trình bày giải thuật giải hệ phương trình đại số tuyến tính dạng:

A11X1 = b1

A21X1 + A22X2 = b2

An1X­1 + An2X2 + … + AnmX­n = bn­

Trong đó để tiết kiệm các hệ số của ma trận được lưu trữ trong một mảng có n(n+1)/2 phần tử.

Bài làm:

Procedure gt(A[1..n, 1..n], B[1..n]);

i := 1;

x[i] := B[1] / A[1,1];

<Lưu x[i] vào mảng>

For i := 2 to n do

S := 0;

Begin

For j := 1 to k – 1 do

S := S + A[k,j]*x[j]

x[k] := (B[k] – S)/ A[k,k];

<Lưu x[k] vào tiếp mảng>

End;

Return;

<In nghiệm>

4) Trình bày giải thuật bổ sung 1 nút mới có chứa dữ liệu X vào trước nút trỏ bởi Q trong danh sách móc nối 2 chiều với: Pdau trỏ vào phần tử đầu, Pcuoi trỏ vào phần tử cuối, mỗi nút có các trường: Data, P_Trai, P_Phai.

Bài làm:

Procedure Insert (Pdau, Pcuoi, Q, X)

New(p); //Tạo nút mới

Data(p):= X;

If Pcuoi := Null then //Danh sách rỗng

P_trai(p) := P_Phai(p) := Null;

Pdau := Pcuoi := p;

Return

End ;

If Q = Pdau then begin //Q trỏ tới nút cực trái

P_Trai(p) := null;

P_Phai(p) := Q;

P_Trai(p) := p;

Pdau :=p;

Return

End ;

P_Trai(p) := P_Trai(Q); //Bổ sung vào giữa

P_Phai(p) := Q;

P_Trai(Q) := p;

P_Phai(P_Trai(p)) :=p;

Return.

5) Trình bày giải thuật loại bỏ nút trỏ bởi M trong danh sách móc nối 2 chiều với : Pdau trỏ vào phần tử đầu, Pcuoi trỏ vào phần tử cuối, mỗi nút có các trường: Data, P_Trai, P_Phai.

Bài làm:

Procedure Delete(Pdau, Pcuoi, M)

If Pcuoi = null then begin //Trường hợp danh sách rỗng

Write (“Danh sach rong”);

Return

End;

Case //Loại bỏ

Pdau := Pcuoi; //Danh sách chỉ có 1 nút và M trỏ tới nút đó

Pdau := Pcuoi := null

M: = Pdau //Phần tử đầu bị loại

Pdau := P_Phai(Pdau);

P_Trai(Pdau) := null;

M := Pcuoi //Phần tử cuối bị loại

Pcuoi := P_Trai(Pcuoi) ;

P_Phai(Pcuoi) := null ;

Else

P_Phai(P_Trai(M)) := P_Phai(M) ;

P_Trai(P_Phai(M)) := P_Trai(M) ;

End case;

Dispose(M) ;

Return.

6) Trình bày giải thuật duyệt cây theo thứ tự: trước, giữa, sau. Cho biết thứ tự các nút được thăm theo các thứ tự: trước, giữa, sau đối với cây nhị phân sau:

A gốc

B: Con trái của A, C: Con phải của A

D: Con trái của B, E: Con phải của B, F: Con trái của C, G: Con phải của C

H: Con trái của E, I: Con phải của F, J: Con phải của G                 I        J     

Bài làm:

Thăm Trước:

Procedure Tham_Truoc(T);

If T = null then

Begin

Write (Info (T));

Tham_Truoc(T(P_Trai));

Tham_Truoc(T(P_Phai)) ;

End ;

Return;

Thăm Giữa

Procedure Tham_Giua(G);

If G <> null then

Begin

Tham_Giua(G(P_Trai);

Write(Info(G));

Tham_Giua(G(P_Phai);

End;

Return;

Thăm Sau

Procedure Tham_Sau(S);

If S <> null then

Begin

Tham_Sau(S(P_Trai));

Tham_Sau(S(P_Phai));

Write(Info(S));

End;

Return;

Duyệt thứ tự trước: A B D E H C F I G J

Duyệt thứ tự giữa: D B H E A F I C G J

Duyệt thứ tự sau: D H E B I F J G C A

7) Biết thứ tự duyệt cây nhị phân theo thứ tự trước là: A B D E H C F I G và theo thứ tự giữa là: D B H E A F I C G, hãy dựng lại cây nhị phân.

Bài làm:

Duyệt theo thứ tự trước: Thăm gốc, cây con trái theo thứ tự trước, cây con phải theo thứ tự trước

Duyệt theo thứ tự giữa: Cây con trái theo thứ tự giữa, thăm gốc, cây con phải theo thứ tự giữa

=> Cây dựng lại: A gốc

B: Con trái của A, C: Con phải của A

D: Con trái của B, E: Con phải của B, F: Con trái của C, G: Con phải của C

H: Con trái của E, I: Con phải của F

Giải thích:

Dựa vào duyệt trước => A: Gốc

Dựa vào duyệt giữa => D, B, H, E thuộc cây con trái của A và F, I, C, G thuộc cây con phải của A

Kết hợp => B: Con trái của A

Dựa vào duyệt giữa => D thuộc cây con trái của B và H, E thuộc cây con phải của B

Kết hợp => D: Con trái của B, E: Con phải của B, H: Con trái của E

C: Con phải của A

Dựa vào duyệt giữa => I, F thuộc cây con trái của C và G thuộc cây con phải của C

Kết hợp => G: Con phải của C, F: Con trái của C, I: Con phải của F

8) Biết thứ tự duyệt cây nhị phân theo thứ tự giữa là: D H B E A F C I G và theo thứ tự sau là: H D E B F I G C A, hay dựng lại cây nhị phân.

Bài làm:

Duyệt theo thứ tự sau: Cây con trái theo thứ tự sau, cây con phải theo thứ tự sau, thăm gốc

Duyệt theo thứ tự giữa: Cây con trái theo thứ tự giữa, thăm gốc, cây con phải theo thứ tự giữa

=> Cây dựng lại: A gốc

B: Con trái của A, C: Con phải của A

D: Con trái của B, E: Con phải của B, F: Con trái của C, I: Con phải của C

H: Con phải của D, G: Con phải của I

Giải thích:

Dựa vào duyệt sau => A: Gốc

Dựa vào duyệt giữa => D H B E thuộc cây con trái của A và F C I G thuộc cây con phải của A

Kết hợp => C: Con phải của A

Dựa vào duyệt giữa => F thuộc cây con trái của C và I G thuộc cây con phải của C

Kết hợp => F: Con trái của C, I: Con phải của C, G: Con phải của I

B: Con trái của A

Dựa vào duyệt giữa => D H thuộc cây con trái của B và E thuộc cây con phải của B

Kết hợp => E: Con phải của B, D: Con trái của B, H: Con phải của D

9) Trình bày giải thuật sắp xếp nhanh (QuickSort)? Trình bày thời gian thực hiện giải thuật với dãy n phần tử. Minh họa diễn biến ở từng bước khi áp dụng giải thuật này với dãy số: 24, 42, 74, 11, 65, 58, 83, 36, 88, 99

Bài làm:

Procedure Quick_Sort(a, vt_dau, vt_cuoi);

Kt:= True;

If vt_cuoi > vt_dau then

Begin

i:= vt_dau + 1;

j:= vt_cuoi - 1;

x:= a[vt_dau];

While kt do

While a[i] < x and I =< vt_cuoi do i:= i+1;

While a[i] > x and j > vt_dau do j:= j+1;

If j>i then

Begin

y := a[j];

a[j] := a[i];

a[i] := y;

End;

Else

Begin

Kt := False;

y := a[vt_dau];

a[vt_dau] := a[j];

a[j] := y;

Quick_Sort(a, vt_dau, j – 1);

Quick_Sort(a, j + 1, vt_cuoi);

End;

End;

Return;

Thời gian thực hiện giải thuật:

Gọi T(n) là thời gian thực hiện giải thuật với dãy n phần tử

P(n) là thời gian để phân chia dãy n phần tử thành 2 đoạn

=> T(n) = P(n) + T(j – vt_dau) + T(vt_cuoi – j)

             = C.n + …

Giả sử: Sau mỗi bước dãy được chia làm 2 phần bằng nhau

=> T(n) = C.n + 2.T(n/2)

             = C.n + 2 C.n/2 + 4.T(n/4)

             = …

             = C.n + 2 C.n/2 + 4 C.n/4 + 2log2n C(n/2log2n) T(1)

             = C.n + C.n + … + C.n

T(1) = 1 khi thực hiện đến bước thứ log2n

Có log2n phần tử C.n

T(n) = C.n log2n = O(nlog2n)

10) Trình bày giải thuật sắp xếp hòa nhập (Merge Sort)? Trình bày thời gian thực hiện giải thuật với dãy n phần tử. Minh họa diễn biến ở từng bước khi áp dụng giải thuật này với dãy số: 34, 15, 74, 11, 65, 58, 83, 36, 88, 99.

Bài làm:

Hòa nhập 2 đường

Procedure Merge(X, b, m, n, Z);

i := b j := m+1; k := b; //Khởi tạo các chỉ số

While (i<m) and (j<n) do //So sánh để chọn phần tử nhỏ hơn

Begin

If X[i] < X[j] then

Begin

Z[k] := X[i; i:= i+ 1;

End;

Else

Begin

Z[k] := X[j]; j := j+1;

End;

k := k+1;

End;

If i > m then

(Z[k],…,Z[n]) := (X[j],…,X[n])

Else //Đoạn sau hết phần tử

(Z[k],…,Z[n]) := (X[i],…,X[m])

Return;

Hòa nhập 2 đường trực tiếp

Thủ tục sắp xếp hòa nhập từng cặp mạch kề cận:

Procedure MPass(X,Y,n,k)

i := 1;

While i =< n – 2k+ 1 do //Vẫn còn đủ 2 mạch ở phía sau

Begin

Merge (X, i, i + k- 1, i + 2k – 1, Y);

i := i + 2k;

end;

//Hòa nhập mạch còn lại có độ dài tổng >k, <2k

If i + k – 1 < n then

Merge(X, i, i + k – 1, n);

Else //Chỉ còn 1 mạch cuối cùng

(Y[i],…,Y[n]) := (X[i],…,X[n]);

Return;

Thủ tục sắp xếp hòa nhập

Procedure Straight_Msort (X,n);

k := 1;

While k < n do

Begin

MPass (X, Y, k); k := 2*k;

MPass (Y,X,k); k := k*2;

End;

Return;

Thời gian thực hiện giải thuật:

Dễ nhận thấy phép chuyển đổi chỗ nhiều hơn phép so sánh do vậy ta chọn phép đổi chỗ làm phép toán tích cực.

Ta thấy mỗi khi gọi đến MPass thì toàn bộ các phần tử của mảng được duyệt qua 1 lần và chuyển sang 1 vùng mới từ X sang Y hoặc từ Y sang X. Do vậy MPass có cấp độ thực hiện thời gian là O(n)

Số lần gọi MPass chính là log2n

=> Độ phức tạp O(nlog2n)

11) Trình bày giải thuật tìm kiếm nhị phân. Trình bày thời gian thực hiện giải thuật với cây có n nút.

Bài làm:

Function Binary_Search (k,r,a,X);

If k>r then

tg := 0 then //Không tìm thấy

Else

Begin

m := (k + r) div 2;

If a[m] = X then

tg := X; //Tìm thấy

Else

If X < a[m] then

Binary_Search (k, m – 1, a, X);

Else

Binary_Search (m+1, r, a, X);

End;

Return tg;

Thời gian thực hiện:

Thuận lợi nhất khi tìm thấy ngay ở giữa: O(1)

Không thuận lợi khi phải gọi đệ qui, gọi thời gian cần thực hiện trong trường hợp này là:

W(r – k + 1)

Với lần gọi ban đầu: k = 1, r = n

Có W(n – 1 + 1) = W(n) = 1 + W(n/2)

= 1 + 1 + W(n/4)… = 1 + 1 + … + W(n/2x)

Dừng khi (n/2x) = 1 vì W(1) = 1

Mà (n/2x) = 1 ó x = log2n

Tức là ta phải gọi đệ qui log2n lần

=> Độ phức tạp là O(log2n)

12) Trình bày giải thuật tìm kiếm có bổ sung trên cây nhị phân tìm kiếm. Dựng cây nhị phân tìm kiếm với dãy khóa nhập vào là: 10, 7, 19, 11, 3, 16, 13, 4, 22, 5.

Bài làm:

Function BST(T,X);

P := null; q = T;

While q <> null do

Case

X <Key(q): p := q; //Lưu cha của q

                  q := P_Trai(q);

X = Key(q) : Return(q);

X > Key(q) : p := q;

                    q := P_Phai(q);

End Case; //Không tìm thấy, cần bổ sung

New(q);

Key(q) := X;

P_Trai(q) := null;

P_Phai(q) := null;

Case

T = null : T := q;

X < Key(P) : P_Trai(P) := q;

X > Key(P) : P_Phai(P) := q;

End Case;

Write(“Khong tim thay, da bo sung”);

Return (q);

Dựng cây nhị phân:

10: Gốc

7: Con trái của 10, 19: Con phải của 10

3: Con trái của 7, 11: Con trái của 19, 22: Con phải của 19

4: Con phải của 3, 16: Con phải của 11

5: Con phải của 4, 13: Con trái của 16

Bạn đang đọc truyện trên: Truyen2U.Pro