数据结构——广度优先搜索求点到点的最短路径

  
    
#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 ;
}

 

你可能感兴趣的:(数据结构)