C++中的Sequence containers(序列容器)


一、pair

C++中的pair是一种将两个值关联到一块儿的数据结构,使用方法如下:

#include "string"

using namespace std;

int main() {
    pair<int, string> a(10, "string"); //初始化方式
    a.first = 102;
    a.second = "this is a demo";
    cout << a.second << endl;
    return 0;
}

二、vector

vector底层是一个2倍动态扩容的数组
 

1.vector中的迭代器

begin() – 指向第一个元素
end() – 指向最后一个元素的后面
rbegin() – 指向最后一个元素
rend() – 指向第一元素的前面
cbegin() – const迭代器,指向第一个元素,该迭代器只能读元素,不能修改元素
cend() – const迭代器,指向最后一个元素的后面,只能读取元素,不能修改元素
crbegin() – 依上类推
crend() – 依上类推
 
代码如下:

#include <vector>
  
using namespace std;
  
int main()
{
    vector<int> g1;
  
    for (int i = 1; i <= 5; i++)
        g1.push_back(i);
  
    cout << "Output of begin and end: ";
    for (auto i = g1.begin(); i != g1.end(); ++i)
        cout << *i << " ";
  
    cout << "\nOutput of cbegin and cend: ";
    for (auto i = g1.cbegin(); i != g1.cend(); ++i)
        cout << *i << " ";
  
    cout << "\nOutput of rbegin and rend: ";
    for (auto ir = g1.rbegin(); ir != g1.rend(); ++ir)
        cout << *ir << " ";
  
    cout << "\nOutput of crbegin and crend : ";
    for (auto ir = g1.crbegin(); ir != g1.crend(); ++ir)
        cout << *ir << " ";
  
    return 0;
}

output

Output of begin and end: 1 2 3 4 5 
Output of cbegin and cend: 1 2 3 4 5 
Output of rbegin and rend: 5 4 3 2 1 
Output of crbegin and crend : 5 4 3 2 1

 

2.vector中的容量相关函数

size() – 返回容器中现有的元素的数量
max_size() – 返回容器中可以容纳的最大的元素数量
capacity() – 返回现在已经开辟的空间可以容纳元素的数量
resize(n) – 调整现有的元素数量,resize如果将原有size变小,就会删掉末尾多余的元素,如果将原有size变大,就会用默认的值对元素进行初始化
empty() – 返回容器是否为空
shrink_to_fit() – 将容器的capacity缩减到size
reserve(n) – 确保容器中至少可以容纳n个元素,如果现有的capacity小于n,容器就会扩容到n,如果现有的capacity大于n,则无事发生
 
代码示例如下:

#include <vector>
  
using namespace std;
  
int main()
{
    vector<int> g1;
  
    for (int i = 1; i <= 5; i++)
        g1.push_back(i);
  
    cout << "Size : " << g1.size();
    cout << "\nCapacity : " << g1.capacity();
    cout << "\nMax_Size : " << g1.max_size();
  
    // resizes the vector size to 4
    g1.resize(4);
  
    // prints the vector size after resize()
    cout << "\nSize : " << g1.size();
  
    // checks if the vector is empty or not
    if (g1.empty() == false)
        cout << "\nVector is not empty";
    else
        cout << "\nVector is empty";
  
    // Shrinks the vector
    g1.shrink_to_fit();
    cout << "\nVector elements are: ";
    for (auto it = g1.begin(); it != g1.end(); it++)
        cout << *it << " ";
  
    return 0;
}

output

Size : 5
Capacity : 8
Max_Size : 4611686018427387903
Size : 4
Vector is not empty
Vector elements are: 1 2 3 4

 

3.vector中的元素操作函数

下标运算符 [g] – 返回第g个元素
at(g) – 返回第g个元素
front() – 返回第一个元素
back() – 返回最后一个元素
data() – 返回指向vector底层数组的指针
 
代码示例如下:

#include <vector>
using namespace std;
  
int main()
{
    vector<int> g1;
  
    for (int i = 1; i <= 10; i++)
        g1.push_back(i * 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

Reference operator [g] : g1[2] = 30
at : g1.at(4) = 50
front() : g1.front() = 10
back() : g1.back() = 100
The first element is 10

 

assign(int n, int val) – 该函数有两种用途
1.首先删除所有的元素,然后在vector中添加n次val,此法可以用于重置vector
2.假设有两个vector v1和v2,v2.assign(v1.begin(), v1.end())可用于复制v1元素到v2
push_back(int val) – 向末尾添加元素
pop_back() – 弹出末尾元素
insert(iterator) – 根据迭代器的位置插入元素
erase(iterator) – 根据迭代器的位置删除元素
swap() – 交换两个vector中的元素,即使size不同,swap做交换的原理是:
如果两个容器的空间配置器相同,就直接交换底层的成员变量,如果空间配置器不同,需要遍历容器进行交换
clear() – 清空vector
emplace_back() – C++11中新增的添加元素的方法,更高效,对应push_back()方法,当调用push或insert成员函数时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中。而当我们调用一个emplace成员函数时,则是将参数传递给元素类型的构造函数。emplace成员使用这些参数在容器管理的内存空间中直接构造元素。
 
代码示例如下

using namespace std;
 
int main()
{
    vector<int> v1;
    int a[] = { 1, 2, 3 };
 
    // assign first 2 values
    v1.assign(a, a + 2);
 
    cout << "Elements of vector1 are\n";
    for (int i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
 
    vector<int> v2;
    // assign first 3 values
    v2.assign(a, a + 3);
 
    cout << "\nElements of vector2 are\n";
    for (int i = 0; i < v2.size(); i++)
        cout << v2[i] << " ";
 
    return 0;
}

output

The vector elements are: 10 10 10 10 10 
The last element is: 15
The vector elements are: 10 10 10 10 10 
The first element is: 5
The first element is: 10
The first element is: 5
The last element is: 20
Vector size after erase(): 0

Vector 1: 1 2 
Vector 2: 3 4 
After Swap 
Vector 1: 3 4 
Vector 2: 1 2

 

三、list

list底层是带头节点的双向循环链表,头节点中存储的是当前list中的元素数量
 

常见操作

emplace(position, value): 同vector的emplace方法

emplace_back(value) :同vector的emplace_back方法

emplace_front(value): 同vector的emplace_front方法

list.merge(list2): 该方法用于merge list2和list1。如果两个list都是有序的,merge之后也是有序的

remove_if(condition): 删除list中符合条件的元素

unique(): 删除list中的重复元素,进行unique操作之前,list必须是有序的

list1.splice(position, list2): 将list2整个插入到list1中的某个位置之后

swap(list2): 交换两个list中的元素
 
示例代码如下

// C++ code to demonstrate the working of
// unique() and splice()
#include <iostream>
#include <list> // for list functions
using namespace std;
  
// Driver Code
int main()
{
    // Initializing list1
    list<int> gqlist1 = { 1, 1, 1, 2, 2, 3, 3, 4 };
  
    // Initializing list2
    list<int> gqlist2 = { 2, 4, 6 };
  
    // Initializing list1 iterator
    list<int>::iterator it = gqlist1.begin();
  
    // using advance() to increment iterator position
    advance(it, 3);
  
    // Displaying list elements
    cout << "list1 before unique operation is : ";
    for (int& x : gqlist1)
        cout << x << " ";
    cout << endl;
  
    // using unique() to remove repeating elements
    gqlist1.unique();
  
    // Displaying list elements
    cout << "list1 after unique operation is : ";
    for (int& x : gqlist1)
        cout << x << " ";
    cout << endl << endl;
  
    // using splice() to splice list2 in list1 at position
    // it inserts list2 after 2nd position
    gqlist1.splice(it, gqlist2);
  
    // Displaying list elements
    cout << "list1 after splice operation is : ";
    for (int& x : gqlist1)
        cout << x << " ";
    cout << endl;
  
    return 0;
}

output
 

list1 before unique operation is : 1 1 1 2 2 3 3 4 
list1 after unique operation is : 1 2 3 4 

list1 after splice operation is : 1 2 4 6 2 3 4 

 

四、forward_list

forward_list底层是单向循环链表,只能向前遍历,进行push和pop操作的时候只能在链表首部进行。
 

常见操作

assign(): 同vector

push_front()

emplace_front()

pop_front()

insert_after()

emplace_after()

erase_after()

remove(value)

remove_if(condition)

clear()

splice_after()

unique()

reverse()

五、Deque

Deque和vector的函数非常类似,逻辑上实现的是双端队列
Deque底层使用的并不是如vector一样完全连续的空间,而是如下图所示一个二维的数组
Deque底层的结构
Deque的动态扩容是针对map数组以2倍方式进行的,而且扩容之后之前的内容并不是从map的开头开始存放,而是从map中间开始存放,方便进行首部和尾部的插入操作。
第二维连续空间的大小和元素类型有关,空间大小=4096/sizeof(T)
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要为自定义的C序列容器添加迭代器,需要定义一个迭代器结构体,包含容器的元素类型、指向当前位置的指针(或索引)、向前移动迭代器的函数指针、向后移动迭代器的函数指针、获取当前元素的函数指针等等。接下来,需要在容器结构体添加一个函数,用于返回迭代器对象。该函数应该接受容器的指针作为参数,并返回一个迭代器对象。 下面是一个简单的示例代码,用于向自定义的C序列容器添加迭代器: ```c typedef struct { int* data; int size; } my_container; typedef struct { int* ptr; int index; } my_iterator; my_iterator* create_iterator(my_container* c) { my_iterator* it = malloc(sizeof(my_iterator)); it->ptr = c->data; it->index = 0; return it; } void advance_forward(my_iterator* it) { it->ptr++; it->index++; } void advance_backward(my_iterator* it) { it->ptr--; it->index--; } int get_current_element(my_iterator* it) { return *(it->ptr); } // 容器结构体 typedef struct { int* data; int size; my_iterator* (*begin)(my_container*); } my_sequence; my_iterator* begin(my_container* c) { return create_iterator(c); } my_sequence* create_sequence(int* data, int size) { my_sequence* s = malloc(sizeof(my_sequence)); s->data = data; s->size = size; s->begin = begin; return s; } int main() { int data[] = {1, 2, 3, 4, 5}; my_sequence* s = create_sequence(data, 5); my_iterator* it = s->begin(s); while (it->index < s->size) { printf("%d\n", get_current_element(it)); advance_forward(it); } return 0; } ``` 在上面的示例代码,我们定义了一个名为`my_iterator`的迭代器结构体,它包含一个指向当前元素的指针和一个当前位置的索引。然后,我们定义了一些用于操作迭代器的函数,例如向前移动、向后移动和获取当前元素。接下来,我们定义了一个名为`my_sequence`的容器结构体,它包含一个指向数据的指针和数据的大小。然后,我们在容器结构体定义了一个函数`begin`,该函数返回容器的迭代器对象。最后,我们在`main`函数使用容器和迭代器进行了简单的测试。 当然,以上只是一个简单的示例,实际情况需要根据具体的需求来定义迭代器的结构体和操作函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值