数据结构——广度优先搜索求点到点的最短路径
#include <iostream>
using namespace std;
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define NULL 0
#define MAX_VERTEX_NUM 20 // 最大顶点数
typedef char VertexType;
typedef int VRType;
typedef int InforType;
typedef struct ArcNode
{
int adjvex; //该边所指的顶点的位置
struct ArcNode *nextarc; //指向下一条边的指针
//int weight; //边的权
}ArcNode; //表的结点
typedef struct VNode
{
VertexType data; //顶点信息(如数据等)
ArcNode *firstarc; //指向第一条依附该顶点的边的弧指针
}VNode, AdjList[MAX_VERTEX_NUM]; //头结点
typedef struct ALGraph
{
AdjList vertices;
int visited[MAX_VERTEX_NUM]; //访问标志数组
int vexnum, arcnum; //图的当前顶点数和弧数
}ALGraph;
//==============================================================================
typedef struct qnode
{
char data;
struct qnode * pre;
struct qnode * next;
}Qnode, * Queueptr; // 创建链 Qnode是struct qnode的别名,Queueptr是struct qnode *的别名
typedef struct
{
Queueptr front; //对头指针
Queueptr rear; //队尾指针
}LinkQueue; //创建队列
//初始化队列
void InitQueue(LinkQueue *Q)
{
Q->front=(Queueptr) malloc(sizeof(Qnode)); //队头和队尾指向头结点
if(!Q->front)
{
cout<<"no memory avaliable"<<endl; //存储分配失败
}
else
{
Q->front->next=NULL;
Q->rear=Q->front;
}
}
//入队列函数
void Enqueue(LinkQueue *Q,int value)
{
Queueptr newp=(Queueptr)malloc(sizeof(Qnode));
if(!newp)
cout<<"no memory avaliable"<<endl; //存储分配失败
newp->data=value;
newp->next=NULL;
Q->rear->next=newp; //p插入原队尾
Q->rear=newp; //p成为新的队尾
}
//================================================================================
//初始化图
void init_ALGraph(ALGraph &g)
{
for(int i=0;i<MAX_VERTEX_NUM;i++)
g.visited[i]=0; //访问标志数组置0,表示没有被访问
g.vexnum=0;
g.arcnum=0;
}
//返回顶点v在顶点向量中的位置
int LocateVex(ALGraph &G, char v)
{
int i;
for(i = 0; v != G.vertices[i].data && i < G.vexnum; i++)
;
if(i >= G.vexnum)
return -1;
return i;
}
//增加节点
void add_vex(ALGraph &G)
{
cout<<"输入无向图顶点数: "<<endl;
cin>>G.vexnum;
//getchar(); //吃回车
cout<<"输入顶点信息:"<<endl;
for(int i = 0; i < G.vexnum; i++)
{
cin>>G.vertices[i].data; //构造顶点向量
G.vertices[i].firstarc = NULL;
//getchar();
}
}
//增加边
void add_arc(ALGraph &G)
{
ArcNode *s, *t;
ArcNode *p;
cout<<"输入无向图边数: "<<endl;
cin>>G.arcnum;
char v1, v2;
cout<<"输入边信息:"<<endl;
for(int k = 0; k < G.arcnum; k++)
{
cin>>v1>>v2;
int i = LocateVex(G, v1);
int j = LocateVex(G, v2); //确定v1 , v2在G中的位置
s = (ArcNode*) malloc (sizeof(ArcNode));
t = (ArcNode*) malloc (sizeof(ArcNode));
s->adjvex = j; //该边所指向的顶点的位置为j
s->nextarc = NULL;
if(!G.vertices[i].firstarc)
{
G.vertices[i].firstarc=s;
}
else
{
for(p = G.vertices[i].firstarc; p->nextarc; p = p->nextarc)
;
p->nextarc=s;
}
t->adjvex = i; //该边所指向的顶点的位置为j
t->nextarc = NULL;
if(!G.vertices[j].firstarc)
{
G.vertices[j].firstarc=t;
}
else
{
for(p = G.vertices[j].firstarc; p->nextarc; p = p->nextarc)
;
p->nextarc=t;
}
}
}
//构造邻接链表
void CreateUDN(ALGraph &G)
{
add_vex(G); //增加节点
add_arc(G); //增加边
}
void PrintAdjList(ALGraph &G)
{
int i;
ArcNode *p;
cout<<"编号 顶点 邻点编号"<<endl;
for(i = 0; i < G.vexnum; i++)
{
cout<<" "<<i<<" "<<G.vertices[i].data<<" ";
for(p = G.vertices[i].firstarc; p; p = p->nextarc)
cout<<p->adjvex<<" ";
cout<<endl;
}
}
//求点到点的最短路径
void Path(ALGraph &g,char ch1, char ch2, char path[]) //从第i个顶点开始搜索
{
ArcNode *p;
int i = LocateVex(g, ch1);
int s = LocateVex(g, ch2);
int found=0;
char gettop;
int top;
LinkQueue *Q=(LinkQueue *)malloc(sizeof(LinkQueue));
//初始化队列
InitQueue(Q);
g.visited[i]=1; //处理源点
Enqueue(Q,g.vertices[i].data); //源点入队
Q->rear->pre=Q->front; //第一个节点的前驱指针指向front
Queueptr temp=Q->front->next; //处理队列中的每个顶点
while(!found)
{
gettop=temp->data;
top= LocateVex(g, gettop);
for(p = g.vertices[top].firstarc; p && !found; p = p->nextarc)
{
if(s == p->adjvex) //找到目标点
{
found=1; //标志设为1,入队列,退出
Enqueue(Q,g.vertices[p->adjvex].data);
Q->rear->pre=temp; //加入队列中的点,前驱指针指向它的源点
}
else if( !g.visited[p->adjvex] ) //如果不是,就访问,并加入队列
{
g.visited[p->adjvex]=1;
Enqueue(Q,g.vertices[p->adjvex].data); //入队
Q->rear->pre=temp;
}
}
temp=temp->next;
}//while
int j=0;
for(temp=Q->rear; temp!=Q->front; temp=temp->pre) //复制队列中的顶点到字符串中去
path[j++]=temp->data;
path[j]='\0';
}
int main()
{
ALGraph G;
init_ALGraph(G); //初始化图
CreateUDN(G); //创建图
PrintAdjList(G); //打印图
//求点到点的最短路径
char ch1,ch2;
char *path; //存放路径
path=(char *)malloc( MAX_VERTEX_NUM*sizeof(char) );
cout<<"please input two points:"<<endl;
cin>>ch1>>ch2;
Path(G,ch1,ch2,path); //广度优先搜索
int i=0;
while(path[i])
cout<<path[i++]; //输出路径
cout<<endl;
return 0;
}