1.8 STL、位运算、常用库函数(DAY 29

1.8 STL、位运算、常用库函数(DAY 29,第1张

文章目录
  • 一:STL
    • 1:vector的三种遍历方式。


    • 2:vector中的auto函数:(重点)
      • (1):让编译器自己去推断类型,并且遍历
      • (2)为了验证猜想,用最简单的int型数组试验一下。


      • (3)试试double类型能否实现遍历
      • (4)试试long long 类型
      • (5)结论:auto只是为了让编译器自己识别数据类型,常与冒号一起使用,实现遍历,其他数据类型也可以,但是必须准确。


    • 3:push_back()
    • 4:pop_back()
  • 二:位运算
    • 1:& 运算
    • 2:|或运算
    • 3:~非
    • 4:异或
    • 5:左移
    • 6:右移
    • 7:用代码表示左移右移:
      • (1):取出数字13的第二位数字(二进制的13)
        • (2)取出想要位子上的数字方法:
        • (3)输出二进制数字所有的位上的值:
    • 8: -a等于 ~a+1
  • 三:常用库函数
    • 1:reverse函数 翻转(非常重要)
      • 小插曲:验证了一下数组越界的访问会出现什么错误:
      • 完美验证了计算机组成原理的重要性。


    • 2:unique函数 去重
      • 一个很强的函数,erase
    • 3:random_shuffle 函数随机打乱
      • 特别注意的是time(0)是个固定用法
    • 4:sort函数(从小到大排序)
    • 快速排序函数中的cmp实现
    • sort函数自定义cmp返回值从大到小排
    • 5:sort排结构体+运算符重载+传参

一:STL 1:vector的三种遍历方式。



#include
#include
using namespace std;

int main()
{
    vector<int>a({1,2,3});
    
    for(int i=0;i<a.size();i++)cout << a[i]<<' ';//和数组一样的遍历方式
    cout << endl;
    
    for(auto i=a.begin();i!=a.end();i++) cout << *i<< ' ';//使用迭代器遍历,迭代器相当于地址。


cout << endl; for(int x:a)cout << x << ' ';//和string一样 cout << endl; return 0; }

2:vector中的auto函数:(重点) (1):让编译器自己去推断类型,并且遍历

定义了一个x变量,但是不确定什么类型,为了方便,就用auto,让编译器自己去猜,x:a 是把a中的元素遍历并送到x中。


通过结果也可以看出来,输出的是1234。


证明 x : a 确实是遍历了,把a中的元素送到了x里面。


(2)为了验证猜想,用最简单的int型数组试验一下。


如果auto是类型,那么 冒号:才代表遍历
经过尝试:

得出结论,为什么auto和冒号: 经常在一起使用,原因可能就是遍历的时候为了方便,不用去考虑类型了,只用把冒号后面想要遍历的一个字符串或者数组或者其他的类型,遍历到冒号前面的变量中,就不用自己再去判断类型了,很方便。



换个类型也一样

(3)试试double类型能否实现遍历

(4)试试long long 类型

(5)结论:auto只是为了让编译器自己识别数据类型,常与冒号一起使用,实现遍历,其他数据类型也可以,但是必须准确。


3:push_back()


在尾部插入一个元素

4:pop_back()

删除vector a的最后一个元素

调用两次:

二:位运算

计算机组成原理中有详细阐述。



位运算中有 & 与,| 或, ~非 ,^异或, << 左移,>> 右移

1:& 运算

类似于乘法, 只有全1才是1,只要有一个0,那么相 与 的结果就是0.

2:|或运算

两个数或者多个数,只要有一个1,那么结果就是1,类似于加法

3:~非

就是取反

4:异或

两个数不同才为1,相同为0。


左移右移比较重要。


5:左移

相当于把二进制数向左移动一位,右边补零
0110 左移一位 01100 左移就是相当于乘2,左移k位就是乘以2的k次方

6:右移

二进制数向右移动一位,0110 右移一位 0011
右移相当于除2,右移n位就是除以2的n次方。


7:用代码表示左移右移: (1):取出数字13的第二位数字(二进制的13)

二进制的13是 1101 那么第二位数字应该是1 我们用代码测试一下

为什么可以这样? 因为与上1可以取出来个位数字,即取得二进制数字表示中自己想要的数字。



想要去除任意一个位子上的数字,我们都可以采用右移n位,然后与1来计算。


如果结果为1,就是1,与1结果为0就是0.这样做可以取出相应位子上的数字。


(2)取出想要位子上的数字方法:

如果想要取出来二进制数的第k位数字,那么就先 让a右移k 再与上1.

(3)输出二进制数字所有的位上的值:

以13为例

8: -a等于 ~a+1


可以看出来 在C++中,-a等于~a+1

三:常用库函数 1:reverse函数 翻转(非常重要)

起到翻转的作用。




可以翻转vector也可以翻转数组也可以翻转链表

小插曲:验证了一下数组越界的访问会出现什么错误: 完美验证了计算机组成原理的重要性。


可以看到,我们reverse的a+6 超出了定义的数组的长度5 ,就出现了一个相对来说很大的数字,32767 这是多少? 2的15次方等于32768 32767就等于2^15 -1 为什么减去1? 在计算机组成原理中,二进制数的范围就是-2的15次方到 +2的十五次方-1。


因为中间有一个0。


从这里我们又可以知道,为什么是15次方? 看来在该编译器中,数组的产长度是 4 个4位
这个是全1的情况,也就是16个1 代表2的十五次方(这里不是补码的意思,如果是补码的话,最开始的1代表负号,也就是最左边的,但是我们在这里只表示数字的大小)。


正确的遍历的范围应该是a,a+5

2:unique函数 去重

对数组的一个判重。




m 调用unique函数 去重 随后输出m,m就是去重之后数组中的不同的值的个数。



unique的参数类型,第一个参数是begin 第二个是end。


和reverse参数类型一样。


去重vector试一下:

一个很强的函数,erase


这个函数的作用是

前一个参数是unique函数,调用完unique函数后,相当于去重了,然后第二个参数是end。


表示结束的位置,这样这样就能从数组中去重过的位置,遍历到末尾,把这一段的元素删除掉。




这两句话的意思是:
先把a.begin() 和a.end() 之间元素判个重然后放在数组的最开头的位置,然后再把后面多余的部分删掉。



这样做完之后,a里面的vector就会变成1 2 3 4 代码也证实了这一点。



3:random_shuffle 函数随机打乱

用法与reverse相同,用在生成数据的时候。


用法:打乱顺序。



用法:函数里面的参数,第一个是a.begin() 第二个就是a.end()
一个开头一个结尾。



即使调用了random_shuffle函数,但是多次调用的结果还是一样,即使顺序乱了,但是每次的结果是一样的。



为什么?
这是因为random_shuffle 函数用到了随机种子这个概念。


srand();
随机种子默认是0. 所以即使打乱了顺序,但是由于随机种子是不变的,所以打乱的顺序也是不变的。


每次运行结果不一样,一般可以把时间传进去,当作一个随机种子。


由于运行时间不一样,所以随机种子不一样,所以结果就会不一样。



time(0)是返回当前到1970年1月1号的秒数。



代码如图:




可以明显的看出来,每次的结果都不一样。



但是,两个必须搭配着用才有用处。


注释掉random_shuffle 后,就不能使结果随机化了。


特别注意的是time(0)是个固定用法

搭配函数使用,不用time(0)行不行?换成其他数据可以吗?

看来是不行的,time(0)是个固定用法

4:sort函数(从小到大排序)

快速排序函数,能够快速地排序一个乱序数组。


特别注意的是,当数据量特别大的时候,推荐用归并排序。



关于sort函数的实现可以看我前一段时间的一篇文章
快速排序算法

sort默认从小到大排序,如果想从大到小按顺序排,需要加一个参数。




可以看出来,第二句输出从1 2 3 4 5 变成了 5 4 3 2 1。


升序变降序了。


快速排序函数中的cmp实现

sort函数自定义cmp返回值从大到小排

5:sort排结构体+运算符重载+传参

看我这一篇文章即可

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/569590.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存