【数据结构】数组笔记

  1. 数组的表示方法

int N=5;
int a1[N];
int *a2=new int[N];//释放用delete

数组几乎可以用vector代替,试着练习了一个重载函数

#include<iostream>
#include<vector>
using namespace std;
ostream&operator <<(ostream& o, const vector<int>& n){
    for(auto x:n){
        o<<x<<endl;
    }
    return o;
}
int main(){
    vector<int>num;
    for(int i=0;i<10;++i){
        num.push_back(i);
    }
    cout<<num;
}

c++11后有一个新的遍历数组的方式for(auto x: array),非常像python里的for i in array。

虽然说向量也可以用vector<int>num(10)的方式指定创建一个大小为10的向量,如果直接用for(int i=0;i<num.size();++i)或者迭代器,for(i=num.begin();i!=num.end();++i),会轮出20个,前面都是0,说明你没有溢出,因为向量就是要给你开辟足够的空间。我们老师说向量不建议这样使用,因为它本身就是一个灵活的容器,都指定大小了,那你不如去用数组。

另外对于ostream中的这个引用,引用就是引用了输入的实参的值,本质上是防止倒灌。(更容易接受周强老师的解释,如果直接传入这个变量,相当于把这个变量的全部都传进去了,比如说该变量是一个结构体,那就会把这个结构体中所有元素都传进去,效率低下。如果只是引用,传进去就是一个地址。)

  1. 向量遍历——迭代器的使用

迭代器就相当于一个遍历。

迭代器遍历可以这样写:

#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>num;
    for(int i=0;i<10;++i){
        num.push_back(i);
    }
    vector<int>::iterator it;
    for(it=num.begin();it!=num.end();++it){
        cout<<*it<<endl;
    }
}

num.begin()相当于该向量的起始位置,array.end()是结束位置,前者指向第一个元素0,后者指向最后一个元素9的后面。迭代器的++是重载。

当需要查找容器内某个元素时,可以使用find(引入头文件algorithm),返回一个迭代器,指向这个元素。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
    vector<int>num;
    for(int i=0;i<10;++i){
        num.push_back(i+7);
    }
    vector<int>::iterator it;
    it=find(num.begin(),num.end(),10);
    cout<<*it<<endl;
}

这时候*it是10,即迭代器指向了10这个元素,it即为这个元素的位置(迭代器形式)

同上,如果没有找到,迭代器就会在移到容器末端(num.end())的时候停止移动,此时*it就是容器末端那个地址指向的数字。

  1. 二维数组

昨天重修c++的时候也听老师说了,二维数组表面上是二维的,实质上还是一维数组,是数组的数组。

下面两种情况第一种是我们熟知的二维数组定义方式。

第一种代表数组元素是由4个整形变量组成的数组

虽然之前说过,int *a2=int [4]可以定义一维数组,但是第二种定义的不是二维数组

int a1[3][4];
int **a2=int [3][4]

分析一下,*a2说明a2是一个指针,指向什么呢?*a2的前面还有一个*,所以a2是指向一个指针的指针,它指向的指针指向一个整型变量。现在分析a2[1][1]。

a2[1]是:a2指向的指针的地址+1后的地址,该地址属于一个指针。

a2[1][0]是:上述指针指向的一个整型变量

所以a2[1][1]是:上述整型变量的地址+1,该地址属于一个整型变量。

回过头我们来看二维数组,数组的所有地址都是连续的,即使变为二维数组,上下两行的地址也是连续的。但是第二种写法,根据我们解析的,指针的地址是连续的,但是指针指向的地址是系统动态分配的,不一定连续。所以后者不是二维数组。

int a1[3][4];
int (*p)[4];
p=a1;

一维数组的时候,数组名即数组首地址。指针指向数组首地址,没毛病。

二维数组的时候,之前说二维数组是数组的数组,数组名还是数组首地址,数组中这里每个元素中有4个元素。p这个指针指向[4],[4]代表是一个有四个元素的数组,前面的变量类型为int,说明p指向一个有4个整型元素的数组。

假如写成了这样:

int *p[4];

意思就变了。p先和括号结合:p[4],代表一个有4个元素的数组,*代表这四个元素都是指针类型,int表示这些指针分别指向一个整型变量

昨天重修听老师说,二维数组可以忽略行数,但必须强调列数。当时老师的解释是:否则数组会不知道如何分配这些元素。

所以说参数中有二维数组的函数要这样写:

int func1(int a[][4],int n);
int func2(int(*p)[4],int n);

根据之前的分析,上述两种都可以。另外如果只是函数声明,可以省去名字,像这样:

int func2(int(*)[4],int n);

小括号不能丢。虽然省去了名字,但名字实际还是在的,否则就会变成我们之前分析过的那种错误写法。

  1. 字符串

字符串可以这样写

char *p="hello";
char p1[]="hello";
char *p2="hello";

会发现p和p2的地址是一样的,但p和p1的地址不同。因为c语言中分常量区和栈区,前者在常量区,后者在栈区。

对于p1字符串,它的长度是6,因为字符串末尾都会有一个'\0'作为结束符号。

c++提供库运行正则表达式

#include<regex>

可以这样用。很多和python里import re之后的用法几乎一样。

#include<iostream>
#include<regex>
#include<string>
using namespace std;
int main(){
    string s="abc123@abc12.xyz12";
    regex r("[a-z]{1,3}[0-9]{1,3}@[a-z]{1,3}[0-9]{1,2}\.[a-z]{1,3}[0-9]{1,2}");
    cout<<regex_match(s,r);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值