数据结构——图的邻接表

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

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值