Bài 11: Kiểu mảng
1. Kiểu mảng một chiều
- Mảng một chiều là dãy hữu hạn các phần tử cùng kiểu.
- Mảng được đặt tên và mỗi phần tử của nó có một chỉ số.
- Để mô tả mảng một chiều cần xác định kiểu của các phần tử và cách đánh số các phần tử của nó.
- Để người lập trình có thể xây dựng và sử dụng kiểu mảng một chiều, các ngôn ngữ lập trình có quy tắc cách thức cho phép xác định:
+ Tên kiểu mảng một chiều;
+ Số lượng phần tử;
+ Kiểu dữ liệu của phần tử;
+ Cách khai báo biến;
+ Cách tham chiếu đến phần tử.
a. Khai báo
Tổng quát, khai báo biến mảng một chiều có dạng:
- Cách 1. Khai báo trực tiếp biến mảng một chiều:
var < tên biến mảng >: array [ kiểu chỉ số ] of < kiểu phần tử >;
- Cách 2. Khai báo gián tiếp biến mảng qua kiểu mảng một chiều:
type < tên kiểu mảng > = array [ kiểu chỉ số ] of < kiểu phần tử >;
var < tên biến mảng >: < tên kiểu mảng >;
Trong đó:
- Kiểu chỉ số thường là một đoạn số nguyên liên tục có dạng n1..n2 với n1, n2 là các hằng hoặc biểu thức nguyên xác định chỉ số đầu và chỉ số cuối (n1 \(\leq\) n2);
- Kiểu phần tử là kiểu của phần tử mảng.
Ví dụ 1. Các khai báo kiểu mảng một chiều sau đây là hợp lệ:
type
ArrayReal = array[-100..200] of real;
ArrayBoolean = array[-n+1..n+1] of boolean;
ArrayInt = [-100..0] of integer;
Trong đó, n là hằng nguyên.
b. Tham chiếu tới phần tử của mảng một chiều
- Tham chiếu tới phần tử của mảng một chiều được xác định bởi tên mảng cùng với chỉ số, được viết trong cặp ngoặc [ và ].
- Cú pháp: tên_mảng[chỉ số]
Ví dụ 2: Tham chiếu tới nhiệt độ của ngày thứ 20, trong chương trình trên, được viết là Nhietdo[20].
Hình 1. Minh họa mảng một chiều
2. Kiểu mảng hai chiều
- Mảng hai chiều là bảng các phần tử cùng kiểu.
- Nhận xét rằng mỗi hàng của mảng hai chiều có cấu trúc như một mảng một chiều cùng kích thước. Nếu ta coi mỗi hàng của mảng hai chiều là một phần tử thì ta có thể nói mảng hai chiều là mảng một chiều mà mỗi phần tử là mảng một chiều.
- Để người lập trình có thể xây dựng và sử dụng kiểu mảng hai chiều, các ngôn ngữ lập trình có quy tắc cách thức cho phép xác định:
+ Tên kiểu mảng hai chiều;
+ Số lượng phần tử của mỗi chiều;
+ Kiểu dữ liệu của phần tử;
+ Cách khai báo biến;
+ Cách tham chiếu đến phần tử.
a. Khai báo
Tổng quát, khai báo biến mảng hai chiều trong Pascal như sau:
- Cách 1. Khai báo trực tiếp biến mảng hai chiều như sau:
var < tên biến mảng > : array[ kiểu chỉ số dòng, kiểu chỉ số cột ] of < kiểu phần tử >;
- Cách 2. Khai báo gián tiếp biến mảng qua kiểu mảng hai chiều:
type < tên kiểu mảng > = array[ kiểu chỉ số dòng, kiểu chỉ số cột ] of < kiểu phần tử >;
var < tên biến mảng >: < tên kiểu mảng >;
Ví dụ 4. Các khai báo sau đây là hợp lệ:
type
ArrayReal = array[-100..200,100..200] of real;
ArrayBoolean = array[-n+1..n+1,n..2*n] of boolean;
var
ArrayInt: array[1..10,1..15] of integer;
ArrayLong:array[0..3*(n+1),0..n] of longint;
Trong đó, n là hằng nguyên.
b. Tham chiếu tới phần tử của mảng hai chiều
- Tham chiếu tới phần tử của mảng hai chiều được xác định bởi tên mảng cùng với hai chỉ số được cách nhau bởi dấu phẩy và viết trong cặp ngoặc [ và ].
- Cú pháp: tên_mảng[chỉ số dòng, chỉ số cột]
Ví dụ 4. Tham chiếu tới phần tử ở dòng thứ 5, cột thứ 9 của biến mảng ArrayInt khai báo được viết: ArrayInt [5, 9].
Hình 2. Minh hoạ mảng hai chiều
Chú ý:
- Các biến mảng thường gồm số lượng lớn các phần tử nên cần lưu ý phạm vi sử dụng chúng để khai báo kích thước và kiểu dữ liệu để tiết kiệm bộ nhớ.
- Ngoài hai kiểu mảng một chiều và hai chiều, còn có kiểu mảng nhiều chiều.
3. Bài tập:
Dạng 1. Một số bài tập vận dụng về mảng một chiều
Ta xét chương trình có sử dụng mảng một chiều cài đặt một số thuật toán giải những bài toán tìm kiếm và sắp xếp.
Bài tập 1. Tìm phần tử lớn nhất của dãy số nguyên
- Xác định bài toán:
+ Input: Số nguyên dương N (N\(\leq\)250) và dãy N số nguyên dương a1, a2 ,..., aN, mỗi số đều không vượt quá 500.
+ Output: Chỉ số và giá trị của phần tử lớn nhất trong dãy số đã cho (nếu có nhiều phần tử lớn nhất chỉ cần đưa ra một trong số chúng).
- Mô tả thuật toán:
+ Bước 1. Nhập N và dãy a1,..., aN;
+ Bước 2. Max \(\leftarrow\) a1, i \(\leftarrow\) 2;
+ Bước 3. Nếu i > N thì đưa ra giá trị Max rồi kết thúc;
+ Bước 4.
- Bước 4.1. Nếu ai > Max thì Max \(\leftarrow\) ai;
- Bước 4.2. i \(\leftarrow\) i + 1 rồi quay lại bước 3;
- Chương trình cài đặt:
program TimMax;
uses crt;
const
Nmax = 250;
type
ArrInt = array[1..Nmax] of integer;
var
N,i, Max, csmax: integer;
A: ArrInt;
begin
clrscr;
write('Nhap so luong phan tu cua day so, N = ');
readln(N);
for i:=1 to N do
begin
write('Phan tu thu ',i,' = ');
readln(A[i]);
end;
Max:= A[1]; csmax:=1;
for i:=2 to N do
if A[i]> Max then
begin
Max:= A[i];
csmax:= i;
end;
writeln('Gia tri cua phan tu Max: ', Max);
writeln('Chi so cua phan tu Max: ', csmax);
readln
end.
Bài tập 2. Sắp xếp dãy số nguyên bằng thuật toán tráo đổi
- Xác định bài toán:
+ Input: Số nguyên dương N (N\(\leq\)250) và dãy A gồm N số nguyên dương a1, a2,..., aN, mỗi số đều không vượt quá 500.
+ Output: Dãy số A đã được sắp xếp thành dãy không giảm.
- Chương trình cài đặt:
program sapxep;
uses CRT;
const Nmax = 250;
type
ArrInt = array[1..Nmax] of integer;
var
N,i,j,t: integer;
A: ArrInt;
begin
clrscr;
write('Nhap so luong phan tu cua day so, N = ');readln(N);
for i:=1 to N do
begin
write('Phan tu thu ',i,' = ');
readln(A[i]);
end;
for j:=N downto 2 do
begin
for i:=1 to j-1 do
if A[i]> A[i+1] then
begin (*Trao doi A[i] va A[i+1]*)
t:= A[i];
A[i]:= A[i+1];
A[i+1]:= t
end;
end;
writeln('Day so duoc sap xep la: ');
for i:=1 to N do write(A[i]: 4);
readln
end.
Bài tập 3. Tìm kiếm nhị phân
- Xác định bài toán:
+ Input: Dãy A là dãy tăng gồm N (N \(\leq\) 250) số nguyên dương a1, a2,..., aN và số nguyên k.
+ Output: Chỉ số i mà ai = k hoặc thông báo "Khong tim thay" nếu không có số hạng nào của dãy A có giá trị bằng k.
- Chương trình cài đặt:
program TK_nhiphan;
uses crt;
const
Nmax = 250;
type
ArrInt = array[1..Nmax] of integer;
var
N, i, k: integer;
Dau, Cuoi, Giua: integer;
A: Arrint;
Tim_Thay: boolean;
begin
clrscr;
write('Nhap so luong phan tu cua day so, N = ');
readln(N);
writeln('Nhap cac phan tu cua day so tang: ');
for i:=1 to N do
begin
write('Phan tu thu ',i,' = ');
readln(A[i]);
end;
write('Nhap gia tri k = ');
readln(k);
Dau:= 1; Cuoi:=N; Tim_thay:= false;
while (Dau <= Cuoi) and not (Tim_Thay) do
begin
Giua:= (Dau+Cuoi) div 2;
if A[Giua] = k then
Tim_thay:= true
else
if A[Giua]>k then Cuoi:= Giua-1
else Dau:= Giua+1;
end;
if Tim_thay then writeln('Chi so tim duoc la: ', Giua)
else writeln('Khong tim thay');
readln
end.
Dạng 2. Một số bài tập vận dụng về mảng hai chiều
Bài tập 4. Chương trình sau tính và đưa ra màn hình bảng cửu chương.
program BangCuuChuong;
uses crt;
var
B: array[1..9,1..10] of integer;
{B: bien mang hai chieu luu bang cuu chuong}
i, j: integer;
begin
clrscr;
for i:=1 to 9 do
for j:= 1 to 10 do
B[i,j]:= i*j;
for i:=1 to 9 do
begin
for j:=1 to 10 do write(B[i,j]:4);
writeln;
end;
readln
end.
Bài tập 5. Chương trình sau nhập vào từ bàn phím các phần tử của mảng hai chiều B gồm 5 dòng, 7 cột với các phần tử là các số nguyên và số nguyên k. Sau đó, đưa ra màn hình các phần tử của mảng có giá trị nhỏ hơn k.
program MangHaiChieu;
uses crt;
var b: array[1..5, 1..7] of integer;
d, i, j, k: integer;
begin
clrscr;
writeln('Nhap cac phan tu cua mang theo dong: ');
for i:= 1 to 5 do
begin
for j:= 1 to 7 do
begin
read(b[i,j]);
write(' ');
end;
writeln;
end;
write('Nhap vao gia tri k = '); readln(k);
d:= 0;
writeln('DS cac phan tu mang nho hon ',k,':');
for i:= 1 to 5 do
for j:= 1 to 7 do
if b[i, j] < k then begin
write(b[i, j], ' ');
d:= d+1;
end;
if d = 0 then writeln(’Khong co phan tu nao nho hon ’,k);
readln
end.
1. Kiểu mảng một chiều
- Mảng một chiều là dãy hữu hạn các phần tử cùng kiểu.
- Mảng được đặt tên và mỗi phần tử của nó có một chỉ số.
- Để mô tả mảng một chiều cần xác định kiểu của các phần tử và cách đánh số các phần tử của nó.
- Để người lập trình có thể xây dựng và sử dụng kiểu mảng một chiều, các ngôn ngữ lập trình có quy tắc cách thức cho phép xác định:
+ Tên kiểu mảng một chiều;
+ Số lượng phần tử;
+ Kiểu dữ liệu của phần tử;
+ Cách khai báo biến;
+ Cách tham chiếu đến phần tử.
a. Khai báo
Tổng quát, khai báo biến mảng một chiều có dạng:
- Cách 1. Khai báo trực tiếp biến mảng một chiều:
var < tên biến mảng >: array [ kiểu chỉ số ] of < kiểu phần tử >;
- Cách 2. Khai báo gián tiếp biến mảng qua kiểu mảng một chiều:
type < tên kiểu mảng > = array [ kiểu chỉ số ] of < kiểu phần tử >;
var < tên biến mảng >: < tên kiểu mảng >;
Trong đó:
- Kiểu chỉ số thường là một đoạn số nguyên liên tục có dạng n1..n2 với n1, n2 là các hằng hoặc biểu thức nguyên xác định chỉ số đầu và chỉ số cuối (n1 \(\leq\) n2);
- Kiểu phần tử là kiểu của phần tử mảng.
Ví dụ 1. Các khai báo kiểu mảng một chiều sau đây là hợp lệ:
type
ArrayReal = array[-100..200] of real;
ArrayBoolean = array[-n+1..n+1] of boolean;
ArrayInt = [-100..0] of integer;
Trong đó, n là hằng nguyên.
b. Tham chiếu tới phần tử của mảng một chiều
- Tham chiếu tới phần tử của mảng một chiều được xác định bởi tên mảng cùng với chỉ số, được viết trong cặp ngoặc [ và ].
- Cú pháp: tên_mảng[chỉ số]
Ví dụ 2: Tham chiếu tới nhiệt độ của ngày thứ 20, trong chương trình trên, được viết là Nhietdo[20].
Hình 1. Minh họa mảng một chiều
2. Kiểu mảng hai chiều
- Mảng hai chiều là bảng các phần tử cùng kiểu.
- Nhận xét rằng mỗi hàng của mảng hai chiều có cấu trúc như một mảng một chiều cùng kích thước. Nếu ta coi mỗi hàng của mảng hai chiều là một phần tử thì ta có thể nói mảng hai chiều là mảng một chiều mà mỗi phần tử là mảng một chiều.
- Để người lập trình có thể xây dựng và sử dụng kiểu mảng hai chiều, các ngôn ngữ lập trình có quy tắc cách thức cho phép xác định:
+ Tên kiểu mảng hai chiều;
+ Số lượng phần tử của mỗi chiều;
+ Kiểu dữ liệu của phần tử;
+ Cách khai báo biến;
+ Cách tham chiếu đến phần tử.
a. Khai báo
Tổng quát, khai báo biến mảng hai chiều trong Pascal như sau:
- Cách 1. Khai báo trực tiếp biến mảng hai chiều như sau:
var < tên biến mảng > : array[ kiểu chỉ số dòng, kiểu chỉ số cột ] of < kiểu phần tử >;
- Cách 2. Khai báo gián tiếp biến mảng qua kiểu mảng hai chiều:
type < tên kiểu mảng > = array[ kiểu chỉ số dòng, kiểu chỉ số cột ] of < kiểu phần tử >;
var < tên biến mảng >: < tên kiểu mảng >;
Ví dụ 4. Các khai báo sau đây là hợp lệ:
type
ArrayReal = array[-100..200,100..200] of real;
ArrayBoolean = array[-n+1..n+1,n..2*n] of boolean;
var
ArrayInt: array[1..10,1..15] of integer;
ArrayLong:array[0..3*(n+1),0..n] of longint;
Trong đó, n là hằng nguyên.
b. Tham chiếu tới phần tử của mảng hai chiều
- Tham chiếu tới phần tử của mảng hai chiều được xác định bởi tên mảng cùng với hai chỉ số được cách nhau bởi dấu phẩy và viết trong cặp ngoặc [ và ].
- Cú pháp: tên_mảng[chỉ số dòng, chỉ số cột]
Ví dụ 4. Tham chiếu tới phần tử ở dòng thứ 5, cột thứ 9 của biến mảng ArrayInt khai báo được viết: ArrayInt [5, 9].
Hình 2. Minh hoạ mảng hai chiều
Chú ý:
- Các biến mảng thường gồm số lượng lớn các phần tử nên cần lưu ý phạm vi sử dụng chúng để khai báo kích thước và kiểu dữ liệu để tiết kiệm bộ nhớ.
- Ngoài hai kiểu mảng một chiều và hai chiều, còn có kiểu mảng nhiều chiều.
3. Bài tập:
Dạng 1. Một số bài tập vận dụng về mảng một chiều
Ta xét chương trình có sử dụng mảng một chiều cài đặt một số thuật toán giải những bài toán tìm kiếm và sắp xếp.
Bài tập 1. Tìm phần tử lớn nhất của dãy số nguyên
- Xác định bài toán:
+ Input: Số nguyên dương N (N\(\leq\)250) và dãy N số nguyên dương a1, a2 ,..., aN, mỗi số đều không vượt quá 500.
+ Output: Chỉ số và giá trị của phần tử lớn nhất trong dãy số đã cho (nếu có nhiều phần tử lớn nhất chỉ cần đưa ra một trong số chúng).
- Mô tả thuật toán:
+ Bước 1. Nhập N và dãy a1,..., aN;
+ Bước 2. Max \(\leftarrow\) a1, i \(\leftarrow\) 2;
+ Bước 3. Nếu i > N thì đưa ra giá trị Max rồi kết thúc;
+ Bước 4.
- Bước 4.1. Nếu ai > Max thì Max \(\leftarrow\) ai;
- Bước 4.2. i \(\leftarrow\) i + 1 rồi quay lại bước 3;
- Chương trình cài đặt:
program TimMax;
uses crt;
const
Nmax = 250;
type
ArrInt = array[1..Nmax] of integer;
var
N,i, Max, csmax: integer;
A: ArrInt;
begin
clrscr;
write('Nhap so luong phan tu cua day so, N = ');
readln(N);
for i:=1 to N do
begin
write('Phan tu thu ',i,' = ');
readln(A[i]);
end;
Max:= A[1]; csmax:=1;
for i:=2 to N do
if A[i]> Max then
begin
Max:= A[i];
csmax:= i;
end;
writeln('Gia tri cua phan tu Max: ', Max);
writeln('Chi so cua phan tu Max: ', csmax);
readln
end.
Bài tập 2. Sắp xếp dãy số nguyên bằng thuật toán tráo đổi
- Xác định bài toán:
+ Input: Số nguyên dương N (N\(\leq\)250) và dãy A gồm N số nguyên dương a1, a2,..., aN, mỗi số đều không vượt quá 500.
+ Output: Dãy số A đã được sắp xếp thành dãy không giảm.
- Chương trình cài đặt:
program sapxep;
uses CRT;
const Nmax = 250;
type
ArrInt = array[1..Nmax] of integer;
var
N,i,j,t: integer;
A: ArrInt;
begin
clrscr;
write('Nhap so luong phan tu cua day so, N = ');readln(N);
for i:=1 to N do
begin
write('Phan tu thu ',i,' = ');
readln(A[i]);
end;
for j:=N downto 2 do
begin
for i:=1 to j-1 do
if A[i]> A[i+1] then
begin (*Trao doi A[i] va A[i+1]*)
t:= A[i];
A[i]:= A[i+1];
A[i+1]:= t
end;
end;
writeln('Day so duoc sap xep la: ');
for i:=1 to N do write(A[i]: 4);
readln
end.
Bài tập 3. Tìm kiếm nhị phân
- Xác định bài toán:
+ Input: Dãy A là dãy tăng gồm N (N \(\leq\) 250) số nguyên dương a1, a2,..., aN và số nguyên k.
+ Output: Chỉ số i mà ai = k hoặc thông báo "Khong tim thay" nếu không có số hạng nào của dãy A có giá trị bằng k.
- Chương trình cài đặt:
program TK_nhiphan;
uses crt;
const
Nmax = 250;
type
ArrInt = array[1..Nmax] of integer;
var
N, i, k: integer;
Dau, Cuoi, Giua: integer;
A: Arrint;
Tim_Thay: boolean;
begin
clrscr;
write('Nhap so luong phan tu cua day so, N = ');
readln(N);
writeln('Nhap cac phan tu cua day so tang: ');
for i:=1 to N do
begin
write('Phan tu thu ',i,' = ');
readln(A[i]);
end;
write('Nhap gia tri k = ');
readln(k);
Dau:= 1; Cuoi:=N; Tim_thay:= false;
while (Dau <= Cuoi) and not (Tim_Thay) do
begin
Giua:= (Dau+Cuoi) div 2;
if A[Giua] = k then
Tim_thay:= true
else
if A[Giua]>k then Cuoi:= Giua-1
else Dau:= Giua+1;
end;
if Tim_thay then writeln('Chi so tim duoc la: ', Giua)
else writeln('Khong tim thay');
readln
end.
Dạng 2. Một số bài tập vận dụng về mảng hai chiều
Bài tập 4. Chương trình sau tính và đưa ra màn hình bảng cửu chương.
program BangCuuChuong;
uses crt;
var
B: array[1..9,1..10] of integer;
{B: bien mang hai chieu luu bang cuu chuong}
i, j: integer;
begin
clrscr;
for i:=1 to 9 do
for j:= 1 to 10 do
B[i,j]:= i*j;
for i:=1 to 9 do
begin
for j:=1 to 10 do write(B[i,j]:4);
writeln;
end;
readln
end.
Bài tập 5. Chương trình sau nhập vào từ bàn phím các phần tử của mảng hai chiều B gồm 5 dòng, 7 cột với các phần tử là các số nguyên và số nguyên k. Sau đó, đưa ra màn hình các phần tử của mảng có giá trị nhỏ hơn k.
program MangHaiChieu;
uses crt;
var b: array[1..5, 1..7] of integer;
d, i, j, k: integer;
begin
clrscr;
writeln('Nhap cac phan tu cua mang theo dong: ');
for i:= 1 to 5 do
begin
for j:= 1 to 7 do
begin
read(b[i,j]);
write(' ');
end;
writeln;
end;
write('Nhap vao gia tri k = '); readln(k);
d:= 0;
writeln('DS cac phan tu mang nho hon ',k,':');
for i:= 1 to 5 do
for j:= 1 to 7 do
if b[i, j] < k then begin
write(b[i, j], ' ');
d:= d+1;
end;
if d = 0 then writeln(’Khong co phan tu nao nho hon ’,k);
readln
end.