Tải bản đầy đủ (.docx) (58 trang)

Đề cương ôn thi Cấu trúc dữ liệu và giải thuật Cao học CNTT

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (922.73 KB, 58 trang )

Ke ban hanh _ CNTT K29

Bổ sung phần tử vào Stack
• Procedure Push(S, T, X)
{Giải thuật này bổ sung phần tử X vào stack lưu trữ bởi vector S có n phần tử. T là con trỏ, trỏ tới đỉnh
stack)}
1. {Xem xét stack có TRÀN (overflow) không? Hiện tượng tràn xảy ra khi S không còn chỗ để tiếp tục
lưu trữ các phần tử của stack nữa. Lúc đó in ra thông báo tràn và kết thúc}
if T≥n then begin
write(‘Stack tràn’);
return
end;
2. {chuyển con trỏ}
T:=T+1;
3. {Bổ sung phần tử mới X}
S[T]:=X;
4. return
Loại bỏ phần tử khỏi Stack
• Function POP(S, T)
{hàm này thực hiện việc loại bỏ phần tử ở đỉnh stack S mà T đang trỏ tới. Phần tử bị loại sẽ được thu
nhận và đưa ra}
1. {Xem xét stack có CẠN (underflow) không? Hiện tượng CẠN xảy ra khi stack đã rỗng, không còn
phần tử nào để loại nữa, lúc đó sẽ in ra thông báo CẠN và kết thúc}
if T≤0 then begin
write(‘STACK CẠN’);
return
end;
2. {chuyển con trỏ}
T:=T-1;
3. {Đưa phần tử bị loại ra}
POP:=S[T+1]


4. return
Bổ sung phần tử Hàng đợi
• Procedure CQINSERT(F,R,Q,n, X)
{Cho con trỏ F và R lần lượt trỏ tới lối trước và lối sau của một queue được lưu trữ bởi vector gồm n
phần tử, theo kiểu vòng tròn. Giải thuật này thực hiện bổ sung một phần tử mới X vào lối sau của queue
đó. Ban đầu khi queue rỗng thì F=R=0}
1. {Chỉnh lại con trỏ R}
if R=n then R:=1
else R:=R+1;
2. {Kiểm tra TRÀN}
1


Ke ban hanh _ CNTT K29

if F=R then begin
write(‘TRÀN’);
return
end
3. {Bổ sung X vào}

Q[R]:=X;
4. {Điều chỉnh con trỏ F khi bổ sung lần đầu}
if F=0 then F:=1;
5. return
Loại bỏ phần tử khỏi hàng đợi
• Function CQDELETE(F, R, Q, n)
{Cho F và R trỏ tới lối trước và lối sau của queue kiểu vòng tròn, được lưu trữ bởi vector Q có n phần tử.
Hàm này thực hiện việc loại bỏ một phần tử ở lối trước của queue và đưa nội dung của phần tử đó ra}
1. {Kiểm tra CẠN}

if F=0 then begin
write(‘CẠN’);
return (0);
end;
2. {Loại bỏ}
Y: = Q[F];
3. {Xử lý trường hợp queue trở thành rỗng sau phép loại bỏ}
if F=R then {F = R tức là lúc đó queue chỉ có một phần tử}
begin
F:=R:=0;
return (Y)
end;
4. {Chỉnh lại con trỏ F sau phép loại bỏ}
if F=n then F:=1
else F:=F+1
5. Return (Y)
Bài tập 1
Các ma trận thưa có cùng kích thước mxn có cấu trúc
Matrix = Record
spt: Số phần tử khác không của mảng;
D: Array[1..max] of Giá trị;
C: Array[1..max] of Chỉ số;
End;
Trong đó max là số phần tử khác không tối đa của các ma trận, phần tử khác không thứ k, tính từ trên
xuống dưới, từ trái qua phải, A(i, j) được lưu vào C[k] = (i-1)*n + j và D[k] = A(i, j)
2


Ke ban hanh _ CNTT K29


Cho trước hai ma trận thưa A và B theo cấu trúc Matrix. Viết thủ tục tính T = A+B
Procedure TongMatran(A: Matrix; B: Matrix; Var T: Matrix);
Var
ka, kb: integer;
Co: Array[1..max] of Boolean;
Begin
T.spt:=0;
for kb:=1 to B.spt do
co[kb]:=false;
for ka:=1 to A.spt do
begin
kb:=1;
while ((kbA.C[ka])) do
kb=kb+1;
if (B.C[kb] = A.C[ka]) then begin
co[kb]:=true;
if (A.D[ka] + B.D[kb]<>0) begin
T.spt::=T.spt+1;
T.C[T.spt]:=A.C[ka];
T.D[T.spt]:=A.D[ka] + B.D[kb];
end;
end
else if (B.C[kb] <> A.C[ka]) begin
T.spt::=T.spt+1;
T.C[T.spt]:=A.C[ka];
T.D[T.spt]:=A.D[ka];
end;
for kb:=1 to B.spt do
if co[kb] = false then begin
T.spt:=T.spt+1;

T.C[T.spt]:=B.C[kb];
T.D[T.spt]:=B.D[kb];
end;
end.;
Bài tập 2
Dùng ngăn xếp đổi biểu diễn số nguyên không âm N từ cơ số 10 sang cơ số a<10
const int n = 100;
struct stack
{
int top;
3


Ke ban hanh _ CNTT K29

int x[n];
};
void Init(stack &s)
{
s.top=-1;
}
bool Full(stack s)
{
if (s.top==n-1)
return true;
else
return false;
}
bool Push(stack &s, int val)
{

if (!Full(s))
{
s.top++;
s.x[s.top]=val;
return true;
}
else
return false;
}
bool Empty(stack s)
{
if (s.top==-1)
return true;
else
return false;
}
bool Pop(stack &s, int &val)
{
if (!empty(s))
{
val = s.x[s.top];
s.top--;
return true;
}
else return false;
}
4


Ke ban hanh _ CNTT K29


Đầu vào: số nguyên không âm n hệ cơ số 10, hệ cơ số a
Đầu ra: in ra số nguyên n ở hệ cơ số a.
void Chuyen(int n, int a)
{
stack s;
Init(s);
while (n!=0)
{
int r = n%a;
Push(s, r);
n = n/a;
}
int val;
while (Pop(s,val))//Hàm pop lấy ra phần tử trên đỉnh của stack s và gán giá trị vào val. Giá trị trả về
của hàm là true nếu còn phần tử để lấy ra trái lại là false.
{
printf("%d",val);
}
}
Bài tập 3
Chuyển biểu thức trung tố không đầy đủ dấu ngoặc về dạng hậu tố
Đầu vào: H là biểu thức trung tố không đầy đủ dấu ngoặc
Đầu ra: N biểu thức ở dạng hậu tố của H
1. Input H; Khởi tạo ngăn xếp S
2. Priority[‘('] < Priority['+'] = Priority['-'] < Priority['*']= Priority['/']
3. N := “”;
4. For each x in H
case x of
case dấu ‘(‘: Push(S, x); break;

case dấu ‘)’:
repeat
{
Pop(S,a);
If(a≠ ‘(‘) then Thêm a vào sau N
} until a=‘(‘;
break;
case toán hạng: Thêm x vào sau N; break;
case toán tử:
While (not empty(S) and Priority(x) ≤ Priority(Top(S)) Do
{
5


Ke ban hanh _ CNTT K29

Pop( S, a );
Thêm a vào sau N;
}
Push(S, x); break;
5. While not Empty(S) Do {
Pop( S, a );
Thêm a vào sau N;}
6. Output N;
Ứng dụng chuyển biểu thức: 12*(5-2)/(6-4) (Chuyển biểu thức trung tố không đầy đủ dấu ngoặc về
dạng hậu tố)
x(Hi)

S


N

12

12

*

*

12

(

*(

12

5

*(

12 5

-

*(-

12 5


2

*(-

12 5 2

)

*

12 5 2 –

/

/

12 5 2 - *

(

/(

12 5 2 - *

6

/(

12 5 2 - * 6


-

/(-

12 5 2 - * 6

4

/(-

12 5 2 - * 6 4

)

/

12 5 2 - * 6 4 -

Lấy ra và hiện các phần tử còn lại trong stack
12 5 2 - * 6 4 - /
Bài tập 4
Dùng ngăn xếp tính giá trị biểu thức số học dạng hậu tố
Đầu vào: Chuỗi H là biểu thức số học ở dạng hậu tố
Đầu ra: Kết quả của biểu thức
1. Input H; Khởi tạo ngăn xếp S.
2. For each x in H
Case x of
case toán hạng:
6



Ke ban hanh _ CNTT K29

push(S, x);
break;
case toán tử:
pop(S, a); pop(S, b);
c = Cal(b,x, a);
push(S, c);
break;
3. pop(S, Ketqua); Output Ketqua;
Áp dụng tính giá trị biểu thức (Dùng ngăn xếp tính giá trị biểu thức số học dạng hậu tố)
6 10 8 - / 24 10 6 - / 2 / Hi (x)

S

Giải thích

6

6

Đọc 6; Đẩy 6 vào ngăn xếp

10

6 10

Đọc 10; Đẩy 10 vào ngăn xếp


8

6 10 8

Đọc 8; Đẩy 8 vào ngăn xếp

-

62

Đọc -; lấy 8 và 10 ra khỏi ngăn xếp; tính 10 – 8 =2; đẩy 2 vào ngăn xếp

/

3

Đọc /; lấy 6 và 2 ra khỏi ngăn xếp; Tính 6/2=3; Đẩy 3 vào ngăn xếp

24

3 24

Đọc 24; Đẩy 24 vào ngăn xếp

10

3 24 10

Đọc 10; Đẩy 10 vào ngăn xếp


6

3 24 10 6

Đọc 6; Đẩy 6 vào ngăn xếp

-

3 24 4

Đọc -; Lấy 10 và 6 ra khỏi ngăn xếp; Tính 10-6=4; Đẩy 4 vào ngăn xếp.

/

38

Đọc /; Lấy 24 và 4 ra khỏi ngăn xếp; Tính 24/4=8; Đẩy 8 vào ngăn xếp

2

382

Đọc 2; Đẩy 2 vào ngăn xếp

/

34

Đọc /; Lấy 8 và 2 ra khỏi ngăn xếp; Tính 8/2=4; Đẩy 4 vào ngăn xếp;


-

-1

Đọc -; Lấy 3 và 4 ra khỏi ngăn xếp; Tính 3-4=-1; Đẩy -1 vào ngăn xếp

Bài tập 5
Tính giá trị biểu thức trung tố không đầy đủ dấu ngoặc
Đầu vào: Chuỗi H là biểu thức trung tố không đầy đủ dấu ngoặc
Đầu ra: Kết quả của biểu thức
1. Input H; Khởi tạo ngăn xếp toán tử St := ∅; ngăn xếp toán hạng Sh := ∅;
2. Pr[‘(‘]3. For each x in H
Case x of
case Toán hạng: Push (Sh, x); break;
7


Ke ban hanh _ CNTT K29

case Ngoặc mở ‘(‘: Push (St, x); break;
case Toán tử { +,- ,*, / }:
While (St≠∅ & Pr[x]≤ Pr[Top(S)])Do {
Pop( St, t ); Pop(Sh, b); Pop(Sh, a);
c := a t b;
Push(Sh, c);}
Push(St, x); break;
case Ngoặc đóng ‘)’:
a) While Top(St) ≠’(‘ Do {
Pop(St, t); Pop(Sh, b); Pop(Sh,a);

c := a t b; Push(Sh, c);}
b) Pop(St, t); break;
4. While St≠∅ Do {
Pop( St, t ); Pop(Sh, b); Pop(Sh,a);
c := a t b;
Push(Sh, c); }
5. Pop (Sh, x); OutPut x;
Áp dụng tính giá trị biểu thức 12*(5-2)/(6-4) Tính giá trị biểu thức trung tố không đầy đủ dấu ngoặc
x
(Hi)

St

12

Sh
12

*

*

12

(

*(

12


5

*(

12 5

-

*(-

12 5

2

*(-

12 5 2

)

*

12 3

/

/

36


(

/(

36

6

/(

36 6

-

/(-

36 6

4

/(-

36 6 4

)

/

36 2


Các bước tiếp theo
8


Ke ban hanh _ CNTT K29

18
Bài tập 6
Tính giá trị biểu thức trung tố không có dấu ngoặc
Đầu vào: H là biểu thức trung tố không có dấu ngoặc.
Đầu ra: Kết quả của biểu thức H.
1. Input H; Khởi tạo ngăn xếp toán tử St := ∅; ngăn xếp toán hạng Sh := ∅;
2. Pr ['+'] = Pr ['-'] < Pr ['*']= Pr ['/']
3. For each x in H
Case x of
case Toán hạng: Push (Sh, x); break;
case Toán tử { +,- ,*, / }:
While (St≠∅ & Pr[x]≤ Pr[Top(S]) Do {
Pop( St, t ); Pop(Sh, b); Pop(Sh, a);
c := a t b;
Push(Sh, c);}
Push(St, x); break;
4. While St≠∅ Do {
Pop(St, t); Pop( Sh, b ); Pop(Sh,a);
c := a t b;
Push(Sh, c);}
5. Pop (Sh, x); OutPut x;
Áp dụng tính biểu thức: 2*4 + 9/3 (Tính giá trị biểu thức trung tố không có dấu ngoặc)
x
(Hi)


St

2

Sh
2

*

*

2

4

*

24

+

+

8

9

+


89

/

+/

89

3

+/

893

Lấy ra và hiện các phần tử còn lại trong stack
+

83
11
9


Ke ban hanh _ CNTT K29

Bài Tập 7
Chuyển biểu thức trung tố không có dấu ngoặc sang dạng hậu tố
Đầu vào: H là biểu thức trung tố không có dấu ngoặc
Đầu ra: Biểu thức N ở dạng hậu tố của H
1. Input H; Khởi tạo ngăn xếp S
2. Priority['+'] = Priority['-'] < Priority['*']= Priority['/']

3. N := ‘’;
4. For each x in H
Case x of
case toán hạng: Thêm x vào sau N; break;
case toán tử:
While ((not empty(S)) and (Priority[x] ≤ Priority[Top(S)])) Do
{
Pop( S, a );
Thêm a vào sau N;
}
Push(S, x); break;
5. While not Empty(S) Do {
Pop( S, a );
Thêm a vào sau N;}
6. Output N;
Áp dụng chuyển biểu thức: 2*4 + 9/3 (Chuyển biểu thức trung tố không có dấu ngoặc sang dạng hậu tố)
Hi

St

2

Output
2

*

*

2


4

*

24

+

+

24*

9

+

24*9

/

+/

24*9

3

+/

24*93


Lấy ra và hiện các phần tử còn lại trong stack
+

24*93/
24*93/+

Bài tập 8
Dùng ngăn xếp tính giá trị của biểu thức ở dạng trung tố đầy đủ dấu ngoặc
10


Ke ban hanh _ CNTT K29

Đầu vào: H là biểu thức trung tố đầy đủ dấu ngoặc
Đầu ra: Kết quả của H
1. Input H; Khởi tạo ngăn xếp S.
2. For each x in H
Case x of
case toán tử, toán hạng:
push(S, x);
break;
case đóng ngoặc:
pop(S, a); pop(S, t); pop(S, b);
c = cal(b, t, a);
push(S, c);
break;
3. pop(S, Ketqua); Output Ketqua;
Áp dụng tính giá trị của biểu thức
((3 + ((2 + 4)/2))*(8 + ((3 - 1)*2))) Dùng ngăn xếp tính giá trị của biểu thức ở dạng trung tố đầy đủ dấu

ngoặc
x
(Hi)

S

(
(
3

3

+

3+

(

3+

(

3+2

+

3+2+

4


3+2+4

)

3+6

/

3+6/

2

3+6/2

)

3+3

)

6

*

6*

(

6*
11



Ke ban hanh _ CNTT K29

8

6*8

+

6*8+

(

6*8+

(

6*8+

3

6*8+3

-

6*8+3-

1


6*8+3–1

)

6*8+2

*

6*8+2*

2

6*8+2*2

)

6*8+4

)

6 * 12

)

72

DANH SÁCH LIÊN KẾT
Bổ sung một nút vào danh sách nối đơn
Cấu trúc dữ liệu mã Pascal:
list = ^node;

node = record
info: DataType;
next: list;
End;
Cấu trúc dữ liệu mã C:
typedef struct node node;
typedef node *list;
typedef struct node
{
DataType info;
list next;
};
Viết thủ tục bổ sung một nút mới vào danh sách L.
Procedure INSERT(L, M, X)
{L là danh sách cần thêm. Thủ tục bổ sung vào sau nút trỏ bởi M một nút mới mà trường info của nó sẽ
có giá trị lấy từ ô nhớ có địa chỉ X}
1. {Tạo nút mới}
NutMoi <=AVAIL;
NutMoi->info = X;
12


Ke ban hanh _ CNTT K29

2. {Thực hiện bổ sung, nếu danh sách rỗng thì bổ sung nút mới vào thành nút đầu tiên, nếu danh sách
không rỗng thì nắm lấy M và bổ sung nút mới vào sau nút đó}
If (L==NULL) {
L = NutMoi;
NutMoi->next = NULL;
}

Else {
NutMoi->next = M->next;
M->next = NutMoi;
}
3. return.
Viết thủ tục bổ sung một nút vào đầu danh sách L
Procedure INSERT(L, X)
{L là danh sách cần thêm. Thủ tục bổ sung vào đầu danh sách mà trường info của nó sẽ có giá trị lấy từ ô
nhớ có địa chỉ X}
1. {Tạo nút mới}
NutMoi <=AVAIL;
NutMoi->info = X;
2. {Thực hiện bổ sung, nếu danh sách rỗng thì bổ sung nút mới vào thành nút đầu tiên, nếu danh sách
không rỗng thì bổ sung nút mới trước nút đầu tiên của L}
If (L==NULL) {
L = NutMoi;
NutMoi->next = NULL;
}
Else {
NutMoi->next = L;
L = NutMoi;
}
3. return.
Viết thủ tục bổ sung một nút vào cuối danh sách L
Procedure INSERT(L, X)
{L là danh sách cần thêm. Thủ tục bổ sung vào cuối danh sách mà trường info của nó sẽ có giá trị lấy từ ô
nhớ có địa chỉ X}
1. {Tạo nút mới}
NutMoi <=AVAIL;
NutMoi->info = X;

2. {Thực hiện bổ sung, nếu danh sách rỗng thì bổ sung nút mới vào thành nút đầu tiên, nếu danh sách
không rỗng thì bổ sung nút mới vào cuối của L}
If (L==NULL) {
L= NutMoi;
13


Ke ban hanh _ CNTT K29

NutMoi->next = NULL;
}
Else {
P= L;
While (P->next!=NULL)
P=P->next;
P->next = NutMoi;
NutMoi->next = NULL;
}
3. return.
Xóa nút trỏ bởi M ra khỏi danh sách
Procedure DELETE(L, M)
{Cho danh sách nối đơn L. Giải thuật thực hiện loại bỏ nút trỏ bởi M ra khỏi danh sách đó}
1. {Trường hợp danh sách rỗng}
If (L== NULL) {
printf(“danh sách rỗng”);
return;
}
2. {Trường hợp nút trỏ bởi M là nút đầu tiên của danh sách}
If (M==L) {
L = M->next;

M => AVAIL;
return;
}
3. {Tìm đến nút đứng trước nút trỏ bởi M}
P=L;
While (P->next!=M) P=P->next;
4. {Loại bỏ nút trỏ bởi M}
P->next = M->next;
5. {Đưa nút bị loại về danh sách chỗ trống}
M=>AVAIL
6. return
Ghép hai danh sách
Procedure COMBINE(P, Q)
{Cho hai danh sách nối đơn P và Q. Giải thuật thực hiện ghép danh sách Q vào cuối danh sách P}
1. {Trường hợp danh sách Q rỗng}
if Q==NULL return;
2. {Trường hợp danh sách P rỗng}
If P==NULL {
14


Ke ban hanh _ CNTT K29

P=Q;
return;
}
3. {Tìm đến nút cuối danh sách}
P1 = P;
While (P1->next!=NULL) P1:=P1->next;
4. {Ghép)

P1->next = Q;
5. return;
• Giải thuật bổ sung một nút vào thành nút đầu tiên của một danh sách nối vòng có “nút đầu danh
sách” trỏ bởi head.
• NutMoi <= AVAIL;
• NutMoi->info = X {đưa dữ liệu mới đặt ở ô X vào trường info của nút trỏ bởi NutMoi}
• NutMoi->next = head->next
• head->next = NutMoi

DANH SÁCH NỐI KÉP
Bổ sung phần tử
Procedure DOUBIN(L, R, M, X)
{Cho con trỏ L và R lần lượt trỏ tới nút cực trái và nút cực phải của danh sách nối kép, M là con trỏ tới
một nút trong danh sách. Giải thuật này thực hiện bổ sung một nút mới, mà dữ liệu chứa ở X, vào trước
nút trỏ bởi M}
1. {Tạo một nút mới}
NutMoi <=AVAIL;
NutMoi->info = X;
2. {Trường hợp danh sách rỗng}
If (R ==NULL){
NutMoi->LPTR = NutMoi->RPTR = NULL;
L = R = NutMoi;
return;
}
3. {M trỏ tới nút cực trái}
If M==L{
NutMoi->LPTR=NULL;
NutMoi->RPTR=M;
M->LPTR=NutMoi;
15



Ke ban hanh _ CNTT K29

L = NutMoi;
return;
}
4. {Bổ sung vào giữa}
NutMoi->LPTR = M->LPTR
NutMoi->RPTR = M;
M->LPTR = NutMoi;
NutMoi->LPTR->RPTR=NutMoi;
return;
Xóa phần tử
Procedure DOUBDEL(L, R, M)
{Cho L và R là hai con trỏ trái và phải của danh sách nối kép. M trỏ tới một nút trong danh sách. Giải thuật
này thực hiện việc loại bỏ nút trỏ bởi M ra khỏi danh sách}
1. {Trường hợp danh sách rỗng}
If R==NULL{
print(“Danh sách rỗng”);
return;
}
2. {Loại bỏ}
Case
{
L = R: {danh sách chỉ có một nút và M trỏ tới nút đó}
L = R = NULL;
M = L: {nút cực trái bị loại}
L = L->RPTR;
L->LPTR = NULL;

M = R: {nút cực phải bị loại}
R = R->LPTR;
R->RPTR = NULL;
default:
M->LPTR->RPTR = M->RPTR;
M->RPTR->LPTR = M->LPTR;
}
3. M =>AVAIL;
return
Bài tập 1
Xóa tất cả các phần tử có giá trị C trong danh sách liên kết đơn
Cấu trúc dữ liệu mã Pascal:
list = ^node;
node = record
16


Ke ban hanh _ CNTT K29

val: DataType;
next: list;
End;
Đầu vào: Danh sách L, giá trị C
Đầu ra: Hàm Xoa xóa tất cả các phần tử trong danh sách L có giá trị C
void Xoa(list *L, int C)
{
node *P1 = NULL;
node *P2 = *L;
node *temp = NULL;
while (P2!=NULL) {

if (P2->val==C) {
temp = P2;
if (P1==NULL) {
*L = P2->next;
P2 = P2->next;
}
else {
P1->next = P2->next;
P2 = P2->next;
}
free(temp);
}
else {
P1=P2;
P2 = P2->next;
}
}
}
Bài tập 2
Thêm vào sau mỗi phần tử có giá trị A một phần tử có giá trị B (A≠B, A=B)
Đầu vào: Danh sách L, các giá trị A và B
Đầu ra: Danh sách L sau khi đã chèn các phần tử có giá trị B vào sau các phần tử có giá trị A.
void Them(list L, DataType A, DataType B)
{
node *P = L;
while (P!=NULL) {
if (P->val == A) {
node *nutmoi = makenode(B);
nutmoi->next = P->next;
17



Ke ban hanh _ CNTT K29

P->next = nutmoi;
P = nutmoi->next; cho P bằng node mới next để tránh vòng lặp vô hạn kiểm tra giá trị P
}
else {
P = P->next;
}
}
}
Bài Tập 3
Tìm kiếm phần tử trong danh sách liên kết đơn
Đầu vào: Danh sách liên kết đơn L, giá trị C
Đầu ra: Hàm Tim trả về phần tử có giá trị C nếu L tồn tại phần tử có giá trị C và trả về NULL nếu L không
tồn tại phần tử nào có giá trị C.
node * Tim(list L, DataType C)
{
node *s1 = L;
while (s1!=NULL && s1->val!=C) {
s1=s1->next;
}
if (s1!=NULL) {
return s1;
}
else {
return NULL;
}
}

Bài Tập 4
Viết giải thuật xóa phần tử cuối cùng trong danh sách liên kết đơn.
Đầu vào: Danh sách L
Đầu ra: Danh sách L sau khi loại bỏ nút cuối cùng nếu có.
void XoaCuoi(list *L)
{
node *temp=NULL, *ptr=NULL;
if(*L==NULL) {
return;
}
if((*L)->next==NULL) {
temp=*L;
*L=NULL;
free(temp);
18


Ke ban hanh _ CNTT K29

return;
}
temp=*L;
while(temp->next->next!=NULL) {
temp=temp->next;
}
ptr=temp->next;
temp->next=NULL;
free(ptr);
return;
}

Bài tập 5
Xóa nút đầu tiên trong danh sách liên kết đơn
Đầu vào: Danh sách liên kết đơn L
Đầu ra: Danh sách L sau khi xóa nút đầu nếu có.
void XoaDau(list *L)
{
if (*L==NULL)
return;
else
{
node *temp = *L;
(*L) = temp->next;
free(temp);
}
}
Bài Tập 6
Cho hai tập hợp được lưu trong 2 danh sách liên kết đơn. Viết thuật toán xác định giao của hai tập hợp
Đầu vào: Danh sách L1 và L2 lưu 2 tập hợp
Đầu ra: hàm Giao trả về danh sách lưu giao của 2 tập hợp
list * Giao(list L1, list L2)
{
list L3 = NULL;
node *p1 = L1;
node *p3 = NULL;
while (p1!=NULL) {
node *p2 = L2;
while (p2!=NULL && p2->val!=p1->val) {
p2 = p2->next;
}
19



Ke ban hanh _ CNTT K29

if (p2!=NULL) {
node *nutmoi <=AVAIL //Khoi tao bo nho cho nut moi
nutmoi ->val=p1->val;
nutmoi ->next=NULL;
if (p3==NULL){
L3 = nutmoi;
p3 = nutmoi;
}
else {
p3->next = nutmoi;
p3 = nutmoi;
}
}
p1=p1->next;
}
return &L3;
}
Bài Tập 7
Cho hai đa thức lưu ở dạng danh sách liên kết đơn, biết rằng các nút lưu các đơn thức (hạng tử)
của đa thức được lưu trữ trong danh sách theo thứ tự giảm dần của số mũ. Viết thuật toán cộng
hai đa thức.
Cấu trúc mã Pascal:
list = ^node;
node = record
heso: real;
sm: integer;

next: list;
End;
Đầu vào: Danh sách A, B lưu đa thức thứ nhất và hai. Cấu trúc của danh sách và mỗi nút như trên.
Đầu ra: Hàm trả về danh sách lưu đa thức là tổng của hai đa thức.
list Add(list A, list B)
{
list C = NULL;
node *p = A;
node *q = B;
while (p!=NULL && q!=NULL) {
if (p->sm==q->sm) {
float heso = p->heso + q->heso;
if (heso!=0) {
//tạo nút mới
20


Ke ban hanh _ CNTT K29

node *nutmoi =
makenode(heso, p->sm);
//bổ sung nutmoi vào cuối danh sách
enqueue(&C, nutmoi); bổ sung node mới vào cuối danh sách
}
p = p->next;
q = q->next;
}
else if (p->sm<q->sm) {
node * nutmoi =
makenode(q->heso, q->sm);

enqueue(&C, nutmoi);
q = q->next;
}
else {
node * nutmoi =
makenode(p->heso, p->sm);
enqueue(&C, nutmoi);
p = p->next;
}
}//Ket thuc While
//Danh sách ứng với đa thức A chua hết
while (p!=NULL) {
node * nutmoi =
makenode(p->heso, p->sm);
enqueue(&C, nutmoi);
p=p->next;
}
//Danh sách ứng với đa thức B chua hết
while (q!=NULL) {
node * nutmoi =
makenode(q->heso, q->sm);
enqueue(&C, nutmoi);
q=q->next;
}
return C;
}
void enqueue(list *C, node * nutmoi)
{
if (*C==NULL)
21



Ke ban hanh _ CNTT K29

{
*C = nutmoi;
}
else
{
node *temp = *C;
while (temp->next!=NULL)
{
temp = temp->next;
}
temp->next = nutmoi;
}
}
node *makenode(float heso, int sm)
{
struct node *temp;
temp= (struct node*)malloc(sizeof(struct node));
temp->heso=heso;
temp->sm = sm;
temp->next=NULL;
return temp;
}

CÂY
Cấu trúc một nút biểu diễn bằng Pascal
tree = ^node;

node = record
D: DataType;
left: tree;
right: tree;
End;
Giải thuật tìm kiếm có bổ sung
Function BST(T, X)

22


Ke ban hanh _ CNTT K29

{Thủ tục này thực hiện tìm kiếm trên cây nhị phân tìm kiếm, có gốc được trỏ bởi T, nút có giá trị khóa
bằng X. Nếu tìm kiếm được thỏa thì đưa ra con trỏ q trỏ tới nút đó, nếu tìm kiếm không thỏa thì bổ sung
nút mới có khóa là X vào T và đưa ra con trỏ q trỏ tới nút mới đó kèm theo thông báo}
1. {Khởi tạo con trỏ}
p=null; q=T;
2. {Tìm kiếm}
While q ≠null do
if (X<q->KEY) {
p=q; q = q->LPTR;
} else if (X=q->KEY)
return q;
else if (X > q->KEY) {
p = q; q = q->RPTR;
}
3. {Bổ sung}
q <=AVAIL;
q->KEY = X;

q->LPTR = q->RPTR=null;
If (T==null)
T=q; //Cây rỗng, đã bổ sung
else if (X < p->KEY)
p->LPTR = q;
else
p->RPTR=q;
Print(‘không thấy, đã bổ sung’);
return q;
Loại bỏ nút trong cây NPTK
Đầu vào: T là địa chỉ của con trỏ trỏ tới nút gốc của cây NPTK và giá trị x của khóa cần xóa
Đầu ra: Nội dung của cây NPTK sau khi đã xóa nút, địa chỉ của con trỏ trỏ tới nút gốc.

23


Ke ban hanh _ CNTT K29

24


Ke ban hanh _ CNTT K29

25


×