2024五一 day3 笔记

位运算

        位运算一共有六种,作用见下图,分别为按位与、按位或、按位异或、按位取反、左移和右移。

        按位与

                运算符:&

                数学表示:&, and

                解释:只有两个对应位都为1时才为1     

        按位或

                运算符:|

                数学表示 :|, or

                解释:只要两个对应位中有一个1时就为1       

        按位异或

                运算符:^

                数学表示:\bigoplus,xor

        按位取反 

                取反是对一个数  进行的位运算,即单目运算。

                取反暂无默认的数学符号表示,其对应的运算符为~~。它的作用是把num的二进制补码中的1和0全部取反(1变为0,0变为1)。有符号整数的符号位在~运算中同样会取反。

---------------------------------------------------------------------------------------------------------------------------------

高级数据结构

        队列

                普通队列

                        支持操作:

                        1.从队尾加入

                        2.从队首删除

                        3.查看队首

                        实际操作:

                

queue<int> q;//定义一个int类型的队列
q.push(10086);
q.push(114514)//从队尾放入一个元素
cout << q.front() << endl;//输出q的队首元素:10086
q.pop()//从队首删除一个元素:10086
cout << q.size() << endl;//输出q的长度:1

                        但是!

                       queue是STL表中的数据结构,如果队列被wmoia吃了呢?

                       数组:俺也一样!

                       只需开出足够大小的数组,用两个变量 head 和 tail 来储存队首和队尾就可以了。

                双端队列

                        双端队列于普通队列不同,双端队列支持在两端访问、插入、弹出。

                        实际操作:

头文件:include <deque>

deque<int> d;//声明一个int类型的双向队列
d.push_back(1);
d.push_back(1);//在d的队尾插入元素
d.push_front(45);
d.push_front(14);//在d的队首插入元素
d.pop_back();//在d的队尾删除元素
d.pop_front();//在d的队首删除元素
cout << q.size() << endl;//输出d的元素个数
cout << q.front() << endl;//输出d的队首元素
cout << q.back() << endl;//输出d的队尾元素

         堆

                支持操作:

                1.插入元素

                2.访问最大元素

                3.删除最大元素

                实际操作:

priority_queue<int> p;//定义一个int类型的堆
p.push(114);
p.push(514);//堆中加入元素
cout << p.top() << endl;//输出队中最大的元素:514
p.pop();//删除堆中最大的元素
cout << p.size() << endl;//输出堆中元素的数量

                堆分大根堆和小根堆,上面的是大根堆。大根堆就是输出和删除都是对最大元素进行操作。小根堆就是对最小元素进行输出、删除操作。那么怎么办呢?

                看到大佬们各种花式做法,这个蒟蒻默默低下了头。

                但是!

                只需把每个元素都变成它的相反数,输出时在变回来就可以了。

                代码省略……

        集合

                集合有个特殊性质:可以去重。

                实际操作:

set<int> s//定义一个集合s
st.insert(114);//在s中放入114这个元素
st.insert(514);
st.insert(514);//因为set去重的特性,所以只有一个514
cout << s.size() << endl;//输出s的元素的个数
cout << s.count(514) << endl;//输出是否存在514这个元素,有输出1,无输出0,这次输出1
s.erase(514);//将514这个元素删除
cout << s.count(514) << endl;//因为514已被删除,所以输出0
for(set<int>::iterator it = s.begin; it != s.end(); it++)//使用迭代器来把s的所有元素全部输出
    cout << (*it) << endl;
s.clear()//清除s的所有元素

                某蒟蒻问:

                啊!这个“for(set<int>::iterator it = s.begin; it != s.end(); it++)”太难写了!有什么简单的方法吗?

                当然!如果嫌那一大长串麻烦,还有个更省事的方法:

                "for(auto it : s)" ! ! !

                某蒟蒻又问:为什么我敲上去之后编译失败了呢?

                解决方法(DEV-C++):

                找到顶部的”Tools“(工具),再点击“compiler options”(编译选项),把上面的对勾勾上,在框中输入“-std=c++11”,就好了。

                但是!考场慎用!!!

        二元组

                实际操作:

pair<int, int> p;//声明一个二元组,第一个元素类型为int
p.first = 114;//将第一个元素定义为114
p.second = 514;//将第二个元素定义为514
//或 p = make_pair(114, 514);

pair<int, int> p1[1145];
cout << (a[1] < a[2]) << endl;//先比较first,在比较second
cout << (a[1] == a[2]) << endl;//只有first和second都相等时,才算这两个二元组相等
sort(a, a + 114);//按照first作为第一关键字, second作为第二关键字从小到大排序

        映射

                映射是一个比较抽象的类型,但它确实挺好用的。

                实际操作:

map<int, int> m;
//第一个int为下标的类型
//第二个int为数值的类型
m[1] = 114514;//下标是整数就行
m[114514] = 114514;//这么大也可以
m[114514114514114514] = 114514;//这也可以!
m[-114514] = 114514;//甚至是负数
cout << m.size() << endl;//m中元素的个数
for(auto it : m) cout << it.frist << " " << it.second << endl;
//first 是下标,second是数值
m.clear()//清空m

map<string, string> m1;//把下标类型定义成string
m1["hellow"] = "word";//之后就可以用string类型来当下标了!

       动态数组

        动态数组就是长度不固定的数组。虽说不用考虑数组越界,但速度比普通数组慢,占用内存比普通数组多。

#include<iostream>
#include<vector>

using namespace std;

vector<int> z;//动态数组 元素类型为int 

//z 已经有32768个数
//push_back
//把占用的内存从32768 -> 65536
//第32769这个位置拿来存数 

int main()
{
	z.push_back(233);
	z.push_back(2333);//在数组后面加入一个数
	z.pop_back();//删除数组最后一个数
	z.push_back(23333);
	cout << z.size() << endl;//数组中有几个数
	for (int i=0;i<z.size();i++)
		cout << z[i] << endl; 
	z.resize(1000);//把vector数组大小变为1000 
	 
	return 0;
}

---------------------------------------------------------------------------------------

并查集


        定义:

                并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题(即所谓的并、查)。比如说,我们可以用并查集来判断一个森林中有几棵树、某个节点是否属于某棵树等。

        主要构成:

                并查集主要由一个整型数组pre[ ]和两个函数find( )、join( )构成。
                数组 pre[ ] 记录了每个点的前驱节点是谁,函数 find(x) 用于查找指定节点 x 属于哪个集合,函数 join(x,y) 用于合并两个节点 x 和 y 。

        作用:

                并查集的主要作用是求连通分支数(如果一个图中所有点都存在可达关系(直接或间接相连),则此图的连通分支数为1;如果此图有两大子图各自全部可达,则此图的连通分支数为2……)

int to[233];//to[i]代表i点的箭头指向谁 

int go(int p)//从p出发最后会走到哪里 O(1)
{
	if (p==to[p]) return p;
	//else return to[p]=go(to[p]);
	else
	{
		to[p] = go(to[p]);
		return to[p];
	}
}

int main()
{
	cin >> n;
	for (int i=1;i<=n;i++)
		to[i] = i;//每个点的箭头都指向自己 
		
	//合并x和y所在的部分 
	to[go(x)] = go(y);
	
	//判断x和y是否属于同一部分
	go(x) == go(y); 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值