数据结构百科全书
数据结构
整理不易,全文比较长,而且有很多的代码段,建议收藏。
vector (动态数组) 的使用`
文件名
vector.cpp
分数
1
初始化代码
#include <iostream>
using namespace std;
int main() {
return 0;
}
第一步
讲解
首先我们引入需要的头文件vector
,在代码头部写下
#include <vector>
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
return 0;
}
第二步
讲解
首先我们学习如何使用一维的vector
。
在main
函数里面通过vector<int> v
来定义一个储存整数的空的vector
。当然vector
可以存任何类型的数据,比如vector<string> v
等等。在本课中我们用 int 来举例。
vector<int> v;
提示
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
return 0;
}
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
return 0;
}
第三步
讲解
我们把 \(1\) 到 \(10\) 的平方依次存到vector
。
在刚才的定义下面写下
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
提示
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
return 0;
}
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
return 0;
}
第四步
讲解
然后依次输出我们刚才压入vector
的值。继续写下
for (int i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
提示
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
for (int i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
return 0;
}
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
for (int i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
return 0;
}
第五步
讲解
到这里,里可以点击运行看看效果。
接下来我们学习二维的vector
的使用。二维的vector
就是一个vector
里面在套一个vector
。通过如下的代码定义一个空的二维的vector
。在刚才的输出代码后面继续写下,特别注意:里面的vector<int>
后面有一个空格,这个空格不能到少,因为在没有开启 c++11 的情况下,会被识别成一个>>
。
vector<vector<int> > v2d;
提示
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
for (int i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
vector<vector<int> > v2d;
for (int i = 0; i < 5; ++i) {
v2d.push_back(vector<int>());
}
return 0;
}
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
for (int i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
vector<vector<int> > v2d;
return 0;
}
第六步
讲解
接下来我们给第一维赋值,第一维是一个一维的vector
,在定义后面写下:
for (int i = 0; i < 5; ++i) {
v2d.push_back(vector<int>());
}
提示
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
for (int i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
vector<vector<int> > v2d;
for (int i = 0; i < 5; ++i) {
v2d.push_back(vector<int>());
}
return 0;
}
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
for (int i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
vector<vector<int> > v2d;
for (int i = 0; i < 5; ++i) {
v2d.push_back(vector<int>());
}
return 0;
}
第七步
讲解
我们让第 \(i\) 行第 \(j\) 列的元素的值为 \(i*j\)。继续写下下面的代码:
for (int i = 0; i < v2d.size(); ++i) {
for (int j = 0; j < 5; ++j) {
v2d[i].push_back(i * j);
}
}
提示
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
for (int i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
vector<vector<int> > v2d;
for (int i = 0; i < 5; ++i) {
v2d.push_back(vector<int>());
}
for (int i = 0; i < v2d.size(); ++i) {
for (int j = 0; j < 5; ++j) {
v2d[i].push_back(i * j);
}
}
return 0;
}
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
for (int i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
vector<vector<int> > v2d;
for (int i = 0; i < 5; ++i) {
v2d.push_back(vector<int>());
}
for (int i = 0; i < v2d.size(); ++i) {
for (int j = 0; j < 5; ++j) {
v2d[i].push_back(i * j);
}
}
return 0;
}
第八步
讲解
然后我们输出一个 \(5\) 行 \(5\) 列的矩阵。
for (int i = 0; i < v2d.size(); ++i) {
for (int j = 0; j < v2d[i].size(); ++j) {
cout << v2d[i][j] << " ";
}
cout << endl;
}
提示
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
for (int i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
vector<vector<int> > v2d;
for (int i = 0; i < 5; ++i) {
v2d.push_back(vector<int>());
}
for (int i = 0; i < v2d.size(); ++i) {
for (int j = 0; j < 5; ++j) {
v2d[i].push_back(i * j);
}
}
for (int i = 0; i < v2d.size(); ++i) {
for (int j = 0; j < v2d[i].size(); ++j) {
cout << v2d[i][j] << " ";
}
cout << endl;
}
return 0;
}
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
for (int i = 1; i <= 10; ++i) {
v.push_back(i * i);
}
for (int i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
vector<vector<int> > v2d;
for (int i = 0; i < 5; ++i) {
v2d.push_back(vector<int>());
}
for (int i = 0; i < v2d.size(); ++i) {
for (int j = 0; j < 5; ++j) {
v2d[i].push_back(i * j);
}
}
for (int i = 0; i < v2d.size(); ++i) {
for (int j = 0; j < v2d[i].size(); ++j) {
cout << v2d[i][j] << " ";
}
cout << endl;
}
return 0;
}
完成讲解
这一节已经完成了,赶紧运行看看效果。
聪明的你一定学会了vector
怎么用了。
set (配对) 的使用`
文件名
set.cpp
分数
1
初始化代码
#include <iostream>
using namespace std;
int main() {
return 0;
}
第一步
讲解
首先我们引入需要的头文件set
,在代码头部写下
#include <set>
代码
#include <iostream>
#include <set>
using namespace std;
int main() {
return 0;
}
第二步
讲解
首先我们学习如何创建一个set
。
在main
函数里面通过set<string> country
来定义一个储存字符串的空的set
。当然set
可以存任何类型的数据,比如set<int> s
等等。在本课中我们用 string 来举例。
set<string> country;
提示
#include <iostream>
#include <set>
using namespace std;
int main() {
set<string> country;
return 0;
}
代码
#include <iostream>
#include <set>
using namespace std;
int main() {
set<string> country;
return 0;
}
第三步
讲解
我们把China
America
France
依次插入到set
。
在刚才的定义下面写下
country.insert("China");
country.insert("America");
country.insert("France");
提示
#include <iostream>
#include <set>
using namespace std;
int main() {
set<string> country;
country.insert("China");
country.insert("America");
country.insert("France");
return 0;
}
代码
#include <iostream>
#include <set>
using namespace std;
int main() {
set<string> country;
country.insert("China");
country.insert("America");
country.insert("France");
return 0;
}
第四步
讲解
然后依次输出我们刚才插入set
的字符串。继续写下
set<string>::iterator it;
for (it = country.begin(); it != country.end(); ++it) {
cout << * it << " ";
}
cout << endl;
提示
#include <iostream>
#include <set>
using namespace std;
int main() {
set<string> country;
country.insert("China");
country.insert("America");
country.insert("France");
set<string>::iterator it;
for (it = country.begin(); it != country.end(); ++it) {
cout << * it << " ";
}
cout << endl;
return 0;
}
代码
#include <iostream>
#include <set>
using namespace std;
int main() {
set<string> country;
country.insert("China");
country.insert("America");
country.insert("France");
set<string>::iterator it;
for (it = country.begin(); it != country.end(); ++it) {
cout << * it << " ";
}
cout << endl;
return 0;
}
第五步
讲解
到这里,里可以点击运行看看效果。
可以发现我们刚才插入的字符串按照字典序排列好了。
接下来我们学习set
的删除操作。
country.erase("American");
country.erase("England");
提示
#include <iostream>
#include <set>
using namespace std;
int main() {
set<string> country;
country.insert("China");
country.insert("America");
country.insert("France");
set<string>::iterator it;
for (it = country.begin(); it != country.end(); ++it) {
cout << * it << " ";
}
cout << endl;
country.erase("American");
country.erase("England");
return 0;
}
代码
#include <iostream>
#include <set>
using namespace std;
int main() {
set<string> country;
country.insert("China");
country.insert("America");
country.insert("France");
set<string>::iterator it;
for (it = country.begin(); it != country.end(); ++it) {
cout << * it << " ";
}
cout << endl;
country.erase("American");
country.erase("England");
return 0;
}
第六步
讲解
接下来我们统计set
中China
字符串的个数
if (country.count("China")) {
cout << "China in country." << endl;
}
提示
#include <iostream>
#include <set>
using namespace std;
int main() {
set<string> country;
country.insert("China");
country.insert("America");
country.insert("France");
set<string>::iterator it;
for (it = country.begin(); it != country.end(); ++it) {
cout << * it << " ";
}
cout << endl;
country.erase("American");
country.erase("England");
if (country.count("China")) {
cout << "China in country." << endl;
}
return 0;
}
代码
#include <iostream>
#include <set>
using namespace std;
int main() {
set<string> country;
country.insert("China");
country.insert("America");
country.insert("France");
set<string>::iterator it;
for (it = country.begin(); it != country.end(); ++it) {
cout << * it << " ";
}
cout << endl;
country.erase("American");
country.erase("England");
if (country.count("China")) {
cout << "China in country." << endl;
}
return 0;
}
第七步
讲解
最后我们将使用完成的set
清空。继续写下下面的代码:
country.clear();
提示
#include <iostream>
#include <set>
using namespace std;
int main() {
set<string> country;
country.insert("China");
country.insert("America");
country.insert("France");
set<string>::iterator it;
for (it = country.begin(); it != country.end(); ++it) {
cout << * it << " ";
}
cout << endl;
country.erase("American");
country.erase("England");
if (country.count("China")) {
cout << "China in country." << endl;
}
country.clear();
return 0;
}
代码
#include <iostream>
#include <set>
using namespace std;
int main() {
set<string> country;
country.insert("China");
country.insert("America");
country.insert("France");
set<string>::iterator it;
for (it = country.begin(); it != country.end(); ++it) {
cout << * it << " ";
}
cout << endl;
country.erase("American");
country.erase("England");
if (country.count("China")) {
cout << "China in country." << endl;
}
country.clear();
return 0;
}
完成讲解
这一节已经完成了,赶紧运行看看效果。
聪明的你一定学会了set
怎么用了。
map (字典) 的使用`
文件名
map.cpp
分数
1
初始化代码
#include <iostream>
using namespace std;
int main() {
return 0;
}
第一步
讲解
首先我们引入需要的头文件map
,在代码头部写下
#include <map>
#include <string>
代码
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
return 0;
}
第二步
讲解
首先我们学习如何创建一个map
。
在main
函数里面通过map<string, int> dict
来定义一个key:value
映射关系的空的map
。当然map
可以存任何类型的数据,比如map<int, int> m
等等。在本课中我们用string:int
来举例。
map<string, int> dict;
提示
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
map<string, int> dict;
return 0;
}
代码
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
map<string, int> dict;
return 0;
}
第三步
讲解
我们把Tom
Jone
Mary
依次插入到map
并一一对应的赋值。
在刚才的定义下面写下
dict["Tom"] = 1;
dict["Jone"] = 2;
dict["Mary"] = 1;
提示
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
map<string, int> dict;
dict["Tom"] = 1;
dict["Jone"] = 2;
dict["Mary"] = 1;
return 0;
}
代码
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
map<string, int> dict;
dict["Tom"] = 1;
dict["Jone"] = 2;
dict["Mary"] = 1;
return 0;
}
第四步
讲解
接下来我们查看map
中Mary
对应的value值,先判断一下map
中是否有Mary
。继续写下
if (dict.count("Mary")) {
cout << "Mary is in class " << dict["Mary"];
}
提示
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
map<string, int> dict;
dict["Tom"] = 1;
dict["Jone"] = 2;
dict["Mary"] = 1;
if (dict.count("Mary")) {
cout << "Mary is in class " << dict["Mary"];
}
return 0;
}
代码
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
map<string, int> dict;
dict["Tom"] = 1;
dict["Jone"] = 2;
dict["Mary"] = 1;
if (dict.count("Mary")) {
cout << "Mary is in class " << dict["Mary"];
}
return 0;
}
第五步
讲解
到这里,里可以点击运行看看效果。
接下来我们学习map
的遍历操作。
for (map<string, int>::iterator it = dict.begin(); it != dict.end(); ++it) {
cout << it->first << " is in class " << it->second << endl;
}
提示
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
map<string, int> dict;
dict["Tom"] = 1;
dict["Jone"] = 2;
dict["Mary"] = 1;
if (dict.count("Mary")) {
cout << "Mary is in class " << dict["Mary"];
}
for (map<string, int>::iterator it = dict.begin(); it != dict.end(); ++it) {
cout << it->first << " is in class " << it->second << endl;
}
return 0;
}
代码
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
map<string, int> dict;
dict["Tom"] = 1;
dict["Jone"] = 2;
dict["Mary"] = 1;
if (dict.count("Mary")) {
cout << "Mary is in class " << dict["Mary"];
}
for (map<string, int>::iterator it = dict.begin(); it != dict.end(); ++it) {
cout << it->first << " is in class " << it->second << endl;
}
return 0;
}
第六步
讲解
到这里,里可以点击运行看看效果。
可以发现map
里的key字符串按照字典序排列好了。
最后我们再清空map
dict.clear();
提示
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
map<string, int> dict;
dict["Tom"] = 1;
dict["Jone"] = 2;
dict["Mary"] = 1;
if (dict.count("Mary")) {
cout << "Mary is in class " << dict["Mary"];
}
for (map<string, int>::iterator it = dict.begin(); it != dict.end(); ++it) {
cout << it->first << " is in class " << it->second << endl;
}
dict.clear();
return 0;
}
代码
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
map<string, int> dict;
dict["Tom"] = 1;
dict["Jone"] = 2;
dict["Mary"] = 1;
if (dict.count("Mary")) {
cout << "Mary is in class " << dict["Mary"];
}
for (map<string, int>::iterator it = dict.begin(); it != dict.end(); ++it) {
cout << it->first << " is in class " << it->second << endl;
}
dict.clear();
return 0;
}
完成讲解
这一节已经完成了,赶紧运行看看效果。
聪明的你一定学会了map
怎么用了。
stack (栈) 的使用`
文件名
stack.cpp
分数
1
初始化代码
#include <iostream>
using namespace std;
int main() {
return 0;
}
第一步
讲解
首先我们引入需要的头文件stack
,在代码头部写下
#include <stack>
代码
#include <iostream>
#include <stack>
using namespace std;
int main() {
return 0;
}
第二步
讲解
首先我们学习如何使用stack
。
在main
函数上方通过stack<int> S
来定义一个全局栈来储存整数的空的stack
。当然stack
可以存任何类型的数据,比如stack<string> S
等等。在本课中我们用 int 来举例。
stack<int> S;
提示
#include <iostream>
#include <stack>
using namespace std;
stack<int> S;
int main() {
return 0;
}
代码
#include <iostream>
#include <stack>
using namespace std;
stack<int> S;
int main() {
return 0;
}
第三步
讲解
我们把1
10
7
三个数依次存到stack
。
在main
函数里写下
S.push(1);
S.push(10);
S.push(7);
提示
#include <iostream>
#include <stack>
using namespace std;
stack<int> S;
int main() {
S.push(1);
S.push(10);
S.push(7);
return 0;
}
代码
#include <iostream>
#include <stack>
using namespace std;
stack<int> S;
int main() {
S.push(1);
S.push(10);
S.push(7);
return 0;
}
第四步
讲解
然后我们判断一下stack
的是否为空。继续写下
while (!S.empty()) {
}
提示
#include <iostream>
#include <stack>
using namespace std;
stack<int> S;
int main() {
S.push(1);
S.push(10);
S.push(7);
while (!S.empty()) {
}
return 0;
}
代码
#include <iostream>
#include <stack>
using namespace std;
stack<int> S;
int main() {
S.push(1);
S.push(10);
S.push(7);
while (!S.empty()) {
}
return 0;
}
第五步
讲解
如果stack
不为空,我们将stack
里的数依次取出来,在while
里继续写下
cout << S.top() << endl;
S.pop();
提示
#include <iostream>
#include <stack>
using namespace std;
stack<int> S;
int main() {
S.push(1);
S.push(10);
S.push(7);
while (!S.empty()) {
cout << S.top() << endl;
S.pop();
}
return 0;
}
代码
#include <iostream>
#include <stack>
using namespace std;
stack<int> S;
int main() {
S.push(1);
S.push(10);
S.push(7);
while (!S.empty()) {
cout << S.top() << endl;
S.pop();
}
return 0;
}
完成讲解
这一节已经完成了,赶紧运行看看效果,可以发现stack
有先进后出的特性。
聪明的你一定学会了stack
怎么用了。
queue (队列) 的使用`
文件名
queue.cpp
分数
1
初始化代码
#include <iostream>
using namespace std;
int main() {
return 0;
}
第一步
讲解
首先我们引入需要的头文件queue
,在代码头部写下
#include <queue>
代码
#include <iostream>
#include <queue>
using namespace std;
int main() {
return 0;
}
第二步
讲解
首先我们学习如何使用queue
。
在main
函数里面通过queue<int> q
来定义一个储存整数的空的queue
。当然queue
可以存任何类型的数据,比如queue<string> q
等等。在本课中我们用 int 来举例。
queue<int> q;
提示
#include <iostream>
#include <queue>
using namespace std;
int main() {
queue<int> q;
return 0;
}
代码
#include <iostream>
#include <queue>
using namespace std;
int main() {
queue<int> q;
return 0;
}
第三步
讲解
我们把1
2
3
三个数依次存到queue
。
在main
函数里写下
q.push(1);
q.push(2);
q.push(3);
提示
#include <iostream>
#include <queue>
using namespace std;
int main() {
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
return 0;
}
代码
#include <iostream>
#include <queue>
using namespace std;
int main() {
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
return 0;
}
第四步
讲解
然后我们判断一下queue
的是否为空。继续写下
while (!q.empty()) {
}
提示
#include <iostream>
#include <queue>
using namespace std;
int main() {
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty()) {
}
return 0;
}
代码
#include <iostream>
#include <queue>
using namespace std;
int main() {
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty()) {
}
return 0;
}
第五步
讲解
如果queue
不为空,我们将queue
里的数依次取出来,在while
里继续写下
cout << q.front() << endl;
q.pop();
提示
#include <iostream>
#include <queue>
using namespace std;
int main() {
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty()) {
cout << q.front() << endl;
q.pop();
}
return 0;
}
代码
#include <iostream>
#include <queue>
using namespace std;
int main() {
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty()) {
cout << q.front() << endl;
q.pop();
}
return 0;
}
完成讲解
这一节已经完成了,赶紧运行看看效果,可以发现queue
有先进先出的特性。
聪明的你一定学会了queue
怎么用了。
priority_queue (优先队列) 的使用`
文件名
priority_queue.cpp
分数
1
初始化代码
#include <iostream>
using namespace std;
int main() {
return 0;
}
第一步
讲解
首先我们引入需要的头文件queue
,在代码头部写下
#include <queue>
代码
#include <iostream>
#include <queue>
using namespace std;
int main() {
return 0;
}
第二步
讲解
首先我们学习如何使用priority_queue
。
在main
函数里面通过priority_queue<int> q
来定义一个储存整数的空的priority_queue
。当然priority_queue
可以存任何类型的数据,比如priority_queue<string> q
等等。在本课中我们用 int 来举例。
priority_queue<int> q;
提示
#include <iostream>
#include <queue>
using namespace std;
int main() {
priority_queue<int> q;
return 0;
}
代码
#include <iostream>
#include <queue>
using namespace std;
int main() {
priority_queue<int> q;
return 0;
}
第三步
讲解
我们把1
2
3
三个数依次存到priority_queue
。
在main
函数里写下
q.push(1);
q.push(2);
q.push(3);
提示
#include <iostream>
#include <queue>
using namespace std;
int main() {
priority_queue<int> q;
q.push(1);
q.push(2);
q.push(3);
return 0;
}
代码
#include <iostream>
#include <queue>
using namespace std;
int main() {
priority_queue<int> q;
q.push(1);
q.push(2);
q.push(3);
return 0;
}
第四步
讲解
然后我们判断一下priority_queue
的是否为空。继续写下
while (!q.empty()) {
}
提示
#include <iostream>
#include <queue>
using namespace std;
int main() {
priority_queue<int> q;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty()) {
}
return 0;
}
代码
#include <iostream>
#include <queue>
using namespace std;
int main() {
priority_queue<int> q;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty()) {
}
return 0;
}
第五步
讲解
如果priority_queue
不为空,我们将priority_queue
里的数依次取出来,在while
里继续写下
cout << q.top() << endl;
q.pop();
提示
#include <iostream>
#include <priority_queue>
using namespace std;
int main() {
priority_queue<int> q;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty()) {
cout << q.top() << endl;
q.pop();
}
return 0;
}
代码
#include <iostream>
#include <queue>
using namespace std;
int main() {
priority_queue<int> q;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty()) {
cout << q.top() << endl;
q.pop();
}
return 0;
}
完成讲解
这一节已经完成了,赶紧运行看看效果,可以发现priority_queue
会自动从大到小排好序。
聪明的你一定学会了priority_queue
怎么用了。
disjoint (并查集) 的使用`
文件名
disjoint.cpp
分数
1
初始化代码
#include <iostream>
using namespace std;
int main() {
return 0;
}
第一步
讲解
首先我们需要定义节点个数n
,father
父节点数组,dist
距离数组,size
权值数组,在main
函数上方写下
int father[110], n;
int dist[110], size[110];
代码
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
int main() {
return 0;
}
第二步
讲解
然后对这些数组进行初始化。在main
函数里写下
n = 10;
init();
提示
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
int main() {
n = 10;
init();
return 0;
}
代码
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
int main() {
n = 10;
init();
return 0;
}
第三步
讲解
接下来具体实现init
函数。继续在main
函数上面写下
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
提示
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
int main() {
n = 10;
init();
return 0;
}
代码
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
int main() {
n = 10;
init();
return 0;
}
第四步
讲解
现在开始学习并查集的merge
操作,我们将1
和2
、10
和7
、3
和4
、3
和7
合并。在main
函数里继续写下
merge(1, 2);
merge(10, 7);
merge(3, 4);
merge(3, 7);
提示
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
int main() {
n = 10;
init();
merge(1, 2);
merge(10, 7);
merge(3, 4);
merge(3, 7);
return 0;
}
代码
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
int main() {
n = 10;
init();
merge(1, 2);
merge(10, 7);
merge(3, 4);
merge(3, 7);
return 0;
}
第五步
讲解
接下来我们具体实现merge
函数。在main
上方继续写下
void merge(int a, int b) {
a = get(a);
b = get(b);
if (a != b) {
father[a] = b;
dist[a] = size[b];
size[b] += size[a];
}
}
提示
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
void merge(int a, int b) {
a = get(a);
b = get(b);
if (a != b) {
father[a] = b;
dist[a] = size[b];
size[b] += size[a];
}
}
int main() {
n = 10;
init();
merge(1, 2);
merge(10, 7);
merge(3, 4);
merge(3, 7);
return 0;
}
代码
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
void merge(int a, int b) {
a = get(a);
b = get(b);
if (a != b) {
father[a] = b;
dist[a] = size[b];
size[b] += size[a];
}
}
int main() {
n = 10;
init();
merge(1, 2);
merge(10, 7);
merge(3, 4);
merge(3, 7);
return 0;
}
第六步
讲解
接下来我们查找1
所在集合的根节点并输出1
到根节点的距离dist
。在main
函数里继续写下
get(1); // 一定要先 get,可能没有直接连接根节点
cout << dist[1] + 1 << endl;
提示
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
void merge(int a, int b) {
a = get(a);
b = get(b);
if (a != b) {
father[a] = b;
dist[a] = size[b];
size[b] += size[a];
}
}
int main() {
n = 10;
init();
merge(1, 2);
merge(10, 7);
merge(3, 4);
merge(3, 7);
get(1); // 一定要先 get,可能没有直接连接根节点
cout << dist[1] + 1 << endl;
return 0;
}
代码
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
void merge(int a, int b) {
a = get(a);
b = get(b);
if (a != b) {
father[a] = b;
dist[a] = size[b];
size[b] += size[a];
}
}
int main() {
n = 10;
init();
merge(1, 2);
merge(10, 7);
merge(3, 4);
merge(3, 7);
get(1); // 一定要先 get,可能没有直接连接根节点
cout << dist[1] + 1 << endl;
return 0;
}
第七步
讲解
我们接着实现get
函数。在merge
函数上方继续写下
int get(int x) {
if (father[x] == x) {
return x;
}
int y = father[x];
father[x] = get(y);
dist[x] += dist[y];
return father[x];
}
提示
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
int get(int x) {
if (father[x] == x) {
return x;
}
int y = father[x];
father[x] = get(y);
dist[x] += dist[y];
return father[x];
}
void merge(int a, int b) {
a = get(a);
b = get(b);
if (a != b) {
father[a] = b;
dist[a] = size[b];
size[b] += size[a];
}
}
int main() {
n = 10;
init();
merge(1, 2);
merge(10, 7);
merge(3, 4);
merge(3, 7);
get(1); // 一定要先 get,可能没有直接连接根节点
cout << dist[1] + 1 << endl;
return 0;
}
代码
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
int get(int x) {
if (father[x] == x) {
return x;
}
int y = father[x];
father[x] = get(y);
dist[x] += dist[y];
return father[x];
}
void merge(int a, int b) {
a = get(a);
b = get(b);
if (a != b) {
father[a] = b;
dist[a] = size[b];
size[b] += size[a];
}
}
int main() {
n = 10;
init();
merge(1, 2);
merge(10, 7);
merge(3, 4);
merge(3, 7);
get(1); // 一定要先 get,可能没有直接连接根节点
cout << dist[1] + 1 << endl;
return 0;
}
第八步
讲解
到这里,里可以点击运行看看效果。
接下来我们查找3
所在集合的根节点并输出3
到根节点的距离dist
。在main
函数里继续写下
get(3);
cout << dist[3] + 1 << endl;
提示
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
int get(int x) {
if (father[x] == x) {
return x;
}
int y = father[x];
father[x] = get(y);
dist[x] += dist[y];
return father[x];
}
void merge(int a, int b) {
a = get(a);
b = get(b);
if (a != b) {
father[a] = b;
dist[a] = size[b];
size[b] += size[a];
}
}
int main() {
n = 10;
init();
merge(1, 2);
merge(10, 7);
merge(3, 4);
merge(3, 7);
get(1); // 一定要先 get,可能没有直接连接根节点
cout << dist[1] + 1 << endl;
get(3);
cout << dist[3] + 1 << endl;
return 0;
}
代码
#include <iostream>
using namespace std;
int father[110], n;
int dist[110], size[110];
void init() {
for (int i = 1; i <= n; ++i) {
father[i] = i, dist[i] = 0, size[i] = 1;
}
}
int get(int x) {
if (father[x] == x) {
return x;
}
int y = father[x];
father[x] = get(y);
dist[x] += dist[y];
return father[x];
}
void merge(int a, int b) {
a = get(a);
b = get(b);
if (a != b) {
father[a] = b;
dist[a] = size[b];
size[b] += size[a];
}
}
int main() {
n = 10;
init();
merge(1, 2);
merge(10, 7);
merge(3, 4);
merge(3, 7);
get(1); // 一定要先 get,可能没有直接连接根节点
cout << dist[1] + 1 << endl;
get(3);
cout << dist[3] + 1 << endl;
return 0;
}
完成讲解
这一节已经完成了,赶紧运行看看效果。
聪明的你一定学会了disjoint
怎么用了。
队列`
简介
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
- 重要特性:元素先进先出
实现方式
- 数组
- 链表
- STL
标程
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
struct Queue {
/* 数组实现 */
void Queue_Array() {
int q[1005] = {0};
int head = 0;
int tail = head;
q[tail++] = 1;
q[tail++] = 2;
q[tail++] = 3;
while (head < tail) {
printf("%d\n", q[head]);
head++;
}
}
/* STL实现 */
void Queue_STL() {
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty()) {
printf("%d\n", q.front());
q.pop();
}
}
}Q;
int main() {
Q.Queue_Array();
Q.Queue_STL();
return 0;
}
单调队`
简介
单调队列,即单调递减或单调递增的队列。使用频率不高,但在有些程序中会有非同寻常的作用。
- 重要特性:元素可以从两端进出
实现方式
- 数组
- 链表
- STL
deque的性质
- 容器中间插入和删除效率很低
- 与vector容器操作类似
例题
题意:n个数字一开始排成一行,有两个指针L和R,指向了这串数字的一个区间的端点。
现在有7种操作
- 使一个指针左移
- 使一个指针右移
- 在L后插入一个数字X
- 在R前插入一个数字X
- 删除L所指元素
- 删除R所指元素
- 翻转[L,R]区间
Question:m次操作后,整串数字是什么样的?
分析:如果区间L和R每一次都是任意范围的,那么肯定是平衡树问题。但是现在区间断点L和R每次只能左移一位或右移一位,那么可以将整串数字以L、R为中点分为三段,然后模拟这几种操作。但是翻转不能直接模拟,用一个标记来判断一下正反。
双端队列`
简介
双端队列(deque,全名double-ended queue)是一个限定插入和删除操作的数据结构,具有队列和栈的性质。双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。
双端队列是限定插入和删除操作在表的两端进行的线性表。这两端分别称做端点1和端点2。也可像栈一样,可以用一个铁道转轨网络来比喻双端队列。
- 重要特性:元素可以从两端进出
实现方式
- 数组
- 链表
- STL
deque的性质
- 容器中间插入和删除效率很低
- 与vector容器操作类似
例题
题意:n个数字一开始排成一行,有两个指针L和R,指向了这串数字的一个区间的端点。
现在有7种操作
- 使一个指针左移
- 使一个指针右移
- 在L后插入一个数字X
- 在R前插入一个数字X
- 删除L所指元素
- 删除R所指元素
- 翻转[L,R]区间
Question:m次操作后,整串数字是什么样的?
分析:如果区间L和R每一次都是任意范围的,那么肯定是平衡树问题。但是现在区间断点L和R每次只能左移一位或右移一位,那么可以将整串数字以L、R为中点分为三段,然后模拟这几种操作。但是翻转不能直接模拟,用一个标记来判断一下正反。
标程
#include<algorithm>
#include<deque>
#include<iostream>
using namespace std;
int main() {
deque<int> dq;
dq.push_back(1);
dq.push_back(2);
dq.push_back(3);
dq.push_front(4);
dq.push_front(5);
dq.push_front(6);
dq.pop_back();
dq.pop_front();
deque<int>::iterator it;
for (it = dq.begin(); it != dq.end(); it++) {
cout << *it << " ";
}
cout << endl;
return 0;
}