算法-计算无向图中两个节点之间所有的路径

本文介绍了一种基于深度优先搜索的图论算法,用于找出图中任意两点间的所有路径。该算法采用递归方式实现,并通过标记已访问节点避免重复路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

图论--寻找节点间所有路径

       最近在论文中,要获得节点间的路由,由此又开始继续去年的算法学习。下面的就关于寻找两个节点之间所有的路径。因为是在获得路径后,再加上权重,所以不能将那些求最短路径的算法给之间粘贴上。

   下面是我的一个路径的设想。在图中存在着7个节点,连通情况如下:

 

    首先,想到的就是树中的深度遍历。因为我们需要循着上轮访问的节点,才能确定整个路径。如果仅仅完成没有问题,最关键的在于如何记录下所有的路径。一开始,我想利用两个栈,一个放最后所有路径的结果,一个放临时刚出栈的元素。但是后面发现,本程序的起始节点是A,终止节点是E比如在从a->b->c>e,当e节点已经为最后的节点,对于临时数组中的c,它的存在没有任何的意义。

   所以本程序的关键是在于如何存放之前的路径。要避免走回路。

程序代码如下

本代码的主要思想为:

创建一个结构体Node保存key值,flag为这个元素开始遍历所在的索引位置。比如,从A->B,那么flag为1,当遍历完B,开始继续遍历到D,A的flag为3.

其中深度遍历的元素的key值可以以flag作为标准,flag+1即为下个元素的key值。在这里我们要清楚的是,比如要A->B->C,其中C为新元素,则B的flag为2,赋值给C的键值为3。

如果D连接的所有元素都被访问了,那么将D的flag重新设置为0,并设置它未被访问。因为D的访问可能来自B,也可能来自A.而A先访问,如果不设置未被访问,由A到D遍历E的路径将无法被读取

#include <iostream>
using namespace std;

#define  NUM 6+2
#define MAX_PATH 100
struct Node
{
	int key;
	int flag;//获得当前节点的范围索引
	Node()
	{
		flag=0;
	}
};

class Graph
{
public:
	//stack<int> searchStack;
	int resultPath[MAX_PATH][NUM];
	int result[NUM+1];//将result设为NUM+1,主要是为了避免发生B->D->B的事情

	Node headNode;//起始节点
	Node endNode;//终止节点
	int pathNum;
    int nPos;
	bool Mark[NUM];

public: 
	Graph()
	{
		//将矩阵中的元素置为空
		for (int i=0;i<NUM;i++)
		{
			for (int j=0;j<MAX_PATH;j++)
			{
				resultPath[j][i]=0;
			}
			result[i]=0;

			Mark[i]=false;
		}
		result[NUM]=0;
		pathNum=0;
		nPos=0;
	}

	void test()
	{
		//对应无向图的矩阵
		int Matrix[NUM][NUM]={
			{0,1,0,1,0,0,0,0}, //A
			{1,0,1,1,0,0,0,0},//B
			{0,1,0,0,1,0,0,0},//C
			{1,1,0,0,1,1,0,0}, //D
			{0,0,1,1,0,0,1,0},  //E
			{0,0,0,1,0,0,1,1},  //F
			{0,0,0,0,1,1,0,0},  //G
			{0,0,0,0,0,1,0,0}  //H
		};
		//开始节点
		headNode.key=1;
		headNode.flag=1;

		//结束节点
		endNode.key=5;

		FindAllPath(Matrix,headNode,endNode);
		cout<<"路径数目为:"<<pathNum<<endl;
		for (int i=0;i<pathNum;i++)
		{
			cout<<"第"<<i<<"条: ";
			for(int j=0;j<NUM;j++)
			{
				if (resultPath[i][j]==0)
				{
					break;
				}
				cout<<resultPath[i][j]<<"  ";
			}
			cout<<endl;
		}
		int i=0;

	}

	/************************************************************************/
	/* 函数功能:找到图中两个节点之间的所有路径
	   参数说明:1、Matrix   初始矩阵,将路径矩阵的形式存储,本程序对应的是一个无向图。
	             2、headNode 初始节点
				 3、endNode  结束节点

	    主要的思想  利用深度优先遍历的算法
	 1、利用result来存放每次从栈中出栈的数据,里面很可能就是要找的路径,为什么要单独提取出来,因为包含了多条路径
     2、通过设置 访问是否的变量来避免回路/
	/************************************************************************/
	void FindAllPath(int Matrix[NUM][NUM],Node startNodeKey,Node endNodeKey)
	{
		result[nPos]=startNodeKey.key;  //将当前元素放入结果集中
		Mark[startNodeKey.key-1]=true;  //将访问标记为已访问
		nPos++;  //结果集索引加1
		while(nPos!=0)  
		{  
			int tempVal=result[nPos-1];//获取到最前面的元素  
			if (tempVal==endNodeKey.key)  //若当前元素为目标节点
			{  
				for (int j=0;j<nPos;j++)  
				{  
					resultPath[pathNum][j]=result[j];  //将结果集复制于最后的路径矩阵中
				}  
				nPos--;  //回溯至上一个节点
				result[nPos]=0;  //结果集对应索引置为空
				pathNum++;  //路径数目加1
				Mark[endNodeKey.key-1]=false;  
				break;  
			}  
			while(startNodeKey.flag<NUM)//利用flag来指示每次的元素的索引  
			{  
				if (Matrix[tempVal-1][startNodeKey.flag]==1)  
				{  
					if (Mark[startNodeKey.flag]==false)//利用Mark来判断是否已经访问过该节点  
					{  
						Node tempNode;  
						tempNode.key=startNodeKey.flag+1;  
						FindAllPath(Matrix,tempNode,endNodeKey);//深度优先遍历算法,  
					}             
				}  
				startNodeKey.flag++;//索引值相应的加一  
			}  

			if (startNodeKey.flag==NUM)//如果已经是到最后的邻居,说明访问结束,  
			{                           //将对应的值置为空  
				nPos--;  //再次向上回溯
				startNodeKey.flag=0;  //将节点的索引置为空
				result[nPos]=0;  //将结果集中对应的索引置为空
				Mark[startNodeKey.key-1]=false;  //访问之后标记为未访问。因为下面的元素已经访问结束,便于下次的访问
				break;  
			}  
		}  
	}
};


运行结果:

 

 

 

2、matlab对应的代码

 

function [resultMatrix,nPos,result,numPath]=getPath(Graph,startData,endData,nPos,result,resultMatrix,numPath)

result(1,nPos)=startData.key;
nPos=nPos+1;
while nPos~=1
    tempVal=startData.key;
    if tempVal==endData.key
        for lengthPath=1:(nPos-1)
            resultMatrix(numPath,lengthPath)=result(lengthPath);
        end
       nPos=nPos-1;
       result(nPos)=0;
       startData.flag=1;
       numPath=numPath+1;
       break;
    end
    while startData.flag<=(length(Graph))
        t= Graph(tempVal,startData.flag);
        if t==1
          if  length(find(result==startData.flag))==0
              newData=struct('key',startData.flag,'flag',1);
              [resultMatrix,nPos,result,numPath]=getPath(Graph,newData,endData,nPos,result,resultMatrix,numPath);
          end
        end
        startData.flag=startData.flag+1;
    end
    if startData.flag==(length(Graph)+1)
        nPos=nPos-1;
        startData.flag=1;
        result(nPos)=0;
        break;
    end
end

 

小结:

 

1)节点数目增加的话,时间会很长,还需要改进

2)访问后的节点应该将路径记录下来,这里还是有问题

3)大家多多指教

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值