数据结构:以邻接表为存储结构,实现深度优先遍历的非递归算法
难点:1.邻接表结构的实现(链表学好了就很顺利,学的不好危)
2.用栈实现非递归DFS(不要忘了递归的本质就是栈的进出)
关键函数实现:
邻接表构造函数:
template<class T>
ALGraph<T>::ALGraph()
{
int n, m;
int start, end;
cout << "请输入你所要构建的图的顶点数目和边的数目" << endl;
cin >> n >> m;
vNum = n;
arcNum = m;
cout << "请依次输入各顶点的值" << endl;
for (int i = 1; i <= n; i++)
{
cin >> adjlist[i].vertex;
adjlist[i].firstarc = NULL;
}
cout << "请输入每条边的两个顶点" << endl;
for (int i = 1; i <= m; i++)
{
cin >> start >> end;
insert(start, end);
insert(end, start);
}
}
template<class T>
void ALGraph<T>::insert(int start, int end)
{
if (adjlist[start].firstarc == NULL)
{
ArcNode *Node = new ArcNode;
Node->adjvex = end;
adjlist[start].firstarc = Node;
Node->nextarc = NULL;
}//当头结点是孤岛时的情况,做直接连接
else
{
ArcNode *Node = new ArcNode;
Node->adjvex = end;
Node->nextarc = adjlist[start].firstarc;
adjlist[start].firstarc = Node;
}//当头节点已经有路的时候,做链表插入
}
非递归DFS:
template<class T>
void ALGraph<T>::staDFS(int v)
{
int Vis[MAXSIZE];//标记是否访问
memset(Vis, 0, sizeof(Vis));
stack<int>s;
s.push(v);
Vis[v] = 1;
int j = 0;
while (s.empty() != 1)//当栈非空时
{
ArcNode *Node = adjlist[s.top()].firstarc;
int npop = 1;//判断是否弹出栈顶,1时弹出
while (Node)//不是空结点时,向后推进
{
if (Vis[Node->adjvex] == 0)//该结点还没有被访问过
{
s.push(Node->adjvex);
Vis[Node->adjvex] = 1;
npop = 0;
break;
}
Node = Node->nextarc;
}
if (npop)
{
cout << adjlist[s.top()].vertex << " ";
s.pop();
}
//cout << "进行栈操作" << ++j << "次" << endl;
}//以加入或弹出为单独一次操作
cout << endl;
}
遇到的困难总结:
邻接表构造的时候链表插入,忽略了表头一开始是NULL为空的情况,导致一直指不对
总代码:
ALGraph.h
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
#define MAXSIZE 10
struct ArcNode {
int adjvex;//数据域,邻接顶点下标
ArcNode *nextarc;//指针域,指向下一条弧结点 (疑教材有误)
};//弧结点
struct VertexNode {
char vertex;//数据域,顶点信息
ArcNode *firstarc;//指针域:指向第一条弧
};//顶点结点
template<class T>class ALGraph
{
public:
ALGraph();
//~ALGraph();
//void DFS(int v);
//void BFS(int v);
void staDFS(int v);
void insert(int start, int end);//将每一条路插入进邻接表里
void print();
private:
VertexNode adjlist[MAXSIZE];//结点
int vNum, arcNum;//顶点数目和弧的数目
};
template<class T>
ALGraph<T>::ALGraph()
{
int n, m;
int start, end;
cout << "请输入你所要构建的图的顶点数目和边的数目" << endl;
cin >> n >> m;
vNum = n;
arcNum = m;
cout << "请依次输入各顶点的值" << endl;
for (int i = 1; i <= n; i++)
{
cin >> adjlist[i].vertex;
adjlist[i].firstarc = NULL;
}
cout << "请输入每条边的两个顶点" << endl;
for (int i = 1; i <= m; i++)
{
cin >> start >> end;
insert(start, end);
insert(end, start);
}
}
//template<class T>
//void ALGraph<T>::DFS(int v)
//{
// int visited[MAXSIZE];
// memset(visited, 0, sizeof(visited));
// cout << adjlist[v].vertex << endl;
// visited[v] = 1;
// ArcNode *p = adjlist[v].firstarc;
// while (p)
// {
// int j = p->adjvex;
// if (visited[j] == 0)
// DFS(j);
// p = p->nextarc;
// }
//}
template<class T>
void ALGraph<T>::insert(int start, int end)
{
if (adjlist[start].firstarc == NULL)
{
ArcNode *Node = new ArcNode;
Node->adjvex = end;
adjlist[start].firstarc = Node;
Node->nextarc = NULL;
}//当头结点是孤岛时的情况,做直接连接
else
{
ArcNode *Node = new ArcNode;
Node->adjvex = end;
Node->nextarc = adjlist[start].firstarc;
adjlist[start].firstarc = Node;
}//当头节点已经有路的时候,做链表插入
}
template<class T>
void ALGraph<T>::print()
{
for (int i = 1; i <= vNum; i++)
{
ArcNode *Node = adjlist[i].firstarc;
cout << adjlist[i].vertex ;
while (Node)
{
cout <<"->"<< Node->adjvex ;
Node = Node->nextarc;
}
cout << endl;
}
}
template<class T>
void ALGraph<T>::staDFS(int v)
{
int Vis[MAXSIZE];//标记是否访问
memset(Vis, 0, sizeof(Vis));
stack<int>s;
s.push(v);
Vis[v] = 1;
int j = 0;
while (s.empty() != 1)//当栈非空时
{
ArcNode *Node = adjlist[s.top()].firstarc;
int npop = 1;//判断是否弹出栈顶,1时弹出
while (Node)//不是空结点时,向后推进
{
if (Vis[Node->adjvex] == 0)//该结点还没有被访问过
{
s.push(Node->adjvex);
Vis[Node->adjvex] = 1;
npop = 0;
break;
}
Node = Node->nextarc;
}
if (npop)
{
cout << adjlist[s.top()].vertex << " ";
s.pop();
}
//cout << "进行栈操作" << ++j << "次" << endl;
}//以加入或弹出为单独一次操作
cout << endl;
}
//FOR Caicai
main.cpp
#include<iostream>
#include"ALGraph.h"
using namespace std;
int main()
{
ALGraph<char>ALG;
cout << "邻接表构造结果如下:" << endl;
ALG.print();
// ALG.DFS(1);
cout << "遍历结果如下" << endl;
ALG.staDFS(1);
}
//6 1
//1 2
//2 5
//1 3
//3 2
//3 4
//FOR Caicai
测试样例图:
效果图:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现