数据结构:以邻接表为存储结构,实现深度优先遍历的非递归算法

难点: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

测试样例图:

效果图:

 

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是按深度优先遍历图的非递归算法的C++实现,使用邻接表作为图的存储结构: ```c++ #include<iostream> #include<stack> #include<vector> using namespace std; const int MAXN = 1005; // 邻接表结构体 struct EdgeNode { int to; // 边的终点 int weight; // 边的权值 int next; // 下一个邻接点的下标 }edges[MAXN]; int head[MAXN]; // 存储每个节点的第一个邻接点的下标 int edge_cnt = 0; // 边的数量 int node_cnt = 0; // 节点的数量 // 添加一条边 void add_edge(int u, int v, int w) { edges[++edge_cnt].to = v; edges[edge_cnt].weight = w; edges[edge_cnt].next = head[u]; head[u] = edge_cnt; } // 深度优先遍历 void dfs(int start) { vector<bool> visited(node_cnt + 1, false); // 记录每个节点是否被访问过 stack<int> s; s.push(start); visited[start] = true; cout << start << " "; while(!s.empty()) { int u = s.top(); bool flag = false; // 判断是否有未访问过的邻接点 for(int i = head[u]; i; i = edges[i].next) { int v = edges[i].to; if(!visited[v]) { s.push(v); visited[v] = true; cout << v << " "; flag = true; break; } } if(!flag) { s.pop(); } } } int main() { int n, m; cin >> n >> m; // 输入节点数量和边数量 node_cnt = n; // 输入每条边的起点、终点、权值 for(int i = 1; i <= m; i++) { int u, v, w; cin >> u >> v >> w; add_edge(u, v, w); } int start; cin >> start; // 输入起点 dfs(start); // 按深度优先遍历图 return 0; } ``` 在这个算法中,我们使用了一个栈来模拟递归的过程。首先将起点压入栈中,并标记为已访问。然后对于当前栈顶节点,遍历它的邻接点,如果有未访问过的邻接点,则将其压入栈中,并标记为已访问。如果当前节点没有未访问过的邻接点,则将其弹出栈。重复这个过程,直到栈为空。这样,就可以按深度优先遍历图,且不需要使用递归。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值