非带权无向图的广度优先遍历

非带权无向图的广度优先遍历

【问题描述】输入一个不带权值的无向图的信息,用邻接表存储图,输出邻接表,然后输入一个起始顶点,从该顶点开始进行广度优先遍历,输出遍历的顶点序列

【输入形式】输入有多行,第1行输入两个整数m, n,第1个m为顶点数,第2个n为边数,第2行输入全部顶点名字(一般用大写字母表示),后面还有n行数据,分别是每一条边的2个顶点的名字,最后一行输入广度优先遍历起始顶点的名字

【输出形式】输出图的邻接表,具体格式见Sample Output,最后一行输出图得广度优先遍历的顶点序列,各个顶点之间用一个空格隔开,最后一个顶点后也有一个空格,不用单独处理

【样例输入】

9 10

ABCDEFGHI

AD

AC

AB

BE

BC

CF

DF

EG

FH

HI

A

【样例输出】

0 A–>1–>2–>3
1 B–>2–>4–>0
2 C–>5–>1–>0
3 D–>5–>0
4 E–>6–>1
5 F–>7–>3–>2
6 G–>4
7 H–>8–>5
8 I–>7
A B C D E F G H I

代码如下(含有注释):
#include<iostream>

using namespace std;

//邻接边的结点定义
struct EdgeNode
{
	int Ver_position;//邻接结点的位置
	string Edge_info;//邻接边的信息
	EdgeNode* Next_edge;//下一个邻接边
	EdgeNode()
	{
		Ver_position = -1;
		Edge_info = "";
		Next_edge = NULL;
	}
	EdgeNode(int x, string y)
	{
		Ver_position = x; 
		Edge_info = y; 
		Next_edge = NULL; 
	}
};

//顶点的结点定义
template<class T>
struct VertexNode
{
	T data;//顶点的值
	EdgeNode* Adj_edge;//顶点的第一条邻接边的信息
	VertexNode()
	{
		data = 0;
		Adj_edge = NULL;
	}
};

//队列结点定义
template<class T>
struct QueneNode
{
	VertexNode<T>* data;//以顶点指针为数据域
	QueneNode* link;//下一个队列结点
	QueneNode()
	{
		data = NULL;
		link = NULL;
	}
	QueneNode(VertexNode<T>* x)
	{
		data = x;
		link = NULL;
	}
};

//无向图的类定义
template<class T>
class UndirGraph
{
public:
	UndirGraph(int x, int y);//构造函数
	int Judge_ver(T x);//判断顶点的位置
	char output_ver(int x)//输出某个位置的顶点的值
	{
		return array[x].data;
	}
	void Insert_edge(string x);//插入边
	void display();//输出邻接边
	VertexNode<T>* Get_ver()//取得顶点数组的首地址
	{
		return array;
	}
private:
	VertexNode<T>* array;//顶点数组指针
	int Len;//顶点的个数
};

//队列类的定义
template<class T>
class Quene
{
public:
	Quene();//构造函数
	bool Join_quene(VertexNode<T>* x);//入队
	bool Leave_quen(VertexNode<T>*& x);//出队
	bool Is_Empty();//判断队列是否为空
private:
	QueneNode<T>* front;//队头指针
	QueneNode<T>* rear;//队尾指针
};

//无向图的构造函数,构造邻接表
template<class T>
UndirGraph<T>::UndirGraph(int x, int y)//x为顶点数目,y为边的数目
{
	Len = x;
	array = new VertexNode<T>[x];//构造顶点数组
	for (int i = 0; i < Len; i++)
		cin >> array[i].data;//顶点赋值
	string temp = "";//边的定义
	for (int i = 0; i < y; i++)
	{
		cin >> temp;//输入边
		Insert_edge(temp);//插入边
		temp = "";
	}
}

//判断顶点为某值的顶点的位置
template<class T>
int UndirGraph<T>::Judge_ver(T x)
{
	for (int i = 0; i < Len; i++)
	{
		if (array[i].data == x)//值对应,则返回顶点位置
		{
			return i;
		}
	}
}

//插入邻接边
template<class T>
void UndirGraph<T>::Insert_edge(string str)
{
	EdgeNode* newedgeleft = NULL, * newedgeright = NULL;//无向图一条边属于两个结点,所以两个结点后都要插入边
	int num, pos;
	pos = Judge_ver(str[0]);//获取第一个顶点的位置
	num = Judge_ver(str[1]);//获取邻接顶点的位置
	newedgeleft = new EdgeNode(num,str);//构造邻接顶点的边
	newedgeleft->Next_edge = array[pos].Adj_edge;
	array[pos].Adj_edge = newedgeleft;//第一个顶点后面插入边
	pos = Judge_ver(str[1]);//获取邻接顶点的位置
	num = Judge_ver(str[0]);//获取第一个顶点的位置
	newedgeright = new EdgeNode(num, str);//构造第一个顶点的边
	newedgeright->Next_edge = array[pos].Adj_edge;
	array[pos].Adj_edge = newedgeright;//邻接顶点后面插入边
}

//输出邻接表
template<class T>
void UndirGraph<T>::display()
{
	EdgeNode* current = NULL;//边遍历指针
	for (int i = 0; i < Len; i++)
	{
		cout << i << ' ' << array[i].data;//输出顶点值
		current = array[i].Adj_edge;
		while (current != NULL)//遍历输出边值
		{
			cout << "-->" << current->Ver_position;
			current = current->Next_edge;
		}
		cout << endl;
	}
}

//队列构造函数
template<class T>
Quene<T>::Quene()
{
	front = new QueneNode<T>;//空头结点
	rear = front;//尾指针最开始向头结点
}

//入队
template<class T>
bool Quene<T>::Join_quene(VertexNode<T>* x)
{
	QueneNode<T>* newquenenode = NULL;//队列指针定义
	newquenenode = new QueneNode<T>(x);//队列结点的新建
	if (newquenenode==NULL)//分配空间失败
	{
		return false;
	}
	//队尾入队
	newquenenode->link = rear->link;//新结点的指针指向rear的指针域(NULL)
	rear->link = newquenenode;//rear的指针域指向新结点
	rear = newquenenode;//队尾指针指向新结点
	return true;
}

//出队
template<class T>
bool Quene<T>::Leave_quen(VertexNode<T>*& x)
{
	QueneNode<T>* p = front->link;//队头结点的指针定义
	if (front == rear)//判断队列是否为空
	{
		return false;
	}
	if (p == rear)//front指针域指向的是rear
		rear = front;//删除p时,避免rear成为野指针
	front->link = p->link;//头结点的指针域指向队头结点的指针域
	x = p->data;//传值
	delete p;//删除队列结点
	p = NULL;//避免野指针
	return true;
}

//判断队列是否为空
template<class T>
bool Quene<T>::Is_Empty()
{
	if (front == rear)//判空条件
	{
		return true;
	}
	else
	{
		return false;
	}
}

//无向图的广度遍历
void Graph_tra(UndirGraph<char> t, int n)
{
	char x;//遍历开始的顶点
	cin >> x;//输入遍历开始的顶点
	VertexNode<char>* p = NULL;//顶点遍历指针
	VertexNode<char>* temp = t.Get_ver();//顶点数组
	EdgeNode* current = NULL;//边遍历指针
	bool* Judge_ver_tra;//顶点是否被访问数组
	Judge_ver_tra = new bool[n];
	for (int i = 0; i < n; i++)
		Judge_ver_tra[i] = false;//被访问顶点所在位置为true,否者为false
	Quene<char> s;//队列
	if (temp == NULL)//如果顶点数组为空,不进行遍历
	{
		return;
	}
	s.Join_quene(&temp[t.Judge_ver(x)]);//入队开始遍历的顶点,通过顶点值找到顶点结点
	while (!s.Is_Empty())//队列为空,结束循环
	{
		int num ;//顶点位置
		s.Leave_quen(p);//出队
		num = t.Judge_ver(p->data);//顶点位置赋值
		if (!Judge_ver_tra[num])//如果没有被访问输出
		{
			cout << p->data << ' ';//输出顶点
			Judge_ver_tra[num] = true;//访问数组对应值改变为已经被访问
		}
		current = p->Adj_edge;//边遍历指针赋值
		while (current!=NULL)//边遍历指针为空,停止循环
		{
			if (!Judge_ver_tra[current->Ver_position])//如果边邻接的顶点未被访问,入队
				s.Join_quene(&temp[current->Ver_position]);
			current = current->Next_edge;//边遍历指针改变下一条边
		}
	}
	cout << endl;//保证格式
}

int main()
{
	int m, n;
	cin >> m >> n;//输入顶点数,边数
	UndirGraph<char> t(m, n);//构造无向图邻接表
	t.display();//输出无向图邻接表
	Graph_tra(t,m);//无向图的广度遍历
}
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值