2.1 C++ STL 数组向量容器

2023-10-11 14:43:43 浏览数 (2)

Vector容器是C STL中的一个动态数组容器,可以在运行时动态地增加或减少其大小,存储相同数据类型的元素,提供了快速的随机访问和在末尾插入或删除元素的功能。

该容器可以方便、灵活地代替数组,容器可以实现动态对数组扩容删除等各种复杂操作,其时间复杂度O(l)常数阶,其他元素的插入和删除为O(n)线性阶,其中n为容器的元素个数,vector具有自动的内存管理机制,对于元素的插入和删除可动态调整所占用的内存空间。

2.1 数组向量基础应用

如下C 代码,展示了如何使用STL的vector容器对数组进行元素添加、弹出、大小重置和空间调整等操作,并使用自定义函数MyPrint()输出结果。

在代码中,首先使用初始化列表给vector<int>容器var赋初值{ 1, 2, 3 }

使用push_back()函数向容器中添加元素4,并使用MyPrint()函数输出结果。

使用pop_back()函数弹出容器中的一个元素,并再次使用MyPrint()函数输出结果。 使用resize()函数重新设置容器的最大存储空间为10,并使用reserve()函数调整容器的空间大小为30,并再次使用MyPrint()函数输出结果。

在输出容器中的元素值时,可以使用for循环遍历整个vector容器,也可以使用for_each()算法遍历整个vector容器。在自定义函数MyPrint()中,使用容器提供的函数empty()、size()、capacity()max_size()来获取容器的一些基本属性信息。

代码语言:javascript复制
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

void MyPrint(vector<int>& var)
{
  cout << "empty = " << var.empty() << " --> size = " << var.size()  << endl;
  cout << "capacity = " << var.capacity() << " --> max_size = " << var.max_size() << endl;
  for_each(var.begin(), var.end(), [](int val){ cout << val << endl; });
  cout << "---------------------------------------------------------" << endl;
}

int main(int argc, char* argv[])
{
  vector<int> var{ 1, 2, 3 };

  var.push_back(4);  // 放入元素
  MyPrint(var);
  var.pop_back();    // 弹出一个元素
  MyPrint(var);
  var.resize(10);    // 重新设置最大存储
  var.reserve(30);   // 调整数据空间大小
  MyPrint(var);

  system("pause");
  return 0;
}

2.2 数组向量正/反向遍历

如下C 代码,展示了三种不同的遍历方法,分别是使用数组下标、使用正向迭代器和反向迭代器遍历,用于演示vector容器遍历的方法。

定义int_array容器,并使用const_iterator类型的迭代器item遍历输出容器中的每个元素。

定义rint_array容器,使用reverse_iterator类型的迭代器startend进行反向遍历,遍历输出容器中的每个元素。

在使用迭代器遍历容器时,需要使用begin()end()函数指定迭代器的起始位置和结束位置,反向遍历使用的是rbegin()rend()函数。

代码语言:javascript复制
#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main(int argc, char* argv[])
{
  // 第一种遍历数组的方式,使用数组的下标实现遍历
  vector<string> str_array{ "admin", "guest", "lyshark" };
  cout << "str_array sizeof:" << str_array.capacity() << endl;
  for (int x = 0; x < str_array.size(); x  )
  {
    cout << "str_array --> " << str_array[x] << endl;
  }
  cout << endl;

  // 第二种遍历数组的方式,使用迭代器实现的正向遍历
  vector<int> int_array{ 1, 2, 3, 4, 5 };
  vector<int>::const_iterator item;
  int each = 0;
  for (item = int_array.begin(), each = 0; item != int_array.end();   item,   each)
  {
    cout << "int_array[" << each << "] --> " << (*item) << endl;
  }
  cout << endl;

  // 第三种遍历数组的方式,使用迭代器实现的反向遍历
  vector<int> rint_array{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  vector<int>::reverse_iterator start, end; // 定义向量迭代器
  end = int_array.rend();
  for (start = int_array.rbegin(); start != end; start  )
  {
    cout << "int_array --> " << *start << endl;
  }

  system("pause");
  return 0;
}

2.3 数组向量正/反向排序

如下C 代码,展示了如何使用STL的sort()函数对vector容器进行正向排序和反向排序,并通过迭代器遍历输出结果。

在代码中,首先使用new运算符动态申请了一个名为int_arrayvector<int>类型的动态数组,并使用for循环向数组插入10个随机数。

使用std::sort()函数对int_array动态数组进行正向排序,排序时使用了int_array->begin()int_array->end()表示排序的起始位置和结束位置。

通过const_iterator类型的item迭代器遍历整个int_array数组,并使用cout输出每个元素的值。

使用std::sort()函数对int_array动态数组进行反向排序,排序时使用了MyCompare()回调函数来实现反向排序。

在使用迭代器遍历整个vector容器时,需要使用begin()end()函数来指定迭代器的起始位置和结束位置。

代码语言:javascript复制
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 实现的一个排序回调函数,反向排序需要使用该回调
bool MyCompare(int value1, int value2){ return value1 > value2; }

int main(int argc, char* argv[])
{
  vector<int> *int_array = new vector<int>;

  // 生成10个随机数用于测试
  for (int x = 0; x < 10; x  )
    int_array->push_back(rand() % 100);

  // 遍历的方式实现 正向排序
  std::sort(int_array->begin(), int_array->end());
  vector<int>::const_iterator item = int_array->cbegin();
  while (item != int_array->cend())
  {
    cout << (*item) << " ";
    item  ;
  }
  cout << endl;

  // 遍历的方式实现 反向排序
  std::sort(int_array->begin(), int_array->end(), MyCompare);
  vector<int>::const_iterator item_1 = int_array->cbegin();
  while (item_1 != int_array->cend())
  {
    cout << (*item_1) << " ";
    item_1  ;
  }

  system("pause");
  return 0;
}

2.4 向数组向量中插入元素

如下C 代码,展示了如何使用vector容器对字符串数组进行插入和删除操作,并使用循环遍历输出结果。

在代码中,首先定义了一个vector容器str_array,该容器存放的是字符串类型的元素,使用了初始化列表给其赋予了初始值:adminguestlyshark

使用push_back()函数分别将"django""python"元素加入到容器的末尾,使用pop_back()函数弹出容器的末尾元素。

使用insert()函数在容器的索引2位置及末尾位置分别插入"ruby""C "元素。

使用for循环遍历整个vector容器str_array,并使用cout输出每个元素的值。

在输出容器中的元素值时,可以使用下标运算符或迭代器进行遍历。

代码语言:javascript复制
#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main(int argc, char* argv[])
{
  // 定义数组容器,并赋予初始值
  vector<string> str_array{ "admin", "guest", "lyshark" };

  str_array.push_back("django");     // 插入元素
  str_array.push_back("python");     // 插入元素
  str_array.pop_back()               // 弹出元素
  // cout << str_array[3] << endl;                   // 通过元素下标遍历数据
  str_array.insert(str_array.begin()   2, "ruby");   // 在数组索引2的位置插入元素
  str_array.insert(str_array.end(), "C  ");          // 在数组最后插入元素

  for (int x = 0; x < str_array.size(); x  )
    cout << "str_array[" << x << "] --->" << str_array[x] << endl;

  system("pause");
  return 0;
}

2.5 向数组向量中插入结构指针

如下C 代码,展示了如何定义结构体、创建结构体数组,并在其中加入数据后使用迭代器输出数据。

在代码中,定义了一个名为Person的结构体,该结构体包含两个成员变量IDszName,并使用typedefPerson对象定义了一个Ptr类型的别名。

使用for循环遍历ary数组,通过迭代器输出每个vector容器中的第一个元素的IDszName成员变量的值。

在输出结构体数组的成员变量值时,需要使用(*item).ID(*item).szName表示从结构体中取出相应的成员变量值。另外,因为ary是一个结构体数组,所以在遍历ary数组时,需要使用数组下标运算符及迭代器实现。

代码语言:javascript复制
#include <iostream>
#include <vector>

using namespace std;

typedef struct
{
  int ID;
  char szName[20];
}Person, *Ptr;

int main(int argc, char* argv[])
{
  vector<Person> ary[10];

  Person p1 = { 1, "admin" };
  Person p2 = { 2, "lyshark" };
  Person p3 = { 3, "guest" };

  ary[0].push_back(p1);
  ary[1].push_back(p2);
  ary[2].push_back(p3);

  for (int x = 0; x < 3; x  )
  {
    vector<Person>::iterator item = ary[x].begin();
    cout << "ID: " << (*item).ID <<" ---> Name: " << (*item).szName << endl;
  }
  system("pause");
  return 0;
}

2.6 向数组向量中插入类指针

如下C 代码,展示了如何以指针类型存储对象,并使用迭代器进行遍历。

代码中定义了MyAnimal类,并分别实例化了pDog、pMonkeypSnake三个成员,通过使用push_back()函数将这三个对象指针加入到var中,最后通过使用遍历的方法输出该迭代器中的所有元素。

在进行遍历时,需要使用迭代器类型的元素,记得要保证迭代器的有效性。

代码语言:javascript复制
#include <iostream>
#include <vector>

using namespace std;

class MyAnimal{
public:
  char *name;
  int id;
public:
  MyAnimal(char* name, int id)
  {
    this->name = name;
    this->id = id;
  }
};

int main(int argc, char* argv[])
{
  MyAnimal* pDog = new MyAnimal("dog", 1);
  MyAnimal* pMonkey = new MyAnimal("monkey", 2);
  MyAnimal* pSnake = new MyAnimal("psnake", 3);

  vector<MyAnimal *> var;     // 定义模板
  var.push_back(pDog);        // 将指针放入列表
  var.push_back(pMonkey);
  var.push_back(pSnake);
  // 指针列表的遍历器
  vector<MyAnimal*>::iterator start, end;
  end = var.end();
  for (start = var.begin(); start != end; start  )
  {
    cout <<"ID: "<<(*start)->id << " ---> " << "Name: " << (*start)->name << endl;
  }
  system("pause");
  return 0;
}

2.7 在数组容器中嵌套容器

如下C 代码,展示了如何定义和遍历内嵌在vector容器中的子容器。

在代码中,首先定义vector<vector<int>>的变量var,它是一个外层vector容器,其中包含两个内层的vector容器v1和v2。

接着,使用for循环分别向内层vector容器v1和v2中插入了5个整数元素。然后,将内层vector容器v1和v2分别插入到外层vector容器var中。此时,var中包含了两个内层vector容器。

代码使用双重循环遍历所有容器中的数据,首先遍历var中的外层容器,然后分别遍历内层容器v1和v2,输出其中的元素值。

代码语言:javascript复制
#include <iostream>
#include <vector>

using namespace std;

int main(int argc, char* argv[])
{
  // 容器中内嵌容器
  vector< vector<int> > var;
  vector<int> v1;
  vector<int> v2;

  for (int x = 0; x < 5; x  )
  { // 放入小容器中的数据
    v1.push_back(x);
    v2.push_back(x   10);
  }
  // 将小容器放入大容器中
  var.push_back(v1);
  var.push_back(v2);
  
  // 遍历所有容器中的数据, 由于是嵌套容器,所以我们要先来遍历第一层,在第一层中遍历第二层.
  for (vector<vector<int>>::iterator item = var.begin(); item != var.end(); item  )
  {
    for (vector<int>::iterator vitem = (*item).begin(); vitem != (*item).end(); vitem  )
    {
      cout << (*vitem) << " ";
    }
    cout << endl;
  }
  system("pause");
  return 0;
}

2.8 函数参数定义为容器类型

如下C 代码,展示了如何创建向量容器(vector)并实现容器间的构造、赋值、互换等操作。

代码使用两种方式构造了包含整数元素的向量容器v1和v2。其中,v1使用数组arrysizeof(arry)/sizeof(int)的方式进行初始化。v2则继承自v1,使用了迭代器的方式初始化。

代码在v3中使用assign()函数生成10个元素为20的向量容器,并使用MyPrintVector()打印出v3中的元素。

代码使用v3中的元素对v4进行赋值,并使用MyPrintVector()打印出v4中的元素。

代码使用swap()函数交换v2和v4中的元素,并使用MyPrintVector()打印出v4中的元素,此时v4已经包含了原先的v2的元素。

代码语言:javascript复制
#include <iostream>
#include <vector>

using namespace std;

void MyPrintVector(vector<int> &var)
{
  for (vector<int>::iterator item = var.begin(); item != var.end(); item  )
  {
    cout << (*item) << " ";
  }
  cout << endl;
}

int main(int argc, char* argv[])
{
  vector <int> var;
  int arry[] = { 1, 2, 3, 4, 5 };

  // 两种不同的容器构造方式
  vector<int> v1 (arry, arry   sizeof(arry) / sizeof(int));
  vector<int> v2(v1.begin(), v1.end());

  MyPrintVector(v2);       // 打印v2容器中的内容

  vector<int> v3(10, 20);  // 生成容器,里面包含10个20
  MyPrintVector(v3);

  vector<int> v4;          // 赋值的使用,里面包含10个20
  v4.assign(v3.begin(), v3.end());
  MyPrintVector(v4);

  v4.swap(v2);             // v2与v4容器内容互换
  MyPrintVector(v4);

  system("pause");
  return 0;
}

2.9 数组向量元素的删除

如下C 代码,展示了如何删除vector容器中指定的元素,并通过遍历输出剩余的元素。

在代码中,定义了vector<int>类型的变量int_array,并使用花括号列表初始化的方式插入了10个整数元素。

使用find()函数查找元素7在vector中的位置,并使用erase()函数将此位置处的元素从vector中删除。如果元素7不存在于vector中,则不进行任何操作。

需要注意的是,在遍历vector时,可以使用迭代器类型的元素,也可以使用下标访问以控制循环次数。但需要确保迭代器的有效性,因为erase()函数会使迭代器失效,从而导致遍历错误。

代码语言:javascript复制
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main(int argc, char* argv[])
{
  vector<int> int_array {1,2,3,4,5,6,7,8,9,10};

  // find 找到元素7并删除
  vector<int>::iterator item = find(int_array.begin(), int_array.end(), 7);
  if (item != int_array.cend())
    int_array.erase(item);  // 删除指定元素

  // 删除后对数组进行遍历
  vector<int>::iterator start, end;
  end = int_array.end();
  for (start = int_array.begin(); start != end; start  )
  {
    cout << (*start) << endl;
  }
  system("pause");
  return 0;
}

本文作者: 王瑞 本文链接: https://www.lyshark.com/post/c5809a2f.html 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

0 人点赞