[STL] So sánh giữa Vector và List trong C++
Khi làm việc với dữ liệu, mình thường cần sử dụng các cấu trúc dữ liệu để lưu trữ và quản lý dữ liệu. Trong STL (Standard Template Library) của C++, std::vector và std::list là hai cấu trúc dữ liệu phổ biến. Mặc dù cả hai đều cung cấp khả năng lưu trữ dữ liệu, nhưng chúng có những đặc điểm khác nhau về cách thức lưu trữ và hiệu suất. Bài viết này sẽ so sánh giữa std::vector và std::list trong STL của C++, cung cấp giải thích cho mỗi điểm khác biệt và cung cấp ví dụ minh họa.


Vector trong C++
Ưu điểm:
- Truy cập ngẫu nhiên nhanh chóng: std::vector được triển khai như một mảng liên tục các phần tử, cho phép truy cập ngẫu nhiên vào bất kỳ phần tử nào với thời gian hằng số O(1).
- Thêm và xóa phần tử ở cuối vector hiệu quả: Thao tác thêm và xóa phần tử ở cuối vector chỉ mất thời gian hằng số O(1).
Nhược điểm:
- Thêm và xóa phần tử ở vị trí khác không phải cuối vector có thể chậm: Khi thêm hoặc xóa phần tử ở đầu hoặc ở giữa vector, toàn bộ vector phải được sao chép lại, có thể tốn nhiều thời gian O(n).
Ví dụ:
Bài viết này được đăng tại [free tuts .net]
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// Truy cập ngẫu nhiên
std::cout << "Element at index 2: " << vec[2] << std::endl;
//freetuts.net
// Thêm phần tử vào cuối vector
vec.push_back(6);
// Xóa phần tử cuối cùng của vector
vec.pop_back();
return 0;
}
List trong C++
Ưu điểm:
- Thêm và xóa phần tử ở bất kỳ vị trí nào hiệu quả: std::list được triển khai dưới dạng danh sách liên kết, cho phép thêm và xóa phần tử ở bất kỳ vị trí nào với thời gian hằng số O(1).
- Không cần phải di chuyển dữ liệu khi thêm hoặc xóa: Do danh sách liên kết không cần phải di chuyển các phần tử khác khi thêm hoặc xóa, giúp tăng hiệu suất.
Nhược điểm:
- Truy cập ngẫu nhiên chậm: Việc truy cập phần tử trong std::list yêu cầu phải đi qua từng nút, do đó có độ phức tạp thời gian tuyến tính O(n).
Ví dụ:
#include <iostream>
#include <list>
//freetuts.net
int main() {
std::list<int> mylist = {1, 2, 3, 4, 5};
// Thêm phần tử vào đầu danh sách
mylist.push_front(0);
// Xóa phần tử ở vị trí thứ 3
auto it = std::next(mylist.begin(), 2);
mylist.erase(it);
return 0;
}
So sánh giữa Vector và List trong C++
Độ phức tạp thời gian và không gian
- Vector: Thời gian truy cập ngẫu nhiên là O(1), nhưng thêm và xóa phần tử ở vị trí bất kỳ có độ phức tạp là O(n) do cần di chuyển các phần tử. Chiếm không gian liên tục trong bộ nhớ.
- List: Thời gian truy cập ngẫu nhiên là O(n) do phải đi qua từ đầu đến vị trí cần truy cập. Thêm và xóa phần tử ở bất kỳ vị trí nào có độ phức tạp là O(1) vì không cần di chuyển các phần tử. Chiếm không gian không liên tục trong bộ nhớ vì cần lưu trữ con trỏ.
Tốc độ truy cập và tìm kiếm:
- Vector có tốc độ truy cập ngẫu nhiên nhanh hơn so với List do dữ liệu được lưu trữ liên tục trong bộ nhớ.
- Trong trường hợp tìm kiếm, cả Vector và List đều có độ phức tạp O(n) vì phải đi qua từ đầu đến cuối dữ liệu.
Thêm và xóa phần tử:
- Vector không linh hoạt trong việc thêm và xóa phần tử ở vị trí bất kỳ do độ phức tạp thời gian là O(n).
- List linh hoạt trong việc thêm và xóa phần tử ở bất kỳ vị trí nào với độ phức tạp thời gian là O(1).
Sử dụng phù hợp của Vector và List
Sử dụng Vector khi:
- Cần truy cập ngẫu nhiên đến các phần tử.
- Dữ liệu có kích thước không thay đổi và ít thao tác thêm/xóa.
- Yêu cầu không gian liên tục trong bộ nhớ.
Sử dụng List khi:
- Cần thực hiện các thao tác thêm/xóa phần tử thường xuyên ở bất kỳ vị trí nào.
- Cần tiết kiệm thời gian cho các thao tác thêm/xóa phần tử.
- Dữ liệu có thể mở rộng và thay đổi kích thước linh hoạt.
Ví dụ:
#include <iostream>
#include <vector>
#include <list>
int main() {
// Sử dụng Vector
std::vector<int> vec = {1, 2, 3};
vec.push_back(4); // Thêm phần tử vào cuối Vector
vec.erase(vec.begin() + 1); // Xóa phần tử ở vị trí thứ 2 trong Vector
// bài viết được đăng tại freetuts.net
// Sử dụng List
std::list<int> li = {1, 2, 3};
li.push_back(4); // Thêm phần tử vào cuối List
li.erase(++li.begin()); // Xóa phần tử ở vị trí thứ 2 trong List
return 0;
}
Trong ví dụ trên, ta có thể thấy cách sử dụng Vector và List để thêm và xóa phần tử, và sự khác biệt về độ phức tạp thời gian của từng cấu trúc dữ liệu.
Ví dụ thực hành Vector trong C++
Ví dụ về sử dụng Vector trong C++:
#include <iostream>
#include <vector>
int main() {
// Khai báo và khởi tạo Vector
std::vector<int> vec = {1, 2, 3, 4, 5};
// Thêm một phần tử vào cuối Vector
vec.push_back(6);
// Truy cập và hiển thị các phần tử trong Vector
std::cout << "Vector: ";
for (int i : vec) {
std::cout << i << " ";
}
std::cout << std::endl;
//Bài viết được đăng tại freetuts.net
// Xóa phần tử ở vị trí thứ 3 trong Vector
vec.erase(vec.begin() + 2);
// Hiển thị Vector sau khi xóa phần tử
std::cout << "Vector sau khi xoa: ";
for (int i : vec) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
Kết quả:

Ví dụ về sử dụng List trong C++:
#include <iostream>
#include <list>
int main() {
// Khai báo và khởi tạo List
std::list<int> li = {1, 2, 3, 4, 5};
// Thêm một phần tử vào cuối List
li.push_back(6);
// Truy cập và hiển thị các phần tử trong List
std::cout << "List: ";
for (int i : li) {
std::cout << i << " ";
}
std::cout << std::endl;
//Bài viết được đăng tại freetuts.net
// Xóa phần tử ở vị trí thứ 3 trong List
auto it = std::next(li.begin(), 2);
li.erase(it);
// Hiển thị List sau khi xóa phần tử
std::cout << "List sau khi xoa: ";
for (int i : li) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
Kết quả:

Trong các ví dụ trên, ta đã sử dụng Vector và List để thực hiện các thao tác thêm và xóa phần tử. Vector được sử dụng cho các trường hợp cần truy cập ngẫu nhiên và không cần thêm/xóa phần tử nhiều, trong khi List được sử dụng khi cần thêm/xóa phần tử thường xuyên ở bất kỳ vị trí nào.
Kết bài
Trong bài viết này, mình đã tìm hiểu về hai cấu trúc dữ liệu phổ biến trong STL của C++, đó là Vector và List. Chúng ta đã đi vào chi tiết về định nghĩa, tính chất, ưu điểm và nhược điểm của mỗi loại cấu trúc dữ liệu, cũng như so sánh giữa chúng dựa trên các yếu tố như độ phức tạp thời gian, tốc độ truy cập, thêm và xóa phần tử.
Thông qua các ví dụ minh họa, mình đã thấy cách sử dụng Vector và List trong các tình huống khác nhau, từ đó đưa ra quyết định về việc lựa chọn cấu trúc dữ liệu phù hợp cho mỗi bài toán cụ thể.
Tùy thuộc vào yêu cầu và đặc điểm của từng vấn đề, mình có thể lựa chọn sử dụng Vector hoặc List để tối ưu hiệu suất và tiện ích của chương trình. Hi vọng bài viết này đã cung cấp cho bạn cái nhìn tổng quan và chi tiết về sự khác biệt giữa hai cấu trúc dữ liệu quan trọng này trong STL của C++.

Các kiểu dữ liệu trong C ( int - float - double - char ...)
Thuật toán tìm ước chung lớn nhất trong C/C++
Cấu trúc lệnh switch case trong C++ (có bài tập thực hành)
ComboBox - ListBox trong lập trình C# winforms
Random trong Python: Tạo số random ngẫu nhiên
Lệnh cin và cout trong C++
Cách khai báo biến trong PHP, các loại biến thường gặp
Download và cài đặt Vertrigo Server
Thẻ li trong HTML
Thẻ article trong HTML5
Cấu trúc HTML5: Cách tạo template HTML5 đầu tiên
Cách dùng thẻ img trong HTML và các thuộc tính của img
Thẻ a trong HTML và các thuộc tính của thẻ a thường dùng