Algorithm - cpp
绿色小光头
这个作者很懒,什么都没留下…
展开
-
AVL树
AVL树基本操作/* 定义结点 */struct node{ int v, h; // 值,高度 node *lchild, *rchild;};/* 新建结点 */node* newNode(int x){ node* root = new node; root->v = x; root->h = 1; ...原创 2018-03-07 12:41:33 · 88 阅读 · 0 评论 -
先序中序后序求二叉树
先序中序后序求二叉树问题给定一棵二叉树的先序序列(后序序列)和中序序列,要求重建这棵二叉树。解法由二叉树的性质可知,先序序列的第一个元素是当前二叉树的根节点,根节点将中序序列分为左子树和右子树。先序序列的第一个元素即为整棵二叉树的根节点,在中序序列中找到该元素,则中序中该元素左侧为左子树,右侧为右子树,依照左右子树个数又可将先序序列剩余元素进行划分,接着只要对左子树和右子树进行递归...原创 2018-03-04 16:39:26 · 536 阅读 · 0 评论 -
next_permutation和prev_permutation(全排列)
next_permutation和prev_permutation(全排列)algorithm头文件中包含了next_permutation及prev_permutation这两个全排列函数,分别给出一个序列在全排列中的下一个和上一个序列(按字典序),如果存在这样的序列则返回true,不存在则返回false。算法分析对于一个任意元素不相同的序列来说,正序排列是最小的排列方式,相应的逆序...原创 2018-02-25 12:35:50 · 354 阅读 · 0 评论 -
Bellman-Ford算法
Bellman Ford算法用途用于解决单源最短路径问题,即在给定图和起始结点的基础上,求所有其他结点到起始结点的最短路径。与Dijkstra算法不同的是,BF算法可以处理含有负边权边的图(如果图中存在负环则不适用,因为路径可以不断穿过负环来使最短路径越来越小,无法解出答案)。算法描述与Dijkstra算法相似,BF算法也是利用已经找到的最短路径来更新其他结点到源点的最短路径。不同...原创 2018-03-12 15:45:40 · 803 阅读 · 0 评论 -
随机选择算法
随机选择算法问题从一个无序数组中求出第k大的数。解法原理与快速排序相似,在快排基础上用数组中随机元素代替第一个元素,这样可以保证不存在一组特定的数据能使该算法出现最坏情况(例如对于快速排序来说,最坏情况是序列中元素已经接近有序,这时时间复杂度会劣化到O(n2)O(n2)O(n^2))。利用randPartition函数重排数组,使得随机元素p左边的数均小于等于p,右边的数均大于...原创 2018-03-05 14:04:29 · 549 阅读 · 0 评论 -
SPFA算法
SPFA算法用途用于解决单源最短路径问题,可以处理含有负边权边的图(若存在源点可达负环则无解)。算法描述SPFA算法是在Bellman-Ford算法基础上改进得来的 (关于BF算法可参考 《Bellman-Ford算法》)。BF算法时间复杂度较高,原因在于每一次循环都需要遍历图中所有边,其中包含了大量的重复遍历,这就会使算法效率大大降低。SPFA算法依据的原理是:只有当某个结点到源...原创 2018-03-12 22:18:20 · 657 阅读 · 0 评论 -
求最深根贪心证明
求最深根贪心证明本证明转载自 《pat1021Deepest Root (25)》。问题直接给出一个树的拓扑结构,求出这棵树最深的根,言外之意就是指:当以这个节点为根的时候,树具有最深的深度。解法从任意一个节点开始进行深度优先遍历,找到离他最远的节点(可能不止一个,记为集合A);再从A中任意选一个节点出发进行深度优先遍历,找到离他最远的节点(记为集合B),最后最深根就是这两...转载 2018-03-13 15:26:46 · 406 阅读 · 0 评论 -
查找最近公共祖先
查找最近公共祖先查找的前提是,结点a和结点b都在树中。主要操作对象是二叉查找树,具体步骤如下:记当前根结点为x;如果 a < x 且 b > x (或反过来),则说明x即为要求的祖先;如果a,b都小于(大于)x,说明也要继续向左(右)子树查找;如果 x == a(b),说明a(b)就是b(a)的祖先。/* 查找公共祖先 */int findAncestor(...原创 2018-03-19 22:55:16 · 1344 阅读 · 0 评论 -
Floyd算法
Floyd算法用途解决全源最短路问题,即求给定图中任意两点间的最短路径长度。算法描述如果图中存在一结点k,使得以k作为中转点能使结点i和结点j之间的距离减小,那么就更新i与j之间的最小距离,即:if (d[i][k] + d[k][j] < d[i][j]) d[i][j] = d[i][k] + d[k][j];Floyd算法通过枚举所有结点k作为中转点...转载 2018-03-13 20:40:04 · 185 阅读 · 0 评论 -
Prim算法
Prim算法用途处理最小生成树(MST)问题,即在给定的图中求树,使得这棵树拥有图中所有顶点,且所有边都是图中已知的边,且满足整棵树的边权之和最小。适用于边多的稠密图。算法描述与Dijkstra算法思想相似: 1. 创建并维护树结点集合S, 以及结点到集合S的最短距离数组d; 2. 每次循环遍历图中所有未访问结点,将离集合S最近的结点u并入集合,并累加边权; 3. 以结点u为...原创 2018-03-14 00:06:02 · 173 阅读 · 0 评论 -
Dijkstra算法
Dijkstra算法用途用于解决单源最短路径问题,即在给定图和起始结点的基础上,求所有其他结点到起始结点的最短路径。算法描述创建集合S用来存放已访问结点,集合D用来存放所有结点到起始结点的最短路径;从D中找到值最小的结点i(即起始结点能到达的未访问结点中路径最短的那个),将其并入S;以i为新的接入点,遍历所有未访问结点,如果存在结点j到i的距离加上起始结点到i的距离小于起始结...原创 2018-03-10 13:42:47 · 210 阅读 · 0 评论 -
欧拉筛(求素数)
欧拉筛(求素数)线性筛,复杂度为O(n)。与埃氏筛相比,不会对已经被标记过的合数再进行重复标记,故效率更高。欧拉筛将合数分解为 (最小质因数 * 一个合数) 的形式,通过最小质因数来判断当前合数是否已经被标记过。 const int maxn = 101; // 表长int prime[maxn], pNum = 0; // prime记录素数,pNum记录素数个数 b...原创 2018-02-20 12:46:27 · 2688 阅读 · 0 评论 -
最大公约数
最大公约数利用辗转相除法计算a和b最大公约数(greatest common divisor),该方法基于以下定理:gcd(a,b)=gcd(b,a%b)gcd(a,b)=gcd(b,a%b)gcd(a, b) = gcd(b, a \% b)证明: 设 a = kb + r,则有 r = a - kb。 设d是a和b的一个公约数,则d也必是r的一个约数。 ...原创 2018-02-20 12:47:27 · 803 阅读 · 0 评论 -
并查集
并查集树结构,主要用来合并两个集合以及用来判断两个元素是否在一个集合。判断方法:一个集合只能存在一个根结点。给定两个元素,查找其根结点,如果两者根结点相同,那么说明这两个元素属于同一个集合。基本操作/* 初始化 */int father[maxn], n; // 父结点数组void initialize(){ for (int i = 0; i &lt...原创 2018-03-07 12:49:17 · 639 阅读 · 0 评论 -
堆操作
堆操作堆是完全二叉树,因此用数组表示比较方便,i为当前结点,则 2*i(若存在) 为i的左孩子,2*i+1(若存在) 为i的右孩子。堆中每个结点的值都不小于左右孩子的值(大顶堆),或都不大于左右孩子的值(小顶堆),所以每个结点都是以其为根节点的子树的最大(小)值。int heap[maxn], n; // 定义堆数组以及元素个数,注意完全二叉树数组第一个元素的下标必须为1...原创 2018-03-07 15:45:13 · 195 阅读 · 0 评论 -
中缀式转后缀式
中缀式转后缀式给出一个中缀表达式,要求计算结果,往往需要先将中缀式转变成后缀式以方便计算。转换的主要步骤如下:设立一个操作符栈,用以临时存储操作符;从左到右扫描中缀式,如果是数字则直接输出;如果是操作符x,则将其优先级与栈顶操作符进行比较,并遵照下列规则进行处理: 若x的优先级高于栈顶操作符,则压入操作符栈;若x的优先级低于或等于栈顶操作符,则将栈中操作符不断出栈输出,直到x的优...原创 2018-02-28 15:42:40 · 1549 阅读 · 0 评论 -
n皇后(回溯法)
n皇后(回溯法)在 n * n 的棋盘上放置n个皇后,使得每一行、每一列、每一条对角线有且只有一个皇后,实质上可以抽象为对 1 ~ n 这n个自然数进行全排列,排列中数字i所处的位置顺序代表行号,i代表列号,那么得到的排列组合必定满足每行每列不重复,只要再对对角线位置进行判断即可。为了方便起见,使用递归进行处理。const int maxn = 11;int queen[maxn];...原创 2018-02-20 12:44:14 · 449 阅读 · 0 评论 -
埃氏筛(求素数)
埃氏筛(求素数)众多筛法中最简单且容易理解的一种,时间复杂度为O(nloglogn)(∑n1ni∑1nni\sum_1^n\frac{n}{i}),在找到一个素数后,马上将所求范围内该素数的倍数标记为合数。埃氏筛法存在的问题是会对同一合数进行多次标记,从而影响效率。const int maxn = 101; // 表长int prime[maxn], pNum = 0; // pr...原创 2018-02-20 12:45:30 · 455 阅读 · 0 评论 -
扩展欧几里得算法
扩展欧几里得算法问题给定两个非零整数a和b,求一组整数解(x, y),使得 ax+by=gcd(a,b)ax+by=gcd(a,b)ax + by = gcd(a, b),其中 gcd(a, b) 表示a和b的最大公约数。解法已证 gcd(a,b)=gcd(b,a%b)gcd(a,b)=gcd(b,a%b)gcd(a, b) = gcd(b, a\%b);必存在一组解使得等式成...原创 2018-02-20 12:30:55 · 133 阅读 · 0 评论 -
拓扑排序
拓扑排序用途将有向无环图的所有顶点排成一个线性序列,且对于图中任意两个顶点u、v,如果存在边 u->v,则保证在线性序列中u一定在v前面。可以用来判断给定的图中是否存在环。算法描述对于结点i,只有当它的所有前驱结点都在序列内后,才能将i加入序列中。根据这个思想,算法具体步骤如下:找到所有入度为0的结点,并将它们入队;队首结点u出队,并使所有u指向的结点v的入度-1...原创 2018-03-14 22:20:06 · 153 阅读 · 0 评论 -
快速幂(二分幂)
快速幂(二分幂)问题给定正整数a、b、m,求 ab%mab%ma^b\%m。方法一运用递归思想,考虑以下两个步骤:b为奇数,则 ab=a∗ab−1ab=a∗ab−1a^b = a * a^{b - 1}b为偶数,则 ab=ab2∗ab2ab=ab2∗ab2a^b = a^{\frac{b}{2}} * a^{\frac{b}{2}}时间复杂度为 O(logb)O(lo...原创 2018-02-21 10:55:31 · 1037 阅读 · 0 评论 -
最小公倍数
最小公倍数正整数a和b的最小公倍数(least common multiple,lcm)与最大公约数gcd之间满足以下关系:lcm∗gcd=a∗blcm∗gcd=a∗blcm * gcd = a * b可作Venn图进行证明。int lcm(int a, int b){ int d = gcd(a, b); return a / d * b; //...原创 2018-02-20 12:47:59 · 204 阅读 · 0 评论 -
Kruskal算法
Kruskal算法用途处理最小生成树(MST)问题,即在给定的图中求树,使得这棵树拥有图中所有顶点,且所有边都是图中已知的边,且满足整棵树的边权之和最小。适用于边少的稀疏图。算法描述总体思路为:每次找到当前图中未被选中的边权最小的边,如果边的两个顶点不在同一个连通块中,那么就把该边加入到最小生成树集合中。具体步骤如下:创建并维护一个并查集,用于判断结点所属连通块;对图中所有...原创 2018-03-14 11:11:41 · 254 阅读 · 0 评论