Tải bản đầy đủ (.pdf) (96 trang)

bài tập thực hành cấu trúc dữ liệu và giải thuật

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 (505.51 KB, 96 trang )

TRƯỜNG ĐẠI HỌC SƯ PHẠM KỸ THUẬT HƯNG YÊN
KHOA CÔNG NGHỆ THÔNG TIN

BÀI TẬP THỰC HÀNH

HỌC PHẦN: CẤU TRÚC DỮ LIỆU
VÀ GIẢI THUẬT

Trình độ đào tạo : Đại học
Hệ đào tạo : Chính quy

Hưng Yên năm 2012


Bài tập thực hành CTDL & GT

Trang 2

MỤC LỤC

BÀI THỰC HÀNH 1.

KIỂU DỮ LIỆU CÓ CẤU TRÚC ................................................................................ 3

BÀI THỰC HÀNH 2.

ĐỘ PHỨC TẠP TÍNH TOÁN .................................................................................. 16

BÀI THỰC HÀNH 3+4.

DANH SÁCH NỐI ĐƠN......................................................................................... 22



BÀI THỰC HÀNH 5.

NGĂN XẾP - STACK ............................................................................................. 42

BÀI THỰC HÀNH 6.

HÀNG ĐỢI - QUEUE ........................................................................................... 53

BÀI THỰC HÀNH 7.

DANH SÁCH LIÊN KẾT KÉP ................................................................................. 59

BÀI THỰC HÀNH 8.

DANH SÁCH LIÊN KẾT VÒNG ............................................................................. 70

BÀI THỰC HÀNH 9.

CÂY NHỊ PHÂN .................................................................................................. 81

BÀI THỰC HÀNH 10.

Kiểm tra thực hành .......................................................................................... 96


Bài tập thực hành CTDL & GT

BÀI THỰC HÀNH 1.


Trang 3

KIỂU DỮ LIỆU CÓ CẤU TRÚC

* Mục tiêu
Hệ thống lại kiến thức về kiểu dữ liệu mảng, xâu, tệp, cấu trúc: Cách khai báo, các
thao tác trên, cách thức tổ chức bộ nhớ của mảng, xâu, tệp, cấu trúc
* Yêu cầu:
A. Bài tập mẫu
Bài 1: Cho n số nguyên dương a0,a1,a2,...,an-1.
a.Chèn phần tử x vào vị trí k của dãy.
b.Xóa tất cả các số nguyên tố trong dãy.
Gợi ý:
a.Khởi tạo một mảng trung gian tmp có độ dài là (a.Length+1) sau đó gán các giá
trị : tmp[i]=a[i] với i từ 0 ->k-1 (k-1 là vị trí trước vị trí cần chèn)
tmp[k]=giá trị cần chèn
tmp[i+1]=a[i] với i từ k->a.Length-1
Cuối cùng gán mảng a=tmp.
b.Thực hiện duyệt các phần tử trong mảng kiểm tra xem phần tử đó có phải là số
nguyên tố hay không (số nguyến tố là số chỉ chia hết cho 1 và chính nó) :
+ Nếu là số nguyên tố: Duyệt mảng từ trái sang phải.Từ vị trí số nguyên tố đó tiến
hành dời các phần tử về phía trước cho đến khi kết thúc mảng, sau đó giảm kích
thước mảng
+Ngược lại, chuyển sang kiểm tra phần tử kế tiếp
Lời giản mẫu
using System;
class VD
static int[] a;

{


static void Nhap()
{

int n;
Console.Write("Nhap n=");
n = int.Parse(Console.ReadLine());
a = new int[n];


Bài tập thực hành CTDL & GT
for (int i = 0; i < a.Length; ++i)
{
Console.Write("a[" + i + "]=");
a[i] = int.Parse(Console.ReadLine());
}
}
static void Chen(int x, int k)
{
if (k >= 0 && k <= a.Length - 1)
{
int[] tmp = new int[a.Length + 1];
for (int i = 0; i < k; ++i)
tmp[i] = a[i];
tmp[k] = x;
for (int i = k; i < a.Length; ++i)
tmp[i + 1] = a[i];
a = tmp;
}
else Console.WriteLine("Du lieu khong hop le");

}
static bool ngto(int x)
{
bool ok = true;
for (int i = 2; i < x - 1; ++i)
if (x % i == 0) { ok = false; break; }
return ok;
}
static void Xoa()
{
int n = a.Length;
for (int i = 0; i < n; )
if (ngto(a[i]))

Trang 4


Bài tập thực hành CTDL & GT

Trang 5

{
for (int j = i; j < a.Length - 1; ++j)
a[j] = a[j + 1];
n = n - 1;
}
else ++i;
int[] tmp = new int[n];
for (int i = 0; i < n; ++i)
tmp[i] = a[i];

a = tmp;
}
static void Hien()
{
for (int i = 0; i < a.Length; ++i)
Console.Write(a[i] + "\t");
Console.WriteLine();
}
static void Main()
{
Nhap();
Chen(333, 1);
Hien();
Xoa();
Hien();
Console.ReadKey();
}
}
Bài 2: Cho một danh sách lưu trữ thông tin về các nhân viên trong một công ty, thông tin
gồm :
- Mã nhân viên
- Họ và tên
- Năm sinh (số nguyên)


Bài tập thực hành CTDL & GT

Trang 6

- Phòng ban

- Lương cơ bản (số nguyên)
- Thưởng (số nguyên)
- Thực lĩnh (số nguyên, trong đó thực lĩnh = lương cơ bản + thưởng )
Hãy thực hiện các yêu cầu sau:
a.Tính tổng thực lĩnh tháng của tất cả nhân viên trong công ty.
b.In danh sách những nhân viên có mức lương cơ bản thấp nhất.
Gợi ý:
Để lưu trữ thông tin của từng nhân viên ta khai báo một cấu trúc lưu trữ các thông tin
struct NhanVien
{
public string MaNV;
public string Hoten;
public int Namsinh;
public string Phongban;
public int LuongCB;
public int Thuong;
}
class VD
{
static NhanVien[] DS;
a.Thực hiện duyệt từng nhân viên : tính thực lĩnh của từng người sau đó cộng các
thực lĩnh lại với nhau
b.Trước tiên ta tìm mức lương cơ bản thấp nhất bằng cách :
+ Gán một giá trị min bằng lớn vô cùng : int min = int.MaxValue;
+Duyệt qua từng nhân viên nếu nhân viên nào có mức lương nhỏ hơn min thì
gán min bằng mức lương đó
Cuối cùng in ra thông tin của các nhân viên có mức lương bằng min
Lời giản mẫu
using System;
struct NhanVien

{


Bài tập thực hành CTDL & GT

Trang 7

public string MaNV;
public string Hoten;
public int Namsinh;
public string Phongban;
public int LuongCB;
public int Thuong;
}
class VD
{
static NhanVien[] DS;
static void Nhap()
{
int n;
Console.Write("Nhap n="); n = int.Parse(Console.ReadLine());
DS = new NhanVien[n];
for (int i = 0; i < DS.Length; ++i)
{
Console.WriteLine("Nhap thong tin NV thu:" + i);
Console.Write("Ma nhan vien:"); DS[i].MaNV = Console.ReadLine();
Console.Write("Ho ten:"); DS[i].Hoten = Console.ReadLine();
Console.Write("Nam sinh:"); DS[i].Namsinh = int.Parse(Console.ReadLine());
Console.Write("Phong ban:"); DS[i].Phongban = Console.ReadLine();
Console.Write("Luong co ban:"); DS[i].LuongCB =

int.Parse(Console.ReadLine());
Console.Write("Thuong:"); DS[i].Thuong = int.Parse(Console.ReadLine());
}
}
static int ThucLinh(int i)
{
return DS[i].Thuong + DS[i].LuongCB;
}
static void HienMin()


Bài tập thực hành CTDL & GT

Trang 8

{
int min = int.MaxValue;
for (int i = 0; i < DS.Length; ++i)
if (min > DS[i].LuongCB) min = DS[i].LuongCB;
Console.WriteLine("Danh sach luong cb min");
for (int i = 0; i < DS.Length; ++i)
if (DS[i].LuongCB == min)
Console.WriteLine(DS[i].MaNV + "\t" + DS[i].Hoten + "\t" + DS[i].Namsinh
+ "\t" + DS[i].Phongban + "\t" + DS[i].LuongCB + "\t" + DS[i].Thuong + "\t" +
ThucLinh(i));
}
static void TongLuongCTy()
{
int t = 0;
for (int i = 0; i < DS.Length; ++i)

t += ThucLinh(i);
Console.WriteLine("Tong luong cty:" + t);
}
static void Main()
{
Nhap();
TongLuongCTy();
HienMin();
Console.ReadKey();
}
}
B. Bài tập tự giải
Bài 1: Cho n số nguyên dương a0,a1,a2,...,an-1.
a.Chèn phần tử x vào vị trí k của dãy.
b.Xóa tất cả các số nguyên tố trong dãy.
c.Kiểm tra dãy có tăng dần hay không ?
d.Tìm số nhỏ nhất chia hết cho tất cả các số của dãy.


Bài tập thực hành CTDL & GT

Trang 9

e.Tìm các cặp số nguyên tố cùng nhau (hai số nguyên dương được gọi là nguyên
tố cùng nhau nếu ước số chung lớn nhất của chúng bằng 1).
f.Tìm tần số xuất hiện của các số trong dãy.
Gợi ý:
a. Khởi tạo một mảng trung gian tmp có độ dài là (a.Length+1) sau đó gán các
giá trị : tmp[i]=a[i] với i từ 0 ->k-1 (k-1 la vị trí trước vị trí cần chèn)
tmp[k]=giá trị cần chèn

tmp[i+1]=a[i] với i từ k->a.Length-1
Cuối cùng gán mảng a=tmp.
b. Thực hiện duyệt các phần tử trong mảng kiểm tra xem phần tử đó có phải la số
nguyên tố hay không (số nguyến tố là số chỉ chia hết cho 1 và chính nó) :
+ Nếu là số nguyên tố: Duyệt mảng từ trái sang phải. Từ vị trí số nguyên tố đó tiến
hành dời các phần tử về phía trước cho đến khi kết thúc mảng,sau đó giảm kích
thước mảng
+ Ngược lại,chuyển sang kiểm tra phần tử kế tiếp
c. Duyệt qua các phần tử a[i] của mảng với i từ 0->n-2, tại mỗi phần tử kiểm tra
xem nó có nhỏ hơn các phần tử a[j] kế tiếp không với j=i+1->n-1
+ Nếu không, thoát khỏi vòng lặp trả ra giá trị False (không tăng dần)
+ Ngược lại, kiểm tra phần tử a[i] kế tiếp
d. Đầu tiên ta xây dựng một hàm BCNN(int x,int y) tính BCNN của 2 số. Sau đó
ta khởi tạo giá trị int bc = 1 rồi thực hiện tính BCNN của bc với từng phần tử của
mảng, kết quả thu được đưa vào bc
e. Xây dựng một hàm tìm UCLN của 2 số
Thực hiện duyệt qua từng phần tử a[i] của mảng với i từ 0->n-2, với mỗi phần tử
ta tìm UCLN của phần tử đó với từng phần tử a[j] kế tiếp nó với j từ i+1 -> n-1 .
nếu UCLN =1 ta in ra cặp a[i],a[j] đó.
f. Ta tạo 2 mảng mới: mảng b chứa các phần tử không trùng nhau của mảng a,
mảng c chứa tần số xuất hiện của các số tương ứng ở mảng b ( khởi tạo các phần
tử của c =0)
Khởi tạo b[0]=a[0]. Duyệt qua các phần tử của mảng a:
+Nếu a[i] = b[i] thì c[i] =c[i]+1
+Nếu a[i] !=b[i] thì b[i+1]=a[i]


Bài tập thực hành CTDL & GT

Trang 10


Bài 2: Cho ma trận vuông n dòng và n cột; các phần tử là các số nguyên (0≤ n < 100).
Viết các hàm thực hiện các yêu cầu sau:
a.Tính tổng tất cả các phần tử của ma trận.
b.Tìm giá trị dương nhỏ nhất của ma trận.
c.Tính tổng các phần tử nằm trên đường chéo phụ.
d.Kiểm tra xem các phần tử nằm trên đuờng chéo chính có tăng dần hay không ?
(theo chiều từ góc trên bên trái xuống góc dưới bên phải).
Gợi ý:
a. Khởi tạo 1 giá trị t=0.Sau đó duyệt qua từng phần tử của ma trận , thực hiện
cộng t với từng phần tử trong ma trận:
b. Khởi tạo giá trị min bằng dương vô cùng int min = int.MaxValue;
Thực hiện duyệt qua các phần tử của ma trận,nếu thấy phần tử đó nhỏ hơn
min và lớn hơn 0 thì gán vào min
c.Ta nhận thấy rằng các phần tử a[i,j] thuộc đường chéo chính của ma trận cấp n
thì có j=(n-1)-i với i ,j chạy từ 0 ->n-1
Để tính tổng các phần tử đường chéo phụ ta duyệt qua các phần tử a[i,j] của
ma trận nếu phần tử nào thỏa mãn j=(n-1)-i thì ta thực hiện cộng các phần tử đó lại
d.Ta thấy trong ma trận cấp n thì số phần tử trên đường chéo chính la n.
+ Đầu tiên , ta thực hiện việc khai báo một mảng một chiều []tg có n phần tử chứa
các phần tử a[i,j] trên đường chéo chính của ma trận(với i=j) theo chiều từ góc bên
trái phía trên đến bên phải phía dưới
+ Duyệt qua các phần tử tg[i] của mảng tg với i từ 0->n-2, tại mỗi phần tử kiểm tra
xem nó có nhỏ hơn các phần tử tg[j] kế tiếp không với j=i+1 ->n-1
*Nếu không ,thoát khỏi vòng lặp trả ra giá trị False (không tăng dần)
*Ngược lại,kiểm tra phần tử tg[i] kế tiếp
Bài 3: Cho ma trận vuông n dòng n cột; mỗi phần tử của ma trận là một phân số (giả thiết
rằng tử số và mẫu số của các phân số này là các số nguyên). Hãy thực hiện các yêu cầu
sau:
a.Tìm phân số có giá trị nhỏ nhất nằm trong khoảng.(0;1).

b.Đếm số lượng phân số nằm trong ma trận tam giác trên có giá trị nằm trong
khoảng (0,1)


Bài tập thực hành CTDL & GT

Trang 11

c.Sắp xếp các phân số trong ma trận tăng dần từ trái qua phải và từ trên xuống
dưới.
Gợi ý:
Để lưu trữ thông tin của từng phần tử phân số ma trận ta khai báo một trường lưu
trữ các thông tin của một phân số(tử số và mẫu số)
struct Phanso
{
public int Tu;
public int Mau;
}
class VD
{
static Phanso[] DS;
a.Khởi tạo giá trị nhỏ nhất double min = 1 .
+Thực hiện duyệt qua các phần tử của ma trận.Tại mỗi phần tử thực hiện so sánh
giá trị của tử số chia cho mẫu số với min ,nếu nhỏ hơn min va lớn hơn 0 thì gán
min bằng giá trị đó:
+Hiện ra phần tử có giá trị tử số chia mẫu số bằng min .Dùng một biến đếm int
d=0 đếm các giá trị bằng min,nếu ra khỏi vòng lặp mà d=0 ta kết luận không có
phân số cần tìm
b.Ta thấy các phần tử nằm trong ma trận tam giác trên thì luôn có vị trí hàng nhỏ
hơn vị trí cột (i

DS[i,j] thỏa mãn ic.Thực hiện duyệt các phần tử DS[i,j] của mảng với i từ 0->n-1 và j từ 0->n-2,
Với mỗi phần tử ta so sánh với từng phần tử kế tiếp nó nếu phần tử kế tiếp có giá
trị nhỏ hơn thì thực hiện đổi chỗ 2 phần tử đó với nhau:
Bài 4: Cho một danh sách lưu trữ thông tin về các nhân viên trong một công ty, thông tin
gồm :
- Mã nhân viên
- Họ và tên
- Năm sinh (số nguyên)
- Phòng ban


Bài tập thực hành CTDL & GT

Trang 12

- Lương cơ bản (số nguyên)
- Thưởng (số nguyên)
- Thực lĩnh (số nguyên, trong đó thực lĩnh = lương cơ bản + thưởng )
Hãy thực hiện các yêu cầu sau:
a.Tính tổng thực lĩnh tháng của tất cả nhân viên trong công ty.
b. In danh sách những nhân viên có mức lương cơ bản thấp nhất.
c. Đếm số lượng nhân viên có mức thưởng >= 1200000.
d. In danh sách các nhân viên tăng dần theo phòng ban, nếu phòng ban trùng nhau
thì giảm dần theo mã nhân viên.
e. Cập nhật tăng lương của tất cả các nhân viên lên 5%
Gợi ý: Để lưu trữ thông tin của từng nhân viên ta khai báo một trường lưu trữ các thông
tin
struct NhanVien
{

public string MaNV;
public string Hoten;
public int Namsinh;
public string Phongban;
public int LuongCB;
public int Thuong;
}
class VD
{
static NhanVien[] DS;

a.Trước hết ta xây dựng một hàm thuclinh(int x) để tính thực lĩnh của một nhân
viên bất kỳ. Sau đó ta duyệt từ đầu đến cuối danh sách nhân viên rồi gọi hàm
thuclinh(i) ra. Khi đó ta sẽ được tổng số thực lĩnh tháng của tất cả các nhân viên
trong công ty.
b.Đầu tiên ta gán một biến min=int.MaxValue(giá trị dương vô cùng).


Bài tập thực hành CTDL & GT

Trang 13

+Tiếp theo duyệt qua tất cả các nhân viên kiểm tra xem min>DS[i].LuongCB hay
không?
-Nếu thoả mãn min = DS[i].LuongCB
-Ngược lại,tiếp tục duyệt các nhân viên tiếp theo.
+Khi kết thúc vòng lặp kiểm tra đó ta sẽ tìm được danh sách những người có mức
lương cơ bản thấp nhất.
+Tiếp tục
c. +Khởi tạo biến dem=0,duyệt qua các phần tử của danh sách. Tại mỗi phần tử

kiểm tra xem DS[i].Thuong >= 1200000 nếu thoả mãn thì dem++.
d. Duyệt qua tất cả các phần tử trong mảng. Tại mỗi phần tử ta thực hiện in ra các
thông tin của nhân viên đó. Riêng ở phần thông tin về lương thì ta tăng thêm
5%nữa
Bài 5:Viết chương trình tạo tập tin văn bản có tên là “BANGSO.INP” có cấu trúc như
sau:
-Dòng đầu tiên ghi hai số m và n (m, n là các số nguyên dương nhập từ bàn phím)
-Trong m dòng tiếp theo mỗi dòng ghi n số nguyên ngẫu nhiên trong phạm vi từ 0
đến 1000 (các số cách nhau ít nhất một dấu cách)
Hãy thực hiện các công việc sau:
a.Hãy cho biết chỉ số các dòng có chứa số nguyên tố (giả thiết các dòng trong tập
tin văn bản được đánh số từ 0 đến m-1).
b.Xoay vòng các cột qua phải một vị trí (cột 0 sẽ qua cột 1, cột 1 qua cột 2,... cột
n-1 về cột 0).
c.Sắp xếp các phần tử tăng dần trên từng cột.
Hãy ghi các kết quả trên vào file văn bản có tên là “BANGSO.OUT”.
Bài 6: Cho mảng vuông n. Hãy tìm phần tử lớn nhất trên mỗi đường chéo song song với
đường chéo chính.
Gợi ý: Xây dựng 2 hàm tính max của đường chéo thuộc ma trận đường chéo trên có phần
tử đầu tiên thuộc cột jvà max của đường chéo thuộc ma trận đường chéo dưới có phần tử
đầu tiên thuộc hàng i:


Bài tập thực hành CTDL & GT
*Với

đường

chéo


thuộc

Trang 14

ma

trận

đường

chéo

trên.Khởi

tạo

giá

trị

max=int.MinValue.Duyệt qua các phần tử của mảng tại mỗi phần tử a[i ,j] có j-i =địa chỉ
cột nếu a[i ,j]>max gán max =a[i,j].
*

Với

đường

chéo


thuộc

ma

trận

đường

chéo

dưới.Khởi

tạo

giá

trị

max=int.MinValue.Duyệt qua các phần tử của mảng tại mỗi phần tử a[i ,j] có i-j =địa chỉ
hàng nếu a[i ,j]>max gán max =a[i,j].
Tại hàm Main() thực hiện:
+Duyệt qua số cột của ma trận ,tại mỗi cột gọi hàm tính max chéo trên của cột đó va in ra
+Duyệt qua số hang của ma trận ,tại mỗi hang gọi hàm tính max chéo dưới của hàng đó
và in ra
C. Bài tập làm thêm
Bài 1: Cho mảng một chiều gồm n tọa độ điểm (giả sử hoành độ và tung độ của các
điểm là các số nguyên).
a.Hãy tìm một điểm trong mảng xa gốc tọa độ nhất.
b.Hãy tìm tọa độ hai điểm gần nhau nhất.
c.Hãy xác định tọa độ của hình chữ nhật nhỏ nhất bao hết cả n điểm trên (tọa độ

góc trên bên trái và tọa độ góc dưới bên phải của hình chữ nhật).
Ví dụ n = 5 và tọa độ 5 điểm là: (0,0); (0,3); (3,3); (4,1); (4,4).
Thì kết quả câu a là điểm (4,4), kết quả câu b là (3,3) và (4,4), kết quả câu c là
(0,4); 4(,0).
Bài 2: Viết chương trình tạo một tập tin văn bản có tên là “DAYSO.INP” có cấu trúc như
sau:

-Dòng đầu tiên ghi n (n là số nguyên dương nhập từ bàn phím).
-Trong các dòng tiếp theo ghi n số nguyên ngẫu nhiên trong phạm vi từ 1 đến
10000, mỗi dòng 10 số (các số cách nhau ít nhất một dấu cách).

Hãy thực hiện các công việc sau đây:
a.Tìm giá trị lớn nhất của các số trong tập tin DAYSO.INP.
b.Đếm số lượng số chẵn, số lượng số lẻ trong tập tin DAYSO.INP.
c.Hãy đếm số lượng số nguyên tố, số chính phương, số hoàn hảo, số Amstrong
trong tập tin DAYSO.INP.
Hãy ghi kết quả của các câu a,b,c trên vào tập tin văn bản có tên là “DAYSO.OUT”.


Bài tập thực hành CTDL & GT

Trang 15

Bài 3: Một đơn vị quan tâm về dân số lặp một bản thống kê số lượng người sinh trong
từng năm, kể từ năm 1920 đến 1970 và lưu trữ bảng đó trong máy tính tính bằng một
mảng một chiều N[1920..1970] với N[k] có giá trị bằng số người sinh trong năm k.
Hãy viết giải thuật thực hiện:
a. In ra những năm mà không có người nào được sinh ra
b. Tính số lượng những năm mà số người sinh ra không quá 10
c. Tính số người trên 50 tuổi tính đến năm 1985.



Bài tập thực hành CTDL & GT

Trang 16

BÀI THỰC HÀNH 2. ĐỘ PHỨC TẠP TÍNH TOÁN
* Mục tiêu

Lựa chọn thuật toán tốt để tiết kiện được thời gian, không gian nhớ tốt nhất cho
mỗi bài toán
* Yêu cầu:

A. Bài tập mẫu
Bài 1: Giả sử n ≥ 0 và x là số thực.Hãy tính giá trị của biểu thức sau đây.

Gợi ý:
Algorithms1: O(N2)
double s=1;
for (int i=1;i<=n;i++)
s=s+pow(x,i)/giaithua(i);// giaithua(i) = i!=1.2.3….i
Độ phức tạp theo cách này là O(N2), tuy nhiên chương trình không thể thực hiện
được khi n lớn; chẳng hạn n =100 - do phép tính giai thừa của n không thể thực
hiện..
Algorithms2: O(N2)
double s=1,p;
for (int i=1; i<=n;i++)
{
p=1;
for (int j=1; j<=i;j++)

p=p*x/j;
s=s+p;
}
Độ phức tạp theo cách này vẫn là là O(N2), tuy nhiên chương trình đã không
cần tính giai thừa của n.
Algorithms3: O(N) – độ phức tạp tuyến tính
double s=1,p=1;
for (int i=1;i<=n;i++)
{


Bài tập thực hành CTDL & GT

Trang 17

p=p*x/i;
s=s+p;
}
Lời giản mẫu
using System;
class VD
{
static void Main()
{
double s = 1, p = 1, x;
int n;
Console.Write("Nhap n="); n = int.Parse(Console.ReadLine());
Console.Write("Nhap x="); x = double.Parse(Console.ReadLine());
for (int i = 1; i <= n; i++)
{

p = p * x / i;
s = s + p;
}
Console.WriteLine("Ket qua:" + s);
Console.ReadKey();
}
}
Bài 2: Cộng hai số nguyên lớn a và b, trong đó số a có m chữ số và số b có n chữ số.
Số nguyên lớn ở đây là số có thể có đến vài trăm chữ số. Để lưu trữ các số nguyên
lớn này ta có thể dùng chuỗi (mỗi ký tự của chuỗi là một chữ số) hoặc dùng mảng một
chiều (mỗi phần tử của mảng một chiều là một chữ số).
Gợi ý :Giả sử có 2 số a,b nhập vào ở dạng xâu so1 và so2

Đầu tiên ta thực hiện chuẩn hóa 2 số như sau : kiểm tra xem xâu nào có độ dài nhỏ
hơn thì thêm 0 vào đầu xâu cho đến khi thu được 2 xâu so1 và so2 có độ dài như nhau
Thực hiện tính tổng :Khai báo một biến nhớ =0; Thực hiện duyệt qua các phần tử
của 2 xâu từ phần tử cuối đến phần tử đầu, tại mỗi phần


Bài tập thực hành CTDL & GT

Lời giản mẫu
using System;
using System.Text;
class BaiXau
{
static void chuanHoaSo(ref string so1, ref string so2)
{
StringBuilder s1 = new StringBuilder(so1);
StringBuilder s2 = new StringBuilder(so2);

if (s1.Length > s2.Length)
while (s2.Length < s1.Length)
s2.Insert(0, "0");
else
if (s2.Length > s1.Length)
while (s1.Length < s2.Length)
s1.Insert(0, "0");
so1 = s1.ToString();
so2 = s2.ToString();
}

static string tinhTong(string so1, string so2)
{
string s;
int t, a, b, nho = 0;
int n;
chuanHoaSo(ref so1, ref so2);
StringBuilder kq = new StringBuilder("");
n = so1.Length - 1;
while (n >= 0)
{
a = so1[n] - 48;
b = so2[n] - 48;

Trang 18


Bài tập thực hành CTDL & GT

Trang 19


t = a + b + nho;
s = t.ToString();
if (s.Length == 1) s = "0" + s;
nho = s[0] - 48;
kq.Insert(0, s[1]);
n = n - 1;
}
if (nho == 1) kq.Insert(0, "1");
return kq.ToString();
}
static void Main()
{
string so1, so2;
StringBuilder x = new StringBuilder("");
StringBuilder y = new StringBuilder("");
StringBuilder s = new StringBuilder("");
Console.WriteLine("\t\t BAN HAY NHAP VAO HAI SO NGUYEN");
Console.Write(" "); so1 = Console.ReadLine();
Console.WriteLine("+");
Console.Write(" "); so2 = Console.ReadLine();

x.Append('-', so1.Length > so2.Length ? so1.Length : so2.Length);
y.Append(' ', Math.Abs(so1.Length - so2.Length));

s.AppendFormat("\t\t{0}\n\n", "BAN HAY NHAP VAO HAI SO NGUYEN");
if (so1.Length < so2.Length)
s.AppendFormat(" {0}{1}\n", y.ToString(), so1);
else
s.AppendFormat(" {0}\n", so1);

s.AppendFormat("{0}\n", "+");
if (so2.Length < so1.Length)
s.AppendFormat(" {0}{1}\n", y.ToString(), so2);


Bài tập thực hành CTDL & GT

Trang 20

else
s.AppendFormat(" {0}\n", so2);
s.AppendFormat(" {0}\n", x.ToString());
s.AppendFormat(" {0}", tinhTong(so1, so2));
Console.Clear();
Console.WriteLine(s);
Console.ReadKey();
}
}
B. Bài tập tự giải
Bài 1: Giả sử n ≥ 0 và x là số thực.Hãy tính giá trị của biểu thức sau đây.

Gợi ý:

Ta nhận thấy (x ^ n)/n!=(x.x.x…x)/(n(n-1)(n-2)…2.1) .Để tính S, khai báo 2 biến
p và s
Duyệt qua các số tự nhiên từ 1->n ,tại mỗi số ta thực hiện tính tích của thương x
và số đó với thương x và các số trước nó (p=p*x/i) sau đó thực hiện cộng dồn các kết
quả đó lại ta được tổng S
Bài 2: Cho dãy n số nguyên a0,a1,...,an-1. Hãy chuyển k phần tử đầu tiên của dãy về cuối
dãy.

Gợi ý: Sử dụng một mảng tg chứa k phần tử và mảng tmp chứa n-k phần tử. Duyệt qua

các phần tử a[i] của mảng (i: 0->n):
+Nếu i < k tg[i]=a[i] (chuyển k phần tử đầu sang tg
+Ngược lai, tmp[j++] =a[i] ( khởi tạo j=0) chuyển các phần tử còn lại sang tmp
Sau đó thực hiện ghép 2 mảng tmp và tg với nhau
Bài 3: Cho dãy n số nguyên {ai, ở đây giả sử i=1..n} Dãy con liên tiếp là dãy mà thành
phần của nó là các thành phần liên tiếp nhau trong {a}, ta gọi tổng của dãy con là tổng tất
cả các thành phần của nó. Tìm tổng lớn nhất trong tất cả các tổng của các dãy con của
{a}. Ví dụ nếu n = 7;
4 –5 6 –4 2 3 -7


Bài tập thực hành CTDL & GT

Trang 21

Thì kết quả tổng là 7.
Bài 4. Giả sử n ≥1 và x là số thực. Hãy viết hàm tính giá trị của biểu thức sau đây
(với độ phức tạp tuyến tính):

Gợi ý: Xây dựng một hàm tính biểu thức mẫu với đối số là một số tự nhiên bất kỳ, giả sử

ta có hàm Mau(int n) trả giá trị 1+1/2+…+1/n
Tại hàm Main ta duyệt qua các số tự nhiên i từ 1->n.Tại mỗi số i ta tính tích của (1)mũ i với x mũ i và chia cho hàm Mau (với đối số là số i đó), đồng thời tiến hành cộng
dồn các kết quả đó lại được S
C. Bài tập làm them
Bài 1: Cộng hai số nguyên lớn a và b, trong đó số a có m chữ số và số b có n chữ số. Số
nguyên lớn ở đây là số có thể có đến vài trăm chữ số. Để lưu trữ các số nguyên lớn này ta
có thể dùng chuỗi (mỗi ký tự của chuỗi là một chữ số) hoặc dùng mảng một chiều (mỗi

phần tử của mảng một chiều là một chữ số). Tuy nhiên trong hai phương án này thì
phương án dùng mảng một chiều để lưu trữ sẽ có thuật toán tốt hơn.
Bài 2: Tìm số hạng thứ n của dãy Fibonasci (giải quyết khi n là một số lớn – khi đó ta
không thể sử dụng đệ quy và cũng không thể sử dụng mảng để lưu trữ).
Bài 3: Cho dãy n số nguyên a0,a1,...,an-1.Hãy tìm dãy con liên tiếp tăng dài nhất.
Bài 4: Cho dãy n số nguyên a0,a1,...,an-1.Hãy tìm đoạn con dài nhất chứa toàn số 0.
Bài 5: Cho dãy n số nguyên a0,a1,...,an-1.Hãy tìm dãy con tăng chứa nhiều số


Bài tập thực hành CTDL & GT

Trang 22

BÀI THỰC HÀNH 3+4. DANH SÁCH NỐI ĐƠN
* Mục tiêu

Hệ thống lại những kiến thức liên quan đến danh sách liên kết và các phép toán
trên nó
* Yêu cầu:

A. Bài tập mẫu
Bài 1: Cho một danh sách liên kết đơn l (l chứa địa chỉ nút đầu tiên của danh sách), mỗi
nút là một số nguyên dương.
a.Đếm xem trong danh sách có bao nhiêu số bằng x ?
b.Tìm phần tử dương nhỏ nhất trong danh sách.
c. Xóa phần tử x xuất hiện đầu tiên trong danh sách.
Gợi ý: Khởi tạo một danh sách toàn cục l

a.Khởi tạo một biến đếm d=0.Duyệt qua từng phần tử của danh sách, nếu phần tử
nào có giá trị là x thì tăng d=d+1;

b.Khởi tạo biến minduong=int.MaxValue .Duyệt qua từng phần tử của danh sách
nếu phần tử nào nhỏ hơn min thì gán bằng min
c.Sử dụng 2 nút p và t ,với p=l ,t trỏ vào nút phía trước nút p.Duyệt qua các phần
tử của danh sách đến khi gặp phần tử có giá trị x .Lúc này p trỏ vào phần tử cần
xóa ,ta xóa nút p bằng cách cho nút t nắm thông tin của nút sau nút p
*Chú ý:
+ Có 3 trường hợp p trỏ vào l (phần tử đầu), p trỏ vào cuối (p=null), p trỏ vào
giữa
+ Để quan sát kết quả ta nhập dữ liệu cho danh sách liên kết l
Lời giản mẫu
using System;
class Node
{
public int info;
public Node link;
}
class DSLKD


Bài tập thực hành CTDL & GT

Trang 23

{
static Node l = new Node(); // l dùng để chứa địa chỉ của nút đầu tiên trong danh sách
static void Nhap()
{
Console.WriteLine("Nhap vao day so nguyen");
int i = 0; l = null; Node tg; char kt;
do

{
Console.WriteLine("Nhap so nguyen thu:" + ++i);
tg = new Node();
Console.Write("Info="); tg.info = int.Parse(Console.ReadLine());
tg.link = null;
// bổ sung nút tg vào đầu danh sách l
if (l == null) l = tg;
else { tg.link = l; l = tg; }
Console.WriteLine("Ban nhap tiep C/K"); kt = char.Parse(Console.ReadLine());
} while (char.ToUpper(kt) == 'C');
}
static void Hien()
{
Console.WriteLine("Cac phan tu co trong danh sach");
Node tg = l;
while (tg != null)
{
Console.Write(tg.info + "\t");
tg = tg.link;
}
Console.WriteLine();
}
static int Dem(int x)
{
int d = 0;


Bài tập thực hành CTDL & GT

Node tg = l;

while (tg != null)
{
if (x == tg.info) d++;
tg = tg.link;
}
return d;
}
static int MinDuong()
{
if (l == null) throw new Exception("Danh sach rong");
else
{
int m = int.MaxValue;
Node tg = l;
while (tg != null)
{
if (m > tg.info && tg.info >= 0) m = tg.info;
tg = tg.link;
}
return m;
}
}
static void Xoa(int x)
{
Node p = l;
Node t = p;
while (p != null && p.info != x)
{
t = p;
p = p.link;

}

Trang 24


Bài tập thực hành CTDL & GT

Trang 25

if (p == null) Console.WriteLine("x khong ton tai trong danh sach");
else
{
if (p == l) l = l.link;
else if (p.link == null) t.link = null;
else t.link = p.link;
}
}
//Ham thuc hien cac chuc nang cua chuong trinh
static void Main()
{
Nhap();
Xoa(3);
Hien();
Console.WriteLine("Min duong nho nhat:" + MinDuong());
Console.ReadKey();
}
}
Bài 2: Hãy viết phần khai báo cấu trúc dữ liệu để mô tả một danh sách liên kết đơn l mà
mỗi phần tử chứa một số nguyên. Viết các hàm thực hiện các yêu cầu sau:
a.Tạo một danh sách l1 chỉ chứa các số chẵn và chia hết cho 3 từ danh sách l.

b.Sắp xếp các phần tử của danh sách theo chiều giảm dần.
Gợi ý: Khởi tạo 1 danh sách toàn cục l

a.Tạo một danh sách l1. Sử dụng một nút tg duyệt qua từng phần tử của danh sách
l nếu có phần tử thỏa mãn là số chẵn và chia hết cho 3 thì ta gán 1 nút tmp =tg và
tmp.link=null và đưa tmp vào danh sách l1 :
+Nếu l1 =null thì l=tmp
+Ngược lại them tmp vào danh sách l1 ( tmp.link=l1;l1=tmp)
b.Thực hiện so sánh từng nút i của danh sách với các nút j ở phía sau nó nếu giá trị
của nút i > nút j ta đổi giá trị của 2 nút cho nhau
Lời giải mẫu
using System;


×