Tổng hợp vector trong C++

₵++ là từ ngữ mạnh khỏe nhờ tính linh động, thân thiện với từ ngữ máy. Ngoài ra còn tồn tại khả năng lập trình dựa theo mẫu có sẵn (template). Sức mạnh của ₵++ nằm ở STL (Standard Template Library) – một thư viện template giành riêng cho ₵++ tổng hợp các kết cấu dữ liệu cũng như giải thuật & các vector trong ₵++ được xây dựng một cách tổng quát cho nhiều trường hợp.

Giới thiệu literals & operators”]

Bộ thư viện này thực hiện toàn thể các hoạt động ra vào của dữ liệu (iostream), làm chủ mảng (vector) & đa phần các chức năng của các kết cấu dữ liệu căn bản như (stack, queue, map, set…). Không những thế, STL còn bao gồm các thuật toán căn bản: tính tổng, tìm min, max, xếp đặt (với phong phú thuật toán xếp đặt), thay thế các phần tử, tìm kiếm (tìm kiếm bình bình & tìm kiếm dười dạng nhị phân). Toàn thể những chức năng trên đều được phân phối dưới dạng template nên việc sử dụng chúng cực kỳ tiện dụng & phù hợp với nhiều tình huống. Nhờ vậy, STL khiến cho từ ngữ ₵++ trở nên “xịn xò” hơn.

Nhưng nói tới STL thì sẽ là bài tập rất dài nên lúc này mình sẽ chỉ đề cập đến vector thôi.

Vậy Vector trong ₵++ là gì?

Không giống như array (mảng), chỉ một số giá trị khẳng định có thể được lưu trữ dưới một tên biến duy nhất. Vector trong ₵++ giống dynamic array (mảng động) nhưng có khả năng auto biến đổi kích cỡ khi một phần tử được chèn hoặc xóa tùy theo vào nhu cầu của tác vụ được thực thi, với việc lưu trữ của chúng sẽ được vùng chứa auto giải quyết. Các phần tử vector được đặt trong contiguous storage (bộ nhớ lưu trữ liền kề) để chúng có thể được truy cập & duyệt qua bằng cách dùng iterator.

Tại sao nên dùng Vector

Nếu bạn đã phát chán việc làm chủ mảng động qua con trỏ trong ₵++ hay chán phải tạo mảng mới, sao chép các phần tử qua mảng mới, rồi lại xóa mảng cũ mỗi khi bạn mong muốn resize kích cỡ mảng động trong ₵++. Thật thừa thải, tốn thời gian & này là thời điểm ta nhận thấy ₵++ còn tồn tại vector.

Một số điểm đặc biệt của Vector

– Bạn không cần phải khai báo kích cỡ của mảng chẳng hạn int ?[100]…, vì vector có thể auto nâng kích cỡ lên.

– Nếu bạn thêm 1 phần tử vào vector đã đầy rồi, thì nó sẽ auto tăng kích cỡ của nó lên để dành chỗ cho giá trị mới này.

– Vector còn hỗ trợ cho bạn biết số lượng các phần tử mà bạn đang lưu trong đó.

– Dùng số phần tử âm vẫn được trong vector chẳng hạn ?[-6], ?[-9], rất tiện trong việc setup các giải thuật.

Vector có thứ tự trong ₵++ không?

Không có vector nào không được xếp đặt trong ₵++. Các phần tử vector được đặt trong bộ nhớ lưu trữ liền kề để chúng có thể được truy cập & di chuyển qua các iterator. Trong vector, dữ liệu được chèn vào cuối. Việc chèn một phần tử vào cuối sẽ mất thời gian chênh lệch, vì đôi lúc có thể cần mở rộng vector. Việc xóa phần tử cuối cùng chỉ mất thời gian không đổi vì không xảy ra biến đổi kích cỡ. Chèn & xóa ở đầu hoặc giữa vector là tuyến tính theo thời gian.

Các vector được lưu trữ trong ₵++ như vậy nào?

Để tạo một vector, bạn cần thực hiện theo cú pháp dưới đây:

Cú pháp:

#include <vector>
//...
vector<object_typevàgt; variable_name;

Chẳng hạn:

#include <vector>
int main()
{
    std::vector<intvàgt; my_vector;
}

Vậy là tất cả chúng ta đã có một vector với mỗi phần tử có kiểu dữ liệu (object_type) là int. Sau đó bạn có thể gắn giá trị cho vector như này:

vector<intvàgt; my_vector = {1,2,3,4,5}

Hoặc bạn cũng có thể tạo một vector rồi gán giá trị của một vector khác cho nó bằng cách:

vector<intvàgt; my_vector = {1,2,3,4,5}; vector<intvàgt; your_vector = my_vector;

Chế độ ngăn chặn rò rỉ bộ nhớ lưu trữ của Vector

Khi một biến vector rời khỏi phạm vi đoạn code mà chương trình đang chạy, nó sẽ auto giải phóng những phần bộ nhớ lưu trữ mà nó kiểm tra (nếu cần). Điều này không những tiện lợi (vì bạn không cần tự tay giải phóng bộ nhớ lưu trữ), mà nó còn hỗ trợ ngăn ngừa lỗi rò rỉ bộ nhớ lưu trữ (memory leaks).

Xem Thêm  Thuộc tính id - thuộc tính id thẻ kiểu html

Xem hàm dưới đây:

void

doSomething(

bool

earlyExit) {

int

*

array

=

new

int

[

3

]{

1

,

3

,

2

};

if

(earlyExit)

return

;

delete

[]

array

; }

Nếu biến earlyExit được gán là true, mảng array sẽ không lúc nào được giải phóng, & bộ nhớ lưu trữ sẽ bị rò rỉ.

Bên cạnh đó, nếu biến array là một vector, điều này sẽ không xảy ra, bởi vì bộ nhớ lưu trữ sẽ được giải phóng ngay sau khoảng thời gian biến array nằm ngoài phạm vi đoạn code mà chương trình đang chạy (bất cứ hàm có bị thoát ra sớm hay không). Điều này khiến cho vector an toàn hơn nhiều đối với việc bạn phải tự cảnh báo tới việc giải phóng bộ nhớ lưu trữ.

Vector tự ghi nhớ độ dài của mình

Không giống như mảng động được tích hợp sẵn của ₵++, cái mà không hiểu rằng độ dài của mảng mà nó đang trỏ tới là bao nhiêu, std::vectors tự theo dõi độ dài của chính nó. Tất cả chúng ta có thể lấy được độ dài của vector thông qua hàm size():

#include <iostreamvàgt;
#include <vector>

void printLength(const std::vector<intvàgt;& array)
{

 

std::cout << "The length is: " << array.size() << 'ռ'; } int main() {

 

std::vector array { 9, 7, 5, 3, 1 };

 

printLength(array);

 

return 0; }

Output:

The length is

:

5

Tương đương với array, hàm size() sẽ trả về một giá trị thuộc kiểu nested type (kiểu dữ liệu lồng) là size_type, nó là một số nguyên không dấu.

Các hàm của Vectors trong ₵ ++

Vector trong STL phân phối cho tất cả chúng ta nhiều công dụng hữu hiệu khác nhau.

1. Modifiers
2. Iterators
3. Capacity
4. Element access

Modifiers

1. push_back(): Hàm đẩy một phần tử vào địa điểm sau cùng của vector. Nếu kiểu của đối tượng được truyền dưới dạng tham số trong push_back() không giống với kiểu của vector thì sẽ bị ném ra.

ten-vector.push_back(ten-cua-phan-tu);

2. assign(): Nó gán một giá trị mới cho các phần tử vector bằng cách thay thế các giá trị cũ.

ten-vector.assign(int size, int value);

3. pop_back(): Hàm pop_back () được sử dụng để xóa đi phần tử cuối cùng một vector.

ten-vector.pop_back();

4. insert(): Hàm này chèn các phần tử mới vào trước phần tử trước địa điểm được trỏ bởi vòng lặp. Tất cả chúng ta cũng có thể chuyển một số đối số thứ ba, đếm số lần phần tử được chèn vào trước địa điểm được trỏ.

ten-vector.insert(position, value);

5. erase(): Hàm được sử dụng để xóa các phần tử tùy thuộc địa điểm vùng chứa

ten-vector.erase(position);

ten-vector.erase(start-position, end-position);

6. emplace(): Nó mở rộng vùng chứa bằng cách chèn phần tử mới vào

ten-vector.emplace(ten-vector.position, element);

7. emplace_back(): Nó được sử dụng để chèn một phần tử mới vào vùng chứa vector, phần tử mới sẽ được thêm vào cuối vector

ten-vector.emplace_back(value);

8. swap(): Hàm được sử dụng để hoán đổi bài viết của một vector này với một vector khác cùng kiểu. Kích cỡ có thể khác nhau.

ten-vector-1.swap(ten-vector-2);

9. clear(): Hàm được sử dụng để loại bỏ toàn bộ các phần tử của vùng chứa vector.

ten-vector.clear();

Chẳng hạn:

/ Modifiers in vector 
#include <bits/stdc++.hvàgt; 
#include <vector> 
using namespace std; 
   
int main() 
{ 
    // Assign vector 
    vector<intvàgt; vec; 
   
    // fill the array with 12 seven times 
    vec.assign(7, 12); 
   
    cout << "The vector elements are: "; 
    for (int ι = 0; ι < 7; ι++) 
        cout << vec[i] << " "; 
   
    // inserts 24 to the last position 
    vec.push_back(24); 
    int s = vec.size(); 
    cout << "nThe last element is: " << vec[s - 1]; 
 
     // prints the vector 
    cout << "nThe vector elements after push back are: "; 
    for (int ι = 0; ι < vec.size(); ι++) 
    cout << vec[i] << " "; 
   
    // removes last element 
    vec.pop_back(); 
   
    // prints the vector 
    cout << "nThe vector elements after pop_back are: "; 
    for (int ι = 0; ι < vec.size(); ι++) 
        cout << vec[i] << " "; 
   
    // inserts 10 at the beginning 
    vec.insert(vec.begin(), 10); 
   
    cout << "nThe first element after insert command is: " << vec[0]; 
   
    // removes the first element 
    vec.erase(vec.begin()); 
   
    cout << "nThe first element after erase command is: " << vec[0]; 
   
    // inserts at the beginning 
    vec.emplace(vec.begin(), 5); 
    cout << "nThe first element emplace is: " << vec[0]; 
   
    // Inserts 20 at the end 
    vec.emplace_back(20); 
    s = vec.size(); 
    cout << "nThe last element after emplace_back is: " << vec[s - 1]; 
   
    // erases the vector 
    vec.clear(); 
    cout << "nVector size after clear(): " << vec.size(); 
   
    // two vector to perform swap 
    vector<intvàgt; obj1, obj2; 
    obj1.push_back(2); 
    obj1.push_back(4); 
    obj2.push_back(6); 
    obj2.push_back(8); 
   
    cout << "nnVector 1: "; 
    for (int ι = 0; ι < obj1.size(); ι++) 
        cout << obj1[i] << " "; 
   
    cout << "nVector 2: "; 
    for (int ι = 0; ι < obj2.size(); ι++) 
        cout << obj2[i] << " "; 
   
    // Swaps obj1 and obj2 
    obj1.swap(obj2); 
   
    cout << "nAfter Swap nVector 1: "; 
    for (int ι = 0; ι < obj1.size(); ι++) 
        cout << obj1[i] << " "; 
   
    cout << "nVector 2: "; 
    for (int ι = 0; ι < obj2.size(); ι++) 
        cout << obj2[i] << " "; 
}

Output:

Xem Thêm  Ngày 10: Hướng dẫn và ví dụ về Bootstrap 4 Navbar - navbar bootstrap 4 ví dụ

vector-trong-c++

Bạn có thể thấy cách dùng các hàm thuộc nhóm Modifiers mà tất cả chúng ta đã tìm hiểu ở trên qua chẳng hạn thực tế.

Iterators

  1. begin(): đặt iterator đến phần tử trước nhất trong vectorten-vector.begin();
  2. end(): đặt iterator đến sau phần tử cuối cùng trong vectorten-vector.end();
  3. rbegin(): đặt reverse iterator (trình lặp đảo) đến phần tử cuối cùng trong vector (reverse begin). Nó di chuyển từ phần tử cuối cùng đến phần tử trước nhất

    ten-vector.rbegin();

  4. rend(): đặt reverse iterator (trình lặp đảo) đến phần tử trước nhất trong vector (reverse end)

    ten-vector.rend();

  5. cbegin(): đặt constant iterator (trình vòng lặp) đến phần tử trước nhất trong vectorten-vector.cbegin();
  6. cend(): đặt constant iterator (trình vòng lặp) đến phần tử cuối cùng trong vectorten-vector.cend();
  7. crbegin(): đặt constant reverse iterator (trình lặp đảo liên tục) đến phần tử cuối cùng trong vector (reverse begin). Nó di chuyển từ phần tử cuối cùng đến phần tử trước nhấtten-vector.cbregin();
  8. crend(): đặt constant reverse iterator (trình lặp đảo liên tục) đến phần tử trước nhất trong vector (reverse end)ten-vector.crend();

Chẳng hạn 1:

#include <iostreamvàgt; 
#include <vector> 
   
using namespace std; 
   
int main() 
{ 
    vector<intvàgt; vec1; 
   
    for (int ι = 1; ι <= 10; ι++) 
        vec1.push_back(ι); 
   
    cout << "Understanding begin() and end() function: " << endl; 
    for (tự động ι = vec1.begin(); ι != vec1.end(); ++ι) 
        cout << *ι << " "; 
 
    return 0; 
}

Output:

vector-trong-c++

Trong chẳng hạn trên, tất cả chúng ta có thể thấy cách dùng hàm begin() & end(). Trước nhất, tất cả chúng ta xác nhận một vector là vec1, chúng đẩy lùi các giá trị trong đó từ 1 đến 10 bằng cách dùng vòng lặp for. Sau đó, chúng in các giá trị của các vector của http://phptravels.vn/ bằng cách dùng vòng lặp for, http://phptravels.vn/ sử dụng hàm begin() & end() để chỉ định điểm đầu & điểm cuối của vòng lặp for của http://phptravels.vn/.

Chẳng hạn 2:

// ₵++ program to illustrate the 
// iterators in vector 
#include <iostreamvàgt; 
#include <vector> 

using namespace std; 

int main() 
{ 
    vector<intvàgt; g1; 

    for (int ι = 1; ι <= 5; ι++) 
        g1.push_back(ι); 

    cout << "Output of begin and end: "; 
    for (tự động ι = g1.begin(); ι != g1.end(); ++ι) 
        cout << *ι << " "; 

    cout << "nOutput of cbegin and cend: "; 
    for (tự động ι = g1.cbegin(); ι != g1.cend(); ++ι) 
        cout << *ι << " "; 

    cout << "nOutput of rbegin and rend: "; 
    for (tự động ir = g1.rbegin(); ir != g1.rend(); ++ir) 
        cout << *ir << " "; 

    cout << "nOutput of crbegin and crend : "; 
    for (tự động ir = g1.crbegin(); ir != g1.crend(); ++ir) 
        cout << *ir << " "; 

    return 0; 
}

Output:

Chẳng hạn 3:

// CPP program to illustrate working of crbegin()  
// crend() 
#include <iostreamvàgt; 
#include <vector> 
using namespace std; 

int main () 
{ 
  // initializing vector with values 
  vector<intvàgt; vect = {10, 20, 30, 40, 50}; 

  // for loop with crbegin and crend 
  for (tự động ι = vect.crbegin(); ι != vect.crend(); ι++) 
    cout << ' ' << *ι;  //printing results 

  cout << 'ռ'; 
  return 0; 
}

Output:

50 40 30 20 10

Capacity

  1. size(): hàm sẽ trả về số lượng phần tử đang được sử dụng trong vectorten-vector.size();
  2. max_size(): hàm trả về số phần tử tối đa mà vector có thể chứaten-vector.max_size();
  3. capacity(): hàm trả về số phần tử được cấp phát cho vector nằm trong bộ nhớ lưu trữten-vector.capacity();
  4. resize(ռ): Hàm này biến đổi kích cỡ vùng chứa để nó chứa đủ ռ phần tử. Nếu kích cỡ hiện thời của vector to hơn ռ thì các phần tử phía sau sẽ bị xóa khỏi vector & trái lại nếu kích cỡ hiện thời bé hơn ռ thì các phần tử bổ sung sẽ được chèn vào phía sau vectorten-vector.resize(int ռ, int value);
  5. empty(): Trả về liệu vùng chứa có trống hay không, nếu trống thì trả về True, nếu có phần tử thì trả về Falseten-vector.empty();
  6. shrink_to_fit(): Giảm dung tích của vùng chứa để phù hợp với kích cỡ của nó & hủy toàn bộ các phần tử vượt quá dung tíchten-vector.shrink_to_fit();
  7. reserve(ռ): hàm cấp cho vector số dung tích vừa đủ để chứa ռ phần tửten-vector.reserve(ռ);

Chẳng hạn:

#include <iostreamvàgt; 
#include <vector> 
   
using namespace std; 
   
int main() 
{ 
    vector<intvàgt; vec1; 
   
    for (int ι = 1; ι <= 10; ι++) 
        vec1.push_back(ι); 
   
    cout << "Size of our vector: " << vec1.size(); 
    cout << "nCapacity of our vector: " << vec1.capacity(); 
    cout << "nMax_Size of our vector: " << vec1.max_size(); 
   
    // resizes the vector size to 4 
    vec1.resize(4); 
   
    // prints the vector size after resize() 
    cout << "nSize of our vector after resize: " << vec1.size(); 
   
    // checks if the vector is empty or not 
    if (vec1.empty() == false) 
        cout << "nVector is not empty"; 
    else
        cout << "nVector is empty"; 
   
    return 0; 
}

Output:

Xem Thêm  Cách chuyển đổi một chuỗi thành một mảng trong JavaScript - chuỗi javascript vào danh sách

capacity-vectors-in-c++

Cảnh báo: Khi biến đổi kích cỡ mảng vector, các giá trị của phần tử hiện có cần giữ nguyên, thì các phần tử mới được khởi tạo bằng giá trị mặc định của kiểu dữ liệu mảng.

Tất cả chúng ta có thể thấy cách hoạt động của các hàm capacity như đã luận bàn ở trên.

Element access

  1. at(ɢ): Trả về một tham chiếu đến phần tử ở địa điểm ‘g’ trong vectorten-vector.at(position);
  2. data(): Trả về một con trỏ trực tiếp đó (memory array) bộ nhớ lưu trữ mảng được vector sử dụng bên trong để lưu trữ các phần tử thuộc sở hữu của nóten-vector.data();
  3. front(): hàm dùng để lấy ra phần tử trước nhất của vectorten-vector.front();
  4. back(): hàm dùng để lấy ra phần tử cuối cùng của vectorten-vector.back();

Chẳng hạn: 

// ₵++ program to illustrate the 
// element accesser in vector 
#include <bits/stdc++.hvàgt; 
using namespace std; 
  
int main() 
{ 
    vector<intvàgt; g1; 
  
    for (int ι = 1; ι <= 10; ι++) 
        g1.push_back(ι * 10); 
  
    cout << "nReference operator [g] : g1[2] = " << g1[2]; 
  
    cout << "nat : g1.at(4) = " << g1.at(4); 
  
    cout << "nfront() : g1.front() = " << g1.front(); 
  
    cout << "nback() : g1.back() = " << g1.back(); 
  
    // pointer to the first element 
    int* pos = g1.data(); 
  
    cout << "nThe first element is " << *pos; 
    return 0; 
}

Output:

Thực hiện nén nhiều giá trị bools

Vector còn tồn tại một thủ thuật hay ho khác là sử dụng một setup đặc biệt giành riêng cho vector kiểu bool mà nó có thể nén 8 giá trị booleans vào trong chỉ một byte (amazing!!) Công cuộc này đã được cài sẵn, toàn bộ những gì bạn cần chỉ là sử dụng nó như một chức năng trợ giúp khi lập trình. Thủ thuật này cũng sẽ không tác động gì đến cách mà bạn sử dụng vector.

#include <vector>
#include <iostreamvàgt;

int main()
{

 

std::vector<boolvàgt; array { true, false, false, true, true };

 

std::cout << "The length is: " << array.size() << 'ռ';

 

for (int ι : array)

     

std::cout << ι << ' ';

   

std::cout << 'ռ';

   

return 0; }

Output:

The length is: 5
1 0 0 1 1

Kết

Với những cú pháp mẫu & chẳng hạn thực tế trên, tất cả chúng ta chấm dứt phần khám phá về vector trong ₵++. Tôi mong ước bạn đã phân biệt được các hàm khác nhau của vector & nắm được cách hoạt động của từng hàm. Vì vector trợ giúp rất tốt trong việc thao tác với mảng động, bảo đảm an toàn & đơn giản hơn. Chúng ta nên sử dụng vector trong đa phần các trường hợp đụng tới mảng động.

Nguồn tri thức về vector chúng ta nên đọc qua:

Có thể bạn mong muốn đọc thêm:

Tham khảo thêm việc làm ₵++ Developer tại TopDev

Viết một bình luận