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

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

  • 一、常用容器
    • 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);//删除元素2vector<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个元素的链表并全部初始化为0list<int> l(n, m)  	声明一个含n个元素的链表并全部初始化为mlist<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,否则返回false4、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的元素赋值给l2int arr []={10, 20, 30, 40};list3.assign(arr, arr+4);2、l.get_allocator() 			返回list的配置器3、l.merge() 					合并两个listlist1.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() 					合并两个listlist1.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 是否小于 c2c1 > 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_iteratorconst_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: d2: 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,否则返回falseequal_range();      // 返回集合中与给定值相等的上下限的两个迭代器insert();           // 在集合中插入元素 set<int> s;//定义 s.insert(1);//插入元素1erase();            // 删除集合中的元素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...)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32 | PWM脉冲宽度调制(第五天按键中断,控制电机正/反转、加速、减速、暂停与继续源码解析)

​ STM32 | PWM脉冲宽度调制(第五天)STM32 | PWM脉冲宽度调制(第五天呼吸灯源码解析)STM32 | PWM脉冲宽度调制(第五天电机速度控制源码解析)PWM 技术在以下其他机器学习领域和应用中也可以发挥作用: 自然语言处理 (NLP):调节文本生成模型(例如 GPT-3)的输出长度和多样…

NFT-前端开发(一)

使用 在我们想要保存项目的目录下打开终端运行npx create-react-app test2命令初始化&#xff0c;test2是我们的项目名字&#xff0c;可以自己去更改。 初始化完成后&#xff0c;我们目录下就会多出一个test2文件夹 &#xff0c;然后我们在vscode中打开该文件夹 然后我们打开j…

Java8之接口默认方法

Java8之接口默认方法 一、介绍二、代码1、接口2、实现类3、测试代码4、效果 一、介绍 在Java8中&#xff0c;允许为接口方法提供一个默认的实现。必须用default修饰符标记这样一个方法。默认方法也可以调用其他方法 二、代码 1、接口 public interface PersonService {void…

代码随想录算法训练营第二十五天| 回溯算法理论基础、LeetCode77.组合

一、216.组合总和III 题目链接/文章讲解/视频讲解&#xff1a; https://programmercarl.com/0216.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8CIII.html 状态&#xff1a;已解决 1.思路 做过77题&#xff08;上篇博客&#xff09;后&#xff0c;这道题也就不难了&#xff0c;无非是多…

python--sys模块,time模块

1&#xff1a;sys模块 time.struct_time 实现时间转换 >>> import sys >>> dir(sys) getallocatedblocks, getdefaultencoding, getfilesystemencodeerrors, getfilesystemencoding, getprofile, getrecursionlimit, getrefcount, getsize…

python中pow()函数的使用

在Python中&#xff0c;pow() 函数用于计算指定数字的幂。它的语法如下&#xff1a; pow(x, y) 这个函数返回 x 的 y 次方。相当于 x**y。 pow() 函数也可以接受一个可选的第三个参数&#xff0c;用于指定一个取模值&#xff0c;即计算结果与该模值的余数。其语法如下&#…

考研数学|《1800》+《660》精华搭配混合用(经验分享)

肯定不行&#xff0c;考研数学哪有这么容易的&#xff01; 先说说这两本习题册&#xff0c;李永乐老师推出的新版660题&#xff0c;相较于18年前的版本&#xff0c;难度略有降低&#xff0c;更加适合初学者。因此&#xff0c;对于处于基础阶段的学习者来说&#xff0c;新版660…

Docker Swarm安装部署应用

一、Docker Swarm核心概念 1、什么是Docker Swarm GitHub地址 Docker Swarm 是 Docker 官方推出的容器集群管理工具&#xff0c;基于 Go 语言实现。使用它可以将多个 Docker 主机封装为单个大型的虚拟 Docker 主机&#xff0c;快速打造一套容器云平台。 Docker Swarm 是生产…

C# winform校验文件版本差异及版本号

界面 代码 using System.Diagnostics;namespace VersionTool {public partial class Form1 : Form{List<string> fileNmaes new List<string>() { "PhotoMes.Base.dll", "PhotoMes.App.exe", "PhotoMes.Cameras.dll" };public F…

分治实现快速排序和归并排序

本文用于记录个人算法竞赛学习&#xff0c;仅供参考 一.快速排序&#xff08;升序为例&#xff09; 思想&#xff1a;确定分界点x&#xff0c;将小于分界点的值放在分界点的左边&#xff0c;将大于分界定的值放在分界点的右边&#xff0c;再递归处理两边的左右区间。 步骤&am…

如何注册Claude3?解决Claude3无海外手机号接收验证码的问题以及如何订阅Claude Pro

原文链接&#xff1a;如何注册 Claude3&#xff1f;解决 Claude3 无海外手机号接收验证码的问题以及如何订阅 Claude Pro 前言 Claude3已经出来有一段时间了&#xff0c;大家有没有体验过呢&#xff1f;不过从目前来看&#xff0c;Anthropic公司总共推出了3个模型&#xff1…

使用 golang 以及 Gin 框架,将上传的图片在不保存至本地的情况下添加水印,并上传至阿里云 OSS

正如标题所述&#xff0c;使用golang对上传图片添加水印&#xff0c;以及将图片上传到阿里云OSS&#xff0c;网上一搜索&#xff0c;便有你想要的结果了&#xff0c;可是&#xff0c;他们却先将上传图片添加水印后保存在本地&#xff0c;而后再将添加了水印的图片上传到阿里云O…

当iPhone中的Wi-Fi变灰时别担心,可以尝试这些解决办法

这篇文章解释了当iPhone上的Wi-Fi变灰时,你应该检查并修复的所有事情。 确保飞行模式关闭 这听起来可能很傻,但在执行任何其他操作之前,请确保未打开飞机模式。此功能禁用Wi-Fi(和蜂窝网络),因为它旨在允许你在通常不允许传出无线通信的飞机上使用手机。 查看飞行模式…

Linux 动静态库的制作,使用和加载

Linux 动静态库的制作,使用和加载 一.前置说明1.mylib.h2.mylib.c3.mymath.h mymath.c4.如何制作库 二.动静态库的制作1.静态库的制作1.制作2.使用一下静态库,验证是否成功打包 2.动态库的制作1.编译.c源文件文件生成.o目标文件2.打包生成动态库3.编写makefile文件,自动化制作动…

从0开始打架基于VUE的前端项目

准备与版本 安装nodejs(v20.11.1)安装vue脚手架(@vue/cli 5.0.8) ,参考(https://cli.vuejs.org/zh/)vue版本(2.7.16),vue2的最后一个版本初始化项目 创建一个git项目(可以去gitee/github上创建),注意创建一个空项目创建项目vue create mvp-admin-vue-ui删除自己创建的gi…

OpenHarmony实战:烧录Hi3516DV300开发板

前言 烧录开发板是每个开发者的必修课&#xff0c;每次对系统的修改务必进行烧录测试&#xff0c;确保修改正确和不会引入新问题。 本文基于 Windows10&#xff0c;以 Hi3516DV300 开发板为例&#xff0c;指导如何烧录 OpenHarmony 镜像&#xff0c;镜像也叫固件。 这块开发…

C++ :STL中deque的原理

deque的结构类似于哈希表&#xff0c;使用一个指针数组存储固定大小的数组首地址&#xff0c;当数据分布不均匀时将指针数组内的数据进行偏移&#xff0c;桶不够用的时候会像vector一样扩容然后将之前数组中存储的指针拷贝过来&#xff0c;从原理可以看出deque的性能是非常高的…

ISP-VPN实验

文章目录 ISP-VPN实验一&#xff0c;实验拓扑二、实验要求三、IP规划四、实验配置1、IP配置R1的配置R2的配置R3的配置R4的配置R5的配置 2、配置缺省路由3、认证与被认证配置4、HDLC封装5、构建MGRE和GRE6、整个私有网络基于RIP全网可达7、查看路由配置和PC端配置8、PC端pingR5的…

环境影响与碳排放生命周期评估应用及案例分析

生命周期分析 (Life Cycle Analysis, LCA) 是评价一个产品系统生命周期整个阶段——从原材料的提取和加工&#xff0c;到产品生产、包装、市场营销、使用、再使用和产品维护&#xff0c;直至再循环和最终废物处置——的环境影响的工具。这种方法被认为是一种“从摇篮到坟墓”的…

用JSch实现远程传输文件并打包成jar

本文将简单介绍一下 JSch 这个Java的第三方库的一个简单用法&#xff0c;并以此为实例&#xff0c;讲解 IntelliJ 中打包成 jar 包的2种方式。 实现目标 我们的目标是&#xff0c;做出一个jar包&#xff0c;它能够实现类似于 scp 命令的远程传输文件的功能。用法如下&#xf…