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

HƯỚNG DẪN LẬP TRÌNH C pdf

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 (481.51 KB, 36 trang )

HƯỚNG DẪN LẬP TRÌNH C
Mục Lục Trang
CHƯƠNG 1: Cơ bản Lập Trình C
1. Lịch Sử Của C++ 2
2. 1 chương trình C 2
3. Các kiểu dữ liệu 2
4. Khai báo Biến 2
5. BiỂU THỨC (EXPRESSION) 3
6. Khai báo mảng của các kiểu dữ liệu 3
7. Nhập xuất cơ bản 3
8. Hàm Con 4
9. Lệnh điều kiện if else if else 4
10. Lệnh switch( ) 5
11. Lệnh vòng lặp while(điều kiện lặp) 5
12. Lệnh vòng lặp do{} while() 5
13. Lệnh vòng lặp for 5
14. Xử lý Hàm 6
CHƯƠNG 2: Mảng 1 chiều
1. Định nghĩa 7
2. Truyền mảng vào hàm 7
3. Kĩ thuật tìm 7
4. Kỹ thuật đặt lính canh 7
5. Kĩ thuật liệt kê vị trí 8
6. Kĩ thuật tính tổng 8
7. Kĩ thuật đếm 8
8. Kĩ thuật thêm 8
9. Kĩ thuật xoá 8
10. Một số bài tập minh hoạ 9
CHƯƠNG 3: Ma trận – Con trỏ
1. Ma trận 12
2. Con Trỏ 12


3. Một số bài tập minh hoạ 13
CHƯƠNG 4: Trừu tượng hoá dữ liệu
1. Định nghĩa 15
2. Nhập – Xuất 15
3. Các bài tập minh hoạ 15
CHƯƠNG 5: Đệ Quy – Độ phức tạp của thuật toán (tham khảo)
1. Đệ quy 18
2. Độ phức tạp thuật toán 19
CHƯƠNG 6: Tìm kíêm
1. Tìm kíêm tuyến tính 20
2. Tìm kiếm nhị phân 20
CHƯƠNG 7: Sắp Xếp Mảng
1. Sắp xếp tuần tự (InterchangeSort) 21
2. Sắp xếp chèn (InsertionSort) 21
3. Sắp xếp chọn (SelectionSort) 21
4. Sắp xếp nổi bọt (BubbleSort) 22
5. Một số bài tập minh hoạ 22
6. Sắp xếp ma trận tăng dần 23
CHƯƠNG 8: Danh sách Liên Kết
1
1. Danh sách liên kết đơn 24
2. Danh sách liên kết kép (tham khảo) 25
3. Bài tập minh hoạ 26
CHƯƠNG 9: STACK & QUEUE (tham khảo)
1. STACK (Ngăn Xếp) 27
2. Queue (Hàng Đợi) 27
CHƯƠNG 10: CÂY
1. Cấu trúc Cây 28
2. Cây nhị phân 28
3. Cây Nhị Phân Tìm Kiếm 30

CHƯƠNG 11: Chuyển qua lại các Dạng Cấu Trúc
CHƯƠNG 1: Cơ bản Lập Trình C
1. Lịch Sử Của C++
• C++ dựa trên ngôn ngữ lập trình C. C được phát minh trước 1970 bởi Dennis Ritchie, là ngôn ngữ cài đặt hệ
thống cho hệ điều hành Unix.
• C++ được phát minh bởi Bijarne Stroustroup, bắt đầu năm 1979.
• Các chuẩn ngôn ngữ C++ hiện tại được điều khiển bởi ANSI và ISO
2. CHƯƠNG trình C gồm 3 phần chính:
a) Khai báo thư viện, định nghĩa (define) các bíên ko đổi
b) Khai báo các hàm con
c) Khai báo void main()
#include<conio.h>
#include<stdio.h>
#define swap(a,b){ int t = a; a = b; b = t; }
#define MAX 50
void nhap(int a[], int &n){

}
void xuat(int a[], int n){

}
void main(){
clrscr();
int a[MAX], n;
getch();
}
3. Các kiểu dữ liệu: Có 2 loại:
• Kiểu thông thường, sẵn có trg C:
o int : số nguyên _ dung lượng 2byte _ VD: -7, -2, 0, 3, 5, 15, 200, …
o long : số nguyên dài _ dung lượng 4byte _ VD: 0951020158, 1234567890

o float : số thực _ dung lượng 4byte _ VD: -5.6, -8.0, -1, 0, 15.3, …
o char : kí tự _ dung lượng 1byte _ VD: a, b, c, +, -,….
o char* : chuỗi kí tự _ dung lượng n _ VD: dsdsds, Tran Anh Minh, … (n là độ dài chuỗi)
o char[n] : chuỗi kí tự _ dung lượng n (nhưng ko thể thay đổi n, khác với char* có thể thay đổi )
• Kiểu mới, do ng` dùng định nghĩa (sử dụng struct):
o sv : kiểu sinh viên _ gồm hoten(kiểu char[30] ), MaSV( kiểu long ), tb( kiểu float )
o nv : kiểu nhân viên _ gồm hoten(kiểu char[30] ), MaNV( kiểu long ), luong( kiểu float )
• Lưu ý : Các kiểu mới tuỳ theo đề bài sẽ có thay đổi (VD MaSV là kiểu char[5]), 2 kiểu trên là thường đc sử
dụng.
4. Khai báo Biến:
• Khai báo rồi mới khởi tạo biến. VD: int a; a = 5;
• Vừa khai báo, vừa khởi tạo biến.VD: int a = 5;
• Biến mặt nạ: &”tên biến” = “biến” : chỉ là 1 tên gọi khác của biến kia, tức nếu có xử lý trên biến mặt nạ thì biến
kia cũng bị thay đổi y như vậy, do đó cũng chỉ là 1 tên khác
2
a
b
c
VD:
int a = 5;
int &b = a;
a++;
b++;
printf(“%d”,a);
printf(“%d”,b);
Khai báo như vậy có nghĩa:
- ta khai báo 1 biến số nguyên a, gán cho a = 5.
- Sau đó ta đặt 1 tên khác cho a, là b.
- khi lệnh a++ đc thực hiện thì a = b = 6.
- Và khi b++ đc thực hiện thì a = b = 7.

- Khi printf a và b đều cho ra kết quả là 7
- Nếu xuất ra địa chỉ của a và b thì ta sẽ thấy chúng cùng địa chỉ, b chỉ là 1 tên khác
của a
• Biến đồng cấp: “biến 1” = “bíên 2”: bíên 1 sẽ là 1 biến độc lập so với biến 2, khác địa chỉ của biến 2, có giá trị
giống biến 2. Những gì xảy ra cho “biến 1” ko ảnh hưởng gì “biến 2”
VD:
int a = 5;
int b = a;
a = a + 5;
b = b + 2;
printf(“a = %d\n”,a);
printf(“b = %d”,b);
Khi xuất ra màn hình ta sẽ có:
a = 10
b = 7
Nếu xem địa chỉ thì sẽ thấy địa chỉ 2 biến sẽ khác nhau
5. BiỂU THỨC (EXPRESSION)
6. Khai báo mảng của các kiểu dữ liệu (mảng là 1 tập hợp các ptử cùng kiểu dữ liệu):
• MAX là do ng` dùng định nghĩa bằng cách : #define MAX 100 // có thể là 100 hoặc 1 số khác
• Khai báo 1 mảng số nguyên: int a[MAX];
• Khai báo 1 mảng số nguyên dài: long a[MAX];
• Khai báo 1 mảng số thực: float a[MAX];
• Khai báo 1 mảng kí tự: char a[MAX]; => Mảng kí tự chính là 1 chuỗi cố định
• Khai báo 1 mảng sv: sv a[MAX];
7. Nhập xuất cơ bản:
• Nhập: scanf(“ … ”, &… ); và gets(…);
o int : scanf(“%d”, &a);
o long : scanf(“%ld”, &a);
o float : scanf(“%f”, &a);
o char : scanf(“%c”, &a);

o char* : gets(a); // Lưu ý: trước dòng gets(a); phải có flushall();
o char[n] : gets(a); // Lưu ý: trước dòng gets(a); phải có flushall();
• Xuất : printf(“ % ”, … ); hoặc printf(“ 1 câu văn ”); hoặc printf(“ 1 câu văn % ”, …);
o int : printf(“%d”, a);
o long : printf(“%ld”, a);
o float : printf(“%f”, a);
o char : printf(“%c”, a);
o char* : printf(“%s”, a);
o char[n] : printf(“%s”, a);
#include<conio.h>
#include<stdio.h>
void main(){
clrsrcr();
int n;
3
char* s;
printf(“ Moi nhap so nguyen n “);
scanf(“%d”,&n);
printf(“Moi nhap 1 chuoi”);
flushall();
gets(s);
printf(“So nguyen vua nhap la : %d,” n);
printf(“Chuoi vua nhap la : %s”,s);
getch();
}
4
Các câu lệnh nhập
Các câu lệnh xuất
8. Hàm Con: có thể chuyển VD trên thành 1 CT có 2 hàm con, đó là hàm nhập & xuất
Dòng

#include<conio.h>
#include<stdio.h>
void nhap(int &n, char* &s){
printf(“ Moi nhap so nguyen n “);
scanf(“%d”,&n);
printf(“Moi nhap 1 chuoi”);
flushall();
gets(s);
}
void xuat(int n, char *s){
printf(“So nguyen vua nhap la : %d,” n);
printf(“Chuoi vua nhap la : %s”,s);
}
void main(){
clrscr();
int n;
char* s;
nhap(n,s);
xuat(n,s);
getch();
}
Khi ta sửa đổi 1 biến (nhập, tăng thêm, giảm đi, xoá …) thì
khi truyền vào hàm con, ta phải thêm &
Khi xuất ra hay ko thay đổi ảnh hưởng tới biến thì ko cần &
Lưu ý: thay đổi trên mảng thì ko cần &
VD:
void nhap(int a[], int &n) {

}
Tham số truyền vào hàm trong void main() ko nhất thíet phải

trùng tên với trong hàm con (dòng 3 và dòng 18), VD hàm
nhập ta có thể sửa lại như sau và vẫn đúg:
void nhap(int &a, char* &b){
printf(“ Moi nhap so nguyen n “);
scanf(“%d”,&a);
printf(“Moi nhap 1 chuoi”);
flushall();
gets(b);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
9. Lệnh điều kiện if else if else:

Chỉ 1 điều kiện Chỉ 2 điều kiện Hơn 2 đk
Cấu trúc if( điều kiện )
<Xử lý>;
if( điều kiện )
<Xử lý>;
else
<Xử lý>;
if( điều kiện )
<Xử lý>;
else if( điều kiện )
<Xử lý>;
………………
else if( điều kiện )
<Xử lý>;
else
<Xử lý>;
VD if( a > b)
printf(“%d”,a);
if( dem == 0 )
printf(“Ko co ptu ”);
else
printf(“Co ptu”);
if( tb > 9)
printf(“Xuat sac”);
else if( tb > 8 )
printf(“Gioi”);
………………
else if( tb > 7 )
printf(“Kha”);
else

printf(“loại”);
Nhận xét Dùng cho các điều kiện chỉ
có 2 giả thuyết. VD:
đúng/sai, khác hoặc bằng,
>= hoặc < , tồn tại hay ko
tồn tại…
Câu lệnh sẽ xét từ trên xuống, nếu đúg đk trog if
thì xử lý và thoát ra, nếu ko sẻ đi tới cuối và xử lý
của else cuối sẽ đc thực hiện
VD: tb = 8 thì sẽ bỏ qua 2 if đầu và xuất ra “Khá”
VD: tb = 2 thì sẽ bỏ qua 3 if đầu và xuất ra “Loại”.
• Nếu có nhiều hơn 2 xử lý thì các xử lý nằm trong {…}. VD:
if( a > b)
{
printf(“ %d ”, b);
return;
}
• Nếu ko có {…} thì lệnh xử lý gần if nhất là của if, các lệnh còn lại thì ko phải. VD:
if( a > b)
printf(“ %d ”, b);
printf(“%d”,a);
• Nếu có nhiều hơn 2 giả thuyết (phần nằm trong if ) thì các giả thuyết liên kết bởi “&&” hoặc “||” tuỳ TH. VD:
if( a > b && b > 0 )
printf(“%d”,a);
Chỉ thực hiện “xử lý” xuất ra a khi a dương và lớn hơn b
( do a > b > 0 )
if( x == 1 || x == 2 )
printf(“Thoả ”);
Chỉ thực hiện “xử lý” xuất ra “Thoả” khi x = 1 hoặc x = 2
10. Lệnh switch( ) :

5
• Cấu trúc:
switch(“biến”) {
case “giá trị” :
“xử lý”;
break;
……
case “giá trị” :
“xử lý”;
break;
}
• “biến” có thể trong 3 kiểu dữ liệu: int / long / char
• Hàm switch đc dùng thay cho if else if else khi số if else lớn,
khó nhìn. Nhưng cũng có mặt hạn chế là ko dùng cho float / chuỗi,
và ko so sánh đc.
• Khi “biến” có giá trị = với “giá trị” ở case thì các lệnh xử lý ở case
đó sẽ đc thực thi đến khi gặp lệnh break
VD:
switch(thang) // thang la bien kieu int
{
case 1 :
printf(“Thang 1”);
break;
……
case “12” :
printf(“Thang 12”);
break;
}
VD:
switch(c) // c la bien kieu char

{
case ‘a’ :
printf(“a”);
break;
……
case “z” :
printf(“z”);
break;
}
11. Lệnh vòng lặp while(điều kiện lặp): Đkiện lặp sẽ xét trước khi thực hiện các “xử lý” sau nó.
V
D
while( a > b ) {
a ;
b++;
}
while( a > b )
a ;
b++;
while( a > b && a > 0)
a ;
b++;
Nếu có { } thì các lệnh trg dấu
ngoặc đều thuộc vòng lặp, sẽ đc
thực hiện đến khi nào đk lặp sai
(tức a <= b)
Nếu ko có { } thì lệnh gần while nhất sẽ
thuộc vòng lặp & sẽ đc thực hiện đến khi
nào đk lặp sai (tức a <= b)
còn b++ chỉ xãy ra khi a <= b

Liên kết 2 đk lặp cũng giống như
if()
12. Lệnh vòng lặp do{} while(): Giống while nhưng khác là các hàm xử lý trong do { } sẽ diễn ra trước khi xét đk lặp
ở while()
VD do {
a ;
b++;
} while( a > b );
do {
a ;
b++;
} while( a > b && a > 0 );
Nếu có { } thì các lệnh trg dấu ngoặc đều thuộc vòng lặp,
sẽ đc thực hiện đến khi nào đk lặp sai (tức a <= b)
Liên kết 2 đk lặp cũng giống như if()
13. Lệnh vòng lặp for(“biểu thức 1” ; ”biểu thức 2” ; ”biểu thức 3”) :
d) Biểu thức 1 dùng khởi tạo các bíên, biến đếm, biến cộng, biến con trỏ , … VD: int i = 0 ; node* p = h; …
e) Biểu thức 2 dùng làm đk lặp, nếu đk này sai thì for dừng. VD : i<n; p (tương đương với p != NULL) ;…
f) Biểu thức 3 dùng để xử lý biến đếm
g) Các biểu thức đi theo trình tự :
xảy ra biểu thức 1 -> so sánh trong biểu thức 2 -> thực thi các xử lý vòng for -> xử lý trog biểu thức 3
h) Biểu thức 1 & 3 ko có cũng đc, nhưng biểu thức 2 nếu ko có thì for sẽ lặp lại mãi vì ko có đk dừng
V
D
for(;;) for(int i=0; i<n; i++)
t++;
a++;
for(int i=0; i<n; i++) {
t++;
a++;

}
for(int i=0; i<n; i++);
t++;
a++;
for lặp lại mãi t++ sẽ đc thực hiện n lần
còn a++ chỉ xảy ra sau khi vòng
for dừng
t++ & a++ xãy ra n lần Cả a++ và t++ đều ko
thuộc vòng for do có
dấu “;” cuối vòng for.
6
14. Xử lý Hàm
void xuly(int a, int b){
int a++;
int b ;
printf(“a = %d\n”,a);
printf(“b = %d”,b);
}
void tong(){
int x = 5, y = 3;
xuly(x,y);
printf(“x = %d\n”,x);
printf(“y = %d”,y);
}
Lúc này nếu trong void main ta gọi đến hàm tong() , thì sau khi khai báo x = 5, y = 3,
CT sẽ gọi đến hàm xuly(x,y) … lúc này trước khi vào thân hàm xuly, sẽ xảy ra các
câu lệnh sau:
int a = x;
int b = y;
=> ta gán 2 bíên khác, là a và b, có giá trị bằng với x và y => Khi xử lý a,b trong hàm

xuly thì x,y ở ngoài ko thay đổi giá trị ban đầu. Khi ta xuất a, b ra màn hình thì
a = 6
b =2
Nhưng khi thoát khỏi xuly(x,y) trở lại tong(), ta xuất x, y ra màn hình thì vẫn đc gía trị
x, y ban đầu : x = 5, y = 3
void xuly(int &a, int &b){
int a++;
int b ;
printf(“a = %d\n”,a);
printf(“b = %d”,b);
}
void tong(){
int x = 5, y = 3;
xuly(x,y);
printf(“x = %d\n”,x);
printf(“y = %d”,y);
}
Lúc này nếu trong void main ta gọi đến hàm tong() , thì sau khi khai báo x = 5, y = 3,
CT sẽ gọi đến hàm xuly(x,y) … lúc này trước khi vào thân hàm xuly, sẽ xảy ra các
câu lệnh sau:
int &a = x;
int &b = y;
=> ta gán 2 bíên mặt nạ, hay nói cách khác, đặt lại tên cho x,y để có thể dùng trong
hàm, là a và b, có giá trị bằng với x và y => Khi xử lý a,b trong hàm xuly thì x,y ở
ngoài sẽ thay đổi y như vậy. Khi ta xuất a, b ra màn hình thì:
a = 6
b =2
Và khi thoát khỏi xuly(x,y), trở lại tong(), ta xuất x, y ra màn hình thì đc gía trị x, y như
a,b trong hàm:
x = 6

y = 2
void xuly(int &x, int y){
int a++;
int b ;
printf(“a = %d\n”,a);
printf(“b = %d”,b);
}
void tong(){
int x = 5, y = 3;
xuly(x,y);
printf(“x = %d\n”,x);
printf(“y = %d”,y);
}
Lưu ý : Tên biến trong và ngoài hàm có thể khác nhau hoặc giống nhau. Chỉ có tên
biến trong cùng 1 hàm thì phải khác nhau.
Dù cho tên biến trong và ngoài hàm có giống nhau, nhưng nếu đó ko phải khai báo
biến mặt nạ, thì cũng ko làm thay đổi khi ra khỏi hàm. VD bên:
Biến x thay đổi trong hàm xuly sẽ làm x ngoài hàm tong thay đổi theo. Nhưng biến y
thì ko
Trong TH này, kiểu khai báo x ta gọi là khai báo tham số (thay đổi sau lới gọi hàm), y
ta gọi là khai báo tham trị (ko thay đổi sau lời gọi hàm)
7
CHƯƠNG 2: Mảng 1 chiều
1. Định nghĩa: Mảng 1 chiều thực chất là 1 tập hợp các biến có cùng kiểu, có địa chỉ sát bên nhau. VD : thay vì khai
báo a,b,c,d,e,f,g,h là các biến số nguyên, ta có thể khai báo int a[8]. Ta sẽ có a[0], a[1], ,a[7] là các biến int cũng
giống như a,b,c,d,e,f,g,h, nhưng dễ dàng quản lý bởi vòng for: for( int i=0; i<n; i++ )
2. Truyền mảng vào hàm: Khi truyền vào hàm con, ta luôn truyền theo cách tham số: thay đổi cả trong & ngoài
hàm. VD về nhập xuất mảng:
#include<conio.h>
#include<stdio.h>

#define MAX 50
void nhap(int a[ ], int &n){
printf(“ Moi nhap n “);
scanf(“%d”,&n);
printf(“Moi nhap mang ”);
for( int i=0; i<n; i++ )
nhap1ptu(a[i]);
}
void xuat(int a[ ], int n){
printf(“Mang vua nhap: ”);
for( int i=0; i<n; i++ )
xuat1ptu(a[i]);
}
void main(){
int a[MAX];
int n;
nhap(a,n);
getch();
}
#include<conio.h>
#include<stdio.h>
#define MAX 50
void nhap(float a[ ], int &n){
printf(“ Moi nhap n “);
scanf(“%d”,&n);
printf(“Moi nhap mang ”);
for( int i=0; i<n; i++ )
nhap1ptu(a[i]);
}
void xuat(float a[ ], int n){

printf(“Mang vua nhap: ”);
for( int i=0; i<n; i++ )
xuat1ptu(a[i]);
}
void main(){
float a[MAX];
int n;
nhap(a,n);
getch();
}
#include<conio.h>
#include<stdio.h>
#define MAX 50
void nhap(sv a[ ], int &n){
printf(“ Moi nhap n “);
scanf(“%d”,&n);
printf(“Moi nhap mang ”);
for( int i=0; i<n; i++ )
nhap1ptu(a[i]);
}
void xuat(sv a[ ], int n){
printf(“Mang vua nhap: ”);
for( int i=0; i<n; i++ )
xuat1ptu(a[i]);
}
void main(){
sv a[MAX];
int n;
nhap(a,n);
getch();

o Ta phải gọi n bằng cách tham số trong hàm nhập do n trước & trong khi gọi hàm nhập có sự thay đổi, và ta muốn
lưu sự thay đổi này để dùng cho các hàm sau đó như hàm xuất mảng.
o Trong hàm xuất ta ko cần gọi n theo tham số do ko có sự thay đổi n trong hàm xuat()
o Còn mảng a thì mặt định là đã dùng theo cách tham số
3. Kĩ thuật tìm ptử đầu / cuối thoả yêu cầu: bằng cách gặp ptử thoả yêu cầu thì return. Tương tự cho tìm vị trí.
int duong_dau(int a[], int n)
{
for(int i=0; i<n; i++)
if(a[i]>0)
return a[i];
return -1;
}
int chan_cuoi(int a[], int n)
{
for(int i=n-1; i>=0 ; i )
if(a[i]%2==0)
return a[i];
return -1;
}
int vitri_ngto_dau(int a[], int n)
{
for(int i=1; i<n; i++)
if(a[i]%2==0)
return i;
return -1;
}
4. Kỹ thuật đặt lính canh: gán 1 biến # bằng ptử thứ nhất của mảng. so sánh bíên đó với các ptử còn lại để tìm:
lớn nhất, nhỏ nhất, tìm ptử chẵn/lẻ/ngtố lớn nhất/ nhỏ nhất. Hoặc tìm vị trí của chúng.
int ptu_max(int a[], int n)
{

int ln=a[0];
for(int i=0; i<n; i++)
if(a[i] > ln)
ln=a[i];
return ln;
}
int duong_min (int a[], int n)
{
int vt = vitri_duong_dau(a,n);
if( vt == -1 ) return 0;
int dnn = a[vt];
for(int i = vt; i<n; i++)
if( a[i] < dnn && a[i] > 0 )
dnn = a[i];
return dnn;
}
int ptu_ngto_max(int a[], int n)
{
int vt = vitri_ngto_dau(a,n);
if( vt == -1 ) return 0;
int ln = a[vt];
for(int i = vt; i<n; i++)
if( xetngto(a[i]) && a[i] > ln )
ln = a[i];
return ln;
}
int ptu_max(int a[], int n)
{
int t=0;
for(int i=0; i<n; i++)

if( a[i] > a[t] )
t=i;
return t;
}
int vitri_ptu_min (int a[], int n)
{
int vt = 0;
for(int i=1; i<n; i++)
if(a[i] < a[vt])
vt = i;
return t;
}
int vitri_duong_min (int a[], int n)
{
int vt = vitri_duong_dau(a,n);
if( vt == -1 ) return 0;
for(int i = vt; i<n; i++)
if( a[i] < a[vt] && a[i] > 0 )
vt = i;
return vt;
}
8
5. Kĩ thuật liệt kê vị trí: Thay vì return như kĩ thuật tìm vị trí đầu, cuối, với mỗi ptử thoã yêu cầu, ta xuất ra màn
hình vị trí của nó. VD: liệt kê vị trí các ptử max, liệt kê vị trí các ptử dương min, hay liệt kê các ptử ngtố
void lietke_ptu_lonhon_k(int a[], int n, int k)
{
for(int i = vt; i<n; i++)
if( a[i] > k )
printf("%5d",a[i]);
}

void lietke_ptu_chan(int a[], int n)
{
for(int i = vt; i<n; i++)
if( a[i]%2 == 0 )
printf("%5d",a[i]);
}
void lietke_ptu_ngto(int a[], int n)
{
for(int i = vt; i<n; i++)
if( xetngto(a[i]) )
printf("%5d",a[i]);
}
void lietke_vitri_ptu_max(int a[], int n)
{
int t = ptu_max(a,n);
for(int i=0; i<n; i++)
if(a[i] == t)
printf("%5d",i);
}
int lietke_vitri_duong_min (int a[], int n)
{
int t = duong_min(a,n);
if( t == 0 ) return 0;
for(int i = vt; i<n; i++)
if( a[i] == t )
printf("%5d",i);
return 1;
}
6. Kĩ thuật tính tổng: Đặt 1 biến s = 0 trước khi vào vòng for. Kiểm tra từng ptử a[i], ptử nào thoả yêu cầu thì cộng
dồn vào s.

long tong(int a[], int n)
{
long s=0;
for(int i=0; i<n; i++)
s += a[i];
return s;
}
long tong_duong(int a[], int n)
{
long s=0;
for(int i=0; i<n; i++)
if( a[i] > 0 )
s += a[i];
return s;
}
long tong_ngto(int a[], int n)
{
long s=0;
for(int i=0; i<n; i++)
if( xetngto(a[i]) )
s += a[i];
return s;
}
7. Kĩ thuật đếm: Đặt 1 biến đếm d = 0 trc khi vào vòng for, Kiểm tra từng ptử a[i], ptử nào thoả yêu cầu thì tăg biến
đếm lên 1.
int dem_chan(int a[], int n)
{
int dem=0;
for(int i=0; i<n; i++)
if ( a[i]%2==0 )

dem+
+;
return dem;
}
int dem_ngto(int a[], int n)
{
int dem=0;
for(int i=0; i<n; i++)
if ( xet_so_nt(a[i])==1 )
dem++;
return dem;
}
int dem_ptu_max( int a[], int n )
{
int dem=0;
int ln=lonnhat(a,n);
for(int i=0; i<n; i++)
if(a[i]==ln)
dem++;
return dem;
}
8. Kĩ thuật thêm:
Thêm 1 ptử t vào vị trí k Cho 1 mảng tăng. Thêm t vào mà mảng vẫn tăng
void them_ptu(int a[],int &n, int k, int t)
{
for (int i=n; i>k; i )
a[i]=a[i-1];
a[k] = t;
n=n+1;
}

void them_tang(int a[],int &n int t)
{
for (int i=n-1; i>=0 && a[i] > t; i )
a[i+1]=a[i];
a[i+1] = t;
n=n+1;
}
9. Kĩ thuật xoá:
Xoá ptử ở vị trí k Xoá các ptử lớn nhất mảng
void xoa_ptu(int a[], int &n,int k)
{
for (int i=vitrixoa; i<n; i++)
a[i]=a[i+1];
n=n-1;
}
void xoa_max(int a[], int &n)
{
int ln=ptu_max(a,n);
for(int i=0; i<n; )
if( a[i] == ln ) xoavitri(a,n,i);
else i++;
}
9
10. Một số bài tập minh hoạ:
• Tính tổng các ptử dương trong mảng các số thực
#include<conio.h>
#include<stdio.h>
#define maximum 100
void nhap(float a[],int &n) {
printf("Nhap vao tong cac phan tu :");

scanf("%d", &n);
printf("Bat dau nhap cac ptu cua mang : \n");
for( int i=0; i<n; i++) {
printf("Ptu thu %d : ",i+1 );
scanf("%f",&a[i]);
}
}
void xuat(float a[], int n) {
for(int i=0; i<n; i++)
printf("%4.1f",a[i]);
}
float tongptuduong(float a[], int n) {
float s=0;
for(int i=0; i<n; i++)
if(a[i]>0)
s = s + a[i];
return s;
}
void main()
{
clrscr();
int n;
float a[maximum];
nhap(a,n);
printf("\nMang vua nhap : "); xuat(a,n);
float s = tongptuduong(a,n);
printf("\nTong cac ptu duong trong mang : %4.1",s);
getch();
}
• Tính tổng các giá trị chính phương trong mảng các số nguyên

#include<conio.h>
#include<stdio.h>
#include<math.h>
#define maximum 100
void nhap(int a[],int &n) {
printf("Nhap vao tong cac phan tu, luu y phai <=100 va >0 :");
scanf("%d", &n);
printf("Bat dau nhap cac ptu cua mang : \n");
for( int i=0; i<n; i++) {
printf("So thu %d : ",i+1 );
scanf("%d",&a[i]);
}
}
void xuat(int a[], int n) {
for(int i=0; i<n; i++)
printf("%4d",a[i]);
}
int xet_chinh_phuong(int k) {
if(k<4) return 0;
else if( sqrt(k) == (int) sqrt(k) ) return 1;
return 0;
}
long tongptu_chinhphuong(int a[], int n) {
long s=0;
for(int i=0; i<n; i++)
if ( xet_chinh_phuong(a[i])==1 )
s += a[i];
return s;
}
void main() {

clrscr();
int n,a[maximum];
nhap(a,n);
printf("\nMang vua nhap : "); xuat(a,n);
long s = tongptu_chinhphuong(a,n);
if(s==0) printf("\nMang ko co ptu chinh phuong. ");
else printf("\nTong cac ptu chinh phuong: %ld",s);
getch();
}
• Đếm số lượng giá trị dương chia hết cho 7 trong mảng các số thực
#include<conio.h>
#include<stdio.h>
#define maximum 100
void nhap(float a[],int &n) {
printf("Nhap vao tong cac phan tu:");
scanf("%d", &n);
printf("Bat dau nhap cac ptu cua mang : \n");
for( int i=0; i<n; i++) {
printf("So thu %d : ",i+1 );
scanf("%f",&a[i]);
}
}
void xuat(float a[], int n) {
for(int i=0; i<n; i++)
printf("%4.1f",a[i]);
}
int demchiahetbay(float a[], int n) {
int dem=0;
for(int i=0; i<n; i++)
if ( a[i] – (int) a[i] == 0 )

if( a[i]%7==0 && a[i]>0 )
dem++;
return dem;
}
void main() {
clrscr();
int n;
float a[maximum];
nhap(a,n);
printf("\nMang vua nhap : "); xuat(a,n);
int dem = demchiahetbay(a,n);
printf("\nMang co %d ptu duong chia het cho 7 ",dem);
getch();
}
10
• Đếm số lượng số nguyên tố trong mảng các số nguyên
#include<conio.h>
#include<stdio.h>
#include<math.h>
#define maximum 100
void nhap(int a[],int &n) {
printf("Nhap vao tong cac phan tu :");
scanf("%d", &n);
printf("Bat dau nhap cac ptu cua mang : \n");
for( int i=0; i<n; i++) {
printf("So thu %d : ",i+1 );
scanf("%d",&a[i]);
}
}
void xuat(int a[], int n)

{
for(int i=0; i<n; i++)
printf("%4d",a[i]);
}
int xet_so_nt(int k) {
if (k<2) return 0;
if (k==2) return 1;
if (k%2==0) return 0;
for (int j=3; j*j<= k ; j++)
if (k%j==0) return 0;
return 1;
}
int demnguyento(int a[], int n) {
int dem=0;
for(int i=0; i<n; i++)
if ( xet_so_nt(a[i])==1 )
dem++;
return dem;
}
void main() {
clrscr();
int n,a[maximum];
nhap(a,n);
printf("\nMang vua nhap : "); xuat(a,n);
int dem = demnguyento(a,n);
printf("\nMang co %d so nguyen to.",dem);
getch();
}
• Kiểm tra mảng số thực có tồn tại giá trị chẵn hay ko
#include<conio.h>

#include<stdio.h>
#define maximum 100
void nhap(float a[],int &n) {
printf("Nhap vao tong cac phan tu :");
scanf("%d", &n);
printf("Bat dau nhap cac ptu cua mang : \n");
for( int i=0; i<n; i++) {
printf("So thu %d : ",i+1 );
scanf("%f",&a[i]);
}
}
void xuat(float a[], int n) {
for(int i=0; i<n; i++)
printf("%4.1f",a[i]);
}
int tontaichan(float a[], int n) {
for(int i=0; i<n; i++)
if( a[i] – (int) a[i] == 0 )
if( a[i]%2==0)
return 1;
return 0;
}
void main() {
clrscr();
int n;
float a[maximum];
nhap(a,n);
printf("\nMang vua nhap : "); xuat(a,n);
int t = tontaichan(a,n);
if(t==0) printf("\nMang ko co gia tri chan.");

else printf("\nMang co gia tri chan.");
getch();
}
• Kiểm tra mảng số nguyên có tăng dần hay ko
#include<conio.h>
#include<stdio.h>
#define maximum 100
void nhap(int a[],int &n)
{
printf("Nhap vao tong cac phan tu :");
scanf("%d", &n);
printf("Bat dau nhap cac ptu cua mang : \n");
for( int i=0; i<n; i++) {
printf("So thu %d : ",i+1 );
scanf("%d",&a[i]);
}
}
void xuat(int a[], int n) {
for(int i=0; i<n; i++)
printf("%4d",a[i]);
}
int kttang(int a[], int n) {
for(int i=0; i<n-1; i++)
if( a[i]>a[i+1] )
return 0;
return 1;
}
void main() {
clrscr();
int n,a[maximum];

nhap(a,n);
printf("\nMang vua nhap : ");
xuat(a,n);
int t = kttang(a,n);
if(t==0) printf("\nMang ko co tinh tang dan.");
else printf("\nMang co tinh tang dan.");
getch();
}
11
• Xoá các ptử âm trong mảng số thực
#include<conio.h>
#include<stdio.h>
#define maximum 100
void nhap(float a[],int &n) {
printf("Nhap vao tong cac phan tu:"); scanf("%d", &n);
printf("Bat dau nhap cac ptu cua mang : \n");
for( int i=0; i<n; i++) {
printf("So thu %d : ",i+1 );
scanf("%f",&a[i]);
}
}
void xuat(float a[], int n) {
for(int i=0; i<n; i++)
printf("%4.1f",a[i]);
}
void xoavitri(float a[], int &n,int vitrixoa) {
for (int i=vitrixoa; i<n; i++)
a[i]=a[i+1];
n=n-1;
}

void xoaam(float a[], int &n) {
for(int i=0; i<n; )
if(a[i]<0) xoavitri(a,n,i);
else i++;
}
void main() {
clrscr();
int n,k;
float a[maximum];
nhap(a,n);
printf("\nMang vua nhap : "); xuat(a,n);
xoaam(a,n);
printf("\nMang vua xoa gia tri : ");
xuat(a,n);
getch();
}
• Xoá các ptử nguyên tố trong mảng số nguyên
#include<conio.h>
#include<stdio.h>
#define maximum 100
void nhap(int a[],int &n) {
printf("Nhap vao tong cac phan tu:"); scanf("%d", &n);
printf("Bat dau nhap cac ptu cua mang : \n");
for( int i=0; i<n; i++) {
printf("So thu %d : ",i+1 );
scanf("%d",&a[i]);
}
}
void xuat(int a[], int n) {
for(int i=0; i<n; i++)

printf("%4d",a[i]);
}
int xet_so_nt(int k) {
if (k<2) return 0;
if (k==2) return 1;
if (k%2==0) return 0;
for (int j=3; j*j<= k ; j++)
if (k%j==0) return 0;
return 1;
}
void xoavitri(int a[], int &n,int vitrixoa) {
for (int i=vitrixoa; i<n; i++)
a[i]=a[i+1];
n=n-1;
}
void xoanguyento(int a[], int &n)
{
for(int i=0; i<n;)
if( xet_so_nto(a[i])==1 ) xoavitri(a,n,i);
else i++;
}
void main() {
clrscr();
int n,k, a[maximum];
nhap(a,n);
printf("\nMang vua nhap : "); xuat(a,n);
xoaam(a,n);
printf("\nMang vua xoa gia tri : ");
xuat(a,n);
getch();

}
12
CHƯƠNG 3: Ma trận – Con trỏ
1. Ma trận
• Ma trận thực chất chính là mảng 1 chiều nếu xét về cách tổ chức trong bộ nhớ. Chỉ khác là khi xuất ra màn hình
ta có dạng bảng.

• Khai báo ma trận: KDL <tên>[<hằng số>][<hằng số>].
• VD: int a[ 10 ][ 50 ]  Ma trận 10 dòng 50 cột
• Nhập xuất ma trận:
Nhập ma trận Xuất ma trận
void nhaphangcot( int &m, int &n )
{
printf("Nhap vao so hang ma tran: ");
scanf("%d", &m);
printf("Nhap vao so cot ma tran:");
scanf("%d", &n);
}
void nhap( int a[ ][MAX], int m, int n )
{
printf("Bat dau nhap cac ptu: \n");
for( int i=0; i<m; i++ )
for( int j=0;j<n; j++ ) {
printf(“\na[%d][%d] = ”,i,j);
scanf(“%d”,&a[i][j])
}
}
void xuat( int a[][mx], int m, int n )
{
for( int i=0; i<m; i++ )

{
for( int j=0;j<n; j++ )
printf("%5d",a[i][j] );
printf("\n");
}
}
• Các kĩ thuật đếm, tính tổng, tìm kiếm, đặt cơ hiệu thực tương tự mảng 1 chiều, chỉ khác ở 2 vòng for
2. Con Trỏ:
• Định nghĩa: Con trỏ đơn giản chỉ là địa chỉ của một vị trí bộ nhớ và cung cấp cách gián tiếp để truy xuất dữ liệu
trong bộ nhớ. VD:
o Trong VD bên, ta khai báo 1 biến int tên num có giá trị = 10
o Biến num nằm ở địa chỉ 1000 trên bộ nhớ
o Ta khai báo tiếp 1 con trỏ kiểu int tên prt1.
o Con trỏ này cũng là 1 biến, nên cũng có địa chỉ, nó nằm ở
địa chỉ 2000 trên bộ nhớ.
o Con trỏ chứa địa chỉ của biến num  giá trị của con trỏ là
1000
o Khi ta xuất *ptr1, ta sẽ xuất ra giá trị nằm ở địa chỉ mà con trỏ ptr1 chứa, tức giá trị tại vị trí 1000  xuất
ra 10
• Cấp phát: cách dễ nhất là dùng new: KDL *<tên con trỏ> = new KDL[bề rộng vùng cấp phát]
o int *p = new int; // Cấp phát 1 vùng nhớ rộng 2 byte
o float *a = new float[n] ; // Cấp phát 1 vùng nhớ rộng 4n byte
o sv *ptr = new sv[5]; // Cấp phát 1 vùng nhớ rộng 5.sizeof(sv) byte
o Ta phải cấp phát trong các trường hợp chưa biết địa chỉ của bíên cần trỏ tới, hay muốn cấp phát 1 mảng
động: sử dụng mảng động giúp giảm chi phí bộ nhớ hơn mảng tĩnh.VD:
 sv a[50]; // mảg tĩnh ko thay đổi chỉ số ptử. nếu sử dụng < 50 ptử thì gây lãn phí
 sv *a = new sv[n]; // mảng động sẽ tuỳ theo số ptử người dùng nhập (vd 20 ptử)
• Gỉai phóng bộ nhớ: Dùng delete: delete <tên con trỏ>
o delete p;
o delete a[];

o delete ptr[];
13
14
3. Một số bài tập minh hoạ:
• Tính tích các số lẻ trong ma trận các số thực
#include<conio.h>
#include<stdio.h>
#define mx 30
void nhaphangcot( int &m, int &n ) {
printf("Nhap vao so hang ma tran :"); scanf("%d", &m);
printf("Nhap vao so cot ma tran :"); scanf("%d", &n);
}
void nhap( float a[][mx],int m, int n ) {
printf("Bat dau nhap cac ptu cua ma tran. \n");
for( int i=0; i<m; i++ )
for( int j=0;j<n; j++ ){
printf(“a[%d][%d] = ”,i,j);
scanf(“%f”,&a[i][j]);
}
}
void xuat( float a[][mx], int m, int n ) {
for( int i=0; i<m; i++ ) {
for( int j=0;j<n; j++ )
printf("%5.1f",a[i][j] );
printf("\n");
}
}
long tich_le( float a[][mx], int m, int n ) {
long t = 1;
for( int j=0; j<n; j++ )

for( int i=0; i<m; i++ )
if( a[i][j]%2==0 )
t *= a[i][j];
return t;
}
void main() {
clrscr();
float a[mx][mx]
int m,n;
nhaphangcot(m,n);
nhap(a,m,n);
printf("\nMa tran vua nhap la : \n"); xuat(a,m,n);
long kq = tich_le(a,m,n);
printf(“\nTich cac so lecua ma tran: %4.1f”,kq);
getch();
}
• Tính trung bình cộng các số dương trong ma trận các số nguyên
#include<conio.h>
#include<stdio.h>
#define mx 30
void nhaphangcot( int &m, int &n ) {
printf("Nhap vao so hang ma tran:"); scanf("%d", &m);
printf("Nhap vao so cot ma tran:"); scanf("%d", &n);
}
void nhap( int a[][mx],int m, int n ) {
printf("Bat dau nhap cac ptu cua ma tran. \n");
for( int i=0; i<m; i++ )
for( int j=0;j<n; j++ ){
printf(“a[%d][%d] = ”,i,j);
scanf(“%d”,&a[i][j]);

}
}
void xuat( int a[][mx], int m, int n ) {
for( int i=0; i<m; i++ ) {
for( int j=0;j<n; j++ )
printf("%5d",a[i][j] );
printf("\n");
}
}
float tbcongduong( int a[][mx], int m, int n ) {
int s=0, dem=0;
for( int i=0; i<m; i++ )
for( int j=0;j<n; j++ )
if(a[i][j]>0) {
s += a[i][j];
dem++;
}
if(dem!=0) return (float) s/dem;
return 0;
}
void main() {
clrscr();
int a[mx][mx],m,n;
nhaphangcot(m,n);
nhap(a,m,n);
printf("\nMa tran vua nhap la : \n"); xuat(a,m,n);
float kq = tbcongduong(a,m,n);
if(kq==0) printf("\nMa tran ko co ptu duong. ");
else printf("\nTBC cac ptu duong la : %6.2f",kq);
getch();

}
• Đếm số ngtố trong ma trận các số thực
#include<conio.h>
#include<stdio.h>
#define mx 30
void nhaphangcot( int &m, int &n ) {
printf("Nhap vao so hang ma tran:"); scanf("%d", &m);
printf("Nhap vao so cot ma tran:"); scanf("%d", &n);
}
void nhap( float a[][mx],int m, int n ) {
printf("Bat dau nhap cac ptu cua ma tran. \n");
for( int i=0; i<m; i++ )
for( int j=0;j<n; j++ ){
printf(“a[%d][%d] = ”,i,j);
scanf(“%f”,&a[i][j]);
}
}
void xuat( float a[][mx], int m, int n ) {
for( int i=0; i<m; i++ ) {
for( int j=0;j<n; j++ )
printf("%5.1f",a[i][j] );
printf("\n");
}
}
int xetngto(float x) {
if( x – (int) x != 0 ) return 0;
if(x<2) return 0;
if(x==2) return 1;
if(x%2==0) return 0;
for(int i=3;i*i<=x;i++)

if(x%i==0) return 0;
return 1;
}
int demngto( float a[][mx], int m, int n ) {
int dem=0;
for( int i=0; i<m; i++ )
for( int j=0;j<n; j++ )
if( xetngto(a[i][j])==1) dem++;
return dem;
}
void main() {
float a[mx][mx];
int m,n;
nhaphangcot(m,n); nhap(a,m,n);
printf("\nMa tran vua nhap la : \n"); xuat(a,m,n);
int kq = demngto(a,m,n);
if(kq==0) printf("\nMa tran ko co ptu ngto. ");
else printf("\nSo cac ptu ngto la : %d",kq);
getch();
}
15
• Đếm số lượng số âm trên 1 hàng trong ma trận các số nguyên
#include<conio.h>
#include<stdio.h>
#define mx 30
void nhaphangcot( int &m, int &n ) {
printf("Nhap vao so hang ma tran:"); scanf("%d", &m);
printf("Nhap vao so cot ma tran:"); scanf("%d", &n);
}
void nhap( int a[][mx],int m, int n ) {

printf("Bat dau nhap cac ptu cua ma tran. \n");
for( int i=0; i<m; i++ )
for( int j=0;j<n; j++ ){
printf(“a[%d][%d] = ”,i,j);
scanf(“%d”,&a[i][j]);
}
}
void xuat( int a[][mx], int m, int n ) {
for( int i=0; i<m; i++ ) {
for( int j=0;j<n; j++ )
printf("%5d",a[i][j] );
printf("\n");
}
}
void am_hang( int a[][mx], int m, int n ) {
for( int i=0; i<m; i++ ) {
int dem=0;
for( int j=0;j<n; j++ )
if( a[i][j] < 0 )
dem++;
printf("\nSo am tren hang %d la %d",i+1,dem);
}
}
void main() {
int a[mx][mx],m,n;
nhaphangcot(m,n);
nhap(a,m,n);
printf("\nMa tran vua nhap la : \n");
xuat(a,m,n);
am_hang(a,m,n);

getch();
}
• Kiểm tra ma trận số thực có tồn tại số lẻ ko
#include<conio.h>
#include<stdio.h>
#define mx 30
void nhaphangcot( int &m, int &n ) {
printf("Nhap vao so hang ma tran:"); scanf("%d", &m);
printf("Nhap vao so cot ma tran:"); scanf("%d", &n);
}
void nhap( float a[][mx],int m, int n ) {
printf("Bat dau nhap cac ptu cua ma tran. \n");
for( int i=0; i<m; i++ )
for( int j=0;j<n; j++ ){
printf(“a[%d][%d] = ”,i,j);
scanf(“%f”,&a[i][j]);
}
}
void xuat( float a[][mx], int m, int n ) {
for( int i=0; i<m; i++ ) {
for( int j=0;j<n; j++ )
printf("%5.1f",a[i][j] );
printf("\n");
}
}
int tontai_le( float a[][mx], int m, int n ) {
for( int i=0; i<m; i++ )
for( int j=0;j<n; j++ )
if( (a[i][j]%2) == 1 )
return 1;

return 0;
}
void main()
{
clrscr();
float a[mx][mx];
int m,n;
nhaphangcot(m,n);
nhap(a,m,n);
printf("\nMa tran vua nhap la : \n"); xuat(a,m,n);
int kq = tontai_le(a,m,n);
if(kq==1) printf("\nMa tran co ptu le. ");
else printf("\nMa tran toan chan.");
getch();
}
• Tìm ptử âm lớn nhất trong ma trận số thực
#include<conio.h>
#include<stdio.h>
#define mx 30
void nhaphangcot( int &m, int &n ) {
printf("Nhap vao so hang ma tran:"); scanf("%d", &m);
printf("Nhap vao so cot ma tran:"); scanf("%d", &n);
}
void nhap( float a[][mx],int m, int n ) {
printf("Bat dau nhap cac ptu cua ma tran. \n");
for( int i=0; i<m; i++ )
for( int j=0;j<n; j++ ){
printf(“a[%d][%d] = ”,i,j);
scanf(“%f”,&a[i][j]);
}

}
void xuat( float a[][mx], int m, int n ) {
for( int i=0; i<m; i++ ) {
for( int j=0;j<n; j++ )
printf("%5.1f",a[i][j] );
printf("\n");
}
}
int amlonnhat( float a[][mx], int m , int n) {
float k=0;
for( int i=0;i<m; i++ )
for( int j=0;j<n; j++ )
if( a[i][j] < 0 ) {
k=a[i][j];
break;
}
if(k==0) return 0;
for( i=0;i<m; i++ )
for( int j=0;j<n; j++ )
if ( k<a[i][j] && a[i][j]<0 )
k=a[i][j];
return k;
}
void main() {
float a[mx][mx];
int m,n;
nhaphangcot(m,n);
nhap(a,m,n);
printf("\nMa tran vua nhap la : \n"); xuat(a,m,n);
int kq = amlonnhat(a,m,n);

if(kq == 0) printf("\nMa tran ko co gia tri am");
else printf("\nGia tri am MAX la %d",kq);
getch();
}
16
17
CHƯƠNG 4: Trừu tượng hoá dữ liệu
1. Định nghĩa:
• Trừu tượng hoá dữ liệu chính là tạo ra 1 kiểu dữ liệu mới ( sv, nv, phanso, soao, taikhoan… ) bằng cách hợp các
kiểu dữ liệu đơn giản thành 1 kiểu phức tạp hơn, nhằm mô tả 1 đối tượng trong thế giới thực
• VD: Ta khai báo kiểu dữ liệu sv, gán a là 1 sv: sv a  Ta có a là 1 biến có kiểu sv _ 1 sinh viên, có họ tên,
điểm trung bình, năm sinh …
• Cú pháp:
• Mộ số KDL mới cơ bản:
KDL sinh viên KDL nhân viên KDL đơn thức KDL tài khoản ngân hàng
struct sv
{
char ten[30];
long mssv;
int ns;
float dtb;
};
struct nv
{
char ten[30];
long maNV;
int namsinh;
float luong;
};
struct donthuc

{
float a;
int n;
};
struct tk
{
char ten[30];
long mstk;
float sotien;
};
KDL nút của DSLK KDL nút của cây nhị phân KDL phân số KDL điểm trong mặt phẳng
struct nodeList
{
data info;
nodeList* next;
};
struct nodeTree
{
data info;
nodeTree* left;
nodeTree* right;
};
struct ps
{
int tu;
int mau;
};
struct diem
{
float x;

float y;
};
2. Nhập – Xuất
• Ta nhập – xuất lần lượt từng thành viên của mỗi struct theo như Nhập xuất cơ bản ( chương 1, mục 7 ), chỉ khác
ở nhập float & thêm tên đối tượng của struct. VD: Ta khai báo: sv x;
void nhap(sv &x){
flushall();
printf(“Nhap ten:”); gets(x.ten);
printf(“Nhap mssv:”); scanf(“%ld”,&x.mssv);
printf(“Nam sinh:”); scanf(“%d”,&x.ns);
float t;
printf(“Diem tb:”); scanf(“%f”,&t);
x.dtb = t;
}
void xuat(sv x){
printf(“Ten SV: %s”, x.ten);
printf(“Mssv: %ld”, x.mssv);
printf(“Nam sinh: %d”, x.ns);
printf(“Diem tb:%2.1f”, x.dtb);
}
• Như VD trên, khi nhập thành phần kiểu float thì ko nhập trực tiếp như scanf(“%f”,&x.dtb); mà phải thông qua 1
biến t kiểu float. Và trước khi gets(…) phải có flushall(); Khi xuất ra hay sử dụng thì bình thường.
3. Các bài tập minh hoạ
• Tính tổng 2 phân số
#include<conio.h>
#include<stdio.h>
struct ps {
int tu,mau;
};
void nhap( ps &p ){

printf("\nNhap tu cua phan so : "); scanf("%d",&p.tu);
printf("Nhap mau cua phan so : "); scanf("%d",&p.mau);
}
void xuat( ps p ) {
if(p.mau == 1) printf("%3d",p.tu);
else printf(" %d/%d ",p.tu,p.mau);
}
int UCLN(int a, int b) {
a = abs(a);
b = abs(b);
while(a!=b)
if(a>b) a-=b;
else b-=a;
return a;
}
ps rutgon( ps p ) {
int t = UCLN(p.tu,p.mau);
p.tu /= t;
p.mau /= t;
return p;
}
ps tong( ps m , ps p) {
ps sum = m;
if(m.mau == p.mau) sum.tu += p.tu;
else {
sum.tu = sum.tu*p.mau + p.tu*sum.mau;
sum.mau = sum.mau*p.mau;
}
sum = rutgon(sum);
return sum;

}
void main() {
ps m,p;
printf("\tNhap phan so 1 : "); nhap(m);
printf("\tNhap phan so 2 : "); nhap(p);
printf("\nPhan so vua nhap la : "); xuat(m); xuat(p);
ps kq = tong(m,p);
printf("\nTong 2 phan so la : "); xuat(kq);
getch();
}
18
struct <tên KDL mới> {
// Khai báo các thành phần
};
• Tính khoảng cách giữa 2 điểm trên mặt phẳng Oxy
#include<conio.h>
#include<stdio.h>
#include<math.h>
typedef struct diem {
float x,y;
}dm;
void nhap( dm &a ) {
float t;
printf("\nNhap hoanh do x : "); scanf("%f",&t);
a.x = t;
printf("Nhap tung do y : "); scanf("%f",&t);
a.y = t;
}
void xuat( dm a ) {
printf(" (%4.1f , %4.1f) ",a.x,a.y);

}
float khoangcach( dm a, dm b ) {
return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
}
void main() {
dm a,b;
printf("\tNhap toa do diem A trong Oxy: "); nhap(a);
printf("\tNhap toa do diem B trong Oxy: "); nhap(b);
printf("\nDiem vua nhap la : "); xuat(a); xuat(b);
float kq = khoangcach(a,b);
printf("\nKhoang cach giua A & B la : %f",kq);
getch();
}
• Tính chu vi đường tròn
#include<conio.h>
#include<stdio.h>
struct dm {
float x,y;
};
typedef struct duongtron {
dm I;
float R;
}dt;
void nhapdiem( dm &a ) {
float t;
printf("\nNhap hoanh do x : "); scanf("%f",&t);
a.x = t;
printf("Nhap tung do y : "); scanf("%f",&t);
a.y = t;
}

void nhapdtron( dt &A ) {
float t;
printf("\nNhap tam I : "); nhapdiem(A.I);
printf("Nhap ban kinh : "); scanf("%f",&t);
A.R = t;
}
void xuatdtron( dt A ) {
printf(" ((%4.1f,%4.1f),%4.1f) ",A.I.x,A.I.y,A.R);
}
float chuvi( dt A ) {
return 2*3.14*A.R;
}
void main() {
clrscr();
dt A;
printf("\tNhap duong tron A trong mat phang Oxy: ");
nhapdtron(A);
printf("\nDuong tron A vua nhap la : "); xuatdtron(A);
float kq = chuvi(A);
printf("\nChu vi duong tron A la : %4.1f",kq);
getch();
}
• Tính chu vi tam giác
#include<conio.h>
#include<stdio.h>
#include<math.h>
typedef struct diem {
float x,y;
}dm;
typedef struct tamgiac {

dm A,B,C;
}tg;
void nhapdiem( dm &a ) {
float t;
printf("\nNhap hoanh do x : "); scanf("%f",&t);
a.x = t;
printf("Nhap tung do y : "); scanf("%f",&t);
a.y = t;
}
void nhaptamgiac( tg &P ) {
printf("\nNhap dinh A : "); nhapdiem(P.A);
printf("\nNhap dinh B : "); nhapdiem(P.B);
printf("\nNhap dinh C : "); nhapdiem(P.C);
}
void xuattamgiac( tg P ) {
printf(" ( (%4.1f,%4.1f);(%4.1f,%4.1f);(%4.1f,%4.1f) ) ",P.A.x,P.A.y,P.B.x,P.B.y,P.C.x,P.C.y);
}
float khoangcach( dm a, dm b ) {
return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
}
float chuvi( tg P) {
float ab = khoangcach(P.A,P.B);
float bc = khoangcach(P.B,P.C);
float ac = khoangcach(P.A,P.C);
return ab+bc+ac;
}
void main() {
tg P;
printf("\tNhap Tam giac P: ");
nhaptamgiac(P);

printf("\tTam giac P : ");
xuattamgiac(P);
float kq = chuvi(P);
printf("\nChu Vi cua P: %4.1f",kq);
getch();
}
19
• Kiểm tra 1 ngày nhập từ bàn phím, xem phải ngày đặc biệt ko 596
#include<conio.h>
#include<stdio.h>
typedef struct ngay {
int d,m,y;
}date;
void nhap( date &P ) {
printf("\nNhap ngay : "); scanf("%d",&P.d);
printf("Nhap thang : "); scanf("%d",&P.m);
printf("Nhap nam : "); scanf("%d",&P.y);
}
void xuat( date P ) {
printf(" %d/%d/%d ",P.d,P.m,P.y);
}
void xetngay( date P ) {
if(P.y%4==0) printf("\nDay la nam nhuan");
if(P.d == 1 && P.m == 1) printf(“New Eve”);
else if(P.d == 14 && P.m == 2) printf(“Valentine!”);
else printf(“Ngay thuong.”);
}
void main() {
date P;
printf("\tNhap 1 ngay : "); nhap(P);

printf("\nNgay vua nhap : "); xuat(P);
xetngay(P);
getch();
}
• Nhập 1 lớp sv, tìm sv có đtb cao nhất
#include<conio.h>
#include<stdio.h>
#define MAX 50
struct sv {
char ten[30];
long mssv;
int ns;
float dtb;
};
void nhap1sv(sv &x) {
flushall();
printf("\nNhap Ten Hoc Sinh : "); gets(x.ten);
printf("\nNhap Ma so sinh vien : "); scanf("%ld",&x.mssv);
printf("Nhap Nam sinh : "); scanf("%d",&x.ns);
if(x.ns<100)
x.ns += 1900;
float t;
printf("Nhap diem tb : "); scanf("%f",&t);
x.dtb = t;
}
void xuat1sv(sv x) {
printf("%ld",x.mssv); gotoxy(12,wherey());
printf("%s",x.ten); gotoxy(40,wherey());
printf("%ld",x.ns); gotoxy(47,wherey());
printf("%1.1f",x.dtb);

printf("\n");
}
void nhap(sv a[], int &n) {
printf("Nhap si so lop : "); scanf("%d",&n);
printf("Bat dau nhap danh sach lop : ");
for(int i=0; i<n; i++){
printf("\nNhap sv thu %d:",i+1);
nhap1sv(a[i]);
}
}
void TieuDe(){
printf("\n \n");
printf("MSSV"); gotoxy(12,wherey());
printf("Ho Ten"); gotoxy(40,wherey());
printf("NS"); gotoxy(47,wherey());
printf("DTB");
printf("\n \n");
}
void xuat(sv a[], int n){
printf("\nLop: co Si so : %d",n);
printf("\nDanh sach lop : ");
TieuDe();
for(int i=0; i<n; i++)
xuat1sv(a[i]);
printf("\n \n");
}
sv TB_MAX(sv a[], int n){
sv x = a[i];
for(int i=1; i<n; i++)
if( x.dtb < a[i].dtb )

x = a[i];
return x;
}
void main() {
clrscr();
sv a[MAX];
int n;
printf("Xin nhap thong tin cua 1 lop hoc :\n");
nhap(a,n);
clrscr();
printf("\nThong tin lop hoc vua nhap la : \n");
xuat(a,n);
sv x = TB_MAX(a,n);
printf("\nSV co diem tb cao nhat: \n");
TieuDe();
xuat1sv(x);
getch();
}
20
CHƯƠNG 5: Đệ Quy – Độ phức tạp của thuật toán
1. Đệ quy
• 1 hàm đc gọi là đệ quy nếu trong thân hàm đó có lệnh gọi lại chính tên của hàm đó
• VD: Tính tổng s = 1 + 2 + + n, với n nhập từ bàn phím
Ko đệ quy Đệ quy
long Tong(int n){
long s = 0;
for(int i=1; i<=n; i++)
s += i;
return s;
}

long Tong(int n){
if(!n) return 0;
return ( Tong(n-1) + n );
}
Cơ chế hoạt động của Hàm
s = 0 , i = 1 -> s = 0+1 = 1
s = 1 , i = 2 -> s = 1+2 = 3
s = 3 , i = 3 -> s = 3+3 = 6

return s;
return n + Tong(n-1):
return n-1 + Tong(n-2):

return 2 + Tong(1):
return 1 + Tong(0): return 0;
->CT đi ngược lại:
Tong(0) = 0
Tong(1) = 1
Tong(2) = 3
….
Tong(n) = …
• VD: Đếm số ngtố có trong mảng số nguyên:
Ko đệ quy Đệ quy
int demnguyento(int a[], int n) {
int dem=0;
for(int i=0; i<n; i++)
if ( xet_so_nt(a[i])==1 )
dem++;
return dem;
}

int demnguyento(int a[], int n) {
if(!n) return 0;
if( xet_so_nt(a[n-1])== 1 )
return 1 + demnguyento(a,n-1);
return demnguyento(a,n-1);
}
Cơ chế hoạt động của Hàm
i = 0 , nếu a[0] là ngtố -> dem++
i = 1 , nếu a[1] là ngtố -> dem++

i = n-1, nếu a[n-1] là ngtố -> dem++
return dem
nếu a[n-1] là ngtố -> return 1 + demnguyento(a,n-1):
nếu a[(n-1)-1] là ngtố -> return 1 + demnguyento(a,n-2):
….
nếu a[1] là ngtố -> return 1 + demnguyento(a,0):
n = 0 -> return 0
-> CT đi ngc lại:
demnguyento(a,0) = 0
demnguyento(a,1) = 0 + …

demnguyento(a,n) = …
• Các bài tập minh họa :
o Tính giai thừa p = 1 x 2 x … x n.
Ko đệ quy Đệ quy
long GiaiThua(int n){
long p = 1;
for(int i=2; i<=n; i++)
s *= i;
return p;

}
long GiaiThua(int n){
if(!n) return 1;
return ( Tong(n-1) * n );
}
o Tìm ptử Max của mảng số thực.
Ko đệ quy Đệ quy
int ptuMax (float a[], int n) {
float MAX=a[0];
for(int i=1; i<n; i++)
if (a[i] > MAX )
MAX = a[i];
return MAX;
}
int ptuMax(float a[], int n) {
if(n==1) return a[0];
float MAX = ptuMax(a,n-1);
if( a[n-1] > MAX )
return a[n-1];
return MAX;
}
o Tính tổng các ptử âm trong mảng số nguyên.
Ko đệ quy Đệ quy
long TongAm(int a[], int n){
long s = 0;
for(int i=1; i<=n; i++)
if( a[i] < 0 )
s += i;
return s;
}

long TongAm (int a[], int n){
if(!n) return 0;
if(a[n-1] < 0)
return TongAm (a,n-1) + a[n-1];
return TongAm (a,n-1);
}
21
22
o Kiểm tra xem mảng số thực phải toàn dương ko.
Ko đệ quy Đệ quy
int ktDuong(float a[], int n){
for(int i=0; i<=n; i++)
if( a[i] < 0 )
return 0;
return 1;
}
int ktDuong (float a[], int n){
if(!n) return 1;
if(a[n-1] < 0)
return 0;
return ktDuong(a,n-1);
}
2. Độ phức tạp thuật toán
• Độ phức tạp:
• O(1) : độ phức tạp của phép gán, ss.
• O(n) : độ phức tạp tuyến tính (duyệt mảng, dãy)
• O(nlog
2
n) : tuyến tính logarit (sx mảng)
• O(n

α
)
(
α >1) : đa thức
• O(2
n
), O(n!) : mũ (liệt kê tập con, hoán vị …
• Một số CT:

1
1
n
i=

= n =>
1
b
i a=

=
1
1
b
i=

-
1
1
a
i a


=

= b – a – 1 (a<b)

1
n
i
i
=

=
( 1)
2
n n +
=>
2
2 2
1
( 1)
2
n
i
n n
i
=
+
=



2
1
( 1)(2 1)
6
n
i
n n n
i
=
+ +
=

=>
2 2
3
1
( 1)
4
n
i
n n
i
=
+
=

• Cách tính độ phức tạp:
hàm So sánh Gán
long Tong(int n) {
long s = 0;

for( int i=1; i<=n; i++)
s += i;
return s;
}
1
( 1) 1
n
i=
+

= n+1
1
( 1)
n
i=

: là số phép ss i<n khi i đi từ 1 -> n
1 là ss khi i=n+1 để thoát khỏi vòng for
1
1 1 (1 1)
n
i=
+ + +

= 2+2n
1: phép gán s=0
1: phép gán i=1;
1
(1 1)
n

i=
+

: phép gán i++ và s+=i
• Độ phức tạp là O(n)
Cải tiến
Hàm trên thực chất tính s =
1
n
i

=
( 1)
2
n n +
Hàm cải tíên
long Tong(int n){
return (long) n*(n+1)/2;
}
Cách cải tiến
Mỗi vòng lặp for ta suy ra thành 1 cái
b
a

, a là điểm bđ, b là điểm end. Giải = toán học, sau đó cải tiến lại hàm = cách
suy ngc lại, từ
b
a

thành vòng for. VD:

Hàm Cải Tiến Hàm cải tiến
long Tong(int n){
long s = 0;
for( int i = 1; i<= n; i++)
for( int j = 1; j<=n; j++ )
s += j ;
return s;
}
Tính s =
2
1 1
n i
i j
j
= =
∑∑
=
2 2
1
( 1)
2
n
i
i i
=
+


=
4 2

1
2
n
i
i i
=
+

long Tong(int n){
long a = 0, b;
b = (long) n*(n+1)*(2*n+1)/12;
for( int i = 1; i<= n; i++)
a += i*i*i*i;
return a/2 + b ;
}
23
=
2
4
1 1
1 1
( ) ( )
2 2 2
n n
i i
i
i
= =
+
∑ ∑

=
4
1
1 ( 1)(2 1)
( ) ( )
2 12
n
i
n n n
i
=
+ +
+


= a + b
24
CHƯƠNG 6: Tìm kíêm
1. Tìm kíêm tuyến tính
• Tìm nếu thấy ptử cần tìm trong mảng thì xuất ra vị trí của ptử đó, nếu ko xuất ra -1
• Độ khó thuật toán: O(n)
Mảng số nguyên a Mảng số thực a Mảng sv a
int Tim_tt(int a[], int n, int x){
for(int i=0; i<n; i++)
if(a[i] == x)
return i;
return -1;
}
int Tim_tt(float a[], int n, float x){
for(int i=0; i<n; i++)

if(a[i] == x)
return i;
return -1;
}
int Tim_tt(sv a[], int n, data x){
for(int i=0; i<n; i++)
if(a[i].KDL == x)
return i;
return -1;
}
Tuỳ đề bài muốn tìm dữ liệu gì của 1 sv:
+ Tìm MaSV -> data = long, KDL = mssv
+ Tìm tb -> data = float, KDL = tb
+ Tìm ns -> data = int, KDL = ns
Lưu ý: Nếu muốn tìm tên, thì phải dùng hàm strcmp
VD về tìm kiếm đối với kiểu sv
Tìm sv có mssv x Tìm sv có dtb x Tìm sv có tên là x
int Tim_tt(sv a[], int n, long x){
for(int i=0; i<n; i++)
if(a[i].mssv == x)
return i;
return -1;
}
int Tim_tt(sv a[], int n, float x){
for(int i=0; i<n; i++)
if(a[i].dtb == x)
return i;
return -1;
}
int Tim_tt(sv a[], int n, char* x){

for(int i=0; i<n; i++)
if( strcmp(a[i].ten, x) == 0 )
return i;
return -1;
}
2. Tìm kíêm nhị phân
• Mảng a phải đc sắp xếp rồi thì mới sử dụng đc thuật toán tìm nhị phân.
• Độ khó thuật toán: O(logn)
• Các vd sau dùng cho mảng đã sắp tăng, nếu muốn dùng cho mảng sắp xếp giảm, ta đổi dấu “<” ở if
Mảng số nguyên a đã sắp tăng Mảng số thực a đã sắp tăng Mảng sv a đã sắp tăng
int Tim_np(int a[], int n, int x){
int l = 0, r = n-1, m;
while (l <= r){
m = (l+r)/2;
if(a[m] == x) return m;
if(a[m] < x) l = m+1;
else r = m-1;
}
return -1;
}
int Tim_np(float a[], int n, float x){
int l = 0, r = n-1, m;
while (l <= r){
m = (l+r)/2;
if(a[m] == x) return m;
if(a[m] < x) l = m+1;
else r = m-1;
}
return -1;
}

int Tim_np(sv a[], int n, data x){
int l = 0, r = n-1, m;
while (l <= r){
m = (l+r)/2;
if(a[m].KDL == x) return m;
if(a[m].KDL < x) l = m+1;
else r = m-1;
}
return -1;
}
data & KDL xét như các bài trên
Với tìm tên sv, dùng strcmp :
int Tim_np(sv a[], int n, char* x){
int l = 0, r = n-1, m;
while (l <= r){
m = (l+r)/2;
if( strcmp(a[m].ten, x) == 0) return
m;
if( strcmp(a[m].ten, x) < 0) l =
m+1;
else r = m-1;
}
return -1;
}
• VD: Tìm sv có tên x ( x nhập từ bàn phím ) bằng thuật toán tìm nhị phân
#include<conio.h>
#include<stdio.h>
#include<string.h> // Muon su dung strcmp can thu vien string
#define MAX 50
#define swap(a,b) { sv t = a; a = b; b = t; }

struct sv {
char ten[30];
long mssv;
int ns;
float dtb;
};
void nhap1sv(sv &x) { … }
void xuat1sv(sv x) { … }
void nhap(sv a[], int &n) { … }
void TieuDe(){ … }
void xuat(sv a[], int n){ … }
void SapxepMang(sv a[], int n){ 1 trong các thuật toán sx ở phần sau…}
int Tim_np(sv a[], int n, char* x){ … }
void main() {
clrscr();
sv a[MAX];
int n;
printf("Xin nhap thong tin cua 1 lop hoc :\n"); nhap(a,n);
clrscr();
printf("\nThong tin lop hoc vua nhap la : \n"); xuat(a,n);
SapxepMang(a,n); // Chi Tim nhi phan sau khi sx
char* x;
flushall();
printf(“\nNhap ten sv gan tim: ”); gets(x);
int kq = Tim_np(a,n,x);
if(kq == -1)
printf(“\nKo co sv do trong mang.”);
else
printf(“\nSV do o vi tri thu %d”,kq);
getch();

}
25

×