#include<iostream>
using namespace std;
#define MAX 20
#define NULL 0
typedef struct ArcCell{
int adj;
}ArcCell,AdjMatrix[MAX][MAX];
//定义二维数组矩阵,adj是将来存的权值
typedef struct{
char Vexs[MAX];
AdjMatrix arcs;
int
vexnum,arcnum;
}MGraph;
//点的名称,二维数组,点、边的个数
typedef struct QNode{
int data;
struct QNode *next;
}QNode,*QueuePtr; //队列的结点的申请,并且明确其类型!
typedef struct{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
//创建头尾指针结构体
int LnitQueue(LinkQueue &Q){
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode)); //分配空节点,创建空队列
Q.front->next=NULL;
//头结点next指针为空
return 0;
};
int EnQueue(LinkQueue &Q,int e){ //加入队列,结点值为e
QueuePtr p;
p=(QueuePtr)malloc(sizeof(QNode)); //分配结点空间
p->data=e;
//数据赋值
p->next=NULL;
Q.rear->next=p;
//在尾部插入
Q.rear=p;
//尾部指针指向尾部,所谓的头指针和尾指针都只是指针,只不过指针指向特殊申明的结点,不要把它看成
return
0; //队列的一部分,意想成为也是头结点,其实不是这样的!
};
int DeQueue(LinkQueue &Q,int &e){ //Q.front or
Q.rear仅仅是指针而已,不是什么结点!!!,但队列中还是有头结点概念!
//在创建空队列的时候就决定了一定会有头结
点,并且新加入元素在队伍尾进行!
if(Q.front==Q.rear) cout<<"The Queue is
wrong!"<<endl;
QueuePtr p;
p=Q.front->next;
//p指向第一个结点
e=p->data; //e复制数据
Q.front->next=p->next;
// 队头指针下移一位
if(Q.rear==p) Q.rear=Q.front;
//如果队列为空了,则队头等于对尾,这是常常忽略的,此时还是有空的头结点的!
delete(p);
return 0;
};
int QueueEmpty(LinkQueue Q){
if(Q.front==Q.rear)return 1; //判断是否为空,空为1,不空为0
else return 0;
};
int LocateVex(MGraph &G ,char v){
int i=0;
for(;v!=G.Vexs[i];i++);
//根据点的名称确定其在二维数组中的下标
return i;
};
int CreateUDG(MGraph &G){
cout<<"please input the
vexnum and arcnum"<<endl;
cin>>G.vexnum>>G.arcnum;
//提示输入点和边的个数
int i,j,k,w;
char
v1,v2; //v1,v2作为点的名称的临时存储变量
for(i=0;i<G.vexnum;++i){
cout<<"please
input the name of the point"<<endl;
cin>>G.Vexs[i];
}
//提示输入点的名称,存入Vexs数组中!
for(i=0;i<G.vexnum;++i)
//初始化二维数组,使得其初值都为1000!
for(j=0;j<G.vexnum;++j)
G.arcs[i][j].adj=0;
for(k=0;k<G.arcnum;++k){
cout<<"please
input the link and num"<<endl; //提示输入边及权值的信息!
cin>>v1>>v2>>w;
i=LocateVex(G,v1);
j=LocateVex(G,v2);
//确定输入的点的名称在邻接矩阵中的下标
G.arcs[i][j].adj=w;
//存入邻接矩阵中
G.arcs[j][i].adj=G.arcs[i][j].adj;
//因为是无向图,因此是一个对称阵!
}
return 0;
};
int Visited[MAX]; //标志数组!用来表明是否被访问过
int FirstAdjVex(MGraph G,int v){ //求邻接结点
int j;
for(j=0;j<G.vexnum;j++){ //对邻接矩阵的v行进行遍历!
if(G.arcs[v][j].adj==1
&& Visited[j]==0) //当v与某点有边存在并且没有被访问过,则就是v的邻接结点
return
j;
}
return -1; //没有邻接节点就返回-1!
};
int NextAdjVex(MGraph G,int v,int w){
int j;
for(j=w;j<G.vexnum;j++){
if(G.arcs[v][j].adj==1 &&
Visited[j]==0) //求v的第二个邻接结点,即从v行w点后开始遍历!
return j;
}
return
-1;
};
void BFSTraverse(MGraph G){
int v,u,w;
for(v=0;v<G.vexnum;++v)Visited[v]=0;
//初始化标志数组,均置为0
LinkQueue Q;
LnitQueue(Q);
//创建空队列
for(v=0;v<G.vexnum;++v)
//for循环其实是很重要的,因为它遍历所有结点,考虑了多个分图存在的情况
if(!Visited[v]){
Visited[v]=1;
//对没有访问过的结点进行反复,并且输出!
cout<<G.Vexs[v]<<endl;
EnQueue(Q,v);
//记录访问过的结点,压入队列!做记录
while(!QueueEmpty(Q)){
//可以对队列中的结点的所有未访问的邻接结点进行访问!
DeQueue(Q,u); //取出队列第一个结点
for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w))
if(!Visited[w]){
Visited[w]=1;
//对没有访问过的结点进行反复,并且输出!
cout<<G.Vexs[w]<<endl;
EnQueue(Q,w);
//对一个结点的所有结点进行访问,并全部加入队列
}//if
}//while
}//if
};//BFSTraverse
int main(){
MGraph G; //申请并创建图
CreateUDG(G);
BFSTraverse(G);
//进入函数进行遍历
return 0;
}