图的基本操作

求图的简单路径和回路

下面是用邻接表存储无向图,然后输出图中指定顶点间的指定长度的简单路径,

简单路径就是路径中的顶点不重复,

还有一个就是求出图中经过某顶点的回路,

都是对图的遍历算法的应用,

主要是深度优先的遍历,

加上简单的回溯。

 

下面是代码

 

  1. //文件"graph.h"   

2.       

3.     #include <iostream>   

4.     #include <string>   求图的简单路径和回路

下面是用邻接表存储无向图,然后输出图中指定顶点间的指定长度的简单路径,

简单路径就是路径中的顶点不重复,

还有一个就是求出图中经过某顶点的回路,

都是对图的遍历算法的应用,

主要是深度优先的遍历,

加上简单的回溯。

 

下面是代码

 

  1. //文件"graph.h"   

2.       

3.     #include <iostream>   

4.     #include <string>   

5.     #include <queue>   

6.     using namespace std;  

7.     bool visited[20];  

8.     int path[20];  

9.     struct ArcNode  

10.   {  

11.       int adjvex;  

12.       ArcNode *nextarc;  

13.   };  

14.     

15.   struct VexNode  

16.   {  

17.       string data;  

18.       ArcNode *firstarc;  

19.   };  

20.     

21.   class NDGraph  

22.   {  

23.   private:  

24.       VexNode vertices[20];  

25.       int vexnum;  

26.       int arcnum;  

27.   public:  

28.       NDGraph()  

29.       {  

30.           vexnum=0;  

31.           arcnum=0;  

32.       }  

33.     

34.    //返回顶点数

35.     int GetVexNum()  

36.       {  

37.           return vexnum;  

38.       }  

39.     

          //返回顶点位置

    int Locate_Vex(string v)  

40.       {  

41.           for(int i=0;i<vexnum;i++)  

42.               if(vertices[i].data == v)  

43.                   return i;  

44.           return -1;  

45.       }  

46.     

         //构造无向图

47.       void Create_NDGraph()  

48.       {  

49.           //构造无向图  

50.           string v1,v2;  

51.           int i,j,k;  

52.           cout<<"输入顶点数和边数:";  

53.           cin>>vexnum>>arcnum;  

54.           while(vexnum>20)  

55.           {  

56.               cout<<"请输入少于20个顶点(重新输入顶点数和边数)";  

57.               cin>>vexnum>>arcnum;  

58.           }  

59.     

60.           cout<<"输入顶点名称:";  

61.           for(i=0;i<vexnum;i++)  

62.           {  

63.               cin>>vertices[i].data;  

64.               vertices[i].firstarc=NULL;  

65.           }  

66.     

67.           for(k=0;k<arcnum;k++)  

68.           {  

69.               cout<<"输入每条边对应的两个顶点:";  

70.               cin>>v1>>v2;  

71.                 

72.               i=Locate_Vex(v1);  

73.               j=Locate_Vex(v2);  

74.     

75.               while(i == -1 || j == -1)  

76.               {  

77.                   cout<<"顶点中有不符合要求的,请重新输入:";  

78.                   cin>>v1>>v2;  

79.                   i=Locate_Vex(v1);  

80.                   j=Locate_Vex(v2);  

81.               }  

82.     

83.               ArcNode *p=new ArcNode;  

84.               p->adjvex=j;  

85.               p->nextarc=vertices[i].firstarc;  

86.               vertices[i].firstarc=p;  

87.     

88.               //置对称边  

89.               ArcNode *q=new ArcNode;  

90.               q->adjvex=i;  

91.               q->nextarc=vertices[j].firstarc;  

92.               vertices[j].firstarc=q;  

93.           }  

94.           cout<<"无向图构造完成"<<endl;  

95.       }  

       

 

 

 

      

96.        void DFS_Traverse()  

97.       {  

98.           for(int i=0;i<vexnum;i++)  

99.               visited[i]=false;  

100.        for(i=0;i<vexnum;i++)  

101.            if(!visited[i])  

102.                DFS(i);  

103.    }  

104.  

           //深度优先遍历

105.    void DFS(int v)  

106.    {  

107.        visited[v]=true;  

108.        cout<<vertices[v].data<<"  ";  

109.        ArcNode *p;  

110.        int w;  

111.        for(p=vertices[v].firstarc;p;p=p->nextarc)  

112.        {  

113.            w=p->adjvex;  

114.            if(!visited[w])  

115.                DFS(w);  

116.        }  

117.    }  

118.  

         //广度优先遍历

119.    void BFS_Traverse()  

120.    {  

121.        for(int i=0;i<vexnum;i++)  

122.            visited[i]=false;  

123.        for(i=0;i<vexnum;i++)  

124.            if(!visited[i])  

125.                BFS(i);  

126.    }  

127.  

128.//广度

129.    void BFS(int v)  

130.    {  

131.        visited[v]=true;  

132.        cout<<vertices[v].data<<"  ";  

133.        queue<int> qu;  

134.        int w,k;  

135.        ArcNode *p=NULL;  

136.        qu.push(v);  

137.        while(!qu.empty())  

138.        {  

139.            w=qu.front();  

140.            qu.pop();  

141.            for(p=vertices[w].firstarc;p;p=p->nextarc)  

142.            {  

143.                k=p->adjvex;  

144.                if(!visited[k])  

145.                {  

146.                    visited[k]=true;  

147.                    cout<<vertices[k].data<<"  ";  

148.                    qu.push(k);  

149.                }  

150.            }  

151.        }  

152.    }  

153.  

 //求出一条长度为l的从uv的路径,d刚进来的时候是-1

154.    void Print_X_Y_Path(int u,int v,int l,int d)  

155.    {  

156.         

157.        int m;  

158.        d++;  

159.        visited[u]=true;  

160.        path[d]=u;  

161.        if(u == v && d == l) //找到一条路径  

162.        {  

163.            for(int i=0;i<l;i++)  

164.                cout<<vertices[ path[i] ].data<<"-->";  

165.            cout<<vertices[ path[i] ].data<<endl;  

166.        }  

167.        else if(u == v && d!=l)  

168.        {  

169.            //出现这种情况直接回溯上一顶点,不浪费时间去DFS   

170.            goto loop;  

171.        }  

172.        else  

173.        {  

174.            ArcNode *p=vertices[u].firstarc; //继续DFS   

175.            while(p)  

176.            {  

177.                m=p->adjvex;  

178.                if(!visited[m])  

179.                    Print_X_Y_Path(m,v,l,d);  

180.                p=p->nextarc;  

181.            }  

182.        }  

183.        //恢复环境,使顶点可重新使用  

184.        //路径长度减一  

185.loop:   visited[u]=false;  

186.        d--;  

187.    }  

188.  

 

 

189.    //找出从ii的回路,思想和上面的类似  

190.    void Print_X_X_Path(int i,int j,int d)  

191.    {  

192.            int v,k;  

193.        ArcNode *p;  

194.        visited[i]=true;  

195.        d++;  

196.        path[d]=i;  

197.        if(i == j && d>2)  

198.        {  

199.            for(k=0;k<d;k++)  

200.                cout<<vertices[ path[k] ].data<<"-->";  

201.            cout<<vertices[ path[k] ].data<<endl;  

202.        }  

203.        else if(i == j && d==2)  //一条边只可以走一次  

204.            goto lop;  

205.        else  

206.        {  

207.            p=vertices[i].firstarc;  

208.            while(p)  

209.            {  

210.                v=p->adjvex;  

211.                if(!visited[v] || v == j)  

212.                    Print_X_X_Path(v,j,d);  

213.                p=p->nextarc;  

214.            }  

215.        }  

216.          

217.lop:    visited[i]=false;  

218.        d--;  

219.    }  

220.  

221.};  

主函数文件

  1. #include "graph.h"   

2.     #include <iostream>   

3.     #include <string>   

4.     using namespace std;  

5.       

6.     int main()  

7.     {  

8.         NDGraph G;  

9.         string v1,v2;  

10.       int u,v;  

11.       int num;  

12.       G.Create_NDGraph();  

13.     

14.       cout<<"图的深度优先遍历为:";  

15.       G.DFS_Traverse();  

16.       cout<<endl;  

17.     

18.       cout<<"图的广度优先遍历为:";  

19.       G.BFS_Traverse();  

20.       cout<<endl;  

21.     

22.       cout<<"输入两个顶点名称和一个数字,"<<endl;  

23.       cout<<"将输出长度为输入数字大小的两顶点间路径:";  

24.       cin>>v1>>v2>>num;  

25.     

26.       u=G.Locate_Vex(v1);  

27.       v=G.Locate_Vex(v2);  

28.       if(u == -1 || v == -1)  

29.       {  

30.           cout<<"顶点中有不符合要求的,操作失败"<<endl;  

31.       }  

32.       else  

33.       {  

34.           for(int i=0;i<G.GetVexNum();i++)  

35.               visited[i]=false;  

36.           cout<<"顶点 "<<v1<<"  "<<v2<<" 长度为 "<<num<<" 的简单路径如下:"<<endl;  

37.           G.Print_X_Y_Path(u,v,num,-1);  

38.       }  

39.     

40.       cout<<"输入一个顶点名称,将输出所有经过它的回路:";  

41.       cin>>v1;  

42.       u=G.Locate_Vex(v1);  

43.       if(u == -1)  

44.       {  

45.           cout<<"顶点不存在,操作失败"<<endl;  

46.       }  

47.       else  

48.       {  

49.           for(v=0;v<G.GetVexNum();v++)  

50.               visited[v]=false;  

51.           cout<<"经过顶点 "<<v1<<" 的所有回路如下:"<<endl;  

52.           G.Print_X_X_Path(u,u,-1);  

53.       }  

54.       return 0;  

55.   }  

  1. 输入顶点数和边数:5 6  

2.     输入顶点名称:v1 v2 v3 v4 v5  

3.     输入每条边对应的两个顶点:v1 v2  

4.     输入每条边对应的两个顶点:v1 v4  

5.     输入每条边对应的两个顶点:v2 v4  

6.     输入每条边对应的两个顶点:v2 v3  

7.     输入每条边对应的两个顶点:v3 v5  

8.     输入每条边对应的两个顶点:v4 v5  

9.     无向图构造完成  

10.   图的深度优先遍历为:v1  v4  v5  v3  v2  

11.   图的广度优先遍历为:v1  v4  v2  v5  v3  

12.   输入两个顶点名称和一个数字,  

13.   将输出长度为输入数字大小的两顶点间路径:v1 v3 3  

14.   顶点 v1  v3 长度为 3 的简单路径如下:  

15.   v1-->v4-->v5-->v3  

16.   v1-->v4-->v2-->v3  

17.   输入一个顶点名称,将输出所有经过它的回路:v4  

18.   经过顶点 v4 的所有回路如下:  

19.   v4-->v5-->v3-->v2-->v4  

20.   v4-->v5-->v3-->v2-->v1-->v4  

21.   v4-->v2-->v3-->v5-->v4  

22.   v4-->v2-->v1-->v4  

23.   v4-->v1-->v2-->v3-->v5-->v4  

24.   v4-->v1-->v2-->v4  

25.   Press any key to continue  

 

下面是生成的无向图示例:

为了更好得理解回溯的过程,可以画画像下面这样的示意图,比如我求 V1  V3的长度为3的路径的过程

图可能和你画的不一样,但是主要就是理清一下思路,不会在一重重的递归中乱掉

5.     #include <queue>   

6.     using namespace std;  

7.     bool visited[20];  

8.     int path[20];  

9.     struct ArcNode  

10.   {  

11.       int adjvex;  

12.       ArcNode *nextarc;  

13.   };  

14.     

15.   struct VexNode  

16.   {  

17.       string data;  

18.       ArcNode *firstarc;  

19.   };  

20.     

21.   class NDGraph  

22.   {  

23.   private:  

24.       VexNode vertices[20];  

25.       int vexnum;  

26.       int arcnum;  

27.   public:  

28.       NDGraph()  

29.       {  

30.           vexnum=0;  

31.           arcnum=0;  

32.       }  

33.     

34.    //返回顶点数

35.     int GetVexNum()  

36.       {  

37.           return vexnum;  

38.       }  

39.     

          //返回顶点位置

    int Locate_Vex(string v)  

40.       {  

41.           for(int i=0;i<vexnum;i++)  

42.               if(vertices[i].data == v)  

43.                   return i;  

44.           return -1;  

45.       }  

46.     

         //构造无向图

47.       void Create_NDGraph()  

48.       {  

49.           //构造无向图  

50.           string v1,v2;  

51.           int i,j,k;  

52.           cout<<"输入顶点数和边数:";  

53.           cin>>vexnum>>arcnum;  

54.           while(vexnum>20)  

55.           {  

56.               cout<<"请输入少于20个顶点(重新输入顶点数和边数)";  

57.               cin>>vexnum>>arcnum;  

58.           }  

59.     

60.           cout<<"输入顶点名称:";  

61.           for(i=0;i<vexnum;i++)  

62.           {  

63.               cin>>vertices[i].data;  

64.               vertices[i].firstarc=NULL;  

65.           }  

66.     

67.           for(k=0;k<arcnum;k++)  

68.           {  

69.               cout<<"输入每条边对应的两个顶点:";  

70.               cin>>v1>>v2;  

71.                 

72.               i=Locate_Vex(v1);  

73.               j=Locate_Vex(v2);  

74.     

75.               while(i == -1 || j == -1)  

76.               {  

77.                   cout<<"顶点中有不符合要求的,请重新输入:";  

78.                   cin>>v1>>v2;  

79.                   i=Locate_Vex(v1);  

80.                   j=Locate_Vex(v2);  

81.               }  

82.     

83.               ArcNode *p=new ArcNode;  

84.               p->adjvex=j;  

85.               p->nextarc=vertices[i].firstarc;  

86.               vertices[i].firstarc=p;  

87.     

88.               //置对称边  

89.               ArcNode *q=new ArcNode;  

90.               q->adjvex=i;  

91.               q->nextarc=vertices[j].firstarc;  

92.               vertices[j].firstarc=q;  

93.           }  

94.           cout<<"无向图构造完成"<<endl;  

95.       }  

       

 

 

 

      

96.        void DFS_Traverse()  

97.       {  

98.           for(int i=0;i<vexnum;i++)  

99.               visited[i]=false;  

100.        for(i=0;i<vexnum;i++)  

101.            if(!visited[i])  

102.                DFS(i);  

103.    }  

104.  

           //深度优先遍历

105.    void DFS(int v)  

106.    {  

107.        visited[v]=true;  

108.        cout<<vertices[v].data<<"  ";  

109.        ArcNode *p;  

110.        int w;  

111.        for(p=vertices[v].firstarc;p;p=p->nextarc)  

112.        {  

113.            w=p->adjvex;  

114.            if(!visited[w])  

115.                DFS(w);  

116.        }  

117.    }  

118.  

         //广度优先遍历

119.    void BFS_Traverse()  

120.    {  

121.        for(int i=0;i<vexnum;i++)  

122.            visited[i]=false;  

123.        for(i=0;i<vexnum;i++)  

124.            if(!visited[i])  

125.                BFS(i);  

126.    }  

127.  

128.//广度

129.    void BFS(int v)  

130.    {  

131.        visited[v]=true;  

132.        cout<<vertices[v].data<<"  ";  

133.        queue<int> qu;  

134.        int w,k;  

135.        ArcNode *p=NULL;  

136.        qu.push(v);  

137.        while(!qu.empty())  

138.        {  

139.            w=qu.front();  

140.            qu.pop();  

141.            for(p=vertices[w].firstarc;p;p=p->nextarc)  

142.            {  

143.                k=p->adjvex;  

144.                if(!visited[k])  

145.                {  

146.                    visited[k]=true;  

147.                    cout<<vertices[k].data<<"  ";  

148.                    qu.push(k);  

149.                }  

150.            }  

151.        }  

152.    }  

153.  

 //求出一条长度为l的从uv的路径,d刚进来的时候是-1

154.    void Print_X_Y_Path(int u,int v,int l,int d)  

155.    {  

156.         

157.        int m;  

158.        d++;  

159.        visited[u]=true;  

160.        path[d]=u;  

161.        if(u == v && d == l) //找到一条路径  

162.        {  

163.            for(int i=0;i<l;i++)  

164.                cout<<vertices[ path[i] ].data<<"-->";  

165.            cout<<vertices[ path[i] ].data<<endl;  

166.        }  

167.        else if(u == v && d!=l)  

168.        {  

169.            //出现这种情况直接回溯上一顶点,不浪费时间去DFS   

170.            goto loop;  

171.        }  

172.        else  

173.        {  

174.            ArcNode *p=vertices[u].firstarc; //继续DFS   

175.            while(p)  

176.            {  

177.                m=p->adjvex;  

178.                if(!visited[m])  

179.                    Print_X_Y_Path(m,v,l,d);  

180.                p=p->nextarc;  

181.            }  

182.        }  

183.        //恢复环境,使顶点可重新使用  

184.        //路径长度减一  

185.loop:   visited[u]=false;  

186.        d--;  

187.    }  

188.  

 

 

189.    //找出从ii的回路,思想和上面的类似  

190.    void Print_X_X_Path(int i,int j,int d)  

191.    {  

192.            int v,k;  

193.        ArcNode *p;  

194.        visited[i]=true;  

195.        d++;  

196.        path[d]=i;  

197.        if(i == j && d>2)  

198.        {  

199.            for(k=0;k<d;k++)  

200.                cout<<vertices[ path[k] ].data<<"-->";  

201.            cout<<vertices[ path[k] ].data<<endl;  

202.        }  

203.        else if(i == j && d==2)  //一条边只可以走一次  

204.            goto lop;  

205.        else  

206.        {  

207.            p=vertices[i].firstarc;  

208.            while(p)  

209.            {  

210.                v=p->adjvex;  

211.                if(!visited[v] || v == j)  

212.                    Print_X_X_Path(v,j,d);  

213.                p=p->nextarc;  

214.            }  

215.        }  

216.          

217.lop:    visited[i]=false;  

218.        d--;  

219.    }  

220.  

221.};  

主函数文件

  1. #include "graph.h"   

2.     #include <iostream>   

3.     #include <string>   

4.     using namespace std;  

5.       

6.     int main()  

7.     {  

8.         NDGraph G;  

9.         string v1,v2;  

10.       int u,v;  

11.       int num;  

12.       G.Create_NDGraph();  

13.     

14.       cout<<"图的深度优先遍历为:";  

15.       G.DFS_Traverse();  

16.       cout<<endl;  

17.     

18.       cout<<"图的广度优先遍历为:";  

19.       G.BFS_Traverse();  

20.       cout<<endl;  

21.     

22.       cout<<"输入两个顶点名称和一个数字,"<<endl;  

23.       cout<<"将输出长度为输入数字大小的两顶点间路径:";  

24.       cin>>v1>>v2>>num;  

25.     

26.       u=G.Locate_Vex(v1);  

27.       v=G.Locate_Vex(v2);  

28.       if(u == -1 || v == -1)  

29.       {  

30.           cout<<"顶点中有不符合要求的,操作失败"<<endl;  

31.       }  

32.       else  

33.       {  

34.           for(int i=0;i<G.GetVexNum();i++)  

35.               visited[i]=false;  

36.           cout<<"顶点 "<<v1<<"  "<<v2<<" 长度为 "<<num<<" 的简单路径如下:"<<endl;  

37.           G.Print_X_Y_Path(u,v,num,-1);  

38.       }  

39.     

40.       cout<<"输入一个顶点名称,将输出所有经过它的回路:";  

41.       cin>>v1;  

42.       u=G.Locate_Vex(v1);  

43.       if(u == -1)  

44.       {  

45.           cout<<"顶点不存在,操作失败"<<endl;  

46.       }  

47.       else  

48.       {  

49.           for(v=0;v<G.GetVexNum();v++)  

50.               visited[v]=false;  

51.           cout<<"经过顶点 "<<v1<<" 的所有回路如下:"<<endl;  

52.           G.Print_X_X_Path(u,u,-1);  

53.       }  

54.       return 0;  

55.   }  

  1. 输入顶点数和边数:5 6  

2.     输入顶点名称:v1 v2 v3 v4 v5  

3.     输入每条边对应的两个顶点:v1 v2  

4.     输入每条边对应的两个顶点:v1 v4  

5.     输入每条边对应的两个顶点:v2 v4  

6.     输入每条边对应的两个顶点:v2 v3  

7.     输入每条边对应的两个顶点:v3 v5  

8.     输入每条边对应的两个顶点:v4 v5  

9.     无向图构造完成  

10.   图的深度优先遍历为:v1  v4  v5  v3  v2  

11.   图的广度优先遍历为:v1  v4  v2  v5  v3  

12.   输入两个顶点名称和一个数字,  

13.   将输出长度为输入数字大小的两顶点间路径:v1 v3 3  

14.   顶点 v1  v3 长度为 3 的简单路径如下:  

15.   v1-->v4-->v5-->v3  

16.   v1-->v4-->v2-->v3  

17.   输入一个顶点名称,将输出所有经过它的回路:v4  

18.   经过顶点 v4 的所有回路如下:  

19.   v4-->v5-->v3-->v2-->v4  

20.   v4-->v5-->v3-->v2-->v1-->v4  

21.   v4-->v2-->v3-->v5-->v4  

22.   v4-->v2-->v1-->v4  

23.   v4-->v1-->v2-->v3-->v5-->v4  

24.   v4-->v1-->v2-->v4  

25.   Press any key to continue  

 

下面是生成的无向图示例:

为了更好得理解回溯的过程,可以画画像下面这样的示意图,比如我求 V1  V3的长度为3的路径的过程

图可能和你画的不一样,但是主要就是理清一下思路,不会在一重重的递归中乱掉

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值