数据结构与算法
数据结构及算法学习笔记
zhang35
zhangjqfriend@gmail.com
展开
-
堆排序heapSort C++实现
#include <iostream> using namespace std; // 对arr[i]为根的子树建堆;i:根节点下标 n:堆大小void heapify(int arr[], int n, int i) { int largest = i; // Initialize largest as root int l = 2*i + 1; // left = 2*i + 1 int r = 2*i + 2; // right = 2*i +原创 2020-07-27 20:50:21 · 304 阅读 · 0 评论 -
归并排序MergeSort递归版本+非递归版本(C语言实现)
代码来自:https://www.geeksforgeeks.org/iterative-merge-sort/,对注释进行了翻译和扩充。两个版本的归并排序,仅在mergeSort函数的实现上有区别。非递归版本需要考虑当前mid、r的值是否超出了数组右边界,若超出则取值为n-1。有可能出现mid、r均为n-1的情况,此时调用merge,临时数组R[]的大小 n2 = r - mid = 0,是一个空数组,归并结果即为临时数组L[],关键代码: for (int k=1; k<n; k = 2原创 2020-07-22 14:28:22 · 623 阅读 · 0 评论 -
网络流算法学习笔记——Dinic有效算法
Dinic有效算法同样用来求最大流,相当于FF算法的改进。FF算法参考:网络流算法学习笔记——最大流问题基本概念和Ford-Fulkerson方法(标号法C++实现)改进之处有:FF算法每次只找1条s-t增广链,而Dinic算法每次能找很多条Dinic算法每次都找最短的(边数最少的)s-t增广链(为啥呢? )...原创 2020-04-27 20:48:14 · 1129 阅读 · 1 评论 -
算法设计与分析笔记——顶点覆盖问题VC的NP完全性证明
之前在算法设计与分析笔记——NP完全性中总结了证明NPC的思路,本文拟总结由三元可满足性(3SAT)到顶点覆盖(VC)NP完全性证明。定义3SAT:合取范式中每个简单析取式恰好有3个文字,则称之为3元合取范式。给一个3元合区范式F,问F是可满足的吗?顶点覆盖:任给一个无向图G=<V, E>,再给一个非负整数K<=|V|,问G中有顶点数不超过K的顶点覆盖吗?思路1、显然V...原创 2020-04-24 12:59:21 · 5668 阅读 · 3 评论 -
算法设计与分析笔记——NP完全性
【Ted-ED】病毒谜题:汉密尔顿路径/NP完全问题 The Virus Riddle原创 2020-04-07 20:00:53 · 1628 阅读 · 0 评论 -
什么是伪多项式时间算法
首先一定要搞清楚下面的定义。“输入规模”:一个问题的输入规模是保存输入数据所需要的bit位数。(不理解“伪多项式时间”,可能很大程度上是由于对“输入规模”的误解。输入规模不是指输入的大小,也不是指多少,而是指在2进制下保存它们需要的位数!)“多项式时间算法”:在输入规模为x的情况下,算法能够在O(xk) 时间(k为常数)内解决该问题。伪多项式时间算法:算法的时间复杂度是输入数据大小的多项式...原创 2020-04-02 09:54:43 · 3545 阅读 · 0 评论 -
从农夫过河问题理解顶点覆盖、团和独立集
顶点覆盖(VC)是个顶点集合,去除了这些顶点及其相关的边后,图中没有边剩下了。它有什么用途呢,看下面的例子。经典的农夫过河问题,相冲突的生物之间有连线,每次携带走某几个生物后,要保证剩下的没有连线存在。问船的容量最小是多少呢?视频:【Numberphile】农夫过桥问题和阿尔昆数直观的思路就是,求最小覆盖,即找最少需要几只手盖住顶点后能消除所有连线:但有时只有最小顶点覆盖个位置是不够...原创 2020-04-01 21:31:20 · 1256 阅读 · 0 评论 -
彻底搞懂平衡二叉树(AVL)建树过程(左旋、右旋)
AVL树是最先发明的自平衡二叉查找树,得名于它的发明者G.M. Adelson-Velsky和E.M. Landis。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n),插入和删除可能需要通过一次或多次树旋转来重新平衡这个树。平衡二叉搜索树插入、查找、删除的时间复杂度最好情况和最坏情况都能维持在O(logN)。...原创 2020-03-23 11:56:51 · 8286 阅读 · 5 评论 -
找第k小数和中位数算法——快速排序思想,复杂度O(n) C++实现
屈婉玲《算法设计与分析》第2版第2章,选第k小的select算法思路是,先将S划分成5个一组,每组找中位数。但是怎么找中位数呢,问题死循环了!所以使用了下面这种易懂的方法。找第k小数,可等价于找到一个位置为k的元素,前面的都比它小,后面的都比它大。采用类似于快速排序的划分方法,但根据情况每次只需处理其中一边。划分的工作量是O(n),最坏情况下为n;每次都将子问题规模缩小一半,递推方程是:W...原创 2020-02-27 17:21:02 · 1174 阅读 · 0 评论 -
主定理学习笔记
主定理用于求递推方程的阶。设a>=1, b>1为常数,f(n)为函数,T(n)为非负整数,且T(n) = aT(n/b) + f(n)(注意a、b取值范围)a代表递归调用子问题的个数(子问题数>=小于原问题,故a>=1)n / b代表子问题规模(子问题规模一定是递减的,否则问题无法收敛,故b>1)f(n)代表把子问题的解组合成原问题的总工作量有以下三...原创 2020-02-22 20:55:48 · 2434 阅读 · 0 评论 -
矩阵幂法求Fibonacci数 复杂度O(logn)
求Fibonacci数,用递归法复杂度O(2 ^ n),用动态规划法能优化到O(n),参考:动态规划算法入门——Fibonacci数列、过桥问题其实还有更快的做法:矩阵幂法。设{Fn}是Fibonacci数列,则有:可用归纳法证明:当n=1时,F(2) = F(1) = 1, F(0) = 0,满足上式;当n>1时,四个元素分别为F(n+2) = F(n+1) + F(n), F(...原创 2020-02-22 15:31:23 · 404 阅读 · 0 评论 -
社会名流问题算法详细复杂度分析
题目在n个人中,被所有人认识却不认识所有人的人,被称作社会名流(或称名人)。若存在社会名流,则找出他。可以使用的唯一方法是询问:“请问你知道那个人吗?”请给出提问次数为O(n)的算法,写出伪代码,分析算法的正确性,并给出算法运行时间的精确分析(O(n)中隐藏的系数)。思路用A指向B表示A认识B,那么社会名流如下图中的5号。当问A是否认识B时, 若A认识B则A不是社会名流,若A不认识B则...原创 2020-02-22 15:05:27 · 1588 阅读 · 0 评论 -
最小费用流的最短路径算法和Ford单源最短路径算法(图解)
最小费用流的负回路算法,是先任意分配流量v0,再将流量调整到权值较小的边上,参考:基于Floyd算法的最小费用流的负回路算法(图解)而最小费用流的最短路径算法,则是从0流开始,往最短路径上分配流量,直到流量达到v0为止。最小费用流的最短路径算法图例容量-费用网络,初始分配0流:找出残余容量网络上的最短路径:s->2->t(距离为4),分配5个单位流量,得到f1:更新残余...原创 2020-02-19 18:58:40 · 3313 阅读 · 0 评论 -
基于Floyd算法的最小费用流的负回路算法(图解)
屈婉玲《算法设计与分析》第2版第7章网络流算法学习笔记。概述最小费用流问题,可视为一般化的最短路径问题和最大流问题,即只要选定合适的权重、容量、流量,解决最小费用流的方法就能用来解决上述问题。另一方面,也意味着解最小费用流问题至少和解最短路径或最大流问题一样难。显然可以用来解决物流运输最小成本问题,除此之外还有广泛应用,比如劳动力分配问题:劳动力和任务间用边连接,费用为工人对任务的讨厌程度...原创 2020-02-19 18:56:37 · 3681 阅读 · 1 评论 -
多源最短路径Floyd算法(可用于找负回路) C++实现
概述Dijkstra算法是经典的求单源最短路径算法,当有以下需求时:要求出任意两点间的最短路径;可能有负权边;用Floyd算法,可以在不存在负回路时,算法思想采用动态规划法,...原创 2020-02-17 12:52:45 · 2026 阅读 · 1 评论 -
网络流算法学习笔记——最大流问题基本概念和Ford-Fulkerson方法(标号法C++实现)
基本概念容量网络:N。连通图N=<V,E,C,s,t>容量:c(i, j)。每条边有一个非负实数c(i, j)代表边的容量发点/源点:s收点/汇:t中间点:除发点、收点外的顶点可行流:f设f:E->R*(非负实数集),满足:容量限制,即f(i, j)<=C(i, j);平衡条件,即对于所有中间点,∑f(i, j) = ∑f(j, i),总流入量=总流出量...原创 2020-02-10 21:24:12 · 3932 阅读 · 0 评论 -
图的广度优先遍历(BFS)和深度优先遍历(DFS)C++实现
问题描述对下图分别进行广度和深度优先遍历。期望的输出结果为:BFS:s-1-2-3-4-tDFS:s-1-3-t-4-2基本思路广度优先:借助标记数组+队列,将与当前节点关联的所有未访问过的节点加到队列里,按队列次序输出即可,输出一个,出队一个。深度优先:借助标记数组,依次递归遍历与当前节点关联的所有未访问过的节点,每次输出当前节点。算法实现#include <iostre...原创 2019-12-11 20:51:42 · 1591 阅读 · 1 评论 -
动态规划算法入门——Fibonacci数列、过桥问题
动态规划是另一类常用的算法设计思想,广泛应用于组合优化问题。核心思想对问题自下而上地求解,将中间结果记录下来以供后面使用,用空间换取时间。最简单的例子—— Fibonacci数列Fibonacci数列的定义是:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)递归是自上而下求解,写法如下://递归法int FibRec(int n){ ...原创 2019-12-11 09:09:22 · 556 阅读 · 0 评论 -
分治算法之——快速排序算法(C++实现)
快速排序是分治策略、迭代的典型示例,需要熟练掌握。核心思想将数组中所有元素都跟一个基准元素x比(随意选取,常取第一个或最后一个),比x小的划分成左边一块,比x大的划分成右边一块,得到两个子问题。然后递归处理这两个子问题即可。其关键在于对数组的划分。代码实现下面是C++实现代码:代码参考:常用算法之----快速排序#include <iostream>using nam...原创 2019-12-11 09:08:28 · 2840 阅读 · 0 评论 -
C++全排列算法
参考:【基础算法】- 全排列代码参考上面链接,花了一些功夫才读懂,添加了注释。经验是:读代码时拿纸笔模拟单步执行,方便理解。还学到了不申请额外空间完成值交换的骚操作。感谢作者。#include <iostream>using namespace std;//交换数值的骚操作,三个异或。void swap(char* array , int i , int j){ ...原创 2019-12-11 08:43:06 · 650 阅读 · 0 评论