Kỹ thuật lập trì nh
70
CHươNG 3 CáC THUậT TOáN TRÊN CấU TRúC Dữ LIệU MảNG
I. Mảng không sắp xếp và thuật toán tìm kiếm trên
mảng chưa có thứ tự
I.1. Một số khái niệ m về mảng:
I.1.1. Định nghĩ a:
Mả ng là 1 d y cá c phầ n tử có cùng kiể u dữ liệ u đ ược sắ p xế p liê n tiế p
nhau trong bộ nhớ
0100
0102 1 int
0104 2 Mả ng n phần tử
n-1
Bộ nhớ
!
!!
!Khai báo:
Cú pháp
: Khai bá o mả ng 1 chiề u
Kiể u_DL Tê nmả ng [kí ch thước];
Kiể u_DL : là 1 trong cá c kiể u dữ liệ u cơ bả n, đó là kiể u của phầ n tử
của mả ng
Tê nmả ng: là tê n của mả ng đ ược đặt 1 cá ch hợp lệ
Kí ch thước: là 1 hằ ng nguyê n cho biế t số phầ n tử tối đa của mả ng
Ví dụ 1
: Khai bá o 1 mả ng số nguyê n
int n ;
int M[n] ; SAI
int M[10] ; đúng vì kí ch thước mả ng phả i là hằ ng không phả i là
biế n
#define max 100
int M[max] ;
Ví dụ 2
: Khai bá o 1 danh sá ch họ tê n học viê n của 1 lớp học
char dshv[50][30]; // dshv có thể chứa tối đa họ tê n 50 học viê n,
// chiề u dà i họ tê n mỗi học viê n tối đa là 30 ký tự
Cú pháp
: Khai bá o mả ng 2 chiề u
Kỹ thuật lập trì nh
71
Kiể u_DL Tê nmả ng [kí ch thước 1][kí ch thước 2]
Chú ý
: Một mả ng trong C, cá c phầ n tử đ ược đá nh số từ 0 tới n-1
Ví dụ
: Với M[10]
thì thà nh phầ n thứ 1 là M[0]
thà nh phầ n cuối cùng M[9]
* C không bắ t bẻ , không kiể m tra xem biế n đế m có vượt ra khỏi giới hạ n
cho phép của mả ng chưa. Do đó, chúng ta phả i kiể m tra biế n đế m trong chương
trì nh (phả i nhỏ hơn n)
I.1.2. Khởi động trị cho mảng:
Ta khởi động đ ược trị cho mả ng trong 2 trường hợp sau:
Mả ng đ ược khai bá o là biế n ngoà i (main) nghĩ a là biế n toà n cục
Mả ng đ ược khai bá o cục bộ
Ví dụ 1
: int M[3] = {10,11,12}
main()
{
}
Ví dụ 2
:
main()
{ static int M[ ]={10,22,30};
............
}
Ta có thể gá n 1 hằ ng cho cả mả ng như sau:
memset (M,0,sizeof(int) *3) ; // gá n 0 cho mả ng M với M có 3 phầ n tử
Từ khóa static dùng để khai bá o 1 biế n cục bộ thường trực cho phép duy
trì giá trị riê ng của nó ở những lầ n gọi hà m sau nà y.
Khởi tạ o mả ng 2 chiề u:
int M[2][3]= {{1,2,3},
{0,1,0}};
I.1.3.Truy xuất thành phần của mảng: M[chỉ số]
Truy xuấ t thà nh phầ n thứ 2 của mả ng 1 chiề u: M[1]
Truy xuấ t thà nh phầ n thứ i của mả ng 1 chiề u: M[i-1]
Truy xuấ t thà nh phầ n dòng 2, cột 3 của mả ng 2 chiề u M[1][2]
I.1.4. Đọc (nhập) dữ liệ u cho mảng:
- Để nhậ p dữ liệ u cho mả ng ta phả i nhậ p dữ liệ u cho từng thà nh phầ n của
mả ng.
Ví dụ 1
:
Kỹ thuật lập trì nh
72
int n,i;
float M[10];
printf("\nCho biet so phan tu cua mang:")
scanf (%d,&n);
for ( i=0; i< n; i++)
{ printf(a[%d]= ,i+1);
scanf (%f,&M[i]);
}
Ví dụ 2
: Nhậ p và o mả ng 2 chiề u.
int m, n, i, j;
float M[10] [10];
printf("So dong ="); scanf("%d",&n);
printf("So cot ="); scanf("%d",&m);
for(i= 0; i< n; i++)
for(j= 0; j<m; j++)
{ printf(M[%d] [%d] = ,i,j);
scanf(%f, &M[i][j]);
}
I.1.5. Xuất dữ liệ u kiể u mảng: Để xuấ t dữ liệ u mả ng ta cũng phả i xuấ t dữ
liệ u của từng thà nh phầ n mả ng
Ví dụ
:
int i, n;
float M[10];
for(i = 0; i< n; i++)
printf(a[%d] = %f,i+1, M[i]);
I.2. Thuật toán tì m kiế m trê n mảng chưa có thứ tự:
Do mả ng chưa có thứ tự nê n ta á p dụng phương phá p tì m kiế m tuyế n tí nh tì m
từ đầ u mả ng cho đế n cuối mả ng. Trong chương trì nh sau đâ y, hà m Timkiế m sẽ
trả về trị -1 nế u không có m sinh viê n trong danh sá ch ds, ngược lạ i hà m sẽ trả
về vị trí của m số đó trong danh sá ch ds.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SOSV 100 // số sinh viê n tối đa trong danh sá ch
typedef struct sinhvien // định nghĩ a kiể u sinhvien
Kỹ thuật lập trì nh
73
{ char maso[6];
char hoten[30];
};
typedef struct danhsach_sv // định nghĩ a kiể u danhsach_sv
{ int tssv;
sinhvien sv[MAX_SOSV];
} ;
void Nhap_ds (struct danhsach_sv *psv)
{ char sosv[4];
printf("So sinh vien muon nhap :");
gets(sosv);
psv->tssv=atoi(sosv);
for (int i=0; i<psv->tssv; i++)
{ printf("Ma so :");
gets(psv->sv[i].maso);
printf("Ho ten :");
gets(psv->sv[i].hoten);
}
}
void Lietke_ds (struct danhsach_sv *psv)
{ int i=0;
clrscr();
printf (" Ma so Ho & ten \n");
while (i < psv->tssv)
{ printf ("%8s %-s\n", psv->sv[i].maso,psv->sv[i].hoten);
i++;
}
getch();
}
/* Hàm Timkiem tì m maso trong danhsach *psv */
int Timkiem(danhsach_sv *psv, char maso[])
{ int i=0;
while ((i<psv->tssv) && (strcmp(psv->sv[i].maso, maso)!=0))
i++;
return (i==psv->tssv ? -1 : i) ;
Kỹ thuật lập trì nh
74
}
void main()
{ struct danhsach_sv ds;
char maso[6];
int vitri;
Nhap_ds(&ds); // Gọi hà m Nhap_ds với tham số là ds
Lietke_ds(&ds);
printf("Ma so sinh vien ban can tim :");
gets(maso);
vitri = Timkiem(&ds, maso);
if (vitri !=-1)
printf("Ho ten cua sinh vien la %s",ds.sv[vitri].hoten);
else printf(" Khong co sinh vien voi ma ban nhap vao");
getch();
}
II. Các thuật toán sắp xếp
:
Trong thực tế cuộc sống cũng như trong lĩ nh vực lậ p trì nh, việ c quả n lỹ dữ liệ u
thường đòi hỏi sự tì m kiế m cá c dữ liệ u cầ n thiế t; Để thuậ n tiệ n cho việ c tì m
kiế m, dữ liệ u thường đ ược sẵ p xế p theo một thứ tự nà o đó.
Có rấ t nhiề u phương phá p sắ p thứ tự, trong bà i giả ng nà y ta chỉ khả o sát hai
phương phá p sắ p xế p là Bubble_Sort và Quick_Sort.
Để thuậ n tiệ n ta giả sử mả ng là d y số có tối đa 100 số, và cá c thuậ t toá n dưới
đâ y dùng để sắ p xế p d y số theo thứ tự tă ng dầ n.
II.1. Sắp xế p theo phương pháp Bubble_Sort
(phương pháp nổi bọt)
- Nội dung
: Ta cho i duyệ t d y a[0], .. ,a[n-1]; nế u a[i-1] lớn hơn a[i] thì ta
hoá n đổi (a[i-1],a[i]). Lặ p lạ i quá trì nh duyệ t d y nà y cho đế n khi không có xả y
ra việ c đổi chỗ của hai phầ n tử.
Ví dụ
: Ta sắ p thứ tự d y số sau : 26 33 35 29 19 12 32
Bước 0 1 2 3 4 5 6
26 12 12 12 12 12 12
33 26 19 19 19 19 19
35 33 26 26 26 26 26
29 35 33 29 29 29 29
19 29 35 33 32 32 32
Kü thuËt lËp tr× nh
75
12 19 29 35 33 33 33
32 32 32 32 35 35 35
- Ch¬ng tr× nh:
#include <stdio.h>
#include <conio.h>
int mang[100]; // biÕ n toµ n côc
int size ;
void Bubble_Sort(int A[100], int n)
{ int i,j,temp;
for (i=1; i<n; i++)
for (j=n-1;j>=i; j--)
if (A[j-1] > A[j])
{ temp = A[j-1];
A[j-1] = A[j];
A[j] = temp;
}
}
int Nhap_day_so (int A[])
{ int i,n;
printf("\nSo phan tu cua mang :"); scanf("%d",&n);
for (i=0; i<n; i++)
{ printf ("A[%d] = ",i+1);
scanf("%d",&A[i]);
}
return n;
}
void Liet_ke (int A[], int n)
{ int i;
printf("\n Gia tri mang da duoc sap : \n");
for (i=0; i<n; i++)
printf ("%5d",A[i]);
getch();
}
void main()
{
size= Nhap_day_so(mang);