Mảng trong C++

Mảng trong C++

Đặt vấn đề:

  • Một chương trình sử dụng rất nhiều biến, có nhiều biến có cùng các chức năng tương tự nhau, nếu khai báo các biến một cách rời rạc sẽ rất khó kiểm soát.
  • C++ cung cấp một cấu trúc dữ liệu : mảng

➱ Mảng là tập hợp các biến có cùng chung kiểu dữ liệu đứng liên tiếp nhau.

➱ Kích thước mảng là cố định.

1. Khai báo mảng:

Cú pháp: <kiểu dữ liệu> <tên mảng> [kích thước];

VD:

    int a[5];
    double d[5];

2. Truy cập các phần tử trong mảng:

  • Mảng có kích thước n: int a[n];

Các phần tử trong mảng được đánh chỉ số từ: 0 -> n-1

VD: int a[5];

  • Phần tử đầu tiên có index = 0 -> a[0] // a[0] = 8;
  • Phần tử thứ 2 có index = 1 -> a[1] // a[1] = 5;

+ Phải luôn đảm bảo chỉ số mảng nằm trong đoạn [0, n-1], nếu không thì trong quá trình thực thi chương trình sẽ bị lỗi.

3. Khởi tạo mảng:

Cách 1: Khởi tạo ngay lúc khai báo mảng

VD1: int a[5] = {0, 1, 2, 3, 4};

Lưu ý: Nếu số lượng phần tử bạn khởi tạo nhỏ hơn kích thước mảng => Các giá trị phía sau sẽ được gán các giá trị không xác định.

int a[5] = {0, 1};

VD2: int a[] = {0,1,2,3,4};

Hệ thống sẽ ngầm hiểu mảng có kích thước bằng với số lượng phần tử ta khởi tạo

Cách 2: Gán giá trị từng phần tử riêng lẻ

    int a[5];
    a[2] = 15;
    a[3] = 20;

Dùng vòng lặp gán giá trị cho các phần tử trong mảng:

     int a[n];
     for (int i=0; i<n; i++) {
        cin >> a[i];
     }

Bài tập 1: Khai báo và nhập 1 mảng có kích thước n, tính và in ra màn hình tổng các phần tử trong mảng.

Bài tập 2: Khai báo và nhập 1 mảng có kích thước n, tìm và in ra vị trí của k trong mảng (k nhập từ bàn phím). Nếu k không có trong mảng thì in ra -1;

Bài tập 3: Khia báo và nhập 1 mảng có kích thước n, kiểm tra xem mảng có phải mảng tăng dần hay không?


☛ Lời giải bài tập 1:

#include <iostream>
using namespace std;

int main(){
    int n;
    cout << "Nhap N: "; cin >> n;
    // khai bao mang a co n phan tu
    int a[n];
    // nhap gia tri cho tung phan tu mang
    for(int i=0; i<n; i++){
        cin >> a[i];
    }
    int tong = 0;
    for(int i=0; i<n; i++){
        tong += a[i];
    }
    cout << "Tong: " << tong;
    return 0;
}

☛ Lời giải bài tập 2:

#include <iostream>
using namespace std;

int main(){
    int n;
    cout << "Nhap N: "; cin >> n;
    int a[n];
    for(int i=0; i<n; i++){
        cin >> a[i];
    }
 
    int k;
    cout << "Nhap K: "; cin >> k;
    int index = -1;
    for(int i=0; i<n; i++){
        if(a[i] == k){
            index = i;
            break;
        }
    }
    cout << "Vi tri tim thay: " << index;
    return 0;
}

☛ Lời giải bài tập 3:

#include <iostream>
using namespace std;

int main(){
    int n;  cin>>n;
    int a[n];
    for(int i=0; i<n; i++){
        cin >> a[i];
    }
    bool isAscending = true;
    for(int i=1; i<n; i++){
        if(a[i] <= a[i-1]){
            isAscending = false;
            break;
        }
    }
    if(isAscending) cout << "Mang tang dan";
    else cout << "Khong";
    return 0;
}

Mảng 2 chiều trong C++

➱ Mảng 2 chiều được hiểu là mảng chứa các mảng

1. Khai báo mảng 2 chiều:

Cú pháp: <kiểu dữ liệu> <tên mảng> [số hàng][số cột];

VD: int a[3][4];

float ch[5][5];

    • Mảng 2 chiều sẽ có kích thước là: Số hàng * Số cột

2. Truy cập các phần tử mảng:

Cú pháp: <tên mảng> [chỉ số hàng][chỉ số cột]

    • Việc đánh chỉ số cũng tương tự như ở mảng 1 chiều.

VD: int a[3][5];

    • Phần tử ở hàng đầu tiên, cột đầu tiên: a[0][0] // a[0][0] = 5;
    • Phần tử ở hàng thứ 2, cột thứ 3: a[1][2] // a[1][2] = 2;

3. Khởi tạo mảng 2 chiều:

Cách 1: Trực tiếp

int a[3][3] = { {1,2,3}, {4,5,6}, {7,8,9} };

Cách 2: Gán thủ công cho từng phần tử

VD:

    int a[3][4];
    a[0][0] = 5;
    a[0][1] = 9;
    ....

Dùng vòng lặp gán giá trị cho tất cả phần tử mảng:

     int a[n][m];
     for (int i=0; i<n; i++) {
         for (int j=0; j<m; j++) {
             cin >> a[i][j];
         }
     }

Bài tập 1: Khai báo và nhập vào mảng 2 chiều kích thước có kích thước NxN (N và giá trị các phần tử mảng nhập bất kỳ từ bàn phím). Tính và in ra màn hình tổng các phần tử trên đường chéo chính, đường chéo phụ.


☛ Lời giải bài tập 1:

#include <iostream>
using namespace std;

int main(){
    int n;
    cout << "Nhap N: "; cin >> n;
    int a[n][n];
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            cin >> a[i][j];
        }
    }
    int cheo_chinh = 0;
    for(int i=0; i<n; i++){
        cheo_chinh += a[i][i];
    }
    cout << "Tong cac phan tu tren duong cheo chinh: " << cheo_chinh << endl;
    int cheo_phu = 0;
    for(int i=0; i<n; i++){
        cheo_phu += a[i][n-1-i];
    }
    cout << "Tong cac phan tu tren duong cheo phu: " << cheo_phu << endl;
    return 0;
}

Bài tập về nhà:

  1. Dãy Fibonaccidãy vô hạn các số tự nhiên bắt đầu bằng hai phần tử 0 và 1 hoặc 1 và 1, các phần tử sau đó được thiết lập theo quy tắc mỗi phần tử luôn bằng tổng hai phần tử trước nó. Công thức truy hồi của dãy Fibonacci là:

Hãy viết chương trình nhập vào một số nguyên dương N, in ra màn hình số fibonacci thứ N.

2. Viết chương trình khởi tạo và nhập mảng A có kích thước N. Sau đó, nhập 2 số L, R (0 <= L <= R < N). Tính và in ra màn hình tổng các số trong đoạn từ A[L, L+1, ...., R-1, R].

3. Viết chương trình khởi tạo và nhập mảng A 2 chiều có kích thước NxM. Sau đó, nhập 4 số r1, c1, r2, c2 (0 <= r1 <= r2 < N, 0 <= c1, c2 < M, nếu r1 = r2 thì c1 <= c2). Tính và in ra màn hình tổng các số trong vùng từ A[r1][c1] đến A[r2][c2].

Xem hình vẽ để dễ hình dung:

Với các giá trị nhập vào: r1 = 1, c1 = 1, r2 = 3, c2 = 3

thì yêu cầu tính tổng giá trị các ô có màu xanh: 4+6+1+8+9+2+0+6+3+1+8 = 48

4. Viết chương trình khai báo và nhập mảng có kích thước 10 phần tử. Tìm phần tử có số lần xuất hiện nhiều nhất trong mảng. In ra màn hình giá trị phần tử và số lần xuất hiện đó.

Nếu có nhiều phần tử có số lần xuất hiện nhiều nhất bằng nhau thì chỉ cần chọn 1 số.

5. Viết chương trình khai báo và nhập vào một mảng kích thước N. Sắp xếp và in ra màn hình mảng theo thứ tự tăng dần.

Giải bài tập về nhà:

Bài 1: Ta tiến hành tạo một mảng f[n+1] với ý nghĩa

f[i] : là giá trị số Fibonacci thứ i

Dựa vào công thức truy hồi ở đề bài, ta có thể sử dụng vòng lặp để suy ra giá trị từng phần tử của mảng f[n+1]

#include <iostream>
using namespace std;

int main(){
    int n; cin >> n;
    int f[n+1];
    f[0] = 0;
    f[1] = 1;
    for(int i=2; i<=n ;i++){
        f[i] = f[i-1] + f[i-2];
    }
    cout << f[n];
    return 0;
}

Bài 2: Bài này chỉ đơn giản là duyệt và cộng hết tất cả các giá trị a[i] với i thuộc [L; R]

#include <iostream>
using namespace std;

int main(){
    int n, L, R; 
    cin >> n;
    int a[n];
    int sum = 0;
    for(int i=0; i<n; i++) 
        cin >> a[i];
    cin >> L >> R;
    for(int i=L; i<=R; i++){
        sum += a[i];
    }
    cout << "Tong: " << sum;
    return 0;
}

Bài 3:

  • Cách 1: Thao tác trên mảng 2 chiều
  1. Trường hợp r1 == r2 : ta chỉ cần cộng các giá trị a[r1][j] với j thuộc [c1; c2]
  2. Trường hợp r1 != r2: ta chia vùng màu xanh thành 3 vùng:
    1. Vùng thứ 1 là dòng r1 : Để ý sẽ thấy dòng này có chỉ số cột j chạy trong đoạn [c1; m-1]
    2. Vùng thứ 2 là vùng có các hàng nằm ở giữa r1r2, tức là chỉ số hàng i thuộc (r1; r2), chỉ số cột trong các dòng này sẽ chạy từ [0; m-1]
    3. Vùng thứ 3 là dòng r2: Chỉ số cột trong dòng này sẽ chạy trong đoạn [0; c2]
#include <iostream>
using namespace std;

int main(){
    int n,m; cin >> n >> m;
    int a[n][m];
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++) 
            cin >> a[i][j];
    int sum=0;
    int r1, c1, r2, c2;
    cin >> r1 >> c1 >> r2 >> c2;
    if(r1 == r2){
        for(int j=c1; j<=c2; j++){
            sum += a[r1][j];
        }
    }else{
        for(int j=c1; j<m; j++) 
            sum += a[r1][j];

        for(int i=r1+1; i<r2; i++)
            for(int j=0; j<m; j++)
                sum += a[i][j];

        for(int j=0; j<=c2; j++)
            sum += a[r2][j];
    }
    cout << "Tong: " << sum;
    return 0;
}
  • Cách 2: Ta xem mảng 2 chiều là mảng 1 chiều

Ở mảng 2 chiều, phần tử có vị trí hàng i cột j (i, j) khi chuyển qua mảng 1 chiều sẽ có indexi*m+j

Từ đó ta tạo 2 biến index là LR, duyệt tất cả các chỉ số k trong đoạn [L; R], tại mỗi chỉ số k ta lại chuyển k về thành 2 chỉ số (i, j) bằng cách chia ngược lại với ban đầu. Xem code bên dưới:

#include <iostream>
using namespace std;

int main(){
    int n,m; cin >> n >> m;
    int a[n][m];
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++) 
            cin >> a[i][j];
    int sum=0;
    int r1, c1, r2, c2;
    cin >> r1 >> c1 >> r2 >> c2;
 
    int L = r1*m + c1;
    int R = r2*m + c2;
 
    for(int k=L; k<=R; k++){
        int i = k/m;
        int j = k%m;
        sum += a[i][j];
    }
    cout << "Tong: " << sum;
    return 0;
}

Bài 4: Ta tạo 1 mảng count[10] với ý nghĩa:

count[i] : đếm xem giá trị phần tử a[i] xuất hiện bao nhiêu lần

#include <iostream>
using namespace std;

int main(){
    int a[10];
    for(int i=0; i<10; i++) 
        cin >> a[i];
    // count[i] : dem phan tu a[i] xuat hien bao nhieu lan
    int count[10];
    for(int i=0; i<10; i++) 
        count[i]=0;
 
    for(int i=0; i<10; i++){
        int dem = 0;
        for(int j=0; j<10; j++){
            if(a[j] == a[i]) dem++;
        }
        count[i] = dem;
    }
 
    int countMax = 0; // tan suat xuat hien lon nhat
    int indexMax = -1; // vi tri so co tan suat xuat hien lon nhat
    for(int i=0; i<10; i++){
        if(count[i] > countMax){
            countMax = count[i];
            indexMax = i;
        }
    }
    cout << "So " << a[indexMax] << ": xuat hien " << count[indexMax] << " lan";
    return 0;
}

Bài 5: Để sắp xếp 1 mảng có rất nhiều thuật toán, bên dưới mình trình bày Sắp xếp Chọn, vì nó ngắn gọn và dễ hiểu.

Ý tưởng: duyệt mảng với chỉ số i chạy từ [0; n-2]

với mỗi giá trị i, ta lại tạo 1 biến chạy j trong đoạn [i+1; n-1] nhằm tìm ra trong đoạn [i; n-1] phần tử có giá trị bé nhất.

Sau khi tìm được phần tử bé nhất, ta sẽ hoán đổi nó với a[i].

Như vậy, sau mỗi giá trị i chạy xong, mảng từ a[0] -> a[i] được sắp xếp tăng dần.

#include <iostream>
using namespace std;

int main(){
    int n; cin >> n;
    int a[n];
    for(int i=0; i<n; i++)
        cin >> a[i];
  
    for(int i=0; i < n-1; i++){
        int vitri = i;
        int mina = a[vitri];
        for(int j=i+1; j<n; j++){
            if(a[j] < mina){
                mina = a[j];
                vitri = j;
            }
        }
        //hoan doi vi tri a[i] va a[vitri]
        a[vitri] = a[i];
        a[i] = mina;
    }
 
    cout << "Sau khi sap xep: " << endl;
    for(int i=0; i<n; i++)
        cout << a[i] << " ";
    return 0;
}