#include <stdio.h>
#include <iostream>
#include <iomanip>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -1
typedef int Status;
#define MVNum 20 //最大顶点数
typedef char VertexType; //顶点类型
typedef int InfoType; //权值类型
typedef struct ArcNode{
int adjvex; //该边所指向的顶点的位置
InfoType weight; //权(和边相关的信息)
struct ArcNode *nextarc; //指向下一条边的指针(递归结构体)
}ArcNode;//边结点
typedef struct VNode{
VertexType data; //顶点值
ArcNode *firstarc; //一个指针,指向以该点为起始点的第一条边
}VNode, AdjList[MVNum]; //表头结点 ,AdjList代表邻接表的类型
typedef struct {
int kind; //图的类型
int vexnum,arcnum; //图的顶点数、边数
VNode vertices[MVNum]; //顶点向量表(重点),每个元素是顶点结点
}ALGraph; //图
#define MAXQSIZE 100
typedef char QElemType;
typedef struct{
QElemType *base;
int front;
int rear;
}SqQueue;
SqQueue Q;
//顶点查找函数,返回v在顶点数组中的下标
int LovateVex(ALGraph G,VertexType v){
int i;
for (i=0;i<G.vexnum ;i++)
if ( G.vertices[i].data==v ) return i;//找到则返回该位置的对应下标
return -1; //找不到则返回-1
}
//创建无向网
Status CreateUDN(ALGraph &G){
int i,j,k;
VertexType v1,v2;
InfoType w;
ArcNode *p,*q;
cout<<endl<<"输入图的顶点数和边数:";
cin>>G.vexnum>>G.arcnum;
cout<<endl<<"输入图的顶点信息:";
for (i=0;i<G.vexnum;i++) {
cin>>G.vertices[i].data; //输入顶点信息
G.vertices[i].firstarc=NULL; //初始化每个顶点的邻接表(为空)
}
cout<<endl<<"输入边:(v1,v2,weight)"<<endl; //输入各边,构造邻接表
for (k=0;k<G.arcnum;k++)
{
cout<<"\n第"<<k+1<<"条边:" ;
cin>>v1>>v2>>w; //输入一条边依附的两个结点
i=LovateVex(G,v1); //确定v1,v2在图中的位置,即顶点在G.vertices中的编号
j=LovateVex(G,v2);
if (i==-1 ||j==-1) {
cout<<"\n顶点有误,程序退出!";
return ERROR;
}
p=new ArcNode; //生成一个新的边结点*p
p->adjvex=j; //邻接点序号为j
p->weight=w; //该边对应的权为w
p->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=p; //用头插法将*p插入顶点v1的边表中
q=new ArcNode; //成另一个对称新的边结点*q
q->adjvex=i; //邻接点序号为j
q->weight=w;
q->nextarc=G.vertices[j].firstarc;
G.vertices[j].firstarc=q; //用头插法将*q插入顶点v2的边表中
}//for k
return OK;
}//CreateUDN
//创建无向图
Status CreateUDG(ALGraph &G){
int i,j,k;
VertexType v1,v2;
ArcNode *p,*q;
cout<<endl<<"输入图的顶点数和边数:";
cin>>G.vexnum>>G.arcnum;
cout<<endl<<"输入图的顶点信息:";
for (i=0;i<G.vexnum;i++) {
cin>>G.vertices[i].data; //输入顶点信息
G.vertices[i].firstarc=NULL; //初始化每个顶点的邻接表(为空)
}
cout<<endl<<"输入边:(v1,v2)"<<endl; //输入各边,构造邻接表
for (k=0;k<G.arcnum;k++)
{
cout<<"\n第"<<k+1<<"条边:" ;
cin>>v1>>v2; //输入一条边依附的两个结点
i=LovateVex(G,v1); //确定v1,v2在图中的位置,即顶点在G.vertices中的编号
j=LovateVex(G,v2);
if (i==-1 ||j==-1) {
cout<<"\n顶点有误,程序退出!";
return ERROR;
}
p=new ArcNode; //生成一个新的边结点*p
p->adjvex=j; //邻接点序号为j
p->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=p; //用头插法将*p插入顶点v1的边表中
q=new ArcNode; //成另一个对称新的边结点*q
q->adjvex=i; //邻接点序号为j
q->nextarc=G.vertices[j].firstarc;
G.vertices[j].firstarc=q; //用头插法将*q插入顶点v2的边表中
}//for k
return OK;
}//CreateUDG
//创建有向图
Status CreateDG(ALGraph &G){
int i,j,k;
VertexType v1,v2;
ArcNode *p,*q;
cout<<endl<<"输入图的顶点数和边数:";
cin>>G.vexnum>>G.arcnum;
cout<<endl<<"输入图的顶点信息:";
for (i=0;i<G.vexnum;i++) {
cin>>G.vertices[i].data; //输入顶点信息
G.vertices[i].firstarc=NULL; //初始化每个顶点的邻接表
}
cout<<endl<<"输入边:(v1,v2)"<<endl;
for (k=0;k<G.arcnum;k++) {
cout<<"\n第"<<k+1<<"条边:" ;
cin>>v1>>v2;
i=LovateVex(G,v1);
j=LovateVex(G,v2);
if (i==-1 ||j==-1) {
cout<<"\n顶点有误,程序退出!";
return ERROR;
}
p=new ArcNode;
p->adjvex=j;
p->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=p;
}
return OK;
}//CreateDG
//创建有向网
Status CreateDN(ALGraph &G)
{
int i,j,k;
VertexType v1,v2;
InfoType w;
ArcNode *p,*q;
cout<<endl<<"输入图的顶点数和边数:";
cin>>G.vexnum>>G.arcnum;
cout<<endl<<"输入图的顶点信息:";
for (i=0;i<G.vexnum;i++) {
cin>>G.vertices[i].data; //输入顶点信息
G.vertices[i].firstarc=NULL; //初始化每个顶点的邻接表
}
cout<<endl<<"输入边:(v1,v2,weight)"<<endl;
for (k=0;k<G.arcnum;k++) {
cout<<"\n第"<<k+1<<"条边:" ;
cin>>v1>>v2>>w;
i=LovateVex(G,v1);
j=LovateVex(G,v2);
if (i==-1 ||j==-1) {
cout<<"\n顶点有误,程序退出!";
return ERROR;
}
p=new ArcNode;
p->adjvex=j;
p->weight=w;
p->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=p;
}
return OK;
}//CreateDN
Status CreateGraph(ALGraph &G){
cout<<endl<<"输入图的类型(1:有向图DG,2:有向网DN,3:无向图UDG,4:无向网UDN)\n";
cin>>G.kind;
switch (G.kind){
case 1 :return CreateDG(G);
case 2 :return CreateDN(G);
case 3 :return CreateUDG(G);
case 4 :return CreateUDN(G);
default :return ERROR;
}
return OK;
}//CreateGraph
void FindIndegree(ALGraph G,int indegree[]){
//计算有向图(网)的入度
int num=0;
ArcNode *p;
p=new ArcNode;
for (int i=0;i<MVNum;i++){
indegree[i]=0;
}
for (int i=0;i<G.vexnum;i++){
for (p=G.vertices[i].firstarc; p ;p=p->nextarc)
indegree[p->adjvex]++;
}
for (int i=0;i<G.vexnum;i++){
cout<<G.vertices[i].data<<"顶点的入度为:"<<indegree[i];
cout<<"\n";
}
}//FindIndegree
void FindOutdegree(ALGraph G,int outdegree[]){
//计算有向图(网)的出度
for (int i=0;i<G.vexnum;i++){
outdegree[i]=0;
}
ArcNode *p;
p=new ArcNode;
for (int i=0;i<G.vexnum;i++){
for (p=G.vertices[i].firstarc;p;p=p->nextarc)
outdegree[i]++;
}
for (int i=0;i<G.vexnum;i++){
cout<<G.vertices[i].data<<"该顶点的出度为:"<<outdegree[i];
cout<<"\n";
}
}//FindOutdegree
void FindDegree(ALGraph G,int degree[]){
//计算无向图(网)的度
for (int i=0;i<G.vexnum;i++){
degree[i]=0;
}
ArcNode *p;
p=new ArcNode;
for (int i=0;i<G.vexnum;i++){
for (p=G.vertices[i].firstarc;p;p=p->nextarc){
degree[i]++;
degree[p->adjvex]++;
}
}
for (int i=0;i<G.vexnum;i++){
cout<<G.vertices[i].data<<"该顶点的度为:"<<degree[i];
cout<<"\n";
}
}//FindOutDegree
void GraphDegree(ALGraph G){//计算每个顶点的度,对有向图(网),还需要计算入度和出度
int indegree[MVNum],outdegree[MVNum],degree[MVNum];
//根据图的不同类型:1-DG,2-DN,3-UDG,4-UDN,计算顶点的度(入度/出度),并输出
switch (G.kind){
case 1 :cout<<"该图为有向图\n";
FindIndegree(G,indegree);
FindOutdegree(G,outdegree);
break;
case 2 :cout<<"该图为有向网\n";
FindIndegree(G,indegree);
FindOutdegree(G,outdegree);
break;
case 3 :cout<<"该图为无向图\n";
FindDegree(G,degree);
break;
case 4 :cout<<"该图为无向网\n";
FindDegree(G,degree);
break;
default :break;
}
}//GraphDegree
void PrintGraph(ALGraph G){
int i,j;
ArcNode *p;
cout<<"\n图的顶点数和边数:";
cout<<setw(3)<<G.vexnum<<setw(3)<<G.arcnum;
cout<<"\n图的顶点:";
for (i=0;i<G.vexnum;i++)
cout<<setw(3)<<G.vertices[i].data;
cout<<"\n图的邻接表:\n";
for (i=0;i<G.vexnum;i++){
cout<<setw(3)<<G.vertices[i].data<<"的邻接点:";
for (p=G.vertices[i].firstarc; p ;p=p->nextarc){
j=p->adjvex;
cout<<setw(3)<<G.vertices[j].data;
}//for
cout<<endl;
}//for
}
bool visited[MVNum];
//图的遍历:深度优先搜索
void DFS(ALGraph G,int v){
// 从顶点v出发,对图G进行深度优先搜索
cout<<v;
int w;
visited[v]=true;
ArcNode *p;
p=new ArcNode;
p=G.vertices[v].firstarc;
while(p){
w=p->adjvex;
if (!visited[w])
DFS(G,w);
p=p->nextarc;
}
}//DFS
void DFSTraverse(ALGraph G){
// 对图G进行深度优先搜索
int v=0;
for (v=0;v<G.vexnum;v++){
visited[v]=false;
}
for (v=0;v<G.vexnum;v++){
if(!visited[v])
DFS(G,v);
}
}
//构造一个空队列Q
Status InitQueue(SqQueue &Q){
Q.base=new QElemType[MAXQSIZE];
if (!Q.base) exit(OVERFLOW);
Q.front=Q.rear;
return OK;
}
//判断是否为空队列
Status EmptyQueue(SqQueue Q){
return (Q.front==Q.rear);
}
//入队列
Status EnQueue(SqQueue &Q ,QElemType e){
if ((Q.rear+1)%MAXQSIZE==Q.front)
return ERROR;
Q.base[Q.rear]=e;
Q.rear=(Q.rear+1)%MAXQSIZE;
return OK;
}
//出队列
Status DeQueue(SqQueue &Q,QElemType &e){
if (Q.front==Q.rear)
return ERROR;
e= Q.base[Q.front];
Q.front=(Q.front+1)%MAXQSIZE;
return OK;
}
void BFSTraverse(ALGraph G){
// 对图G进行广度优先搜索
int v=0;
for (v=0;v<G.vexnum;v++){
visited[v]=false;
}
for (v=0;v<G.vexnum;v++){
if (!visited[v])
BFS(G,v);
}
}//BFSTraverse
//图的遍历:广度优先搜索
void BFS(ALGraph G,int v){
// 从顶点v出发,对图G进行广度优先搜索
cout<<v;
visited[v]=true;
InitQueue(Q);
EnQueue(Q,v);
QElemType u;
ArcNode *p;
p=new ArcNode;
int w;
p=G.vertices[v].firstarc;
while(!EmptyQueue(Q)){
DeQueue(Q,u);
while( p && !visited[w]){
w=p->adjvex;
cout<<w;
visited[w]=true;
EnQueue(Q,w);
}
}
}//BFS
int main(){
ALGraph G;
int choice;
if (CreateGraph(G)==OK){//建立图的邻接表
cout<<"图的邻接表建立成功!!\n";
PrintGraph(G);
}
else {
cout<<"图的邻接表建立失败,程序退出!!\n";
return 0;
}
do{ cout<<"\n\n 图的邻接表存储表示及其应用 \n";
cout<<"=============================================\n";
cout<<" 1:计算顶点的度\n";
cout<<" 2:深度优先搜索\n";
cout<<" 3:广度优先搜索\n";
cout<<" 0:退出\n";
cout<<"=============================================\n";
cout<<"输入你的选择:";
cin>>choice;
switch (choice){
case 1: GraphDegree(G);
break;
case 2: DFSTraverse(G);
break;
case 3: BFSTraverse(G);
break;
default:break;
}
cout<<endl;system("pause") ;//按任意键继续
}while (choice);
return 0;
}
数据结构——图的邻接表
最新推荐文章于 2024-08-15 23:11:27 发布