ACwing C++ 语法笔记9位运算与常用库函数1、该系列为ACWing中c++语法课,已购买正版,课程作者为yxc(请大家支持正版)。
2、为啥写在这儿,问就是oneNote的内存不够了QAQ
3、该节是语法课最后一节,完结撒花!!
- 一、 位运算
- 二、 常用库函数
- 2.1 reverse 翻转
- 2.2 unique 去重
- 2.3 random_shuffle 随机打乱
- 2.4 sort
- 2.5 lower_bound/upper_bound 二分
| 符号 | 运算 |
|---|---|
| & | 与 AND |
| | | 或 OR |
| ~ | 非 NOT |
| ^ | 异或 XOR |
| >> | 右移 |
| << | 左移 |
异或可以看成不进位加法,一样就是0,不一样就是1。
#includeusing namespace std; int main() { int a =3, b=2; cout << (a^b) << endl; return 0; }
右移: a >> k (移动k位) 等价于
a
/
2
k
a/2^{k}
a/2k
左移: a << k 等价于
a
∗
2
k
a*2^{k}
a∗2k
- 常用操作:
- 求x的第k位数字(从个位开始) x >> k & 1(先将第k位挪到个位,再用&1可以取个位数字)
查看数字的二进制 int a = 13 for (int i = 5; i>=0; i--) cout << (a >> i & 1) << endl;
- lowbit(x) = x & -x,返回x的最后一位1 (两个数字的前半部分取反,后半部分相同,参考原码和补码)(-x和~x+1的表示方式相同)
- 求x的第k位数字(从个位开始) x >> k & 1(先将第k位挪到个位,再用&1可以取个位数字)
几乎所有的常用库函数都在算法库里面:#include
2.1 reverse 翻转reverse函数是O(n)的。
翻转一个vector:
#include#include #include using namespace std; int main() { vector a({1, 2, 3, 4, 5}); reverse(a.begin(), a.end()); for(int x:a) cout << x <<' '; cout << endl; return 0; }
翻转一个数组,元素存放在下标1 ~ n:reverse(a + 1, a + n + 1);
#include2.2 unique 去重#include #include using namespace std; int main() { int a[] = {1, 2, 3, 4, 5}; reverse(a, a+5); for(int x: a) cout << x << ' '; cout << endl; return 0; }
返回去重(只去掉相邻的相同元素)之后的尾迭代器(或指针),仍然为前闭后开,即这个迭代器是去重之后末尾元素的下一个位置。该函数常用于离散化,利用迭代器(或指针)的减法,可计算出去重后的元素个数。
注意:
1、unique函数需要相同元素挨在一起,才能去重。该函数会把所有不同的元素放在开头。(如下图所示)
2、unique函数的返回值是不同元素的下一个位置(相当于新数组的end)
把一个vector去重:
int m = unique(a.begin(), a.end()) – a.begin(); m表示数组中不同元素的数量 #include#include #include using namespace std; int main() { vector a({1, 1, 2, 2, 3, 4, 5}); int m = unique(a.begin(), a.end()) - a.begin(); cout << m << endl; for(int i = 0; i 将vector数组不同元素之外的删除:
a.erase(unique(a.begin(), a.end()), a.end());把一个数组去重,元素存放在下标1 ~ n:
int m = unique(a + 1, a + n + 1) – (a + 1); #include#include #include using namespace std; int main() { int a[] = {1, 1, 2, 2, 3, 4, 5}; int m = unique(a, a+7) - a; cout << m << endl; for(int i = 0; i 2.3 random_shuffle 随机打乱 用法与reverse相同。
#include2.4 sort#include #include #include using namespace std; int main() { vector a({1, 2, 3, 4, 5}); srand(time(0)); // 随机种子 random_shuffle(a.begin(), a.end()); for(int x: a) cout << x << ' '; cout << endl; return 0; } 对两个迭代器(或指针)指定的部分进行快速排序。可以在第三个参数传入定义大小比较的函数,或者重载“小于号”运算符。
#include#include #include using namespace std; int main() { vector a({1, 5, 3, 2, 4}); sort(a.begin(), a.end()); // 从小到大 for(int x: a) cout << x << ' '; cout << endl; sort(a.begin(), a.end(), greater ()); // 从大到小 return 0; } // 自行设定排序函数 // 如果a应该排在b前面,返回true;否则返回false bool cmp(int a, int b) { return a b; // 实现从大到小的排序 } sort(a.begin(), a.end(), cmp);把一个int数组(元素存放在下标1 ~ n)从大到小排序,传入比较函数:
int a[MAX_SIZE]; bool cmp(int a, int b) { return a > b; } sort(a + 1, a + n + 1, cmp);把自定义的结构体vector排序,有两个方法:
1、重载小于号运算符:
// 全局变量Rec struct Rec { int id, x, y; }; vectora; bool operator <(const Rec &a, const Rec &b) { return a.x < b.x || a.x == b.x && a.y < b.y; } sort(a.begin(), a.end()); 2、自定义比较函数
#include2.5 lower_bound/upper_bound 二分#include #include using namespace std; struct Rec { int x, int y; bool operator< (const Rec &t)const { // 当前的x要不要排到t的前面 // 如果小于t.x那么排到前面 return x < t.x; } }a[5]; bool cmp(Rec a, Rec b) { return a.x < b.x; } int main() { for(int i=0, i<5; i++) { a[i].x = -i; a[i].y = i; } for(int i=0; i<5; i++) printf("(%d, %d)", a[i].x, a[i].y); cout << endl; sort(a, a+5, cmp); // 从小到大 for(int i=0; i<5; i++) printf("(%d, %d)", a[i].x, a[i].y); cout << endl; return 0; } 使用这两个函数首先需要数组或vector已经从小到大排好序。
lower_bound的第三个参数传入一个元素x,在两个迭代器(指针)指定的部分上执行二分查找,返回指向第一个大于等于x的元素的位置的迭代器(指针)。
upper_bound的用法和lower_bound大致相同,唯一的区别是查找第一个大于x的元素。当然,两个迭代器(指针)指定的部分应该是提前排好序的。
在有序int数组(元素存放在下标1 ~ n)中查找大于等于x的最小整数的下标:
int i = lower_bound(a + 1, a + 1 + n, x) - a; // 参数:begin/end/要比较的值#include#include #include using namespace std; int main() { int a[] = {1, 2, 4, 5, 6}; int *p= lower_bound(a, a+5, 3); cout << *p << endl; // 如果参数是7(大于所有值),返回数组的end元素的随机值 int t= lower_bound(a, a+5, 7) -a; // 返回下标5。 return 0; } 在有序vector
中查找小于等于x的最大整数(假设一定存在): int y = *--upper_bound(a.begin(), a.end(), x);#include#include #include using namespace std; int main() { vector a{1, 2, 4, 5, 6}; int t = lower_bound(a.begin(), a.end(), 3) - a.begin(); cout << a[t] << endl; return 0; }



