【前言】:
后续有时间会将纸质笔记中的过程图更新上来。
【1】:图基础概念
【图的存储方式】:
//难点在于表达图数据结构的方式是非常多的。
【表达方式】:
同样的一套算法 , 选择不同的方式来表达图,写法是不一样的,但是算法是一样的。
【有向图】:
一个点到另外一个点 , 它是有方向的。
【邻接表法】:
【边上有权值的图】:
//邻接表的边上可以写上权值~~~
【邻接矩阵】:
【首都数组】:
index下标代表城市的编号 , [index] 下标中的值代表城市往上的父节点。
//这种特殊的情况完全可以用数组来表示 , 每一个节点往上都有一个节点,而且没有环的话。
【二维数组法】:
【解决痛点】:
把图按照你最爱表达的方式实现你所有的算法 ~
【题目中的图结构】====》【自己最熟悉的图结构】
【左神图模板】:
public class Graph {
public HashMap<Integer,Node> nodes; //点集
public HashSet<Edge> edges; //边集
public Graph() {
nodes = new HashMap<>();
edges = new HashSet<>();
}
}
public class Node {
public int value; //自己的数据项———城市A则该项是String类型,存放“城市A”。
public int in; //入度————多少条发散的边指向自己。
public int out; //出度。
public ArrayList<Node> nexts; //由当前这个点出发,直接发散出去的边所指向的点有哪一些。
public ArrayList<Edge> edges; //属于我的边有哪些。由我出发指向其它节点的边。
public Node(int value) {
this.value = value;
in = 0;
out = 0;
nexts = new ArrayList<>();
edges = new ArrayList<>();
}
}
public class Edge { //其实表示的是有向边。
public int weight; //这个边多重 , 权值可以表达距离的意思。
public Node from;
public Node to; //由两条有向边可以拼成一个无向边。————不用管无向边。
public Edge(int weight, Node from, Node to) {
this.weight = weight;
this.from = from;
this.to = to;
}
}
【无向图出入度】:
无向图的入度和出度是一样的。 //因为没有方向~
【有向图出入度】:
【不用管无向边】:
由两条有向边可以拼成一个无向边。
所以——图的描述里只用管有向这个事情就够了。
【2】:宽度
【 图的宽度/广度 】:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VBGricRE-1663994174482)(/Users/yuguangyao/Library/Application Support/typora-user-images/image-20220824132930836.png)]
【图&二叉树 宽度优先遍历的区别】:
二叉树它一定是没有环的,而图它是可能有环的;
//必须要保持一种机制( SET检验机制 ),不要让环的东西一直玩下去,否则就死循环了。
【宽优靠队列】:
//宽优从一个点儿出发就够了;
//只需要一个点结构就可以玩BFS了。
SET是保持一个点不要重复进队列;
只要一个点进入队列了,在SET中就一定有注册(Set检验机制)。
【BFS】:
【 关于set防环 】:
如果输入端的图没有环的话 , SET是可以不加的。
【 点往往就是数字 】:
告诉你最多有1000多个城市 , 0—>零号城市 ; 1—>一号城市。
//你为了更快其实可以把哈希表结构给搞成数组结构;
进一步增加常数时间快的话,可以用数组结构来替代这个哈希表,哈希表虽然也是O( 1 ),但它没有数组寻址快。
城市的编号的数值范围不会特别大;
【3】:深度
【深度优先遍历】:
实际上是用栈来实现的,也需要SET这样的机制。
【深优例子】:
【栈的作用】:
栈永远存放的是宽度优先的路径~~~
【59 :05】:
//我一旦发现我有某个后续的路,我没走过,我先不走其它的路,我先就沿着这条路往死里走( 深度优先遍历 )
//先沿着没走的走到黑,其他的我先不管。
【4】:拓扑排序算法
【适用范围】:
要求有向图,且有入度为0的节点,且没有环。
编译顺序~~~
【拓扑排序】:
有向图,最终所有的点,依赖环境都具备。 //此即拓扑排序~
【依赖配置文件】:
依赖配置Config文件———你这个项目需要依赖哪些底层的包。
【项目组织的实质】:
如果将整张图画出来,你如何决定依次编译的顺序呢???———拓扑排序将解决这个问题。
【拓扑排序----实例】:
【5】:K算法
【判断环】:
【并查集结构】:
并查集结构是又快实现,作查询、作合并都是常数级别的;
今天时间有限,讲另外的一个简单版本。
//进阶班要一个多小时讲并查集结构的。
【6】:P算法
【关于重复放】:
我可以重复放,只是增加了常数时间。
我有可能把一个边重复地扔到队列里去,但是不会影响结论。因为我判断的机制是——新的点,我才要这个边。我才把这个新的点放到Set里去。
【7】:Dijkstra算法
【全局扫描】:
给一个,回一个 ==》 SystemHeap . ( 代价很低 )
但是在某些题目中:
给它的东西你想临时改完之后还让它调整成正确的堆的形式,任何语言的系统中,实现这个都是全局扫描的方式。(全局扫描低效,可以手动改写堆结构)。 //在堆内部的小局部上下移动,这个只能你自己去实现。
【堆的选择问题】:
某个东西进到堆里去之后,无须再去改它的值了。
上去之后还要变,全局扫描非常低效。