一些便宜函数

vector的erase和remove

C++ STL vector删除元素的几种方式(超级详细)
如果想删除 vector 容器中指定位置处的元素,可以使用 erase() 成员函数,该函数的语法格式为:

iterator erase (pos);

其中,pos 为指定被删除元素位置的迭代器,同时该函数会返回一个指向删除元素所在位置下一个位置的迭代器。
(记住vector中erase函数的用法、参数是迭代器,不要以为没用只能删除这种简单的数字数组,比如蓝桥杯区间移位这题,需要移除已经利用过的区间,防止重复利用

#include <vector>
#include <iostream>
using namespace std;

int main()
{
    vector<int>demo{ 1,2,3,4,5 };
    auto iter = demo.erase(demo.begin() + 1);//删除元素 2
    //输出 dmeo 容器新的size
    cout << "size is :" << demo.size() << endl;
    //输出 demo 容器新的容量
    cout << "capacity is :" << demo.capacity() << endl;
    for (int i = 0; i < demo.size(); i++) {
        cout << demo[i] << " ";
    }
    //iter迭代器指向元素 3
    cout << endl << *iter << endl;
    return 0;
}

运行结果为:

1 5 3 4 2
size is :4
capacity is :5
1 5 3 4

当然,除了删除容器中单个元素,还可以删除容器中某个指定区域内的所有元素,同样可以使用 erase() 成员函数实现。该函数有 2 种基本格式,前面介绍了一种,这里使用另一种:

iterator erase (iterator first, iterator last);

其中 first 和 last 是指定被删除元素区域的迭代器,同时该函数会返回指向此区域之后一个位置的迭代器。

#include <vector>
#include <iostream>
using namespace std;
int main()
{
    std::vector<int> demo{ 1,2,3,4,5 };
    //删除 2、3
    auto iter = demo.erase(demo.begin()+1, demo.end() - 2);
    cout << "size is :" << demo.size() << endl;
    cout << "capacity is :" << demo.capacity() << endl;
    for (int i = 0; i < demo.size(); i++) {
        cout << demo[i] << " ";
    }
    return 0;
}

运行结果为:

size is :3
capacity is :5
1 4 5

可以看到,和删除单个元素一样,删除指定区域内的元素时,也会将该区域后续的元素前移,并缩小容器的大小。

如果要删除容器中和指定元素值相同的所有元素,可以使用 remove() 函数,该函数定义在 头文件中。例如

#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    vector<int>demo{ 1,3,3,4,3,5 };
    //交换要删除元素和最后一个元素的位置
    auto iter = std::remove(demo.begin(), demo.end(), 3);
    cout << "size is :" << demo.size() << endl;
    cout << "capacity is :" << demo.capacity() << endl;
    //输出剩余的元素
    for (auto first = demo.begin(); first < iter;++first) {
        cout << *first << " ";
    }
    return 0;
}

运行结果为:

size is :6
capacity is :6
1 4 5

注意,在对容器执行完 remove() 函数之后,由于该函数并没有改变容器原来的大小和容量,因此无法使用之前的方法遍历容器,而是需要向程序中那样,借助 remove() 返回的迭代器完成正确的遍历。
remove() 的实现原理是,在遍历容器中的元素时,一旦遇到目标元素,就做上标记,然后继续遍历,直到找到一个非目标元素,即用此元素将最先做标记的位置覆盖掉,同时将此非目标元素所在的位置也做上标记,等待找到新的非目标元素将其覆盖。因此,如果将上面程序中 demo 容器的元素全部输出,得到的结果为 1 4 5 4 3 5。

另外还可以看到,既然通过 remove() 函数删除掉 demo 容器中的多个指定元素,该容器的大小和容量都没有改变,其剩余位置还保留了之前存储的元素。我们可以使用 erase() 成员函数删掉这些 “无用” 的元素

比如,修改上面的程序:

#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    vector<int>demo{ 1,3,3,4,3,5 };
    //交换要删除元素和最后一个元素的位置
    auto iter = std::remove(demo.begin(), demo.end(), 3);
    demo.erase(iter, demo.end());
    cout << "size is :" << demo.size() << endl;
    cout << "capacity is :" << demo.capacity() << endl;
    //输出剩余的元素
    for (int i = 0; i < demo.size();i++) {
        cout << demo[i] << " ";
    }
    return 0;
}

运行结果为:

size is :3
capacity is :6
1 4 5

remove()用于删除容器中指定元素时,常和 erase() 成员函数搭配使用。

next_permutation、prev_permutation

一、函数参数
next_permutation(a,a+5)
next_permutation(str.begin(),str.end())
int数组ok,字符串也ok,字符串string容器也可以排序噢
参考一
二、
仔细比较各种组合方法和有无sort()的输出,可以发现函数next_permutation()是按照字典序产生排列的,并且是从数组中当前的字典序开始依次增大直至到最大字典序

若一开始无序,则使用next_permutation函数得到的排列组合会少于全部的组合情况噢,因为从当前组合开始走到最大的字典序组合

参考二

atoi函数

int x;
char str[100]={“dwn”};
x=atoi(str);
string类型的可以先用str.c_str()转为char字符串噢

unique

iterator unique(iterator it_1,iterator it_2);

unique函数属于STL中比较常用函数,它的功能是元素去重。
STL中unique的函数 unique的功能是去除相邻的重复元素(只保留一个),因为unique去除的是相邻的重复元素,所以一般用之前都会要排一下序。

还有一个容易忽视的特性是它并不真正把重复的元素删除,而是指重复元素的位置被不重复的元素给占领了,
有很多文章说的是,unique去重的过程是将重复的元素移到容器的后面去,实际上这种说法并不正确,应该是把不重复的元素移到前面来。也就是,部分重复的元素被不重复的元素覆盖掉了,但是后面的元素保持不变

返回值是去重后序列(这个序列不含有重复数值)的末尾的下一个元素
返回值是一个迭代器,它指向的是去重后容器中不重复序列的最后一个元素的下一个元素

#include<iostream>
#include<algorithm>
#include<cassert>
using namespace std;
 
int main()
{
 
    vector<int> a ={1,3,3,4,5,6,6,7};
    vector<int>::iterator it_1 = a.begin();
    vector<int>::iterator it_2 = a.end();
    vector<int>::iterator new_end;
 
    new_end = unique(it_1,it_2); //注意unique的返回值
    a.erase(new_end,it_2);
    cout<<"删除重复元素后的 a : ";
    for(int i = 0 ; i < a.size(); i++)
        cout<<a[i];
    cout<<endl;
 
}

用erase实现彻底去重,反正输入时可以记录重复元素出现的次数
unique用法详解
STL中erase()的用法

lowbit(找半天头文件,原来要自己写)

lowbit()函数用来取一个二进制最低位的一与后边的0组成的数
例:
5(101),lowbit(5)=1(1)

12(1100),lowbit(12)=4(100)

1、x&(-x)

int lowbit(int x)
{
    return x&(-x);
}

原理,二进制数的负数是原码对应的补码,即各位取反加一

12(1100),-12(0100)
(正数补码反码都和原码一样啦)
曾记否,负数一般用补码表示从而进行运算,补码的朴素求法就是对各位取反再加1,但在计算机组成原理中介绍了一种更高明的求负数补码做法:以最低位的1为基准(该位保持不变),左侧全部取反,右侧的0保持不变
这样一来,x&(-x), 最低位的1左侧变为全0,右侧的全0继续保持,从而 保留二进制下最低位出现的1的位置,其余位置置0

2、x- ( x&(x-1) )

先消掉最后一位1,然后再用原数减去消掉最后一位1后的数,答案就是lowbit(x)的结果
曾记否,x&(x-1)用于消去最低位的1,因为 x − 1 x-1 x1, 根据小学数学减法运算的借位原则(滑稽),对一个二进制数进行减1,那么会出现从这个这个数的最
后一个1开始到最后的所有数都取反,即构成一个01111⋯的串, x-1相对于x,最低位的1左边不变,最低位的1变为0,最低位1的右边由全0变为全1,则x&(x-1)就可以消去最低位的0
可用于求一个二进制数中各位上1的总个数

int x;
cin>>x;
int cnt=0;
while(x){
	x=x&(x-1);
	cnt++;
}
cout<<cnt;

3、x&(x^(x-1))

记前两种就好啦
任何数x和1相与得到非x
任何数x和0相与得到x本身

lowbit累计1出现的次数

int x;
cin>>x;
int cnt=0;
while(x){
	x-=(x&-x);
	cnt++;
}
cout<<cnt;

我们可以使用lowbit运算统计一个整数的二进制形式下1的个数。

实现原理很简单啦,就是:我们先用lowbit运算找出lowbit(x),然后用原数减去这个数,依次循环,直到为0为止。

这也是树状数组的实现原理。
关于lowbit运算的相关知识
在这里插入图片描述
lowbit用法

upper_bound 、lower_bound

algoritm中的标准算法,原理是二分法,所以使用前要先升序排列
在map、set中当然也可以用,元素自动进行升序排列,更适用了
参数分别是:查找的数组段的首地址、尾地址、查找的值k
返回值:第一次出现大于等于那个要查找的数的地址
要得到下标需要减去数组的首地址

lower_bound(key_value) ,返回第一个大于等于key_value的定位器
upper_bound(key_value),返回第一个大于key_value的定位器

   	set<int> s;
 	s.insert(1);  
    s.insert(3);  
    s.insert(4);  
    s.insert(5); 
    s.insert(6);
    cout<<*s.lower_bound(1)<<endl;  //3
    cout<<*s.lower_bound(3)<<endl;  //3
    cout<<*s.upper_bound(4)<<endl;  //5 而不是6 

lower_bound(a,a+n,k))-a) 得到的是下标噢(数组下标从0开始),要得到排位需要加1

while(scanf("%d",&k))
   {
       cout<<k<<"的第一个大于等于它的位置在"<<((lower_bound(a,a+n,k))-a)+1<<endl;
   }

所以要在数组中找到 小于等于x的最大元素的下标,应该用upper_bound,讲返回的下标减1指向的一定是小于等于x的元素,而lower_bound则不明就是x还是大于x的数

ll p = upper_bound(a + 1, a + 1 + n, x) - a;
p--;

上链接
多看看
再看

fill

1、fill 与 memset
memset函数
按照字节填充某字符,在头文件里面
fill函数
按照单元赋值,将一个区间的元素都赋同一个值,在头文件里面

因为memset函数按照字节填充,所以一般memset只能用来填充char型数组,(因为只有char型占一个字节)如果填充int型数组,除了0和-1,其他的不能。因为只有00000000 = 0,-1同理,如果我们把每一位都填充“1”,会导致变成填充入“11111111”
在这里插入图片描述

而fill函数可以赋值任何,而且使用方法特别简便:
2、fill初始化一维数组
例如int数组:fill(arr, arr + n, 要填入的内容);

	int arr[10];
    fill(arr, arr + 10, 2);
  

3、fill初始化vector容器
vector也可以:fill(v.begin(), v.end(), 要填入的内容);

 vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  fill(v.begin(), v.end(), -1);

fill函数可以为数组或者vector中的每个元素赋以相同的值,通常用于初始化!
数组的效率往往比vector高,使用assign函数只能对vector赋初值~所以当要对数组赋初值时可以使用fill函数。

3、fill给多维数组赋值

#include <algorithm>
#include <stdio.h>
using namespace std;
int v[10][10];
int main(int argc, char const *argv[])
{
    fill(v[0],v[0]+10*10,-1);//v数组所有元素被初始化为-1
    for (int i = 0; i <10; ++i){
        for (int j = 0; j <10 ; ++j){
            printf("%d ",v[i][j] );
        }
        printf("\n");
    }   
    return 0;
}

原链接
原链接

赋初值正无穷、负无

1、memset(a,0x3f/ 0xc0,sizeof(a))

C语言中可以
0x3f3f3f3f表示正无穷,用0xc0c0c0c0表示负无穷
0x3f3f3f3f = 1061109567
0xc0c0c0c0 = -1061109568
这样设置是因为满足了正无穷加上正无穷还是正无穷并且不会溢出int的存储范围,同时在对变量数组初始化的时候可以用memset把数组的每一个字节都初始化为0x3f(0xc0)来达到把数组中每一个元素都初始化为正(负)无穷的效果
memset 赋初值为无穷大和无穷小

2、使用系统提供的常量INT_MAX,INT_MIN

如果是int型,可以用INT_MAX表示正无穷,INT_MIN表示负无穷,需要包含头文件limits.h

如果是double型,可以用DBL_MAX表示正无穷,-DBL_MAX表示负无穷(注意不是DBL_MIN),需要包含头文件float.h。

vector容器数组初始化

定义和初始化vector类型
1、vector v1; //v1是一个空vector,它潜在的元素是T类型的,执行默认初始化
2、vector v3(n,val);//v3包含了n个重复的元素,每个元素的初始值都是val
3、vector v4(n); //v4包含了n个重复执行了值初始化的对象(n相当于数组容量了)

v.empty()

4、
v[n] //返回v中第n个位置上的元素引用
但是不能用下标形式添加元素
v[idex] = a; //错误
**vector对象(以及string对象)的下标运算符可用于访问已存在的元素,不能用于在指定位置添加元素(用push_back)。**
5、vector二维数组赋值


vector<vector<int> > array(n); //这个n一定不能少//vector<int> array[n];

vector<vecotr<int> > dp(size1,vector<int>(size2,初始值如inf)) 
int main()
{
    int i = 0, j = 0;
	vector< vector<int> > maze(8, vector<int> (12, 0));    
    int A[8][12] = {{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
                    { 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1 },
                    { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1 },
                    { 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1 },
                    { 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1 },
                    { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1 },
                    { 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1 },
                    { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
                   };
    int m, n;
    for(m = 0; m < maze.size(); m++)
    {
        for(n = 0; n < maze[m].size(); n++)
        {
            maze[m][n] = A[m][n];
            cout << maze[m][n] << " ";
        }
        cout << "\n";
    }
 
}

什么?还不懂c++vector的用法,你凭什么勇气来的!
C++ vector 实现二维数组,赋值

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Excel函数是Excel软件中的一种功能,它可以根据用户的需求对数据进行处理和计算。下面是一些Excel函数的应用实例: 1. 求和函数(SUM): SUM函数可以用于对一列或多列数据进行求和。例如,如果有一个销售数据表格,其中包含每天的销售额,我们可以使用SUM函数计算出总销售额。 2. 平均值函数(AVERAGE): AVERAGE函数可以计算出一列或多列数据的平均值。比如,如果有一个学生成绩表格,我们可以使用AVERAGE函数计算出学生们的平均分。 3. 最大值函数(MAX)和最小值函数(MIN): MAX函数可以用于寻找一列或多列数据中的最大值,而MIN函数可以用于寻找最小值。例如,如果有一个存储商品价格的表格,我们可以使用MAX函数找到最贵的商品价格,或使用MIN函数找到最便宜的商品价格。 4. 统计函数(COUNT和COUNTIF): COUNT函数可以用于计算一列或多列数据中的非空单元格数量,而COUNTIF函数可以根据条件统计符合条件的单元格数量。比如,如果有一个学生考试成绩表格,我们可以使用COUNT函数计算出参加考试的学生人数,或使用COUNTIF函数计算及格的学生人数。 5. 文本函数(CONCATENATE和LEFT/RIGHT/MID): CONCATENATE函数可以将多个单元格中的文本合并在一起,而LEFT/RIGHT/MID函数可以从一个单元格中提取部分文本。例如,如果有一个包含名字和姓氏的列,我们可以使用CONCATENATE函数将它们合并成一个完整的姓名。 这些只是Excel函数的一小部分应用实例,Excel函数非常丰富多样,用户可以根据不同的需求选择合适的函数进行数据处理和计算。 ### 回答2: Excel函数是一种非常常用和强大的工具,可以帮助我们进行数据分析、数据处理和数据展示等工作。下面我们以一个实例来详细说明Excel函数的应用。 假设我们有一份销售数据表格,包含了产品名称、销售数量和销售额等信息。我们希望通过Excel函数来计算每个产品的平均销售额和总销售额。 首先,在一个单元格中输入函数"=SUMPRODUCT(销售数量,销售额)",这个函数可以将销售数量和销售额相乘,并求和得到总销售额。 然后,我们可以使用"=AVERAGE(销售额)"函数来计算所有销售额的平均值,这个函数可以快速求解平均值。 接下来,如果我们想要知道每个产品的平均销售额,我们可以使用"=AVERAGEIF(产品名称, A2, 销售额)"函数。其中,产品名称是一个列范围,A2是我们想要计算平均值的产品名称,在销售额列中寻找这个产品名称,并计算其平均销售额。 除了上述函数,Excel还提供了许多其他有用的函数。比如,"SUM"函数可以计算一个范围内的数值的总和;"COUNT"函数可以计算一个范围内的数值的数量;"MAX"和"MIN"函数可以分别计算一个范围内的最大值和最小值;"IF"函数可以根据条件进行判断并返回相应的值等等。 总的来说,Excel函数的应用非常广泛,可以帮助我们高效地处理和分析数据。通过合理地使用这些函数,我们可以轻松地完成各种数据处理任务,并得到我们想要的结果。 ### 回答3: Excel函数是Excel软件中非常重要的功能,它可以帮助用户进行各种数据分析和计算。下面我将通过一个实例来详细解释Excel函数的应用。 假设我们要在一个Excel表格中计算某个班级学生的平均分数。我们已经在表格的A列中输入了学生姓名,B列中输入了学生的分数。首先,我们可以使用SUM函数来计算学生的总分,即在C2单元格中输入“=SUM(B2:B11)”,其中B2:B11表示在B列2行到11行的单元格范围。然后,我们可以使用COUNT函数来统计学生的人数,即在C3单元格中输入“=COUNT(B2:B11)”。接着,我们可以使用AVERAGE函数来计算学生的平均分数,即在C4单元格中输入“=AVERAGE(B2:B11)”。这样,我们就可以得到班级学生的平均分数。 除了上述函数外,在Excel中还有许多其他函数可以应用到不同的数据分析和计算中。比如,我们可以使用IF函数来进行条件判断和计算,使用VLOOKUP函数来进行查找和匹配,使用MAX和MIN函数来找出最大值和最小值,使用COUNTIF和SUMIF函数来进行条件计数和条件求和等等。这些函数的应用可以极大地简化我们的工作,提高工作效率。 总之,Excel函数是Excel软件中非常强大和有用的功能。通过学习和应用各种函数,我们可以轻松地进行各种数据分析和计算,从而更好地理解和利用数据。希望上述的解释对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值