std::vector 在 C++ 标准库中的本质可以理解为一种动态顺序表。它是一种能够自动调整大小的数组,会在需要的时候自动分配更大的内存块,从而实现动态扩展和收缩。它在内存中连续存储元素,就像传统的顺序表一样,但它能够动态管理内存,使得插入、删除和访问元素变得更加高效和方便。
vector的C++接口如下:
#include <iostream>
#include <vector>
using namespace std;
// vector
// vector数据结构和数组非常相似,也称为单端数组
// vector与数组的不同之处在于,数组是静态空间,而vector可以动态扩展
void printVector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
// 1、vector构造
void test_1()
{
vector<int>v1; //默认构造,无参数
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
// 通过区间方式进行构造
vector<int> v2(v1.begin(), v1.end());
printVector(v2);
// n个elem方式构造
vector<int> v3(10, 50); // 构造10个50的元素
printVector(v3);
// 拷贝构造(较为常用)
vector<int> v4(v3);
printVector(v4);
}
//2、vector赋值
void test_2()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
// 赋值 operator =
vector<int> v2;
v2 = v1;
printVector(v2);
// assign
vector<int> v3;
v3.assign(v1.begin(), v1.end());
// n个elem的方式
vector<int>v4;
v4.assign(10, 100);
printVector(v4);
}
// 3、vector容量和大小
void test_3()
{
vector<int> v1;
bool s;
int capacity,size;
for (int i = 0; i < 10; i++)
{
cout << "v1是否为空:" <<(s = v1.empty()) << endl;
v1.push_back(i);
cout << "v1的容量为:" << (capacity = v1.capacity()) << endl;
cout << "v1的大小:" << (size = v1.size()) << endl;
}
}
// 4、vector的插入和删除
void test_4()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i); //尾插
}
printVector(v1);
v1.pop_back(); //尾删
v1.pop_back();
printVector(v1);
v1.insert(v1.begin(), 100); //头插
printVector(v1);
v1.insert(v1.begin(), 4, 200); //头插
printVector(v1);
v1.erase(v1.begin()); //删除
printVector(v1);
v1.erase(v1.begin(), v1.end()); //清空
v1.clear(); //清空
}
//5、vector数据存取:[ ] 和 at
void test_5()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
// 利用[ ]方式访问数组元素
for (int i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl;
//利用at的方式访问元素
for (int i = 0; i < v1.size(); i++)
{
cout << v1.at(i) << " ";
}
cout << endl;
cout << "第一个元素:" << v1.front() << endl; // 返回第一个元素
cout << "最后个元素:" << v1.back() << endl; // 返回最后一个元素
}
// 6、vector互换容器
void test_6()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
vector<int> v2;
for (int i = 10; i >= 0; i--)
{
v2.push_back(i);
}
printVector(v2);
v1.swap(v2); //v1和v2两个容器互换
printVector(v1);
printVector(v2);
}
// 7、reserve预留空间,容器预留len个元素长度,预留位置不初始化,元素不可访问
void test_7()
{
vector<int> v;
//利用reserve预留空间
v.reserve(10000);
int* p = NULL;
int num = 0;
for (int i = 0; i < 10000; i++)
{
v.push_back(i);
if (p != &v[0])
{
p = &v[0];
num++;
}
}
cout << "num = " << num << endl;
}
int main()
{
//test_1();
//test_2();
//test_3();
//test_4();
//test_5();
//test_6();
test_7();
return 0;
}
声明文件
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
//静态顺序表 --不太实用
// N小了不够用 N大了浪费空间
#define N 10
typedef int SLDataType;
//动态顺序表
typedef struct SeqList
{
SLDataType* a;
int size; //记录存储多少个有效数据
int capacity; //空间容量大小
}SL;
void SLInit(SL *ps);
void Destory(SL* ps);
void SLPushBack(SL *ps, int x); //尾插
void SLPopBack(SL *ps); //尾删
void SLPrint(SL* ps); //打印顺序表中的元素
void SLCheckCapacity(SL* ps);
void SLPushFront(SL* ps, SLDataType x); //头插
void SLPopFront(SL* ps); //头删
void SLInsert(SL* ps, int pos, SLDataType x); // 中间插入
void SLErase(SL* ps, int pos); //中间删除
int SLFind(SL* ps, SLDataType x, int begin); //查找顺序表中元素
顺序表增删查改,功能实现:
#include "SeqList.h"
void SLInit(SL *ps)
{
ps->a = NULL;
ps->capacity = 0;
ps->size = 0;
}
void Destory(SL* ps) //销毁顺序表
{
if (ps->a != NULL)
{
free(ps->a);
ps->a = NULL;
ps->capacity = 0;
ps->size = 0;
}
}
void SLPrint(SL* ps) //打印顺序表中的元素
{
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n"); //换行
}
void SLPushBack(SL* ps, int x) //尾插
{
if (ps->capacity == ps->size) //考虑扩容情况
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SLDataType *tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newCapacity); //使用realloc在原有空间上进行扩容
if (tmp == NULL) //这里要对扩容后的情况进行验证,防止扩容失败
{
perror("realloc fail.....");
exit(-1);
}
ps->a = tmp; //将临时的指针tmp指向a
ps->capacity = newCapacity; // 扩容后的新空间
}
ps->a[ps->size] = x;
ps->size += 1;
}
void SLPopBack(SL* ps) //尾删
{
//ps->a[ps->size - 1] = 0; //这一步不必要
//if (ps->size == 0) //如果size为0,证明没有元素存在了
//{
// return;
//}
assert(ps->size > 0); //这里检查方式与STL相同
ps->size --;
}
void SLCheckCapacity(SL* ps)
{
assert(ps);
if (ps->capacity == ps->size) //考虑扩容情况
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newCapacity); //使用realloc在原有空间上进行扩容
if (tmp == NULL) //这里要对扩容后的情况进行验证,防止扩容失败
{
perror("realloc fail.....");
exit(-1);
}
ps->a = tmp; //将临时的指针tmp指向a
ps->capacity = newCapacity; // 扩容后的新空间
}
}
void SLPushFront(SL * ps, SLDataType x) //头插
{
SLCheckCapacity(ps);
// 挪动数据
int end = ps->size - 1;
while (end >= 0)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[0] = x;
ps->size++;
}
void SLPopFront(SL* ps) //头删
{
assert(ps);
assert(ps->size >0);
int begin = 1;
while (begin < ps->size)
{
ps->a[begin - 1] = ps->a[begin];
begin++;
}
ps->size--;
}
void SLInsert(SL* ps, int pos, SLDataType x) // 中间插入
{
assert(ps);
assert(pos >= 0);
assert(pos <= ps->size);
SLCheckCapacity(ps); //检查容量
int end = ps->size - 1;
while (end >= pos)
{
ps->a[end + 1] = ps->a[end]; //将前面一个数往后面挪动,从后往前挪动
end--;
}
ps->a[pos] = x; //将要插入的数据放进去
}
void SLErase(SL* ps, int pos) //中间删除
{
assert(ps);
assert(ps->size > 0);
assert(pos < ps->size - 1);
int begin = pos+1;
while (begin < ps->size)
{
ps->a[begin - 1] = ps->a[begin];
begin++;
}
ps->size--; //容量减1
}
int SLFind(SL* ps, SLDataType x, int begin) //查找顺序表中元素
{
assert(ps);
for (int i = begin; i < ps->size; i++)
{
if (ps->a[i] == x) //如果循序表中存在这个元素,返回该元素的位置
{
return i;
}
}
return -1; //没有找到
}
测试函数:
#include "SeqList.h"
void TestSeqList()
{
SL s1;
SLInit(&s1);
SLPushBack(&s1, 1);
SLPushBack(&s1, 2);
SLPushBack(&s1, 3);
SLPushBack(&s1, 4); //尾插
SLPopBack(&s1); //尾删
SLPushFront(&s1, 6);
SLPushFront(&s1, 6);
SLPushFront(&s1, 6);
SLInsert(&s1, 2, 40); //在第3个位置插入4
SLInsert(&s1, 0, 400); //在第3个位置插入4
SLPrint(&s1);
int pos = SLFind(&s1, 40, 0);
printf("该元素的位置为:%d\n", pos);
if (pos != -1)
{
SLErase(&s1, pos);
}
SLPrint(&s1);
Destory(&s1); //销毁顺序表
}
int main()
{
TestSeqList();
return 0;
}