数据结构算法刷题笔记——题型解法

数据结构算法刷题笔记——题型解法

  • 一、常用容器
    • 1.1 vector
      • 1.1.1 vector基本操作
        • 1.1.1.0 头文件#include<vector>
        • 1.1.1.1 构造一个vector容器
        • 1.1.1.2 元素访问
        • 1.1.1.3 元素个数 .size()
        • 1.1.1.4 最大容量 .capacity()
        • 1.1.1.5 改变容器有效元素个数 .resize(n)
        • 1.1.1.6 改变容器的最大容量 .reserve(n)
        • 1.1.1.7 判断是否为空 .empty()
        • 1.1.1.8 清空容器 clear()
        • 1.1.1.9 迭代器 .begin()、.end()、.rbegin()、rend()
        • 1.1.1.10 插入元素 push_back()
        • 1.1.1.11 删除最后一个值 pop_back()
        • 1.1.1.12 返回最后一个元素 back()
        • 1.1.1.13 返回第一个元素 front()
        • 1.1.1.14 插入一个元素 insert()
        • 1.1.1.15 删除一个元素 erase()
        • 1.1.1.16 查找元素值 find()
        • 1.1.1.17 交换两个容器的值 swap()
        • 1.1.1.18 迭代器失效
      • 1.1.2 vector算法
        • 1.1.2.1 头文件
        • 1.1.2.2 元素翻转reverse()
        • 1.1.2.3 排序 sort()
    • 1.2 list
      • 1.2.1 list基本操作
        • 1.2.1.0 list头文件
        • 1.2.1.1 list定义与声明
        • 1.2.1.2 基本操作
    • 1.3 queue
      • 1.3.1 queue基本操作
        • 1.3.1.0 queue头文件
        • 1.3.1.1 queue定义与声明
        • 1.2.1.2 基本操作
    • 1.3.2 双端队列deque
        • 1.3.1.0 queue头文件
        • 1.3.1.1 queue定义与声明
        • 1.2.1.2 基本操作
      • 1.3.3 优先队列 priority_queue
        • 1.3.3.0 queue头文件
        • 1.3.3.1 queue定义与声明
        • 1.3.3.2 基本操作
    • 1.4 stack
      • 1.4.1 stack基本操作
        • 1.4.1.0 stack头文件
        • 1.4.1.1 stack定义与声明
        • 1.4.1.2 基本操作
    • 1.5 map
      • 1.5.1 map基本操作
        • 1.5.1.0 map头文件
        • 1.5.1.1 map定义与声明
        • 1.5.1.2 基本操作
    • 1.6 unordered_map
      • 1.6.0 map和unordered_map区别
      • 1.6.1 unordered_map基本操作
        • 1.6.1.0 unordered_map头文件
        • 1.6.1.1 unordered_map定义与声明
        • 16.1.2 基本操作
    • 1.7 set
      • 1.7.1 set基本操作
        • 1.7.1.0 set头文件
        • 1.7.1.1 set定义与声明
        • 1.7.1.2 基本操作
    • 1.8 unordered_set
      • 1.7.1 unordered_set基本操作
        • 1.7.1.0 unordered_set头文件
        • 1.7.1.1 unordered_set定义与声明
        • 1.7.1.2 基本操作
  • 三、常用函数库
    • 3.1 优先级队列
    • 3.2 链表结构体
    • 3.3 链表的插入删除操作
    • 3.2 二叉树结构体
  • 1、贪心算法
  • 2 动态规划

一、常用容器

1.1 vector

1.1.1 vector基本操作

1.1.1.0 头文件#include
#include<vector>
1.1.1.1 构造一个vector容器
1、vector<int> v1;//构造一个int类型的空容器
2、vector<int> v2(10,1);//构造一个int类型的容器,并初始化了10个1
3、vector<int> v3(v2);//将容器v2拷贝给v3
4、vector<int> v4(v2.begin(),v2.end());//迭代器拷贝构造
5、string s ("hello");//使用别的容器的迭代器也可以拷贝(不一定是vector,可以是string)
	vector<char> s1(s.begin(), s.end());
1.1.1.2 元素访问
//1.迭代器遍历
//2.范围for遍历(其实就是迭代器)
//3.下标遍历  
//4.array.at(i) //使用at(),当这个函数越界时会抛出一个异常//at()得到编号位置的数据
vector<int>::iterator it;
for(it=array.begin();it!=array.end();it++)
    cout<<*it<<endl;

for(int i=0;i<nSize;i++)    
{    
   cout<<vecClass.at(i)<<"     ";    
}    

for(auto& x:v)
{
		cout<<x<<" ";
}

for (int i = 1; i <= 6; i++)
	{
		v.push_back(i);
	}
1.1.1.3 元素个数 .size()
v1.size();
1.1.1.4 最大容量 .capacity()
v1.capacity();
1.1.1.5 改变容器有效元素个数 .resize(n)
1.假设所给值小于当前容器size则size缩小至所给值
2.假设所给值大于当前容器size值并且小于capacity,size扩大至所给值,增加的数用0去补充
3.假设所给值大于当前容器size值并且大于capacity值,先扩容,之后再重复规则2
v.resize(n);           // 将v的大小改为n,新元素的值为该type的默认值
v.resize(n, value);    // 将v的大小改为n,并将新元素的值设为value
1.1.1.6 改变容器的最大容量 .reserve(n)
1.假设所给值小于当前容量值什么都不会发生改变
2.假如所给值大于当前容容量值扩容至所给值
v.reserve(n);
1.1.1.7 判断是否为空 .empty()
v1.empty();//1为空,0为非空
1.1.1.8 清空容器 clear()
v1.clear();
1.1.1.9 迭代器 .begin()、.end()、.rbegin()、rend()
//通过begin我们可以得到容器中的第一个元素的正向迭代器
//通过end我们可以得到容器中的最后一个元素的正向迭代器
vector<int>v(5,1);
vector<int>::iterator it=v.begin();
while(it!=v.end())
{
		cout<<*it<<" ";
		it++;
}
//通过rbegin我们可以得到容器的最后一个元素的反向迭代器
//通过rend我们可以得到容器的第一个元素的反向迭代器
vector<int> v(5,3);
vector<int>::reverse_iterator it=v.rbegin();
while(it!=v.rend())
{
		cout<<*it<<" ";
		it++;
}
1.1.1.10 插入元素 push_back()
v.push_back(1);
1.1.1.11 删除最后一个值 pop_back()
v.pop_back();
1.1.1.12 返回最后一个元素 back()
v1.back();
1.1.1.13 返回第一个元素 front()
v1.front();
1.1.1.14 插入一个元素 insert()
//1.选择一个位置(迭代器),在其前面,选择一个我们要插入的元素
v.insert(v.begin(),10);//再开头插入一个元素10
//2.选择一个位置(迭代器)选择我们一个要插入的元素的数量并且选择一个要插入的元素
v.insert(v.begin(),5,10);//我们头插5个10
1.1.1.15 删除一个元素 erase()
//1.删除指定位置的内容(迭代器)(删除掉迭代器处的内容)
v.erase(v.begin());
//2.删除指定位置的内容(迭代器)删除区间的末尾(左闭右开)
v.erase(v.begin(),v.begin()+2);//删除(0、1)处的内容
1.1.1.16 查找元素值 find()
//find函数可以找到容器中我们要寻找的值并且返回迭代器
//find函数有三个参数(迭代器左区间)(迭代器右区间)(要查找元素)[左闭右开]
vector<int>::iterator pos=find(v.begin(),v.end(),3);//找到3
1.1.1.17 交换两个容器的值 swap()
//通过sawp我们可以交换两个容器的值
v1.swap(v);
1.1.1.18 迭代器失效
//在使用迭代器之前对整个容器进行了增删改操作,这就是引起迭代器失效的原因
//解决的方法也很简单,就是使用迭代器之前重新赋值一下就行。
  vector<int>::iterator it = find(v.begin(), v.end(), 2);
	v.erase(v.begin());//删除头元素
	it = find(v.begin(), v.end(), 2);//it迭代器失效,重新获取一下
	v.erase(it);//删除元素2
	vector<int>::iterator it2 = v.begin();//begin()迭代器失效,重新获取一下
	while (it2 != v.end())
	{
		cout << *it2 << " ";
		it2++;
	}

1.1.2 vector算法

1.1.2.1 头文件
#include<algorithm>
1.1.2.2 元素翻转reverse()
reverse(array.begin(),array.end()); //将元素翻转,即逆序排列
1.1.2.3 排序 sort()
// 默认升序:
sort(array.begin(),array.end());
//降序则调用: 
sort(array.begin(),array.end(),[](int a, int b) {
		return a > b});

1.2 list

1.2.1 list基本操作

1.2.1.0 list头文件

底层实现是双向链表

#include <list>
1.2.1.1 list定义与声明
	list<int> l			声明一个空链表
	list<int> l{1,2,3}	声明一个含指定元素的链表
	list<int> l(n)    	声明一个含n个元素的链表并全部初始化为0
	list<int> l(n, m)  	声明一个含n个元素的链表并全部初始化为m
	list<int> l(a,b)  	声明一个链表并初始化为区间[a,b]中的元素,a、b是迭代器
1.2.1.2 基本操作
增:
	1、l.insert() 					插入一个元素到list中
				auto pos = ++L.begin();
				// 在pos前插入值为4的元素
				L.insert(pos, 4);
				// 在pos前插入5个值为5的元素
				L.insert(pos, 5, 5);
				// 在pos前插入[v.begin(), v.end)区间中的元素
				L.insert(pos, v.begin(), v.end());
	2、l.push_back() 				在list的末尾添加一个元素 
			l.push_back(i);
	3、l.push_front() 				在list的头部添加一个元素
			L.push_front(i);
	
删:
	1、l.clear() 					清空list的所有元素
			// 将l2中的元素清空
			l2.clear();
	2、l.erase() 					删除一个元素
			// 删除pos位置上的元素
			L.erase(pos);
			// 删除list中[begin, end)区间中的元素,即删除list中的所有元素
			L.erase(L.begin(), L.end());
	3、l.erase(l.begin(),l.end())  将l从begin()end()之间的元素删除。
	4、l.pop_back() 				删除最后一个元素 
	5、l.pop_front() 				删除第一个元素
	6、l.remove() 					从list删除指定元素 
			l.remove(x);//删除与x相等的元素
	7、l.remove_if() 				按指定条件删除元素
			l.remove_if(func);  //func是函数名,容器元素依次传进去,删除返回true的元素
			bool func(const string& value){
 	    		if(value == "last")
   		    		 return true;
		    	return false;
			}
	8、l.unique() 					删除list中重复的元素
	
改:
	1、l.resize() 					改变list的大小
			l.resize(2);
			l.resize(10, b);
	2、l.reverse() 				把list的元素倒转
	
查:
	1、l.front() 					返回第一个元素 
	2、l.back() 					返回最后一个元素
	3、l.empty() 					若list是空的则返回true,否则返回false
	4、l.max_size() 			返回list能容纳的最大元素数量 
	5、l.size() 					返回list中的元素个数

其他操作:
	1、l.assign() 					给list赋值
			l.assign(5,100);	//将100赋值给前5个元素
			l2.assign(l1.begin(), l1.end());		//将l1的元素赋值给l2
			int arr []={10, 20, 30, 40};
			list3.assign(arr, arr+4);
	2、l.get_allocator() 			返回list的配置器
	3、l.merge() 					合并两个list
			list1.merge(list2)//将l2中的元素合并到l1中,并且l1和l2必须已经排号顺序,将一个有序list容器加入另一个有序list容器中,且两个list容器必须都为逆序或顺序,这是很容易不注意导致报错的主要原因。
	4、l.sort() 					给list排序
			l.sort();		//默认升序排列
			l.sort([](int a, int b) {//降序排列
				return a > b;
			});
	5、l.splice() 					合并两个list
			list1.splice(it1, list2)//将list2中的所有元素拷贝到list1中。在list1中的起始位置是it1.复制结束后,list2将为空。
			list1.splice(it1, list2, it2)//将list2中的元素,从it2开始,剪切到list1的it1起始的地方
			list1.splice(it1, list2, it2begin, it2end)
	6、l.swap() 					交换两个list
			// 交换l1和l2中的元素
			l1.swap(l2);
迭代器:
	1begin()/end():返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器
			list<int>::iterator it = l.begin()
	2rbegin()/rend():返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的 reverse_iterator,即begin位置;	
			list<int>::reverse_iterator it = l.rbegin()
	3、l.begin() 					返回指向第一个元素的迭代器 
	4、l.end() 					返回末尾的迭代器
	5、l.rbegin() 					返回指向第一个元素的逆向迭代器 
	6、l.rend() 					指向list末尾的逆向迭代器

1.3 queue

std::queue 容器是一种先进先出(First In First Out, FIFO)的数据结构,且有两个出口。
在这里插入图片描述

1.3.1 queue基本操作

1.3.1.0 queue头文件
#include <queue>
1.3.1.1 queue定义与声明
1、queue<int>q1;		//默认初始化一个空的整数队列
2、queue<int>q2 = {12345};//使用初始化列表初始化队列
3、queue<int>q3(q1)//使用q1来初始化q3
4、queue<std::vector<int>> q; // 初始化一个存储vector的队列  
	q.emplace(1, 2, 3); // 直接在队列中构造一个vector<int>{1, 2, 3}  
5、queue<int> q; // 默认初始化一个空的整数队列  
   q.push(1); // 添加元素1到队列尾部  
6、queue<int> q2(move(q1)); // 使用q1来移动初始化q2,现在q1是空的,q2是{1, 2, 3}  
1.2.1.2 基本操作
1push()	//在队尾插入一个元素
		queue <string> q;
		q.push("first");
2pop()	//删除队列第一个元素
		q.pop();
3size()	//返回队列中元素个数
4empty()	//如果队列空则返回true
5ftont()	//返回队列中的第一个元素
6back()	//返回队列中最后一个元素
7swap()  //将当前queue中的元素与参数queue中的元素交换
		q2.swap(q1);
8emplace():用传给 emplace() 的参数调用 T 的构造函数,在 queue 的尾部生成对象。
		myqueue5.emplace(45);
9、运算符 = != > >= < <=
		// [==]当两个队列front()内容一致,返回true
		// [!=]当两个队列元素front()不相等,返回true
		// [>]左边队列的front()的元素大于右边队列pop的元素,则返回true.
10、迭代器没有意义,只允许队首出队、队尾入队

1.3.2 双端队列deque

  • deque(全称为"double-ended queue",双端队列),它是一种数据结构,允许在队列的两端进行插入和删除操作。
  • deque的特点是可以在队列的两端进行元素的操作,并且可以高效地在队列的任意位置进行元素的插入和删除操作。
  • deque几乎涵盖了queue(队列)、stack(堆栈)、vector(向量 )等的全部用法,功能非常的强大。
    在这里插入图片描述
    deque 通常实现为一组独立区块,第一区块朝某方向扩展,最末区块朝另一方向扩展
    在这里插入图片描述
1.3.1.0 queue头文件
#include <deque>
1.3.1.1 queue定义与声明
//deque的定义 
deque<int>d1; //定义一个储存数据类型为int的双端队列d1 
deque<double>d2; //定义一个储存数据类型为double的双端队列d2 
deque<string>d3; //定义一个储存数据类型为string的双端队列d3 
deque<结构体类型>d4; //定义一个储存数据类型为结构体类型的双端队列d4 
deque<int> d5[N]; //定义一个储存数据类型为int的双端队列数组d5 
deque<double>d6[N]; //定义一个储存数据类型为double的双端队列数组d6 
1.2.1.2 基本操作
1push_back()//在队列的尾部插入元素。
2emplace_back()//与push_back()的作用一样 
3push_front()//在队列的头部插入元素。
4emplace_front()//与push_front()的作用一样 
5pop_back()//删除队列尾部的元素。
6pop_front()//删除队列头部的元素。
7back()//返回队列尾部元素的引用。
8front()//返回队列头部元素的引用。
9clear()//清空队列中的所有元素。
10empty()//判断队列是否为空。
11size()//返回队列中元素的个数。
12resize()//重置元素数量
		d.resize(num)	//将元素数量改为 num(如果 size() 变大,多出来的新元素都需以 default 构造函数完成初始化)
		d.resize(num, elem)	 //将元素数量改为 num(如果 size() 变大,多出来的新元素都是 elem 的拷贝)
12begin()//返回头位置的迭代器
13end()//返回尾+1位置的迭代器
14rbegin()//返回逆头位置的迭代器 
15rend()//返回逆尾-1位置的迭代器 
16insert()//在指定位置插入元素 
		//(或返回 pos———如果没有新元素的话;始自C++11)
		d.insert(pos, n, elem)//在iterator 位置 pos 之前方插入 n 个 elem 拷贝,并返回第一个新元素的位置
		d.insert(pos, beg, end)	在 iterator 位置 pos 之前方插入区间 [beg, end) 内所有元素的一份拷贝,并返回第一个新元素的位置
		d.insert(pos, initlist)	在 iterator 位置 pos 之前方插入初值列 initlist 内所有元素的一份拷贝,并返回第一个新元素的位置
17erase()//在指定位置删除元素 
		d.erase(pos)	移除 iterator 位置 pos 上的元素,返回下一元素的位置
		d.erase(beg, end)	移除 [beg, end) 区间内的所有元素,返回下一元素的位置
18、通过迭代器iterator遍历
			for(it=d.begin();it!=d.end();it++)
			{
				cout<<*it<<" ";
			}
19、通过下标遍历
			for(int i=0;i<d.size();i++)
			{
					cout<<d[i]<<" ";
			}
20、通过foreach遍历
			for(int it:d)
			{
					cout<<it<<" ";
			}
21、运算符
		c1 == c2	返回 c1 是否等于 c2(对每个元素调用==)
		c1 != c2	返回 c1 是否不等于 c2(相当于!(c1==c2))
		c1 < c2	返回 c1 是否小于 c2
		c1 > c2	返回 c1 是否大于 c2(相当于c2<c1)
		c1 <= c2	返回 c1 是否小于等于 c2(相当于!(c2<c1))
		c1 >= c2	返回 c1 是否大于等于 c2(相当于! (c1<c2))
22、 d1.swap(d2)	置换 d1 和 d2 的数据  swap(c1, c2)	置换 c1 和 c2 的数据

1.3.3 优先队列 priority_queue

  • 优先队列是一种容器适配器,采用了堆这样的数据结构,保证了第一个元素总是整个优先队列中最大的(或最小的)元素
  • 优先队列默认使用vector作为底层存储数据的容器,在vector上使用了堆算法将vector中的元素构造成堆的结构,所以其实我们就可以把它当作堆,凡是需要用堆的位置,都可以考虑优先队列。(所以需要先学习堆)
  • 默认为大堆
  • 不允许随机访问,只能访问队列首部元素,也只能对首部元素进行出队
    在这里插入图片描述
1.3.3.0 queue头文件
#include <queue>
1.3.3.1 queue定义与声明
priority_queue<int> q;//储存int型数据 
priority_queue<double> q;//储存double型数据 
priority_queue<string> q;//储存string型数据 
priority_queue<结构体名> q;//储存结构体或者类 
1.3.3.2 基本操作
empty() 如果优先队列为空,则返回真 
pop() 删除第一个元素 
push() 加入一个元素 
size() 返回优先队列中拥有的元素的个数 
top() 返回优先队列中有最高优先级的元素 

  • 快速切换大小顶堆定义
less<储存的数据类型> 即使用大顶堆
greater<储存的数据类型> 即是用小顶堆
priority_queue<储存的类型,vector<储存的类型>,顶堆的类型> 容器名

//使用大顶堆
priority_queue<int,vector<int>,less<int>> q;//储存int型数据 
priority_queue<double,vector<double>,less<double>> q;//储存double型数据 
priority_queue<string,vector<string>,less<string>> q;//储存string型数据 
priority_queue<结构体名,vector<结构体名>,less<结构体名>> q;//储存结构体或者类 

//使用小顶堆
priority_queue<int,vector<int>,greater<int>> q;//储存int型数据
priority_queue<double,vector<double>,greater<double>> q;//储存double型数据
priority_queue<string,vector<string>,greater<string>> q;//储存string型数据
priority_queue<结构体名,vector<结构体名>,greater<结构体名>> q;//储存结构体或者类 
  • 使用结构体重载运算符定义:
新建一个结构体,通过重载运算符改变顶堆的排序,这里是拓展用法,也是必学用法,因为自己写的结构体是没有比较大小功能的,当然也可以在原本的结构体里面重载运算符
struct test{//定义一个结构体test 
		int val;
		test(int v){//构造函数 
			this->val=v;
		}
		bool operator > (const test t)const{//重载运算符> 
			return val>t.val;
		}
		bool operator < (const test t)const{//重载运算符
			return val<t.val;
		}
};
  • 自定义结构体重载括号运算符
    很多时候,我们不应该重载结构体的运算符。像数据结构vector,它有它的基本运算方法,我们不应该重载它的运算符。
    此时,我们就应该自定义结构体替代less<>和greater<>,通过重载括号符就可以更改比较规则
struct cmp{
	bool operator () (const test t1,const test t2)const{//重载括号运算符
		return t1.val<t2.val;//小于号是大根堆,大于号是小根堆 
	}
};
priority_queue<test,vector<test>,cmp> q;//自定义一个优先级队列q 

1.4 stack

  • stack 是一种 先进后出(First In Last Out,FILO)的数据结构,它只有一个出口
  • 栈中只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为 (遍历:非质变算法,在运算期间,不改变容器中的元素)
  • 栈中进入数据称为 — 入栈 push
  • 栈中弹出数据称为 — 出栈 pop
    - 生活中的栈: 子弹夹,先装进弹夹的子弹,最后被打出来
    在这里插入图片描述

1.4.1 stack基本操作

1.4.1.0 stack头文件

底层实现是双向链表

#include <stack>
1.4.1.1 stack定义与声明
// stack 采用模板类实现, stack 对象的默认构造形式
stack<T> stk;
		1、stack<int> myStack;
		2、std::stack<int> myStack; 
    	// 使用push方法初始化stack  
    	myStack.push(1);  
    3、std::vector<int> myVector = {1, 2, 3, 4, 5};  
    	std::stack<int> myStack(myVector.begin(), myVector.end());  
//拷贝构造函数
stack(const stack &stk); 
1.4.1.2 基本操作
1top():返回一个栈顶元素的引用,类型为 T&。如果栈为空,不能用该函数访问,否则报错。
2push(const T& obj):可以将对象副本压入栈顶。这是通过调用底层容器的 push_back() 函数完成的。
3push(T&& obj):以移动对象的方式将对象压入栈顶。这是通过调用底层容器的有右值引用参数的 push_back() 函数完成的。
4pop():弹出栈顶元素。
5size():返回栈中元素的个数。
6empty():在栈中没有元素的情况下返回 true7emplace():用传入的参数调用构造函数,在栈顶生成对象。
8swap(stack<T> & other_stack):将当前栈中的元素和参数中的元素交换。参数所包含元素的类型必须和当前栈的相同。对于 stack 对象有一个特例化的全局函数 swap() 可以使用。

1.5 map

  • map是C++中STL中的一个关联容器,以键值对来存储数据,数据类型自己定义。它的内部数据结构是红黑树,所有它是有默认排列顺序
  • 每一对中的第一个值称之为关键字(key),每个关键字只能在map中出现一次;第二个称之为该关键字的对应值
    • 第一个参数是键的数据类型
    • 第二个参数是值的数据类型
    • 第三个参数是排序规则,不写的话就按照默认的排序规则,也就是按照键的升序
    • 举例:map<int,int>mp; 定义了一个叫mp的map类型,并且键值都是int类型
      在这里插入图片描述

1.5.1 map基本操作

1.5.1.0 map头文件
#inlcude <map>
1.5.1.1 map定义与声明
1、map<string, int> myMap;

2、map<string, int> myMap = {  
        {"apple", 1},  
        {"banana", 2},  
        {"cherry", 3}  
};  
3、insert
map<string, int> myMap;  
myMap.insert(make_pair("apple", 1));  
myMap.insert(pair<string, int>("banana", 2));  
myMap.insert({"cherry", 3}); // C++11及以后版本支持这种写法  
4、复制构造函数
map<string, int> anotherMap = {  
        {"apple", 1},  
        {"banana", 2}  
};  
map<string, int> myMap(anotherMap); // 通过复制构造函数初始化  
5、赋值构造函数
map<string, int> anotherMap = {  
        {"apple", 1},  
        {"banana", 2}  
};  
map<string, int> myMap;  
myMap = anotherMap; // 通过赋值运算符初始化 

6、默认升序
 map<int, int>m;
7、改为降序排列
map<int, int, compare>m2;//注意这个有谓词的map容器的打印是要单独写的
class compare//一个名叫compare的类
{
public://在public下的作用域在类内类外都可以进行访问
	bool operator()(int m, int n)const//注意要在后面加const
	{
		return m > n;//降序排列返回的就两个值中的较大值
	}
};
1.5.1.2 基本操作
###############插入操作insert###################
1、使用[ ]进行单个插入
map<int, string> ID_Name;
// 如果已经存在键值2015,则会作赋值修改操作,如果没有则插入
ID_Name[2015] = "Tom";
2、使用insert进行单个和多个插入
// 插入单个值
mymap.insert(pair<char, int>('a', 100));
//返回插入位置以及是否插入成功
pair<map<char, int>::iterator, bool> ret;
ret = mymap.insert(pair<char, int>('z', 500));insert函数返回一个pair,其中first成员是指向插入元素的迭代器,second成员是一个布尔值,表示是否成功插入(如果键已存在,则插入失败,second为false)。
//指定位置插入
map<char, int>::iterator it = mymap.begin();
mymap.insert(it, pair<char, int>('b', 300));  //效率更高,插入操作不会改变已存在元素的顺序,但你可以指定一个迭代器作为插入位置的提示。这可以提高插入的效率,尤其是在插入大量连续元素时。注意,这只是一个提示,map仍然会保持其排序属性
//范围多值插入
map<char, int> anothermap;
anothermap.insert(mymap.begin(), mymap.find('c'));//anothermap将插入mymap中从begin()到find('c')(不包括find('c')指向的元素)范围内的所有元素。
// 列表形式插入
anothermap.insert({ { 'd', 100 }, {'e', 200} });//使用初始化列表语法来一次性插入多个元素
###############取值操作###################
map<int, string> ID_Name;
1//ID_Name中没有关键字2016,使用[]取值会导致插入
//因此,下面语句不会报错,但打印结果为空
cout<<ID_Name[2016].c_str()<<endl;
2//使用at会进行关键字检查,因此下面语句会报错
ID_Name.at(2016) = "Bob";
##############容量操作###################
bool empty();// 查询map是否为空
size_t size();// 查询map中键值对的数量
size_t max_size();// 查询map所能包含的最大键值对数量,和系统和应用库有关。// 此外,这并不意味着用户一定可以存这么多,很可能还没达到就已经开辟内存失败了
size_t count( const Key& key ) const;  查询关键字为key的元素的个数,在map里结果非0即1

##############删除操作操作###################
iterator erase( iterator pos )// 删除迭代器指向位置的键值对,并返回一个指向下一元素的迭代器
iterator erase( const_iterator first, const_iterator last );// 删除一定范围内的元素,并返回一个指向下一元素的迭代器
size_t erase( const key_type& key );// 根据Key来进行删除, 返回删除的元素数量,在map里结果非0即1
void clear();// 清空map,清空后的size为0
##############交换操作###################
void swap( map& other );// 就是两个map的内容互换
##############查找操作###################
// 关键字查询,找到则返回指向该关键字的迭代器,否则返回指向end的迭代器
// 根据map的类型,返回的迭代器为 iterator 或者 const_iterator
iterator find (const key_type& k);
const_iterator find (const key_type& k) const;
##############操作符操作###################
operator: == != < <= > >= 			注意 对于==运算符, 只有键值对以及顺序完全相等才算成立。

##############迭代器操作###################
1、共有八个获取迭代器的函数:* begin, end, rbegin,rend* 以及对应的 * cbegin, cend, crbegin,crend*2、二者的区别在于,后者一定返回 const_iterator,而前者则根据map的类型返回iterator 或者 const_iterator。const情况下,不允许对值进行修改。如下面代码所示:
map<int,int>::iterator it;
map<int,int> mmap;
const map<int,int> const_mmap;

it = mmap.begin(); //iterator
mmap.cbegin(); //const_iterator

const_mmap.begin(); //const_iterator
const_mmap.cbegin(); //const_iterator

1.6 unordered_map

  • unordered_map是一个将key和value关联起来的容器,它可以高效的根据单个key值查找对应的value。
  • key值应该是唯一的,key和value的数据类型可以不相同。
  • unordered_map存储元素时是没有顺序的,只是根据key的哈希值,将元素存在指定位置,所以根据key查找单个value时非常高效,平均可以在常数时间内完成。
  • unordered_map查询单个key的时候效率比map高,但是要查询某一范围内的key值时比map效率低。
  • 可以使用[]操作符来访问key值对应的value值

1.6.0 map和unordered_map区别

  • 运行效率方面:unordered_map最高,而map效率较低但 提供了稳定效率和有序的序列。
  • 占用内存方面:map内存占用略低,unordered_map内存占用略高,而且是线性成比例的。
  • map: map内部实现了一个红黑树,该结构具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素,因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行这样的操作,故红黑树的效率决定了map的效率。
  • unordered_map: unordered_map内部实现了一个哈希表,因此其元素的排列顺序是杂乱的,无序的

map
优点有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作。
红黑树,内部实现一个红黑书使得map的很多操作在lgn的时间复杂度下就可以实现,因此效率非常的高。
缺点空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点,孩子节点以及红/黑性质,使得每一个节点都占用大量的空间
适用处:对于那些有顺序要求的问题,用map会更高效一些。
unordered_map
优点:内部实现了哈希表加粗样式,因此其查找速度是常量级别的
缺点:哈希表的建立比较耗费时间
适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map

1.6.1 unordered_map基本操作

1.6.1.0 unordered_map头文件
#inlcude <map>
1.6.1.1 unordered_map定义与声明
unordered_map<int, string> umap;
16.1.2 基本操作
unordered_map与map的用法基本一直,最大的区别在于:
map的key是有序的,而unordered_map的key为无序
void f2() {
    map<int, string> commap;
    unordered_map<int, string> umap;
    commap[1]="a"; commap[3]="c"; commap[2]="b"; commap[4]="d";
    umap[1]="aa"; umap[3]="cc"; umap[4]="dd"; umap[2]="bb";
    for(auto node: commap) {
        cout<<node.first<<": "<<node.second<<endl;
    }
    for(auto node: umap) {
        cout<<node.first<<": "<<node.second<<endl;
    }
}
1: a
2: b
3: c
4: d

2: bb
4: dd
3: cc
1: aa

1.7 set

  • set关联式容器

  • 集合(set)是一个内部自动有序且不含重复元素的容器,默认按升序排列,它可以在需要删除重复元素的情况下大放异彩,节省时间,减少思维量。

  • set 就是关键字的简单集合,当只是想知道一个值是否存在时,set 是最有用的。set 内部采用的是一种非常高效的平衡检索二叉树:红黑树(Red-Black Tree),也称为 RB 树,RB 树的统计性能要好于一般平衡二叉树。在 set 中每个元素的值都唯一,而且系统能根据元素的值自动进行排序,set 中元素的值不能直接被改变。

    • map 中的元素是一些关键字 — 值(key–value)对:关键字起到索引的作用,值则表示与索引相关联的数据。
    • 在 set 中每个元素只包含一个关键字,不存储特定值关联:set 支持高效的关键字查询操作 —— 检查一个给定关键字是否在 set 中。
  • 标准库提供 set 关联容器分为:

    • 按关键字有序保存元素:set(关键字即值,即只保存关键字的容器)、multiset(关键字可重复出现的 set);
    • 无序集合:unordered_set(用哈希函数组织的 set)、unordered_multiset(用哈希函数组织的 set,关键字可以重复出现)。

1.7.1 set基本操作

1.7.1.0 set头文件
#include <set>
1.7.1.1 set定义与声明
    1、set<int> name;
    set<double> name;
    set<char> name;
    set<struct node> name;
    set<set<int>> name;
    set<int> arr[10];
    2、set<int> anotherSet = {1, 2, 3};  
    3、set<int> mySet(anotherSet); // 通过复制构造函数初始化  
    4、std::set<int> mySet;  
    	mySet = anotherSet; // 通过赋值运算符初始化  
1.7.1.2 基本操作
0=	直接赋值
1、 set 不提供下标运算符(operator[])来访问其元素。相反,你只能使用迭代器(iterator)来遍历和访问 std::set 中的元素。
set<int>::iterator it;//set 只能通过迭代器(iterator)访问:

2find()find(value) 返回 set 中 value 所对应的迭代器,即 value 的指针(地址),如果没找到则返回 end()
3、删除单个元素:
  st.erase(it),其中 it 为所需要删除元素的迭代器。时间复杂度为 O(1),可以结合 find() 函数来使用。
  st.erase(value),其中 value 为所需要删除元素的值。时间复杂度为 O(logN),N 为 set 内的元素个数。
4、删除一个区间内的所有元素:
    st.erase(iteratorBegin, iteratorEnd),其中 iteratorBegin 为所需要删除区间的起始迭代器, iteratorEnd 为所需要删除区间的结束迭代器的下一个地址,即取 [iteratorBegin, iteratorEnd)
5equal_range():返回一对迭代器,分别表示第一个大于或等于给定关键值的元素和第一个大于给定关键值的元素。这个返回值是一个 pair 类型,第一个是键的 lower_bound,第二个是键的 upper_bound。如果这一对定位器中哪个返回失败,则返回 end() 
	      pr = s.equal_range(3);
        cout << "第一个大于等于3的数是:"<< *pr.first << endl;
        cout << "第一个大于3的数是:"<< *pr.second <<endl;
    begin();            // 返回指向第一个元素的迭代器
    end();              // 返回指向最后一个元素的后一个位置的迭代器
    clear();            // 清除所有元素
    count();            // 返回某个值元素的个数,用于判断set中是否有该元素
    size();             // 返回集合中元素的数目
    empty();            // 如果集合为空,返回true,否则返回false
    equal_range();      // 返回集合中与给定值相等的上下限的两个迭代器
    insert();           // 在集合中插入元素 
    		set<int> s;//定义 
				s.insert(1);//插入元素1
    erase();            // 删除集合中的元素
    find();             // 返回一个指向被查找到元素的迭代器
    get_allocator();    // 返回集合的分配器
    upper_bound();      // 返回大于某个值元素的迭代器
    lower_bound();      // 返回指向大于(或等于)某值的第一个元素的迭代器
    key_comp();         // 返回一个用于元素键值比较的函数
    value_comp();       // 返回一个用于比较元素间的值的函数
    max_size();         // 返回集合能容纳的元素的最大限值
    rbegin();           // 返回set反转后的开始指针(即原来的end-1)
    rend();             // 返回set反转后的结束指针(即原来的begin-1)
    swap();             // 交换两个集合变量

1.8 unordered_set

  • unordered_set 容器,可直译为“无序 set 容器”,即 unordered_set 容器和 set 容器很像,唯一的区别就在于 set 容器会自行对存储的数据进行排序,而 unordered_set 容器不会
    • 不再以键值对的形式存储数据,而是直接存储数据的值;
    • 容器内部存储的各个元素的值都互不相等,且不能被修改。
    • 不会对内部存储的数据进行排序(这和该容器底层采用哈希表结构存储数据有关);

1.7.1 unordered_set基本操作

1.7.1.0 unordered_set头文件
#include <unordered_set>
1.7.1.1 unordered_set定义与声明
    1、unordered_set<int> name;
    unordered_set<double> name;
    unordered_set<char> name;
    unordered_set<struct node> name;
    unordered_set<unordered_set<int>> name;
    unordered_set<int> arr[10];
    2、unordered_set<int> anotherSet = {1, 2, 3};  
    3、unordered_set<int> mySet(anotherSet); // 通过复制构造函数初始化  
    4、unordered_set<int> mySet;  
    	mySet = anotherSet; // 通过赋值运算符初始化  
    5、myUnorderedSet.insert(1); 
1.7.1.2 基本操作
基本操作与set相同

三、常用函数库

3.1 优先级队列

priority_queue<TYPE> q;
  • 用来选取最小元素
    • q.push()
    • q.top()
    • q.pop()
  • 对载入数据进行自动排序,最小的排在顶部

3.2 链表结构体

//Definition for singly-linked list.
struct ListNode {
    int val;
    ListNode *next;
    ListNode() : val(0), next(nullptr) {}
    ListNode(int x) : val(x), next(nullptr) {}
    ListNode(int x, ListNode *next) : val(x), next(next) {}
};

3.3 链表的插入删除操作

3.2 二叉树结构体

 //Definition for a binary tree node.
 struct TreeNode {
     int val;
     TreeNode *left;
     TreeNode *right;
     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 };

1、贪心算法

1、数组重排
2、按照题目总结规律,局部最优,从头按规则搜索,得出最优解

2 动态规划

  • 动态规划问题的一般形式就是求最值
  • 求解动态规划的核心问题是穷举
  • 重叠子问题最优子结构状态转移方程就是动态规划三要素

1、 明确 base case
2、明确「状态」
3、明确「选择」
4、 定义 dp 数组/函数的含义

# 自顶向下递归的动态规划
def dp(状态1, 状态2, ...):
    for 选择 in 所有可能的选择:
        # 此时的状态已经因为做了选择而改变
        result = 求最值(result, dp(状态1, 状态2, ...))
    return result

# 自底向上迭代的动态规划
# 初始化 base case
dp[0][0][...] = base case
# 进行状态转移
for 状态1 in 状态1的所有取值:
    for 状态2 in 状态2的所有取值:
        for ...
            dp[状态1][状态2][...] = 求最值(选择1,选择2...)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/495168.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

详解智慧路灯杆网关的集中供电能力

智慧路灯杆网关是智慧杆物联网系统中不可或缺的设备。智慧杆网关不仅可以作为杆载设备与云平台、设备与设备之间的桥梁&#xff0c;促进数据的无缝传输&#xff0c;而且还能提供高效的能源管理和供电功能。 BMG8200系列交流型智慧路灯杆网关就集成了强大的供电能力&#xff0c;…

数字信号转模拟信号 DA变换 高精度PWM脉宽调制信号100Hz PWM/5KHz PWM /10KHz PWM转4-20mA/0-10V/1-5V/0-5V

主要特性: >>精度等级&#xff1a;0.1级。产品出厂前已检验校正&#xff0c;用户可以直接使用 >>辅助电源&#xff1a;8-32V 宽范围供电 >>PWM脉宽调制信号输入: 1Hz~10KHz >>输出标准信号&#xff1a;0-5V/0-10V/1-5V,0-10mA/0-20mA/4-20mA等&…

如何确保六西格玛培训效果最大化?

近年来&#xff0c;如何确保六西格玛培训的效果&#xff0c;使其真正转化为企业的生产力&#xff0c;成为许多管理者关注的焦点。本文&#xff0c;天行健Six Sigma咨询公司将分享如何确保六西格玛培训效果最大化&#xff0c;帮助企业在实施六西格玛管理的过程中取得更好的成效。…

Java基础-多线程基础

文章目录 1.线程相关概念1.程序2.进程3.线程4.单线程5.多线程6.并发7.并行查看当前电脑cpu数量 2.线程基本使用1.线程类图2.继承Thread创建线程细节说明代码实例 3.实现Runnable来创建线程&#xff08;包括静态代理演示&#xff09;代码实例 3.多线程机制简要介绍代码实例为什么…

qtxlsx 学习

简介&#xff1a; QXlsx是一个可以读写Excel文件的库。不依赖office以及wps组件&#xff0c;可以在Qt5支持的任何平台上使用。 QXlsx和QAxObject 比较 QAxObject使用需要系统中安装了offie或wps&#xff0c;这种方法不推荐使用&#xff1b; 因为如果安装了wps&#xff0c;可…

puzzle(1122)连线迷宫

目录 一&#xff0c;连线迷宫-经典模式 1&#xff0c;规则 2&#xff0c;策略 3&#xff0c;调整的局部性 4&#xff0c;八连通端点的线条合并 taptap小游戏 迷宫解谜 连线迷宫模式 一&#xff0c;连线迷宫-经典模式 1&#xff0c;规则 2&#xff0c;策略 分2步&#x…

Kali远程操纵win7

一.准备 1.介绍 攻击方&#xff1a;kali IPV4:192.168.92.133 被攻击方&#xff1a;win7 IPV4:192.168.92.130 2.使用永恒之蓝漏洞 (1.使用root权限 (2.进入msfconsole (3.添加rhosts (4.run进行一下 二.进行远程操作 1.获取用户名和密码 在cmd5查询 2.获取syste…

Windows下如何查看端口被谁占用

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 开始时经常遇到这种…

LVS负载均衡-DR模式配置

LVS&#xff1a;Linux virtual server ,即Linux虚拟服务器 LVS自身是一个负载均衡器&#xff08;Director&#xff09;&#xff0c;不直接处理请求&#xff0c;而是将请求转发至位于它后端的真实服务器real server上。 LVS是四层&#xff08;传输层 tcp/udp&#xff09;负载均衡…

SpringBoot SpringMVC (详解)

6. SpringBoot Spring 的诞⽣是为了简化 Java 程序的开发的&#xff0c;⽽ Spring Boot 是为了快速开发 Spring 程序开发而诞生的。 Spring Boot 的优点&#xff1a; 快速集成框架&#xff0c;Spring Boot 提供了启动添加依赖的功能&#xff0c;⽤于秒级集成各种框架。内置运⾏…

来了!小学生Python创意编程(视频教学版)

目录 写在前面 推荐图书 推荐理由 写在最后 写在前面 在最好的年纪&#xff0c;一起来学Python吧&#xff01;本期博主给大家推荐一本适合小学生阅读的书籍&#xff0c;一起来看看吧~ 推荐图书 小学生Python创意编程&#xff08;视频教学版&#xff09; 直达链接&#x…

uniapp输入框事件(防抖)

一、描述 在输入框输入内容或者说输入关键词的时候&#xff0c;往往都要进行做防抖处理。如果不做防抖&#xff0c;你输入什么&#xff0c;动态绑定的数据就会保持一致。这样不好吗&#xff0c;同步获取。有个业务场景&#xff0c;如果是搜索框&#xff0c;你每次一个字符&…

【差分约束+并查集】第十三届蓝桥杯省赛C++ A组 Java A组/研究生组《推导部分和》(C++)

【题目描述】 【输入格式】 【输出格式】 【数据范围】 【输入样例】 5 3 3 1 5 15 4 5 9 2 3 5 1 5 1 3 1 2 【输出样例】 15 6 UNKNOWN 【思路】 题解来源&#xff1a;AcWing 4651. $\Huge\color{gold}{推导部分和}$ - AcWing 【代码】 #include<bits/stdc.h> #define…

基于深度学习的心律异常分类算法

基于深度学习的心律异常分类系统——算法设计 第一章 研究背景算法流程本文研究内容 第二章 心电信号分类理论基础心电信号产生机理MIT-BIH 心律失常数据库 第三章 心电信号预处理心电信号噪声来源与特点基线漂移工频干扰肌电干扰 心电信号读取与加噪基于小波阈值去噪技术的应用…

mamba的学习记录

最近新出了一种很火的架构mamba&#xff0c;听说吊打transformer&#xff0c;特此学习一下&#xff0c;总结一下学习的内容。 state-spaces/mamba (github.com)3个月8Kstar&#xff0c;确实有点受欢迎。 目录 1.先验 RNN​ LSTM ​2.mamba State Space Models​ Selecti…

两个有序序列的中位数(全网首篇递归、分治解决)

题目描述 已知有两个等长非降序序列 S 1 S_1 S1​和 S 2 S_2 S2​。先将 S 1 S_1 S1​和 S 2 S_2 S2​ 合并为 S 3 S_3 S3​ &#xff0c;求 S 3 S_3 S3​的中位数。 输入描述 第一行&#xff0c;序列 S 1 S_1 S1​ 和 S 2 S_2 S2​ 的长度 N N N , 第二行&#xff…

Uibot6.0 (RPA财务机器人师资培训第4天 )批量开票机器人案例实战

类似于小北之前发布的一篇博客&#xff08;不能说很像&#xff0c;只能说是一模一样&#xff09; Uibot (RPA设计软件&#xff09;财务会计Web应用自动化(批量开票机器人&#xff09;-CSDN博客https://blog.csdn.net/Zhiyilang/article/details/136782171?spm1001.2014.3001.…

JAVA面试大全之并发篇

目录 1、并发基础 1.1、多线程的出现是要解决什么问题的? 本质什么? 1.2、Java是怎么解决并发问题的? 1.3、线程安全有哪些实现思路? 1.4、如何理解并发和并行的区别? 1.5、线程有哪几种状态? 分别说明从一种状态到另一种状态转变有哪些方式? 1.6、通常线程有哪几…

【Android 源码】Android源码下载指南

文章目录 前言安装Repo初始化Repo选择分支没有梯子替换为清华源 有梯子 下载源码下载开始参考 前言 这是关于Android源码下载的过程记录。 环境&#xff1a;Windows上通过VMware安装的Ubuntu系统 安装Repo 创建Repo文件目录 mkdir ~/bin PATH~/bin:$PATH下载Repo工具&#…

Elastic Search 8.13: 为开发者简化嵌入和排名

作者&#xff1a;来自 Elastic Alvin Richards, Ranjana Devaji Elasticsearch 8.13 扩展了能力&#xff0c;使开发者能够利用人工智能和机器学习模型创建快速和卓越的搜索体验。与 Apache Lucene 9.10 集成&#xff0c;测量向量搜索性能在基准测试中超过 2 倍&#xff0c;扩展…