(写给未来遗忘的自己)
1.常见类型:
- 数组:适用于固定大小的场景,访问速度快,但大小固定。
vector
:动态数组,大小可以自动调整,适用于需要灵活大小的场景。list
:双向链表,适用于需要频繁插入和删除的场景。map
:关联容器,存储键值对,适用于需要快速查找的场景。- 链表:可以使用指针实现,适用于需要动态数据结构的场景
2.使用方法:
2.1 数组
数组是一种固定大小的数据结构,适用于已知大小的场景。
- 一维数组:适用于线性数据结构,大小固定。
- 二维数组:适用于矩阵数据结构,大小固定。
- 动态数组:适用于在运行时确定大小的数组,需要手动管理内存。
这些示例展示了如何初始化和使用一维和二维数组
#include <iostream>
int main() {
// 初始化一维数组
int arr[5] = {1, 2, 3, 4, 5};
// 或者可以逐个元素初始化
int arr2[5];
arr2[0] = 1;
arr2[1] = 2;
arr2[2] = 3;
arr2[3] = 4;
arr2[4] = 5;
// 遍历一维数组
for (int i = 0; i < 5; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
// 初始化二维数组
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 或者可以逐个元素初始化
int arr2[3][4];
arr2[0][0] = 1; arr2[0][1] = 2; arr2[0][2] = 3; arr2[0][3] = 4;
arr2[1][0] = 5; arr2[1][1] = 6; arr2[1][2] = 7; arr2[1][3] = 8;
arr2[2][0] = 9; arr2[2][1] = 10; arr2[2][2] = 11; arr2[2][3] = 12;
// 遍历二维数组
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
std::cout << arr[i][j] << " ";
}
std::cout << std::endl;
}
return 0;
}
静态分配和动态分配的情况
#include <iostream>
int main() {
// 动态分配一维数组
int* arr = new int[5];
// 初始化数组
for (int i = 0; i < 5; i++) {
arr[i] = i + 1;
}
// 遍历数组
for (int i = 0; i < 5; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
// 释放动态数组
delete[] arr;
// 动态分配二维数组
int rows = 3;
int cols = 4;
int** arr = new int*[rows];
for (int i = 0; i < rows; i++) {
arr[i] = new int[cols];
}
// 初始化数组
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
arr[i][j] = i * cols + j + 1;
}
}
// 遍历二维数组
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
std::cout << arr[i][j] << " ";
}
std::cout << std::endl;
}
// 释放动态数组
for (int i = 0; i < rows; i++) {
delete[] arr[i];
}
delete[] arr;
return 0;
}
2.2 vector
vector
是动态数组,可以自动调整大小,适用于需要灵活大小的场景。
#include <iostream>
#include <vector>
int main() {
// 初始化 vector
std::vector<int> vec = {1, 2, 3, 4, 5};
// 添加元素
vec.push_back(6);
// 删除第三个元素(索引为2)
vec.erase(vec.begin() + 2);
// 删除索引为1到3(包括索引1,但不包括索引3)的元素
vec.erase(vec.begin() + 1, vec.begin() + 4);
// 删除所有偶数元素
vec.erase(std::remove_if(vec.begin(), vec.end(), [](int num){ return num % 2 == 0;
}), vec.end());
// 清空整个 vector
vec.clear();
// 访问和修改元素
vec[0] = 10;
// 遍历 vector
for (int i = 0; i < vec.size(); i++) {
std::cout << vec[i] << " ";
}
/***********************************************************************/
// 初始化 二维vector
std::vector<std::vector<int>> vec2d = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 访问和修改元素
std::cout << "Element at (1, 1): " << vec2d[1][1] << std::endl;
vec2d[1][1] = 10;
// 要添加的一行元素
std::vector<int> newRow = {7, 8, 9};
// 将 newRow 添加到 vec2d 的末尾
vec2d.push_back(newRow);
// 遍历二维 vector
for (int i = 0; i < vec2d.size(); i++) {
for (int j = 0; j < vec2d[i].size(); j++) {
std::cout << vec2d[i][j] << " ";
}
std::cout << std::endl;
}
/***********************************************************************/
std::vector<std::vector<std::vector<int>>> vec3d = {
{
{1, 2},
{3, 4}
},
{
{5, 6},
{7, 8}
}
};
// 访问和修改元素
std::cout << "Element at (1, 1, 1): " << vec3d[1][1][1] << std::endl;
vec3d[1][1][1] = 10;
// 遍历三维 vector
for (int i = 0; i < vec3d.size(); i++) {
for (int j = 0; j < vec3d[i].size(); j++) {
for (int k = 0; k < vec3d[i][j].size(); k++) {
std::cout << vec3d[i][j][k] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
return 0;
}
2.3 list
list
是双向链表,适用于需要频繁插入和删除的场景。
#include <iostream>
#include <list>
int main() {
// 初始化 list
std::list<int> lst = {1, 2, 3, 4, 5};
// 添加元素
lst.push_back(6);
lst.push_front(0);
// 遍历 list
for (auto it = lst.begin(); it != lst.end(); ++it) {
std::cout << *it << " ";
}
return 0;
}
2.4 map
map
是一种关联容器,存储键值对,按键排序,适用于需要快速查找的场景。map有三种类型。
td::map
:有序关联容器,根据键进行排序。std::unordered_map
:无序关联容器,使用哈希表实现快速查找。std::multimap
:允许重复键的有序关联容器,可以存储相同键的多个值。
#include <iostream>
#include <map>
int main() {
// 初始化 map
std::map<int, std::string> mp;
mp[1] = "one";
mp[2] = "two";
mp[3] = "three";
// 访问和修改元素
mp[1] = "ONE";
// 遍历 map
for (const auto& pair : mp) {
std::cout << pair.first << ": " << pair.second << "\n";
}
/**************************************************************************************/
std::unordered_map<int, std::string> myMap;
// 插入元素
myMap.insert({1, "apple"});
myMap.insert({2, "banana"});
myMap.insert({3, "cherry"});
// 访问元素
std::cout << "Value for key 2: " << myMap[2] << std::endl;
// 遍历 unordered_map
for (const auto& pair : myMap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
/**************************************************************************************/
std::multimap<int, std::string> myMultimap;
// 插入元素
myMultimap.insert({1, "apple"});
myMultimap.insert({2, "banana"});
myMultimap.insert({2, "orange"}); // 允许重复键
// 访问元素
std::cout << "Values for key 2:" << std::endl;
auto range = myMultimap.equal_range(2);
for (auto it = range.first; it != range.second; ++it) {
std::cout << it->second << std::endl;
}
// 遍历 multimap
for (const auto& pair : myMultimap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
2.5单向链表
链表是一种动态数据结构,可以使用指针实现,适用于需要动态数据结构的场景。
#include <iostream>
struct Node {
int data;
Node* next;
};
int main() {
// 初始化链表
Node* head = new Node{1, nullptr};
head->next = new Node{2, nullptr};
head->next->next = new Node{3, nullptr};
// 遍历链表
Node* current = head;
while (current != nullptr) {
std::cout << current->data << " ";
current = current->next;
}
// 释放链表内存
current = head;
while (current != nullptr) {
Node* next = current->next;
delete current;
current = next;
}
return 0;
}
2.6 双向链表
双向链表比单向链表多了一个指向前一个节点的指针。
#include <iostream>
struct Node {
int data;
Node* next;
Node* prev;
};
int main() {
// 初始化链表
Node* head = new Node{1, nullptr, nullptr};
Node* second = new Node{2, nullptr, head};
head->next = second;
Node* third = new Node{3, nullptr, second};
second->next = third;
// 遍历链表(向前)
Node* current = head;
while (current != nullptr) {
std::cout << current->data << " ";
current = current->next;
}
std::cout << std::endl;
// 遍历链表(向后)
current = third;
while (current != nullptr) {
std::cout << current->data << " ";
current = current->prev;
}
// 释放链表内存
current = head;
while (current != nullptr) {
Node* next = current->next;
delete current;
current = next;
}
return 0;
}
2.7 set
set
是一种关联容器,用于存储唯一值,并且会自动对其进行排序。set
提供了三种常见的类型:std::set
、std::unordered_set
和 std::multiset
,
std::set
:有序关联容器,存储唯一值,并根据元素的值进行排序。std::unordered_set
:无序关联容器,使用哈希表实现存储和查找,插入和查找的平均时间复杂度为 O(1)。std::multiset
:允许存储重复值的有序关联容器,会保持所有插入的元素,并根据元素的值进行排序。
#include <iostream>
#include <set>
int main() {
// 创建一个 std::set
std::set<int> mySet;
// 插入元素
mySet.insert(3);
mySet.insert(1);
mySet.insert(5);
// 遍历 set
for (const auto& elem : mySet) {
std::cout << elem << " ";
}
std::cout << std::endl;
// 检查元素是否存在
if (mySet.find(2) != mySet.end()) {
std::cout << "Element 2 is in the set" << std::endl;
} else {
std::cout << "Element 2 is not in the set" << std::endl;
}
/************************************************************************************/
// 创建一个 std::unordered_set
std::unordered_set<int> mySet;
// 插入元素
mySet.insert(3);
mySet.insert(1);
mySet.insert(5);
// 遍历 unordered_set
for (const auto& elem : mySet) {
std::cout << elem << " ";
}
std::cout << std::endl;
// 检查元素是否存在
if (mySet.find(2) != mySet.end()) {
std::cout << "Element 2 is in the set" << std::endl;
} else {
std::cout << "Element 2 is not in the set" << std::endl;
}
/************************************************************************************/
// 创建一个 std::multiset
std::multiset<int> myMultiset;
// 插入元素
myMultiset.insert(3);
myMultiset.insert(1);
myMultiset.insert(5);
myMultiset.insert(3); // 允许重复值
// 遍历 multiset
for (const auto& elem : myMultiset) {
std::cout << elem << " ";
}
std::cout << std::endl;
// 检查元素个数
std::cout << "Number of occurrences of 3: " << myMultiset.count(3) << std::endl;
return 0;
}