预计会有的算法有DFS,BFS,最短路径Dijskra,最小生成树算法Prim,Kruskal,拓扑排序,慢慢更新吧。这些应该都是基础,大学的数据结构内容应该不太会比这个多多少了,再复杂一点的算法我自己也不会了,慢慢学习了,在后面单独开文了。当然这些肯定不能是先复习一遍再写的,依然是能回忆/推导起来的算法,因为不难,所以甚至可能都没忘。代码部分虽然是C++版的,但是改成C语言非常快,只需要把new改成malloc就行了。
图的表示图的概念就不赘述了,应该一搜一大把,我再继续讲概念也没有意义。
从有没有方向对图分类,可以将图分为无向图和有向图。无向图可以视为有两条有向边——即既有从1到2方向的边,也有从2到1方向的边,其存储也可以按照这种方式。
图的表示有很多种,最常用的两种为邻接矩阵与邻接表。邻接矩阵存储了所有顶点到顶点之间的关系,其中有边相连记为1,无边相连记为0。例如对左边的无向图,其邻接矩阵的表示如图。
当然,如果边有权值,就把1记为权值即可;对于这种情况下,无边相连的两个顶点,则可以记为正无穷。记为0也是可以的,但是得注意每次遍历时得判断0是表示无边连接,而不是有权值为0的边。其表示如下:
struct MGraphNode{int mat[MAXN][MAXN];int v, e;};typedef struct MGraphNode MNode, *MGraph;这里的v,e分别记录的是顶点数与边数。
这里BB几句。在很久之前看完浙大的数据结构课并且完成作业之后,我的数据结构能力得到很大的充实。写出来的代码也比以前的trash好了不少。但是现在常常却陷于格式化的定势思维了,例如一棵树就一定想着用链式存储,其实这里是有很大误区的。数据结构本来就是很灵活的东西,如果需要什么信息加入,就存储哪些。存了之后也要考虑到使用是否方便。所以固定化思维是很不可取的。举个例子吧,这里的图中需要哪些信息,都可以往其中添加的。例如顶点数据,边的信息等等。
甚至来说,为了简便,直接一个int g[maxn][maxn]都能够代表一张图,只不过这种一般就只适合于做题时的小代码了,太不结构化也是不行的。
邻接表如上图,其实就是每个顶点记录与它相邻的点有哪些,构成一个链表。它的优点是省空间,只存储那些相连的边,而不像邻接矩阵存储了很多不相连的边(值为0),因此遍历也很方便省时间。当然也有坏处就是不能判断两条边是否直接相连。所以得看情况来使用邻接矩阵还是邻接表。
typedef struct AdjNode ANode, *Adj;struct AdjNode {int v, weight;Adj next;};struct LGraphNode {Adj list[MAXN];int v, e;};typedef struct LGraphNode LNode, * LGraph;
这是一个最简单的邻接表样例,上面的AdjNode表示邻接点节点,与链表的类似,v是相连的顶点,而weight则是两点之间边的权值了。下面的LGraphNode则是存储的图,有N个顶点的链表,v和e分别表示顶点数和边数。当然邻接表比邻接矩阵要丰富