图那里的算法总结

//这里整理的为图那里的算法
//邻接矩阵和邻接表的图的表示很重要
//这里就不说明MAXSIZE就为最大值的默认了

typedef struct ArcCell{
     VRType adj;                            //这里是点中的值
     InfoType *info;                        //这里是有关点的信息比如这里可以放权值
 }ArcCel,AdjMatrix[MAXSIZE][MAXSIZE];       //后面的是矩阵

typedef struct MGraph{              
	VertexType vexs[MAXSIZE];               //这里是顶点表
	AdjMatrix arcs;                         //这里是邻接矩阵边表
	int vexnum;                             //顶点的数目
	int arcnum;                             //边的数目
	GraphKind kind;                         //图的种类
}MGraph;


//这里是邻接表的表示方法很重要
typedef struct ArcNode{                     //边节点
	int adjvex;                             //指向弧所指向的顶点的位置
    ArcNode* nextarc;                       //指向下一条弧的指针
    InfoType *info;                         //该相关弧的信息
}ArcNode;
typedef struct VexNode{                     //顶点节点
	ElemType data;                          //顶点信息
	ArcNode* firstarc;                      //指向第一条依附该顶点的指针
}VexNode,AdjList[MAXSIZE];
typedef struct ALGraph{
	AdjList vertices;                       //顶点组成的数组
	int vexnum;                             //顶点数目
	int arcnum;                             //边数目
	GraphKind kind;
}ALGraph;

//拓扑排序的代码
//拓扑排序的原理就是每次把入度为0的节点删除,然后再把与其相连的边也删去。
//拓扑排序可以检验是否图中有环
bool Topologicalsort(MGraph M)
{
	Stack s;                                //这里需要一个栈来保存入度为0的节点
	init(s);
	int count = 0;                          //这里记录入度为0的节点的个数
	for(int i = 1;i < M.vexnum)             //这里把刚开始入度为0的节点入栈
	{
		if(indegree[i] == 0)                //indegree[i]表示的是i节点的入度个数
			push(s,i)
	}
	int k;
	while(!IsEmpty(S))                      //判断是不是栈为空
	{	
		pop(s,k);                           //出栈因为栈里面保存的都是度为0的节点
		++count;                            // 把度为0的节点的个数加一
		for(ArcNode* p = M.vertices[k]->firstarc;p;p=p->nextarc) //这里的代码的意思就是删去和刚才出栈的节点的邻接边的入度的数目
		{
			int i = p->adjvex;              //这里找到邻接边所对应的弧所指向的顶点的位置
			if(--indegree[i] == 0)          //删除邻接边的入度的数目 即就是把入度数目减去1
			{
				push(s,i)                   //若入度数目为0,则把其压栈说明他是拓扑排序的下一个节点
			}
		}
	}
	return count == M.vexnum?true:false;	//如果所有的节点都最后度为0,那么说明可以拓扑排序,若不可以则不行;
}

//最小生成树  这里的图使用邻接矩阵表示的
//时间复杂度 O(n^2)                         //这里的closedge保存的是顶点adj和它邻接顶点中邻接边权值最小的邻接点和权值
typedef struct closedge{
	VerTexType adjvex;                      //这里为邻接顶点
	VRType lowcost;                         //这里为邻接顶点的权值
}closedge[MAXSIZE];                         //因为有好多的顶点所有用一个数组来表示
void MinSpanTreePrim(MGraph G,VertexType u)//prime需要一个图和一个顶点作为参数
{
	int k =LocateVex(G,u)                   //定位顶点u在图G中的位置
	for(int i = 0;i<G.vexnum;++i)           //根据图的信息更新closedge G.adjlist[k][i].adj这个保存的是i和k之间的权值
	{
		if(k==i)
		closedge[i]={u,G.arcs[k][i]};
	}
	closedge[k].lowcost = 0;                //这里把closedge[k].lowcost更新为0,说明了把节点k已经加入了最小生成树之中了
	for(int j = 1;j<G.vexnum;++j)           //因为已经有一个节点加入到最小生成树中了,所以循环只需要1-G.vexnum之间
	{
		k=minmum(closedge);                 //找到closedge中的lowcost最小值顶点
		closedge[k].lowcost = 0;            //把最小的lowcost加入到最小生成树中
		for(int l = 0;l<G.vexnum;++l)       //更新K周围的邻接点的最小权值
		{
			if(G.arcs[k][l] < closedge[l].lowcost)//当l与k的权值小于closedge[l].lowcost那么就需要更新closedge[l].lowcost
			{
				closedge[l].adjvex = k;                  //更新需要两部分一部分是邻接点 一部分是权值
			    closedge[l].lowcost = G.arcs[k][l];
			  //closedge[l]={k,G.arcs[k][l]}
			}
				
			 
		}
	}
}

//最短路径算法Dijkstra算法
//这个算是比较复杂的代码,但是不难理解
//使用的是邻接矩阵存储的图
//时间复杂度是O(n^2)适用于稠密的图Kruskal适用稀疏图kruskal时间复杂度是O(elge)
//dijkstra处理的是单源最短路径
//
void Dijkstra(MGraph G,int k,PathMatrix& path,shortMetrix& d)//G是图,k是第一个顶点 path是保存路径的 d是保存到源点的最短距离
{
	int final[MAXSIZE];                     //这个数组是用来标记是不是已经加入了最短路径的节点的标记0表示没有加入,1表示加入了
	for(int m = 0;m<G.vexnum;++m)           //这里是先把k与m之间的弧的权值赋给d[m]
	{
		final[m] = 0;
		d[m] = G.arcs[k][m];
	}
	final[k] = 1;                           //因为第一个顶点是k,所以把k加入到最短路径节点之中
	for(int j = 1;j<G.vexnum;++j)           //因为第一个节点已经找到了所以只需要寻找1-G.vexnum个节点就可以了
	{
		min = 32132322343;                  //min用保存于当前最短路径d[n]中的最短的一条路径
		int v;                              //v用来保存最短路径的那个顶点
		for(int n = 0;n < G.vexnum;++n)     //用来找到当前的最短的一条路径顶点保存在v中,权值保存在min中。
		{
			if(!final[n]&&d[n] < min)
			{
				v = n;
				min = d[n];
			}

		}
		final[v] = 1;                       //找到的当前的最短的一条路径加入到最短路径之中所以把final[v]置1表示找到这个顶点
		for(int l = 0;k<G.vexnum;++k)       //用当前的v结点更新,未加入最短路径的节点的到源点的权值,当然这里更新要最短的权值
		{
			if(!final[l]&&d[l] > min+G.arcs[v][l])//G.arcs[v][l]表示的是顶点v到顶点l之间的权值
			{
				d[l] = min+G.arcs[v][l];
			}
		}
	}
}

//floyd这个算法比较简单
//时间复杂度O(n^3)
void floyd(MGraph G)
{
	for(int i =0;i<G.vexnum;++i)
		for(int j = 0;j<G.vexnum;++j)
			for(int k = 0;k<G.vexnum;++k)     //若v-k的路径大于v-j-k的路径把v-k的路径更新为v-j-k
			{
				if(G.arcs[i][k] > G.arcs[i][j]+G.arcs[j][k])
					G.arcs[i][k] = G.arcs[i][j]+G.arcs[j][k];
			}
}

//深度优先遍历和广度优先遍历
int visited[MAXSIZE];//用来标记是否访问过
void BFSTraverse(ALGraph G)
{
	for(int i = 0;i<G.vexnum;++i)             //这里是每个节点都进行广度优先遍历
	{
		if(!visited[i])
		{
			BFS(G,i)
		}
	}
}
void BFS(ALGraph,int k)
{
	Queue Q;                                  //初始化一个队列
	init(Q);
	EnQueue(Q,k);                             //第一个节点进入队列
	visited[k] = 1;                           //标记第一个节点表示访问
	while(!IsEmpty(Q))
	{
		DeQueue(Q,k);
		for(VexNode* p=G.vertices[k]->firstarc;p&&;p=p->nextarc)//找k节点邻接节点入队
		{
			int k = p->adjvex;
			if(!visited[k])                   //找到未访问的标记并且访问之后再入队列
			{
				visit(k);
				visited[k] = 1;
			    EnQueue(Q,k);
			}
			
		}
	}

}

//深度度优先遍历
int visited[MAXSIZE];
void DFSTraver(MGraph G,int v)
{
	for(int i = 0;i<G.vexnum;++i)              //每个节点都进行深度优先遍历
	{
		if(!visited[i])
		{
			DFS(G,i)
		}
	}
}
void DFS(MGraph G,int v)
{
	visited[v] = 1;
	visit(v);
	for(VexNode* p = G.adjlist[v]->firstarc;p;p=p->nextarc)//邻接边进行深度优先遍历
	{
		int i = p->adjvex;
		if(!visited[i])
		{
			DFS(G,i)
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值