Hãy tổ chức lưu trữ một dãy số nguyên với cấu trúc danh sách liên kết đơn vàthực hiện các yêu cầu sau: 1, Nhập danh sách Thêm đầu - Thêm cuối 2, Xuất danh sách ra màn hình 3, Liệt kê các
Trang 1Phần 1: Giải thuật và độ phức tạp tính toán của giải thuật
Bài 1: Cho đoạn chương trình sau:
int Max(int a[], int n)
a) Đoạn chương trình này thực hiện công việc gì?
b) Xác định độ phức tạp của đoạn chương trình trên
Trả lời:
a) Đoạn chương trình này thực hiện việc sắp xếp mảng theo phương thức sắp xếp chọn(Selection Sort)
b) Xác định độ phức tạp:
- Thời gian thực hiện lệnh {2} là O(1)
- Vòng lặp thực hiện n lần, mỗi lần O(1)
- Độ phức tạp của giải thuật là: T(n) = O(1).O(n) = O(n)
Bài 2:
a) Viết chương trình thực hiện phép toán cộng hai ma trận vuông cấp n
b) Xác định độ phức tạp của đoạn chương trình của câu a)
//Nhap ma tran vuong A cap n
void NhapMaTran(int A[max][max], int n)
//Xuat ma tran vuong A cap n
void XuatMaTran(int A[max][max], int n)
Trang 2//Tong hai ma tran A va B luu vao trong ma tran C
void Tong(int A[max][max], int B[max][max], int C[max][max], int n){
for(int i = 0; i<n ; i++)
for(int j = 0; j<n ; j++)
C[i][j] = A[i][j]+B[i][j];
}
//Tich hai ma tran A va B luu vao trong ma tran C
void Tich(int A[max][max], int B[max][max], int C[max][max], int n)
//In hai ma tran A va B vua nhap
printf("Ma tran A vua nhap\n");
Trang 3//Tong hai ma tran A va B luu vao trong ma tran C
void Tong(int A[max][max], int B[max][max], int C[max][max], int n){
}
Lệnh {3} tốn O(1) thời gian
Vòng lặp {2} thực hiện n lần, mỗi lần O(1) Do đó, vòng lặp {2} tốn O(n).Vòng lặp {1} lặp n lần, vậy độ phức tạp của giải thuật là:
Trang 4Bài 1 Hãy tổ chức lưu trữ một dãy số nguyên với cấu trúc danh sách liên kết đơn và
thực hiện các yêu cầu sau:
1, Nhập danh sách (Thêm đầu - Thêm cuối)
2, Xuất danh sách ra màn hình
3, Liệt kê các phần tử mang phần tử chẵn
4, Tìm phần tử có phần tử nhỏ nhất
5, Đếm số lượng số nguyên tố có trong danh sách
6, Thêm phần tử X vào trước phần tử chẵn đầu tiên (X được nhập và từ bàn phím)
7, Thêm phần tử X vào sau phần tử lẻ cuối cùng (X được nhập và từ bàn phím)
8, Xoá phần tử nhỏ nhất trong danh sách
9, Xoá phần tử đứng trước và sau X trong danh sách (X được nhập và từ bàn phím)
10, Tách danh sách hiện tại thành 2 danh sách sao cho danh sách thứ nhất chứa các phần tử nguyên tố, danh sách thứ hai chứa các phần tử còn lại
11, Viết chương trình tính giá trị trung bình cộng của các phần tử trong danh sách
12, Tìm phần tử có giá trị chẵn lớn nhất trong danh sách và xóa (tất cả) các phần tử này
13, Tìm phần tử có giá trị bé nhất trong danh sách và xóa (tất cả) phần tử này
Trả lời:
//Danh sach lien ket don - cac nut luu tru so nguyen
#include<stdio.h>
struct NODE{
int Data;//Truong luu tru du lieu cua phan tu
NODE *Link;//truong lien ket - chua dia chi cua nut tiep theo
};
typedef struct NODE *DSLK;//Khai bao kieu DSLK
1) Nhập danh sách (thêm đầu)
//Ham chen vao dau danh sach 1 nut co truong du lieu la X
void Insert_Begin(DSLK &pHead,int X){
DSLK p;//p - nut moi
p=new NODE;//Xin cap phat dia chi cho nut moi
p->Data=X;//Gan gia tri X cho nut moi
if(pHead==NULL)//Dsnh sach rong
{
p->Link=NULL;//Gan gia tri cho truong dia chipHead=p;//Nut moi tro thanh nut dau danh sach}
else{//Danh sach khong rong
p->Link=pHead;//Gan p vao dau danh sachpHead=p;//Thay doi dia chi nut dau danh sach}
}
1) Nhập danh sách (thêm cuối)
//Ham chen vao cuoi danh sach 1 nut co truong du lieu la X
void Insert_End(DSLK &pHead,int X){
DSLK p;//p - nut moi
Trang 5p=new NODE;//Xin cap phat dia chi cho nut moi
p->Data=X;//Gan gia tri X cho nut moi
p->Link=NULL;//Nut p la nut cuoi cua dslk nen Link=NULL
if(pHead==NULL)//Danh sach rong
pHead=p;//Nut moi tro thanh nut dau danh sachelse{//Danh sach khong rong
//Tim nut cuoi danh sachDSLK q;
//Duyet danh sach - Hien thi danh sach ra man hinh
void View_List(DSLK pHead){
5) Đếm số lượng số nguyên tố có trong danh sách.
//Dem so nut co trong danh sach, so nut duoc tra ve thong qua ten ham
int Demsonut(DSLK pHead){
int dem=0;
DSLK p;
p=pHead;
Trang 6//Xoa nut dau cua danh sach
void Delete_Begin(DSLK &pHead){
}
}
8) Xoá phần tử nhỏ nhất trong danh sách.
9) Xoá phần tử đứng trước và sau X trong danh sách (X được nhập và từ bàn phím).
//Xóa nut p la nut bat ky co trong danh sach
void Delete_Middle(DSLK pHead,DSLK p){
if(p==pHead){
//Xoa nut dau dspHead=pHead->Link;
delete p;//Xoa p}
void Insert_Middle(DSLK &pHead,DSLK p,int X){
DSLK q;//Nut moi co truogn du lieu X
q=new NODE;
q->Data=X;
//Chen q vao sau p
q->Link=p->Link;
Trang 7printf("Danh sach co %d nut\n",Demsonut(pHead));
printf("Nhap vao gia tri k=");
Insert_Middle(pHead,p,X);//Goi ham chen
printf("\nDanh sach sau khi chen:\n",k);
Trang 8}
Bài 2 Cho 2 danh sách liên kết L1 và L2, gồm các phần tử là số nguyên, thực hiện các
yêu cầu sau:
a, Sắp xếp L1 và L2 tăng dần
b, Nối L1 và L2 thành L3 sao cho L3 tăng dần
Bài 3 Một danh sách sinh viên được tổ chức lưu trữ bằng cấu trúc danh sách liên kết
đơn Mỗi sinh viên có những thông tin sau:
Masv( kieu nguyên),
họ tên (kiểu char[30]),
điểm toán (dt ; kiểu int),
điểm lý (dl ; kiểu int),
điểm hóa (dh; kiểu int)
điểm trung bình – tính dựa vào trung bình cộng của các điểm toán, lý, hóa
Viết chương trình thực hiện các công việc sau:
1, Viết chương trình nhập vào n sinh viên (n nhập từ bàn phím)
2, Đưa ra màn hình tất cả sinh viên thi lại ít nhất 1 môn
3, Đưa ra màn hình tất cả sinh viên thi lại cả 3 môn
4, Đưa ra màn hình tất cả sinh viên là sinh viên giỏi (diem trung binh 3 môn >=8 và không có môn nào thi lại)
5, Đưa ra màn hình tất cả sinh viên là sinh viên khá (8>diem trung binh 3 môn >=7;
và không có môn nào thi lại)
6, Đưa ra màn hình tất cả sinh viên là sinh viên trung bình và không có môn nào thi lại)
7, Đưa ra màn hình tất cả sinh viên là sinh viên có điểm trung bình cao nhất
8, Đưa ra màn hình tất cả sinh viên là sinh viên có điểm trung bình thấp nhất
9, Nhập vào Masv nào đó, cho phép tìm kiếm tuần tự theo Masv
10, Xóa bỏ tất cả những sinh viên có điểm trung bình (dtb) =8
Trả lời:
1) Viết chương trình nhập vào n sinh viên (n nhập từ bàn phím)
Bài 4: Thực hiện các bài 1-3 bằng danh sách liên kết đôi
//Khai bao DSLK doi moi nut luu tru 1 so nguyen
//Quan ly bang nut dau va nut cuoi
typedef struct NODE *DSKEP;
//L - dia chi cua nut ben trai nhat(nut dau ds)
//R - dia chi cua nut ben phai nhat(nut cuoi ds)
//Ham chen dau danh sach
void Insert_Begin(DSKEP &L,DSKEP &R,int X){
DSKEP p;
Trang 9//Ham chen cuoi danh sach
void Insert_End(DSKEP &L,DSKEP &R,int X){
//Tao danh sach, du lieu nhap vao tu ban phim
void Creat_List(DSKEP &L,DSKEP &R){
Trang 10//ham dem so nut trong danh sach
int Demsonut(DSKEP L,DSKEP R){
//ham tim nut thu k co trong danh sach
DSKEP Timk(DSKEP L,DSKEP R,int k){
//Chen vao sau nut thu k mot nut moi co truong du lieu la X
void Insert_Middle(DSKEP &L,DSKEP &R, int k,int X){
DSKEP p,q,r;
p=Timk(L,R,k);//p- luu dia chi cua nut thu k
q=new NODE;//q- la nut moi se chen vao ds
q->Phai=r;//q->Phai=p->Phaip->Phai=q;
q->Trai=p;
}
}
//Xoa mot nut o vi tri thu k
void Delete(DSKEP &L,DSKEP &R,int k){
DSKEP p,q,r;
p=Timk(L,R,k);//Tim dia chi nut can xoa
Trang 11printf("Khong co nut can xoa!");
else
if(p==L){//Nut can xoa la nut dau danh sach
L=L->Phai;//Chinh dia chi nut dauL->Trai=NULL;//Dam bao L luon la nut danh dsdelete p;//Xoa nut p
}else
if(p==R){//Nut can xoa la nut cuoi ds
R=R->Trai;//Chinh dia chi nut cuoiR->Phai=NULL;
delete p;//Xoa nut p}
else{//Nut can xoa la nut giua danh sach
q=p->Trai;//q la nut truoc pr=p->Phai;//r la nut sau pq->Phai=r;
r->Trai=q;
delete p;
}}
//Sap xep danh sach theo thu tu tang dan
void Sapxep(DSKEP &L,DSKEP &R){
Phần 3 (2 điểm) - Kiểu dữ liệu trừu tượng cơ bản: Stack, Queue
Bài 1: Cho một stack được hiện thực trên cơ sở mảng có tình trạng như sau:
Thêm vào Đưa ra
Trang 12I T
↑TopHãy thực hiện một chuỗi các thao tác sau:
Đ A I * H * * O C T * * * I N * *Trong đó, các chữ cái tượng trưng thao tác PUSH – đẩy phần tử vào stack, dấu
* tượng trưng cho thao tác POP và in ra màn hình
Hỏi: Sau khi kết thúc chuỗi thao tác trên:
a) Kết quả in ra màn hình như thế nào?
b) Tình trạng của stack như thế nào ? (Vẽ minh họa cụ thể)
Trả lời:
Khái niệm:
- Stack (ngăn xếp, bộ xếp chồng) là một cấu trúc dữ liệu trừu tượng hoạt động theonguyên lý “vào sau – ra trước” (Last In First Out – LIFO)
- Stack có 2 phép toán cơ bản: PUSH và POP
+ PUSH bổ sung 1 phần tử vào đỉnh (top) của ngăn xếp, tức là sau các phần tử đã cótrong ngăn xếp
+ POP là giải phóng và trả về phần tử đang đứng ở đỉnh của ngăn xếp
- Trong ngăn xếp, các đối tượng có thể được thêm vào stack bất kỳ lúc nào nhưngchỉ có đối tượng thêm vào sau cùng mới được phép lấy ra khỏi stack
Đ A I * H * * O C T * * * I N * *Bước Ký tự đọc
được
Stack
8 O Đ O I H A Đẩy chữ cái vào stack (PUSH)
9 C Đ O C I H A Đẩy chữ cái vào stack (PUSH)
10 T Đ O C T I H A Đẩy chữ cái vào stack (PUSH)
11 * Đ O C I H A T Lấy chữ cái ra màn hình (POP)
12 * Đ O I H A T C Lấy chữ cái ra màn hình (POP)
13 * Đ I H A T C O Lấy chữ cái ra màn hình (POP)
14 I Đ I I H A T C O Đẩy chữ cái vào stack (PUSH)
15 N Đ I N I H A T C O Đẩy chữ cái vào stack (PUSH)
16 * Đ I I H A T C O N Lấy chữ cái ra màn hình (POP)
17 * Đ I H A T C O N I Lấy chữ cái ra màn hình (POP)
Kết quả: I H A T C O N I
a) Kết quả in ra màn hình là chuỗi ký tự: I H A T C O N I
b) Tình trạng của stack: Đang còn lưu trữ 1 ký tự Đ
Bài 2:
Trang 13Cho một queue nối vòng được hiện thực trên cơ sở mảng có tình trạng như sau:
Hãy thực hiện một chuỗi các thao tác sau:
E A S * Y * * Q U E * * * S T * * * I * O NTrong đó, các chữ cái tượng trưng thao tác InsQueue – đưa phần tử vào hàng
đợi, dấu * tượng trưng cho thao tác deQueue và in ra màn hình
Hỏi: Sau khi kết thúc chuỗi thao tác trên:
a) Kết quả in ra màn hình?
b) Tình trạng của queue như thế nào ? (Vẽ minh họa cụ thể)
Trả lời:
Khái niệm:
- Queue (hàng đợi) là một cấu trúc dữ liệu trừu tượng dùng để chứa các đối tượng
làm việc theo cơ chế “vào trước – ra trước” (First In First Out – FIFO)
- Trong hàng đợi, các đối tượng có thể được thêm vào queue bất kỳ lúc nào nhưng
chỉ có đối tượng thêm vào đầu tiên mới được phép lấy ra khỏi queue
+ Thao tác thêm vào hàng đợi gọi là enqueue
+ Thao tác lấy ra khỏi hàng đợi gọi là dequeue
- Việc thêm vào 1 đối tượng luôn diễn ra ở cuối hàng đợi
- Một phần tử luôn được lấy ra ở đầu hàng đợi
EAS*Y**QUE***ST***I*ONBước Ký tự đọc
được
Queue
10 E Y Q U E E A S Đẩy chữ cái vào queue (ENQUEUE)
11 * Q U E E A S Y Lấy chữ cái ra màn hình (DEQUEUE)
12 * U E E A S Y Q Lấy chữ cái ra màn hình (DEQUEUE)
13 * E E A S Y Q U Lấy chữ cái ra màn hình (DEQUEUE)
14 S E S E A S Y Q U Đẩy chữ cái vào queue (ENQUEUE)
15 T E S T E A S Y Q U Đẩy chữ cái vào queue (ENQUEUE)
16 * S T E A S Y Q U E Lấy chữ cái ra màn hình (DEQUEUE)
17 * T E A S Y Q U E S Lấy chữ cái ra màn hình (DEQUEUE)
18 * E A S Y Q U E S T Lấy chữ cái ra màn hình (DEQUEUE)
19 I I E A S Y Q U E S T Đẩy chữ cái vào queue (ENQUEUE)
20 * E A S Y Q U E S T I Lấy chữ cái ra màn hình (DEQUEUE)
21 O O E A S Y Q U E S T I Đẩy chữ cái vào queue (ENQUEUE)
22 N O N E A S Y Q U E S T I Đẩy chữ cái vào queue (ENQUEUE)
Thêm vào Đưa ra
Trang 14- Đẩy phần tử X vào hàng đợi
- Đẩy phần tử L vào hàng đợi
- Đẩy phần tử R vào hàng đợi
- Lấy phần tử ra khỏi hàng đợi và đưa ra màn hình
- Đẩy phần tử A vào hàng đợi
- Lấy phần tử ra khỏi hàng đợi và đưa ra màn hình
- Lấy phần tử ra khỏi hàng đợi và đưa ra màn hình
- Đẩy phần tử Q vào hàng đợib) Kết quả hiển thị ra màn hình như thế nào?
+ Thao tác thêm vào hàng đợi gọi là enqueue
+ Thao tác lấy ra khỏi hàng đợi gọi là dequeue
- Việc thêm vào 1 đối tượng luôn diễn ra ở cuối hàng đợi
- Một phần tử luôn được lấy ra ở đầu hàng đợi
Front Rear
Trang 154 * L R X Lấy chữ cái ra màn hình (DEQUEUE)
Kết quả: X L R
Kết quả in ra màn hình là chuỗi ký tự: X L R
Bài 4: Cho biểu thức P dưới dạng trung tố: P = (a+b^2)*c – (d+e)
(trong đó ^ là ký hiệu chỉ lũy thừa) phép lũy thừa có mức ưu tiên cao nhất)
Hãy áp dụng giải thuật POLISH để biến đổi P sang dạng hậu tố Nêu rõ tình trạng củaStack và dạng hình thành của biểu thức hậu tố qua từng bước thực hiện, kèm theonhững thuyết minh cần thiết
Trả lời:
Quy tắc:
- Nếu là toán hạng: cho ra output
- Nếu là dấu ( : cho vào stack
- Nếu là dấu ) : lấy các toán tử trong stack ra và cho vào output cho đến khi gặp dấu ( Dấu ( cũng được đưa ra khỏi stack
- Nếu là toán tử:
+ Chừng nào ở đỉnh stack là toán tử và toán tử đó có độ ưu tiên lớn hơn hoặc bằng toán tử hiện tại thì lấy toán tử đó ra khỏi stack và cho ra output
+ Đưa toán tử hiện tại vào stack
- Sau khi duyệt hết biểu thức, nếu trong stack còn phần tử thì lấy hết ra output.
P = (a+b^2)*c - (d+e)
- Phần tử đỉnh S là ^ có ưu tiên cao hơn dấu + Đưa toán tử ^ đưa ra xâu ra
- Đưa toán tử + đưa ra xâu ra
- Hủy luôn dấu (
- Phần tử đỉnh stack là * có ưu tiên cao hơn dấu -, lấy * ghi ra xâu ra.
- Đẩy dấu - vào stack
12 d - ( a b 2 ^ + c * d Đưa toán hạng d ra xâu ra
13 + - ( + a b 2 ^ + c * d Đẩy toán tử + vào stack
14 e - ( + a b 2 ^ + c * d e Đưa toán hạng e ra xâu ra
Trang 1615 ) - a b 2 ^ + c * d e + Lấy phần tử ở đỉnh Stack là toán tử + ghi ra xâu ra,
đến khi gặp dấu ( thì hủy luôn dấu (
16 Hết xâu a b 2 ^ + c * d e + - Lấy các phần tử từ stack ra xâu ra
Xâu hậu tố nhận được: P = a b 2 ^ + c * d e +
Bài 5: Cho biểu thức hậu tố P = a b 2 ^ + c * d e +
-Áp dụng giải thuật EVAL để tính giá trị của biểu thức hậu tố P theo các giá trị củabiến: a=2, b=5, c=10, d=8, e=12
Trả lời:
Quy tắc:
- Nếu là toán hạng: push vào stack
- Nếu là toán tử: pop 2 toán hạng trong stack ra và tính giá trị của chúng dựa vào toán tử này Sau đó push kết quả đó lại vào stack.
- Phần tử còn sót lại trong stack sau vòng lặp chính là kết quả của biểu thức.
Với các giá trị biến đã cho, biểu thức hậu tố P có thể viết lại là:
P = 2 5 2 ^ + 10 * 8 12 + Bước Ký tự đọc được Stack S Giải thích
- Đẩy kết quả 27 vào S
6 10 27 10 10 là toán hạng, đẩy 10 vào S
- Lấy 2 phần tử ra khỏi S (lấy 10, rồi lấy 27)
- Thực hiện phép toán: 27 * 10
- Đẩy kết quả 270 vào S
8 8 270 8 8 là toán hạng, đẩy 8 vào S
9 12 270 8 12 12 là toán hạng, đẩy 12 vào S
Phần 4 (2 điểm) – Cấu trúc cây
Bài 1: Phép duyệt theo thứ tự trước của một cây nhị phân tạo ra: A B D C E G F và
phép duyệt thứ tự giữa tạo ra: D B A E G C F
a) Hãy dựng cây nhị phân này và nêu phương pháp dựng
Trang 17b) Hãy duyệt cây nhị phân dựng được ở câu a) theo thứ tự sau
Trả lời:
a) Dựng cây nhị phân
ABD
Thăm các nút của cây con trái theo thứ tự trước
Thăm các nút của cây con phải theo thứ tự trước
+ Đối với phép duyệt theo thứ tự giữa (LNR: Left Node Right)
Thăm các nút của cây con trái theo thứ tự giữa
Thăm gốc
Thăm các nút của cây con phải theo thứ tự giữa
+ Đối với phép duyệt theo thứ tự sau (LRN: Left Right Node)
Thăm các nút của cây con trái theo thứ tự sau
Thăm các nút của cây con phải theo thứ tự sau
Thăm gốc
- Theo phép duyệt trước, ta xác định được gốc là A
- Theo phép duyệt giữa, ta xác định được cây có 2 nhánh lớn, nhánh bên trái có D, B
b) Hãy duyệt cây nhị phân dựng được ở câu a) theo thứ tự sau (LRN: Left Right Node)
Thăm các nút của cây con trái theo thứ tự sau
Thăm các nút của cây con phải theo thứ tự sau
Thăm gốc
D B G E F C A
Bài 2: a) Phép duyệt theo thứ tự sau của một cây nhị phân tạo ra: P S Q N T R O M và
phép duyệt thứ tự giữa tạo ra: P N S Q M R T O Hãy dựng cây nhị phân này và nêuphương pháp dựng
b) Hãy duyệt cây nhị phân dựng được ở câu a) theo thứ tự trước
Trả lời: