数据结构与算法
剑决浮云气
事了拂衣去,深藏功与名
展开
-
朴素版prim算法求最小生成树
无向图 适用于稠密图 时间复杂度O(N^2)原创 2021-01-17 16:05:56 · 81 阅读 · 0 评论 -
kruskal算法求最小生成树
将所有边按权重从小到大排序,每次从中取出最小的,如果不构成回路,就加上这条边,若构成回路,则舍弃这条边#include <iostream>#include <algorithm>using namespace std;const int N = 100010;const int M = N * 2; struct EDGE{ int Start; int End; int Weight; }Edge[M];//存储边及其权重 int n,m;int原创 2021-01-17 16:04:04 · 140 阅读 · 1 评论 -
染色法判断是否是二分图
二分图:把无向图G= (V,E)分为两个集合V1,V2,所有的边都在V1和V2之间,集合内部是没有边的。V1的一个点和V2的一个点关联,称为一个匹配一个图是否为二分图,一般用染色法来进行判断,一条边连接的两个顶点颜色不相同,用两种颜色对所有边进行染色。染色结束后,若所有相邻顶点的颜色不同,那么就是二分图,一个图是二分图,当且仅当他不含奇数边数的圈#include <iostream>#include <cstring>using namespace std; const原创 2021-01-17 16:03:23 · 318 阅读 · 0 评论 -
匈牙利算法求最大匹配
给定二分图 求他的最大匹配 O(N*M)大白话:集合A 男生 集合B 妹子A中部分男生对B中部分妹子存在好感,且一个男生能对多个妹子存在好感,但是需要确定关系,确定关系肯定只能对一个妹子确定(即不存在现实脚踏两只船,心里脚踏几只那管不着(dog)),求最多能确定多少对关系.过程:从前往后遍历每个男生若该男生有好感的女孩,没有确定关系,那好,他两确定关系。若该男生有好感的女生,确定了关系,那再看该男生的备胎,如果备胎中能找到未确定关系的女生,那确定关系。若在备胎中没有找到未确定关系的女生(即原创 2021-01-17 16:02:36 · 194 阅读 · 0 评论 -
SPFA算法判断负环
#include <iostream>#include <queue>using namespace std; const int N = 100010;int n,m;//节点数 边数int Cnt[N];//记录一个点 由他邻居节点更新最短距离的次数 若>= n则存在负权bool IsInQueue[N];//判断节点是否在队列中int Head[N],Value[N],Next[N],Weight[N],Index; //邻接表int Dis[N];/原创 2021-01-16 17:25:43 · 148 阅读 · 0 评论 -
SPFA算法
是对Bellman-Ford算法的一个优化,用队列来存储那些最短距离发生变化的节点。Bellman-Ford算法的核心是询问邻居到S的距离,来更新自己到S的距离。换而言之,只有邻居变化了,我才有可能变化。所以只需要将那些最短距离发生变化的点,放入队列中,更新他的邻居。省去了更新所有节点的操作。#include <iostream>#include <algorithm>#include <queue> using namespace std; const原创 2021-01-16 17:24:46 · 102 阅读 · 0 评论 -
Bellman-Ford算法
解决单源最短路经原理:Bellman-Ford 算法只对相邻节点进行计算,初始时所有人到起点S的距离都为INF。①给所有的N个人,每人一次机会,问他的邻居到S的最短距离是多少?如果他的邻居到S的距离不是INF,则他就能借道这个邻居到S去,并且把自己的INF更新为更短的距离。显然开始的时候,S的直连邻居(比如U)肯定能保持更新,而U的邻居(例如V)在U更新之后,询问U,那么V有机会更新,否则就只能保持INF不变。特别的,在第一轮更新中,存在一个与S距离最近的邻居(例如T),T到S的直连距离就是全图原创 2021-01-16 17:23:54 · 112 阅读 · 0 评论 -
Floyd算法 求多源汇最短路
#include <iostream>#include <algorithm>using namespace std;const int N = 210;const int INF = 0x3f3f3f3f; int Graph[N][N];//邻接矩阵存储图int n,m;//n个节点 m条边 /*Floyd是用来求多源汇最短路的 基于动态规划*/ void Floyd(){ for(int k = 1; k <= n; k++) { for原创 2021-01-16 17:22:41 · 100 阅读 · 0 评论 -
朴素版的Dijkstra算法
适用于单源最短路边权重都是正数 稠密图(边数多)O(N^2) //N是节点个数 M是边的数量原创 2021-01-15 14:02:56 · 164 阅读 · 0 评论 -
堆优化的Dijkstra
#include <iostream>#include <queue>using namespace std;const int N = 100010;//first存储距离 second 存储节点 typedef pair<int ,int> PII;//用邻接表来存储稀疏图//用优先队列来优化每次找最短的那个节点 int n,m;//n表示节点个数 m表示边的个数 int Head[N],Weight[N],Value[N],Next[N],In原创 2021-01-15 14:01:02 · 137 阅读 · 0 评论 -
最短路的大致介绍
概念源:起点汇点:终点N:节点数M:边数最短路问题大致可以分为①单源最短路(即一个起点 到 不同的终点)1.所有边权重都是正数(朴素Dijkstra O(N^2) 稠密图 )(堆优化的Dijkstra算法 O(MlogN) 稀疏图 )2.某些边的权重是负数(Bellman-Ford O(NM) )(SPFA 一般:O(M) 最坏O(N*M))②多源汇最短路(即起点 终点不定)(Floyd O(N^3))...原创 2021-01-15 10:35:58 · 159 阅读 · 0 评论 -
Dfs实现树的重心
#include <iostream>using namespace std;const int N = 100010;const int M = N * 2;int Head[N];int Next[M];int Value[M];bool IsVisit[N];int Index;int Ans = N;int n;void Add(int a, int b){ Value[Index] = b; Next[Index] = Head[a]; Head[a原创 2021-01-14 14:07:55 · 75 阅读 · 0 评论 -
Toop排序
#include <iostream>using namespace std;const int N = 100010;int n,m;int Value[N];//存储节点 int Next[N];//记录下一个节点的下标 int Head[N];//记录头结点 int Index;//存储位置 int Degree[N];//记录每个节点的入度 int Queue[N];//手工模拟的队列 void Add(int Start, int End){ Value[原创 2021-01-14 14:05:51 · 262 阅读 · 1 评论 -
树,图的邻接表存储
树是特殊的无相连通图,有向图是特殊的无向图#include <iostream>using namespace std;const int N = 100010;const int M = N*2;int Value[M];//存储节点的值int Next[M];//存储他的下一个节点的下标int Head[N];//存储头结点的下标int Index;//节点的存储位置bool IsVisit[N];//判断节点是否访问过//在节点a-->b插入一条边//无原创 2021-01-14 11:15:56 · 495 阅读 · 0 评论 -
DFS解决全排列
#include <iostream>using namespace std;const int N = 10;int nSize;int Result[N];//记录路径 int Src[N];//原数组 bool IsUse[N];//记录当前元素是否使用 int nPos = 1;//记录层数 void Dfs(){ if(nPos == nSize + 1) { for(int j = 1; j <= nSize; j++) { cout原创 2021-01-13 22:43:30 · 80 阅读 · 0 评论 -
priority_queue的优先级设置
#include <iostream>#include <queue>#include <string>using namespace std;struct Fruit{ string Name; int Price; //设置价格高的 优先级高 friend bool operator < (Fruit &f1, Fruit &f2) { return f1.Price < f2.Price; } }f原创 2021-01-13 12:08:23 · 152 阅读 · 0 评论 -
STL的set
#include <iostream>#include <set>using namespace std;/*set 是一个内部自动排序且不含重复元素的容器 且只能通过迭代器访问 */int main(int argc, char** argv) { set<int>a; set<int>::iterator it; a.insert(10); a.insert(5); a.insert(20); a.insert(5); //内原创 2021-01-13 11:14:05 · 58 阅读 · 0 评论 -
STL的vector
#include <iostream>#include <vector>#include <algorithm>using namespace std;int main(int argc, char** argv) { vector<int> a;//默认初始化 a为空 vector<int> b(10);//定义大小为10 cout<<b.size()<<endl; vector<i原创 2021-01-12 14:45:43 · 112 阅读 · 0 评论 -
STL的string
#include <iostream>#include <string>using namespace std; int main(int argc, char** argv) { string a = "ZZH"; cout<<a<<endl; a += "NB";//实现字符串的拼接 cout<<a<<endl; cout<<a.substr(0,3)<<endl;//输出[L,R原创 2021-01-12 14:45:02 · 81 阅读 · 0 评论 -
STL的queue
#include <iostream>#include <queue>using namespace std;int main(int argc, char** argv) { queue<int>q; q.push(10); q.push(20); q.push(30); cout<<q.front()<<endl;//读取队首元素 cout<<q.size()<<endl;//队列的大小原创 2021-01-12 14:44:05 · 67 阅读 · 0 评论 -
STL的pair
#include <iostream>#include <algorithm>#include <string>using namespace std;//pair是一个二元组 可以存储任意对象 int main(int argc, char** argv) { pair<int , string>a; a.first = 10; a.second = "abcdefg"; cout<<a.first<<" "原创 2021-01-12 14:43:14 · 77 阅读 · 0 评论 -
STL的优先队列
priority_queue#include <iostream>#include <queue>using namespace std;//优先队列是用堆实现的 默认是大根堆 int main(int argc, char** argv) { priority_queue<int> heap; //优先队列只能通过Top来读取元素 没有front和back heap.push(10); heap.push(5); cout<<原创 2021-01-12 14:42:10 · 235 阅读 · 0 评论 -
哈希表的拉链法
拉链法Hash(KEY) = Positon;在Postion下面形成一个单链表,存储所有以该Positon为存储地址的数据。找一个比数据范围略大的大质数例如数据范围是10W for(int i = 100000; ; i++) { bool bFlag = true; for(int j = 2; j * j <= i; j++) { if(0 == i % j) { bFlag = false; break; } } i原创 2021-01-11 19:37:44 · 333 阅读 · 0 评论 -
Hash开放地址
开放地址处理冲突#include <bits/stdc++.h>using namespace std;const int N = 200003;//大质数 const int MAX = 0x3f3f3f3f;//标记这个位置是否被占用 int Hash[N];//开放地址处理冲突 int Find(int nNum){ int Key = ((nNum % N) + N) % N; //当前这个位置被人占了,而且不是nNum while(MAX != Hash原创 2021-01-11 19:36:21 · 112 阅读 · 0 评论 -
堆排序
堆排序#include <bits/stdc++.h>using namespace std;#define MAX 100010int nSize;int Heap[MAX];//小根堆的向上调整 void HeapUp(int nPos){ int nFather = nPos/2; while(Heap[nPos] < Heap[nFather] && nFather) { swap(Heap[nPos],Heap[nFather]原创 2021-01-11 16:35:06 · 102 阅读 · 0 评论 -
并查集
①将两个集合合并②询问两个元素是不是一个集合基本原理:每个集合用一个树表示,树根的编号就是整个集合的编号。每个节点都存储他的父节点,p[x]代表x的父节点。树根的p[x] = x;如何求x的集合编号呢?while(x != p[x]){ x = p[x];}如何合并两个集合?让一个集合的根的p[x] = 另外一个集合的编号优化:将路径上的点全部指向根节点int Find(int nNum){ if(nNum != Father[nNum]) { Father[nNum]原创 2021-01-10 17:39:25 · 58 阅读 · 0 评论 -
KMP
KMP板子#include <bits/stdc++.h>using namespace std;const int N = 10010,M = 100010;char p[N];char s[M];int n,m; int Next[N];int main(int argc, char** argv) { cin>>n>>p+1; cin>>m>>s+1; for(int i = 2, j = 0; i &原创 2021-01-10 17:15:01 · 78 阅读 · 0 评论 -
Trie字典树数组实现
#include <bits/stdc++.h>using namespace std;const int N = 10010;int Son[N][26];//存储下一个字符的行 int Count[N];//这个单词单词有多少个 int Pos;//当前新分配的存储位置 char szStr[N]; //读取字符串 void StringInsert(const char *pStr){ int p = 0; for(int i = 0; pStr[i];原创 2021-01-10 17:12:39 · 142 阅读 · 0 评论 -
滑动窗口
滑动窗口(单调队列)拿求窗口里的最小值来说,如果这个数在i位置的前面,还比i位置上的数大,那么无论窗口向后移动多少位,这个数永远不可能是最小值,所以将其从队列中拿出.#include <bits/stdc++.h>using namespace std;#define MAX 1000010int nArr[MAX];//存储数组的值 int nQueue[MAX];//队列 里面存储数组的下标int nSize; int nWindow;int main(int a原创 2021-01-09 15:29:39 · 128 阅读 · 0 评论 -
区间合并
区间合并我们只需要将区间按左端点排序,每次只需要维护一个区间,看这个区间是否有可以合并的,若没有,把这个区间加到答案中,并且开始维护那个新的区间。原创 2021-01-09 11:50:53 · 124 阅读 · 0 评论 -
离散化
离散化将一个值域为无穷的有限个数字,映射到size有穷的数组中。例如 有1e5个数,取值范围是-1e9-1e9,若按照取值范围开数组就开不下,但要是开1e5的大小,就可以,那我们得把这些数映射到数组下标,来完成离散化的操作。通常是排序 去重。vector<int>alls;//存储所有待离散化的值sort(alls.begin(),alls.end());//将所有值排序alls.erase(unique(alls.begin(),alls.end()),alls.end())原创 2021-01-09 11:45:37 · 90 阅读 · 0 评论 -
高精度除法
高精度除法#include <bits/stdc++.h>using namespace std;//大整数Num1 小数nNum2 余数nTemp vector<int> Div(vector<int> &Num1, int nNum2,int &nTemp){ nTemp = 0; vector<int> Result; //从最高位开始 for(int i = Num1.size()-1; i >= 0;原创 2021-01-02 21:08:10 · 109 阅读 · 0 评论 -
高精度乘法
高精度乘法vector<int> Multiplication(vector<int> &Num1, int Num2){ int nTemp = 0; vector<int> Result; //每次将Num2看做一个整体 用Num1的位数去乘 //nTemp%10 获取当前位数 从低到高 for(int i = 0; i < Num1.size(); i++) { nTemp = Num1[i] * Num2 + nTemp;原创 2021-01-02 20:37:08 · 91 阅读 · 0 评论 -
高精度减法
高精度减法#include <bits/stdc++.h>using namespace std; bool Campare(vector<int>&Num1, vector<int>&Num2){ //A B两个数位数不等 if(Num1.size() != Num2.size()) { return Num1.size() > Num2.size(); } else { //A B 两个数位数相等 从最高位开原创 2021-01-02 19:38:09 · 81 阅读 · 0 评论 -
高精度加法
高精度加法#include <bits/stdc++.h>using namespace std;vector<int> AddNum(vector<int> &Num1, vector<int> &Num2){ vector<int>Result; int nTemp = 0; //for循环的终止条件是要加到最长的那个数字的最高位 for(int i = 0; i < Num1.size() || i原创 2021-01-02 13:07:12 · 104 阅读 · 0 评论 -
整数二分
整数二分两个模板1.确定左半边的边界while(nLeft < nRight){ //注意此处 多加了一个1 //如若不加1 当Left 和 Right的值只相差1的时候 那么Mid 的值就为 Left //此时若刚好满足条件 则执行Left = Mid 就造成死循环 int nMid = (nRight + nLeft + 1)/2; if(Check(nMid)) { //即当前找到的Mid满足要求了 需要查看Mid的右边是否也满足要求 nLeft = nMid; }原创 2021-01-01 21:38:40 · 101 阅读 · 0 评论 -
归并排序
**归并排序**#include <bits/stdc++.h>#define MAX 100005using namespace std;/* run this program using the console pauser or add your own getch, system("pause") or input loop */int nArr[MAX];//存放原数据int nTemp[MAX];//临时保存数据int nNum;//数据的多少//对从[Le原创 2020-12-31 14:40:44 · 66 阅读 · 0 评论 -
快速排序
快速排序实现#include <bits/stdc++.h>using namespace std;#define MAX 1e6+10;int nArr[MAX];int nNum;void QuickSort(int *p, int nLeft, int nRight){ if(nLeft >= nRight)//当只有一个元素或没有元素时 直接返回 { return; } //i j 指向的位置写法与下面while循环中的写法有关 //是为了每原创 2020-12-31 12:51:35 · 122 阅读 · 0 评论 -
差分
差分差分就是 用一个数组 delta [size] 来维护 数组 arr[i] 与 arr[i-1] 的差值。注意 delta[0] 是原本序列的 arr[0]!举个例子:原数组arr[10] = {10,9,7,7,6,25,41,30,5,1};那么delta[10] = {10,-1,-2,0,-1,19,16,-9,-25,-4};当我们对一段区间【L,R】整体进行+k操作时,区间内的差值 是不变的,因为他们都+k。delta[L]+k,delta[R+1]-k。当对区间端点的修改原创 2020-05-16 19:07:04 · 682 阅读 · 0 评论 -
迪杰斯特拉算法
截图来自B站 青岛大学-王卓老师原创 2020-05-07 18:41:28 · 103 阅读 · 0 评论