浅析向量(Vector),迭代器(Iterator)和数组(Array)

目录

前言(Foreword):

向量(Vector):

1.何为向量?

2.如何初始化Vector向量?

3.向量的基本操作:

4.Range-based For Statement:

5.向量的插入操作:

6.向量的排序操作:

7.向量的删除操作:

推荐阅读:

迭代器(Iterator)

如何定义迭代器?

使用迭代器进行遍历:

数组(Array)

数组的初始化(The Initialization of Array):

如何访问数组内的元素?

多维数组(Multidimensional Arrays):

后记(Postscript)


前言(Foreword):

最近学习C++的类和对象,发现了前面学习的薄弱项,那就是向量,迭代器和数组。

本篇文章主要介绍以上三个内容的基本知识,提供了通俗易懂的样例。

才疏学浅,难免有不足之处,请不吝赐教:

wei.haoran@outlook.com

向量(Vector):

1.何为向量?

Vector可以被理解为能够储存特定类型的动态数组,其大小可以压缩和增加。

使用前,需添加头文件:

#include<vector>

2.如何初始化Vector向量?

空向量:

vector<int> a;//a是一个int类型的空vector;

向量副本:

vector<int> a1(a);
vector<int> a1 = a;//a1是a的副本;

向量的列表初始化:

vector<int> a2(10,5);//a2有10个元素,值为5;
vector<int> a3{10,5};//a3有2个元素,10和5;
vector<int> a4(10);//a4有10个空元素;
vector<string> s(10,"Hello!");//有10个元素,逗号右侧为元素值;

vector<int> a5{1,2,3,4,5,6,7,8,9,10};
vector<string> s1{"Hello","This","is","C++","World"};//列表初始化;

3.向量的基本操作:

1.关于向量间的比较:

若两vector的容量不同,但相同位置上的元素相同,则元素较少的vector<元素较多的vector;

若元素的值不同,则两vector之间的大小关系由第一对不同的元素值的大小关系所决定。

2.push_back()操作:

在Vector类的末尾压入与Vector类的类型相匹配的元素;

#include<iostream>
#include<vector>
#include<string>
//屈平辞赋悬日月,楚王台榭空山丘;

using namespace std;

int main(){
    vector<int> v1;
    vector<int> v2;

    int num;
    cout<<"Please enter the numbers to v1;"<<endl;
    while(cin>>num) v1.push_back(num);
    cout<<"Please enter the numbers to v1;"<<endl;
    while(cin>>num) v2.push_back(num);

    cout<<"The size of v1 & v2 are "<<v1.size()<<" and "
    <<v2.size()<<"."<<endl;//v.size()

    if(v1>v2) cout<<"v2 is smaller than v1;"<<endl;
    if(v1==v2) cout<<"v2 is equal to v1;"<<endl;
    if(v1<v2) cout<<"v1 is smaller than v2;"<<endl;

    //using 'Range For' to visit vector's elements;
    vector<int> v3{0,1,2,3,4,5,6,7,8,9};
    for(auto i: v3) cout<<i<<' ';
    for(auto &i:v3) i *= i;
    for(auto i: v3) cout<<i<<' ';

    return 0;
}

4.Range-based For Statement:

使用范围For语句可以构造必须循环全部内容的循环。

auto关键字:

auto是一个类型说明符,在创建时必须初始化;

auto关键字可以推断表达式所返回的类型;

Attention:C的auto和C++的auto作用不一致;

举个栗子:

//using 'Range For' to visit vector's elements;
    vector<int> v3{0,1,2,3,4,5,6,7,8,9};
    for(auto i: v3) cout<<i<<' ';
    for(auto &i:v3) i *= i;
    for(auto i: v3) cout<<i<<' ';

注:auto &i 可以对v3内的元素进行操作,然而,auto i只能读取v3中的元素;

5.向量的插入操作:

上文我们初识了push_back操作,然而,push_back操作一般用于循环(具有一定规律)等操作中,缺乏灵活性。然而,vector本身也可以通过下标访问,因此,我们可以使用insert操作;

介绍三种常用的插入操作:

初始化:

    vector<int> v1{1,2,3};
    vector<int> v2(v1),v3(v1),v4(v1);
    //创建3个v1的副本

Method1:v1内初始元素为1,2,3;结果为3 3 3 1 2 3;

    //Method1:insert(position,num,value);
    //向Position前插入num个值为value的元素;
    v1.insert(v1.begin(),3,3);
    for(auto i : v1){
        cout<<i<<" ";
    }//3 3 3 1 2 3

Method2:v2内初始元素为1,2,3;结果为3 1 2 3;

    //Method2:insert(position,value);
    //向Position前插入值为value的元素;
    v2.insert(v2.begin(),3);
    for(auto i : v2){
        cout<<i<<" ";
    }//3 1 2 3

Method3:v3内初始元素为1,2,3;结果为4 5 6 1 2 3;

    //Method3:insert(position,list);
    在position之前,插入初始化列表list;
    v3.insert(v3.begin(),{4,5,6});
    for(auto i: v3){
        cout<<i<<" ";
    }//4 5 6 1 2 3;

6.向量的排序操作:

Sort排序:注意头文件:<algorithm>

注意:sort(vector.begin(),vector.end())的结果是升序排列;

如果想得到降序排列,需要使用reverse(vector.begin(),vector.end());

#include<iostream>
#include<vector>
#include<algorithm>//使用sort函数的必要条件;

using namespace std;

int main(){
    vector<unsigned> v;
    int i;

    while(cin>>i) v.push_back(i);

    sort(v.begin(),v.end());//默认升序Sort;

    for(auto i: v) cout<<i<<' ';
    cout<<'\n';

    reverse(v.begin(),v.end());//逆序;

    for(auto i: v) cout<<i<<' ';

    return 0;
}

7.向量的删除操作:

pop_back():可以压缩Vector的大小,单次可弹出Vector末尾的一个元素;

举个栗子:

#include<iostream>
#include<vector>

using namespace std;
//v.pop_back()弹出v中最后一个元素;
int main(){
    vector<int> v1{0,1,2,3,4,5,6,7,8,9};
    vector<int> v2(v1);

    for(auto &i: v1) v1.pop_back();

    if(v1.empty()) cout<<"Now,v1's element is empty."<<endl;
    else cout<<"Sorry,try again"<<endl;

    v2.clear();
    if(v2.empty()) cout<<"Now,v2's element is empty."<<endl;
    else cout<<"Sorry,try again"<<endl;

    return 0;
}

v1.empty():如果v1是空向量,返回值为1,否则为0;

v2.clear()清空v2内的元素;

Method1:erase(position)删除position位置的元素;

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> v1 = {1, 2, 3, 4, 5, 6},v2(v1);
    v1.erase(v1.begin());//删除第1个位置的元素;
    v2.erase(v2.begin()+1);//删除第2个位置的元素;
    for(int i = 0;i < v1.size();i++) cout<<v1[i]<<' ';
    //结果为:2 3 4 5 6
    cout<<endl;
    for(auto i : v2) cout<<i<<' ';
    //结果为:1 3 4 5 6
}

Method2:erase(begin,end):删除向量中序号为[begin,end)中元素;

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> v1 = {1, 2, 3, 4, 5, 6};
    v1.erase(v1.begin(),v1.begin()+2);//删除第1个和第2个位置的元素;
    for(auto i : v1) cout<<i<<' ';
    //结果为:3 4 5 6
    return 0;
}

 注意:v1.begin()返回的类型为指针,并非int;不能通过下标进行直接访问;


当然,上文介绍的Vector操作,仅仅是冰山一角;

推荐阅读:

1.C++ Primer中文版:第5版 作者:李普曼(Lippman,S.B.),拉乔伊(Lajoie,J.),(美)默(Moo,B.E.)译者:王刚,杨巨峰  出版社:电子工业出版社;

​​​​​​https://www.runoob.com/w3cnote/cpp-vector-container-analysis.htmlhttps://docs.microsoft.com/en-us/cpp/cpp/range-based-for-statement-cpp?view=msvc-170

迭代器(Iterator)

迭代器:可以顺序或者逆序访问容器内的元素,形如“指针”;

假定it为迭代器,*it即可对迭代器所指向容器的元素进行访问;

如何定义迭代器?

1.容器类型名::iterator 迭代器名称

2.容器类型名::const_iterator 迭代器名称

3.容器类型名::reverse_iterator 迭代器名称

4.容器类型名::const_reverse_iterator 迭代器名称

两种正向迭代器:(以String类为例)

正向++:Iterator会指向下一个元素;

类型名

    string str("Hello,C++ World");

    string::iterator it;//读写string中的元素;
    string::const_iterator it2;//只可读,不能写;

两种反向迭代器:(以String类为例)

反向++:Iterator会指向上一个元素;

    string str("Hello,C++ World");

    string::reverse_iterator it;//读写string中的元素;
    string::const_reverse_iterator it2;//只可读,不能写;

使用迭代器进行遍历:

正向遍历:

for(it = str.begin(); it != str.end() && !isspace(*it); ++it){
        * it = toupper(*it);
    }

 负向遍历:

for(it2 = str.rbegin(); it2 != str.rend() && !isspace(*it2); ++it2){
        * it2 = toupper(*it2);
    }

Attention:1.正向为 begin和 end;负向为 rbegin 和 rend;

2.选择++it 而非 it++,++it在次数较多的循环内更能节省时间;

举个栗子:

1.将“Hello,C++ World”变为大写,第一行顺序输出每个字母,第二行输出整个字符串;

注意:对"it"解引用可以写成"! it->issapce"

#include<iostream>

using namespace std;

int main(){
    string str("Hello,C++ World");

    string::iterator it;//读写string中的元素;
    string::const_iterator it2;//只可读,不能写;
    for(it = str.begin(); it != str.end() && !isspace(*it); ++it){
        * it = toupper(*it);
    }
    for(it = str.begin(); it != str.end() && !isspace(*it); ++it){
        cout<<*it<<" ";
    }//H E L L O , C + + 
    
    cout<<endl;
    cout<<str<<endl;//HELLO,C++ World
    return 0;
}

2.打印图案,如图所示:

 源码如下:

对迭代器的遍历可以在For循环内进行同时可以使用auto关键字;

当然可以使用:vector<string>::reverse_iterator it;

#include<iostream>
#include<vector>

using namespace std;

int main(){
    string star(7,'*');//定义一个含有7个'*'的字符串;
    vector<string> v1;//创建string类型的vector容器v1;
    
    cout<<star<<endl;//先打印第一行;
    v1.push_back(star);//把原始字符串压入容器v1内;
    for(int i = 0;i<3 ;i++){
        star[i] = ' ';
        star[6-i] = ' ';
        cout<<star<<endl;
        v1.push_back(star);//循环3次,将每次变化的字符串依次压入容器v1内
    }
    v1.pop_back();//弹出含有一个'*'的字符串元素;
    for(auto it = v1.rbegin();it != v1.rend()&&!it->empty(); ++it) cout<<*it<<endl;
    //使用迭代器对容器v1内的字符串元素进行逆序输出;
    return 0;
}

数组(Array)

数组(Array)和向量(Vector)类似,都是存放某种类型的容器(Container);

数组的大小不变,在某种情况下,虽然失去了一定的灵活性,但提高了程序运行的性能;

数组的初始化(The Initialization of Array):

模板如下:

#include<iostream>

using  namespace std;

const int N =1e5 + 10;

int arr0[N];//全局变量,arr0数组内的值均为0;
int main(){
    int arr[10] = {0};//定义了名为arr的int类型的数组,长度为10,并且值均为0;
    int arr1[] = {0,1,3};//[]内为空,但此时数组的大小是3;

    //通过sizeof(数组名)/sizeof(数组中的某一元素)来得到数组的长度
    //sizeof(数组)得到的是数组整体的长度;
    //sizeof(数组的某一元素)得到的是数组的单个元素的长度;
    cout<<"The size of arr is "<<sizeof(arr)/sizeof(arr[0])<<endl;
    cout<<"The size of arr1 is "<<sizeof(arr1)/sizeof(arr1[0])<<endl;

    char ch1[] ={'X','D','X'};//不含空字符,长度为3;
    cout<<"The size of ch1 is "<<sizeof(ch1)/sizeof(ch1[0])<<endl;

    char ch2[] ={'X','D','X','\0'};//含空字符,长度为4;
    cout<<"The size of ch2 is "<<sizeof(ch2)/sizeof(ch2[0])<<endl;

    char ch3[] ="Hello,Xing.DX";
    //含空字符,长度为14,自动添加了空字符'\0';

    //使用Range For语句确定ch3的元素个数;
    for(auto i: ch3){
        cout<<i<<" ";
    }
    cout<<endl;
    cout<<"The size of ch3 is "<<sizeof(ch3)/sizeof(ch3[0])<<endl;

    int *ptr1[10];//包含10个int类型指针数组
    return 0;
}

数组遵循默认初始化:若Build-in-Type变量没有被显式(Explicit)初始化,其值由定义的位置所决定。全局变量(Global Variable)被初始化为0。

如何访问数组内的元素?

Merhod 1:Using Range-Based For Statement;

范围For语句遍历数组:

举个栗子:

#include<iostream>
#include<cctype>

using namespace std;

int main(){
    char ch[14] = "Hello,World";

    //Attention:The size of ch are 14;
    cout<<sizeof(ch)/sizeof(ch[0])<<endl;

    //Method 1: Using Range-Based For Statement;
    for(auto &i : ch){
        if(islower(i)) i -= 32;
        cout<<i<<" ";
    }
    return 0;
}

Merhod 2:Using Subscript Operation;

举个栗子:

#include<iostream>
#include<cctype>

using namespace std;

int main(){
    char ch[14] = "Hello,World";

    //Attention:The size of ch are 14;
    cout<<sizeof(ch)/sizeof(ch[0])<<endl;

    //Method 2: Using Subscript Operation;
    for(int i = 0;ch[i] != '\0';i++){
        if(islower(ch[i])) ch[i] -= 32;
        cout<<ch[i]<<" ";
    }
    return 0;
}

Attention:使用下标访问时,注意边界问题,防止数组越界;

多维数组(Multidimensional Arrays):

多维数组,本质上仍然是一维数组,只不过数组内的元素仍然是数组;

以二维数组为例:

//Express my thanks to DX.Xing
int arr0[3][4] = {0}
int arr1[3][4] = {
    {0,1,2,3},
    {4,5,6,7},
    {8,9,0,0}
    };
int arr2[3][4] = {0,1,2,3,4,5,6,7,8,9,0,0}

我们可以把arr0,arr1和arr2数组想象成一个包含3个元素的数组,每个元素又作为一个数组包含了4个元素;故,把前3个元素称为3行,每个元素数组包含的4个元素称为4列。

int arr3[3][4] = {
    {0},
    {4},   
    {8}
};

访问二维数组亦可用范围For语句以及下标访问法,当然也可以使用指针访问;

#include<iostream>

using namespace std;
int main(){
    int arr[3][4] = {0,1,2,3,4,5,6,7,8,9,0,0};

    //using Range-Based For Statement
    for(auto &i1 : arr){//对外层元素引用
        for(auto &i2 : i1){//对内层元素引用
            cout<<i2+1<<" ";
        }
    }
    return 0;
}

后记(Postscript)

        激励我写博客的原因有很多,背后有许多支持我的朋友,他们给我提供了难得的实验环境,给了我许多启发。学习编程语言,感悟背后的算法思想,需要持久不变的初心,那就是互相奉献心态和共享知识的精神。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云之君若雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值