机试课
一、枚举和模拟(下)
模拟问题——和线性数据结构相关
1、数组——C语言自带
int arr[10];
缺点:
(1)不够灵活——>【纯C语言的修改方法】
①长度不可修改——>开始就申请大数组
②内存分配:局部数组(<1MB) 全局数组(很大,但是可能超过题目限制)——>局部不够放全局,全局不够改算法
③数组作为函数参数不方便(被调用函数只能拿到数组地址,不知道数组长度)——>传2个参数(首地址,长度)
2、链表——自定义实现
解决方法:C++STL库中vector动态数组
任务:了解vector模型并使用
添加头文件
#include <vector>//不需要.h后缀
学习别人写好的数据结构方法:增删查改
增:构造+初始化、插入
查:①访问某个元素——>[]/迭代器
②遍历整个vector
③找已知元素在vector的位置——>查找算法(下一章)
改:
删:①删除一个元素②全部清空
1、增:
(1)构造
//增:构造+初始化
//vector本身不是类型,vector<type>才是类型,type可以使用自定义的类型
vector<int> vec1;
vector<double> vec2;//vec1和vec2不是同一种类型
vector<MyType> vec3;
//vector<vector<int>> vec4;//动态数组的动态数组 二维数组
vector<int> arr[10];//机试推荐用法!!!动态数组的静态数组,有一个静态数组,立马每个元素都是动态数组;应用:图算法邻接表,结点已知,结点周围边不确定
(2)初始化
//增:初始化
vector<int> vec1;
vector<int> vec2(100);//vec2一开始就有100个元素
(3)插入数据
push_back方法:往动态数组尾部插入
//增:插入数据
//push_back方法:往动态数组尾部插入
int a;
while(scanf("%d", &a) != EOF){
vec1.push_back(a);
}
2、查:
(1)根据下标访问(可随机访问)
[]方括号运算符,使用方法同静态数组,范围也同静态数组
//查:根据下标访问,[]方括号运算符
vector<int> vec1 = {1, 3, 5, 7, 9};//初始化
int i = 0;
printf("vec1[i] = %d\n", vec1[i]);
i = 3;
printf("vec1[3] = %d\n", vec1[i]);
i = 5;
注意:赋值初始化时报错
错误信息[Error] in C++98 ‘n’ must be initialized by constructor, not by ‘{…}’
原因:赋值初始化是C++11内容,dev默认使用98版的内容
解决方法:链接: -std=c++11
(2)遍历整个数组
<1>size函数获取实际长度
int size = vec1.size();
for(int i = 0; i < size; i++){
printf("vec1[i] = %d\n", vec1[i]);
}
<2>迭代器※
提供了一种通用方法,可以访问不同的数据结构(vector,list,map等)
可以理解为高级版本指针
类型:动态数组类型::iterator
vector<int>::iterator
作用:类似指针,可以获取元素的位置,从而间接访问整个数据结构的内容
任务:①用迭代器遍历vector②用迭代器表示元素位置
使用:
begin函数:可以获取起始位置
end函数:可以获取尾后的位置(最后一个元素的后一个没有元素的空位置)
++:迭代器后移
①用迭代器遍历vector
//2.迭代器遍历
vector<int> vec1 = {1, 3, 5, 7, 9};
vector<int>::iterator it;//定义迭代器变量
for(it = vec1.begin(); it != vec1.end(); it++){
printf("*it = %d\n", *it);//迭代器和指针使用一样
}
②用迭代器表示元素位置——>※在中间某个位置插入
insert函数(插入位置,插入内容)
insert会修改动态数组的结构,插入完成后迭代器it指向无意义
若想继续插入,迭代器it重新赋值
//在中间某个位置插入
vector<int> vec1 = {1, 3, 5, 7, 9};
vector<int>::iterator it;
it = vec1.begin();
vec1.insert(it,2);//insert函数(插入位置,插入内容)
//插入后迭代器指向未知位置,因此若想继续插入,插入后给迭代器重新赋值
it = vec1.begin();
it = it + 3;//vector的迭代器支持多次++,其他类型不一定
vec1.insert(it,6);
尽量少使用insert,多使用push_back,因为动态数组是顺序表,在中间位置插入,效率低
3、改:
原理同上,迭代器找到任意元素位置
4、删除:
(1)全部清空——clear函数
clear函数只改变size大小,内存中数据仍然在
vector<int> vec1 = {1, 3, 5, 7, 9};
vec1.clear();//清空所有数据, clear函数改变size大小,内存中数据仍然在
(2)只清理一个数据
①删除最后一个元素——>pop_back(与push_back对应)
//(2)只清理一个数据
//删除最后一个元素pop_back(与push_back对应)
vector<int> vec1 = {1, 3, 5, 7, 9};
vec1.pop_back(); //删除最后一个元素(时间复杂度低)
vector<int>::iterator it;
for(it = vec1.begin(); it != vec1.end();it++){
printf("vec[i] = %d\n", *it);
}
②删除任意位置元素——>erase函数+迭代器(指向要删除位置)
//删除任意位置元素——>迭代器指向要删除位置
//erase函数
vector<int> vec1 = {1, 3, 5, 7, 9};
vector<int>::iterator it;
it = vec1.begin() + 2;//指向5
vec1.erase(it);//迭代器也发生变化;不论插入还是删除,重新给迭代器赋值
删除完和插入完一样,迭代器的值发生变化,若还想继续插入或删除,重新给迭代器赋值