#include <iostream>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#define MAX 20 //定义数组的最大值
#define EXT 10000
using namespace std;
typedef struct UDN
{
char vex[MAX]; //顶点向量
int arcs[MAX][MAX]; //邻接矩阵
int vexnum,arcnum; //无向图当前顶点数和弧数
}Udn;
typedef struct ArcNode
{
int adjvex; //该弧所指向的顶点位置
struct ArcNode *nextarc; //指向下一条弧的指针
int w; //权值
}ArcNode;
typedef struct VNode
{
char data; //顶点信息
ArcNode *fristarc; //指向第一条依附该顶点的弧指针
}VNode,AdjList[MAX];
typedef struct
{
AdjList vertices;
int vexnum,arcnum; //图的顶点数和弧数
}ULGraph;
typedef struct QNode //创建队列节点
{
char data;
struct QNode *next;
}QNode,*Queue;
typedef struct
{
Queue front; //头指针
Queue rear; //尾指针
}LinkQueue;
int InitQueue(LinkQueue &Q) //创建一个空队列
{
Q.front=Q.rear=(Queue)malloc(sizeof(QNode));
Q.front->next=NULL;
return 1;
}
bool QueueEmpty(LinkQueue Q) //判断队列是否为空
{
if(Q.front==Q.rear)
return true;
return false;
}
int EnQueue(LinkQueue &Q,int e) //入队(尾)
{
Queue p;
p=(Queue)malloc(sizeof(QNode));
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p; //尾指针后移
return 1;
}
int DeQueue(LinkQueue &Q,int &e) //出队(头)
{
Queue p;
if(Q.front==Q.rear)
return 0; //空队列返回0
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front; //尾指针回送
free(p);
return 1;
}
void CreateUDN(Udn &U) //创捷邻接矩阵
{
printf("请输入无向网的顶点数和弧数:");
scanf("%d%d",&U.vexnum,&U.arcnum);
printf("请输入%d个顶点向量:",U.vexnum);
for(int i=0;i<U.vexnum;i++) //输入顶点信息
{
getchar();
scanf("%c",&U.vex[i]);
}
for(int i=0;i<U.vexnum;i++)
for(int j=0;j<U.vexnum;j++) //将多有权值付付为正无穷
U.arcs[i][j]=EXT;
puts("请输入弧的起始点和终点以及权值(eg:a b 3):");
int m,n,w;
char ch1,ch2;
for(int i=0;i<U.arcnum;i++)
{
cin>>ch1>>ch2>>w; //输入网的信息
for(int j=0;j<U.vexnum;j++)
{
if(ch1==U.vex[j])
m=j;
}
for(int j=0;j<U.vexnum;j++)
{
if(ch2==U.vex[j])
n=j;
}
U.arcs[m][n]=w; //因为是无向的,所以邻接矩阵是对称的
U.arcs[n][m]=w;
}
}
void Display1(Udn U) //显示连接矩阵
{
printf("\t");
for(int i=0;i<U.vexnum;i++)
printf("%c\t",U.vex[i]);
puts("");
for(int i=0;i<U.vexnum;i++)
{
printf("%c\t",U.vex[i]);
for(int j=0;j<U.vexnum;j++)
{
if(U.arcs[i][j]==EXT)
printf("∞\t");
else
printf("%d\t",U.arcs[i][j]);
}
puts("");
}
}
void CreateULGraph(ULGraph &ULG,Udn &U) //以邻接矩阵为基础建立邻接表
{
ULG.arcnum=U.arcnum;
ULG.vexnum=U.vexnum;
for(int i=0;i<U.vexnum;i++)
{
ULG.vertices[i].data=U.vex[i];
ULG.vertices[i].fristarc=NULL;
}
for(int i=0;i<U.vexnum;i++)
for(int j=0;j<U.vexnum;j++)
if(U.arcs[i][j]!=EXT)
{
ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=j;
p->w=U.arcs[i][j];
p->nextarc=ULG.vertices[i].fristarc;
ULG.vertices[i].fristarc=p;
}
}
void Display2(ULGraph ULG) //邻接表的输出
{
puts(" '邻接矩阵转为邻接表' 为(下标~权值):");
for(int i=0;i<ULG.vexnum;i++)
{
printf("%c %d",ULG.vertices[i].data,i);
ArcNode *p=ULG.vertices[i].fristarc;
while(p!=NULL)
{
printf("---> ");
printf("%d~%d",p->adjvex,p->w);
p=p->nextarc;
}
printf(" ^");
puts("");
}
}
void BturntoJ(ULGraph G) //链接表转换为邻接矩阵
{
Udn U;
U.vexnum=G.vexnum;
U.arcnum=G.arcnum;
for(int i=0;i<G.vexnum;i++)
{
U.vex[i]=G.vertices[i].data;
for(int j=0;j<G.vexnum;j++)
U.arcs[i][j]=EXT;
}
for(int i=0;i<G.vexnum;i++)
{
ArcNode *p=G.vertices[i].fristarc;
while(p!=NULL)
{
U.arcs[i][p->adjvex]=p->w;
U.arcs[p->adjvex][i]=p->w;
p=p->nextarc;
}
}
Display1(U);
}
bool visited[MAX];
void setfalse(ULGraph *G)
{
for(int i=0;i<G->vexnum;i++) //初始化图的各个顶点为false,未访问过
visited[i]=false;
}
void DFSB(ULGraph *G,int i) //邻接表深度优先算法
{
visited[i]=true;
printf("%c ",G->vertices[i].data);
ArcNode *p=G->vertices[i].fristarc;
while(p)
{
if(!visited[p->adjvex]) 如果边表结点没有被访问过,则递归调用DFS
DFSB(G,p->adjvex);
p=p->nextarc;
}
}
void DFSTraverseB(ULGraph *G)
{
puts("无向网的 '邻接表深度优先' 搜索:");
for(int i=0;i<G->vexnum;i++)
{
if(!visited[i]) //选取一个未访问过的顶点进行深度优先遍历,如果是连通图DFS只执行一次
DFSB(G,i);
}
puts("");
}
void DFSL(Udn *U,int v) //邻接矩阵的深度优先遍历
{
if(!visited[v])
{
printf("%c ",U->vex[v]);
visited[v]=true;
}
for(int i=0;i<U->vexnum;i++)
if(U->arcs[v][i]!=EXT&&!visited[i])
DFSL(U,i);
}
int LocataVex(ULGraph G,char ch) //返回顶点在网中的位置,无则返回-1
{
for(int i=0;i<G.vexnum;i++)
if(ch==G.vertices[i].data)
return i;
return -1;
}
int FristAdjVex(ULGraph G,char v) //返回v的第一个邻接点打的序号
{
int posi_v=LocataVex(G,v);
ArcNode *p;
p=G.vertices[posi_v].fristarc;
if(p)
return p->adjvex;
else
return -1;
}
int NextAdjVex(ULGraph G,char v,char w)
{
ArcNode *p;
int pos_v,pos_w;
pos_v=LocataVex(G,v);
pos_w=LocataVex(G,w);
p=G.vertices[pos_v].fristarc;
while(p&&p->adjvex!=pos_w)
p=p->nextarc;
if(!p||!p->nextarc)
return -1;
else
return p->nextarc->adjvex;
}
void BFSB(ULGraph G) //无向网链接表的广度优先遍历
{
puts("无向网 '链接表的广度优先' 搜索:");
LinkQueue Q;
InitQueue(Q); //置空一个辅助队列
int u;
for(int i=0;i<G.vexnum;i++)
{
if(!visited[i])
{
visited[i]=true;
printf("%c ",G.vertices[i].data);
EnQueue(Q,i); //入队
while(!QueueEmpty(Q))
{
DeQueue(Q,u); //对头出队,并付给u
for(int j=FristAdjVex(G,G.vertices[u].data);j>=0;j=NextAdjVex(G,G.vertices[u].data,G.vertices[j].data))
if(!visited[j])
{
visited[j]=true;
printf("%c ",G.vertices[j].data);
EnQueue(Q,j);
}
}
}
}
puts("");
}
void BFSL(Udn U,int v) //邻接矩阵的广度优先遍历为
{
puts("无向网 ‘邻接矩阵的广度优先’ 搜索为;");
LinkQueue Q;
InitQueue(Q);
int x;
for(int j=0;j<U.vexnum;j++)
{
if(!visited[j])
{
printf("%c ",U.vex[j]);
visited[j]=true;
EnQueue(Q,j);
}
while(!QueueEmpty(Q))
{
DeQueue(Q,x);
for(int i=0;i<U.vexnum;i++)
if(U.arcs[x][i]!=EXT&&!visited[i])
{
printf("%c ",U.vex[i]);
visited[i]=true;
EnQueue(Q,i);
}
}
}
}
int main()
{
puts("*********************无向网********************\n");
Udn u;
CreateUDN(u);
puts("无向网 ‘向量矩阵’ 表示为:");
Display1(u);
ULGraph ul;
CreateULGraph(ul,u);
Display2(ul);
puts("无向网 ‘邻接表转为邻接矩阵‘ 为:");
BturntoJ(ul);
setfalse(&ul);
DFSTraverseB(&ul);
puts("");
setfalse(&ul);
puts("无向网的 ’邻接矩阵深度优先‘ 搜索:");
for(int i=0;i<u.vexnum;i++)
DFSL(&u,i);
puts("\n");
setfalse(&ul);
BFSB(ul);
puts("");
setfalse(&ul);
BFSL(u,0);
return 0;
}
/*
8 5
a b c d e f g h
a h 5
a f 4
b h 3
d e 2
e h 1
*/