图的基本操作

图的基本操作

 

(1)键盘输入数据,建立一个有向图的邻接表。

(2)输出该邻接表。

(3)在有向图的邻接表的基础上计算各顶点的度,并输出。

(4)以有向图的邻接表为基础实现输出它的拓扑排序序列。

(5)采用邻接表存储实现无向图的深度优先遍历。

(6)采用邻接表存储实现无向图的广度优先遍历。

/*
本算法如果为邻接矩阵存储,无向图默认只求最小生成树,有向图默认只求任意两点最短路径
 */


#define FALSE  0
#define ERROR 0
#define OVERFLOW -2
#define STACK_INIT_SIZE 100
#define STACKINCREMENT  20

采用链式存储实现栈的初始化、入栈、出栈操作

/

//下面为循环队列

#define MAXQSIZE 100  /*队列的最大长度*/
typedef struct {
    int *base;   // 队列的元素空间头指针指示器
    int  front;                  
    int  rear;   /*尾指针指示器*/
}SqQueue;        

int InitQueue(SqQueue &Q) {//初始化操作 
	Q.base = (int * )malloc(MAXQSIZE*sizeof(int));
	if (!Q. base) exit (OVERFLOW);  
	Q.front=Q.rear =0;
	return 1;
} 

int EnQueue(SqQueue &Q,int e) {//入队操作 
	//int e;
	if ((Q. rear+ 1) % MAXQSIZE == Q. front)
	{ 
	//	printf("队列已满,不能进队\n");
		return -1;//满标志 
	} 
	Q.base[Q.rear] = e;//进队
	Q.rear = (Q. rear + 1) % MAXQSIZE;//队尾指针后移
	return 1;
}

int DeQueue (SqQueue &Q) {//出队操作 
	int e;
	if (Q. front == Q. rear) { 
		printf("队列已经为空\n");
		return -1;
	}
	e = Q. base[Q. front];//队头出队
	//printf("%d  出队\n",e);
	Q.front = (Q.front + 1) % MAXQSIZE;//队头下标后移
	return e;
}

int QueueEmpty (SqQueue &Q)
{ 
		if (Q. front == Q. rear)
			return 0;
		else
			return 1;
}

#include<stdio.h>
#include<stdlib.h>
#include"aa.h"
#include<iostream>
using namespace std;
#define MAX 50
#define INFINITY 1000000000
int k,Graph;//定点数
int dgree[MAX];
int visited[MAX];


int max(int a,int b)
{
	return  a>b?a:b;
}

typedef struct ArcNode//hu
{
	int from,to,du;//该弧的尾和头顶点的位置
	struct ArcNode *nextarc;//指向下一条弧的指针
	int weigh;//权值
}ArcNode,*Linklist;

typedef struct VNode
{
	int in,out,data;//定点信息;
	ArcNode *firstarc;
}VNode; 
struct VNode AdjList[MAX];

typedef struct{//邻接矩阵
    int arcs[MAX][MAX];
	int vexnum,arcnum;//边数和顶点数
	int kind;//有向图,无向图
}MGraph;
MGraph M;

int cmp(const void *a,const void *b)
{ 
	return *(int *)a-*(int *)b;
}

Linklist create()
{
	Linklist p;
	p=(Linklist)malloc(sizeof(ArcNode));
	p->nextarc=NULL;
	p->from=-1;
	p->to=-1;
	p->weigh=-1;
	p->du=0;
	return p;
}

void CreateGraph()//创建邻接表
{  
	
	int a,b,w,i;
	Linklist p,q,s,t;
	
	
    cout<<"请输入顶点的个数K:";	//顶点的个数
	cin>>k; 
	cout<<"请输入始点(输入-1结束):";
	
	for(i=0;i<k;i++)//度的初始化
	{
		AdjList[i].data=AdjList[i].in=AdjList[i].out=0;
		AdjList[i].firstarc=create();
	}
	
	while(scanf("%d",&a))//from
	{  
		if(a==-1)
			break;
		if(Graph==0)//有向图
		{
			//AdjList[a].firstarc=create();//初始化
			p=AdjList[a].firstarc;
			cout<<"请输入尾点和权值(当尾点为-1时,输入结束):";
			while(scanf("%d",&b))
			{
				if(b==-1)
					break;
				
				scanf("%d",&w);
				
				AdjList[a].out++;
				AdjList[b].in++;
				q=create();
				q->from=a;
				q->to=b;
				q->weigh=w;
				p->nextarc=q;
				p=p->nextarc;
				
				cout<<"请输入尾点和权值(当尾点为-1时,输入结束):";
			}
			cout<<"请输入始点(输入-1结束):";
		}
		else
		{
			cout<<"请输入尾点和权值(当尾点为-1时,输入结束):";
			p=AdjList[a].firstarc;
			
			while(scanf("%d",&b))
			{
				if(b==-1)
					break;
				
				scanf("%d",&w);
				s=AdjList[b].firstarc;
				AdjList[a].data++;
				AdjList[b].data++;
				q=create();
				q->from=a;
				q->to=b;
				q->weigh=w;
				
				while(p->nextarc) p=p->nextarc;
				p->nextarc=q;	
				
				t=create();
				t->from=b;
				t->to=a;
				t->weigh=w;
				
				while(s->nextarc) s=s->nextarc;
				s->nextarc=t;	
				
				cout<<"请输入尾点和权值(当尾点为-1时,输入结束):";
			}
			cout<<"请输入始点(输入-1结束):";
		}
	}	
}

void print()//输出图
{ 
	int i;
	Linklist p;
	for(i=0;i<k;i++)
	{
		p=AdjList[i].firstarc;
		if(!p)
			continue;
		p=p->nextarc;
		while(p)
		{
			printf("<%d,%d>%d ",p->from,p->to,p->weigh);
			p=p->nextarc;
		}
		printf("\n");
	}
	//cout<<"k"<<k<<"   ";	
}

void TuoPuSort()//拓扑排序
{ 
	int i,top=0;
	Linklist p;
	cout<<"拓扑序列为:";
	if(Graph==0)//有向图
	{ 
		for(i=0;i<k;i++)
		{ 
			if(AdjList[i].in==0)
				dgree[top++]=i;
			
		}
		top--;
		
		while(top>=0)
		{ 
			if(top<0)
				break;
			cout<<"V"<<dgree[top]<<"  ";
			p=AdjList[dgree[top]].firstarc;
			top--;//出战
			if(!p)  continue;
			p=p->nextarc;
			while(p)
			{  
				AdjList[p->to].in--;
				if(AdjList[p->to].in==0)
				{
					top++;
					dgree[top]=p->to;
				}
				p=p->nextarc;
				
			}
			
		}
		
	}
	cout<<endl;
	
}

void GraphDu()//求图的度
{
	int i;
	for(i=0;i<k;i++)
	{ 
		if(Graph==0)
			AdjList[i].data=AdjList[i].in+AdjList[i].out;
		cout<<"V"<<i<<"的度为"<<AdjList[i].data<<endl;
	}
}

void DFS(int v)
{ 
	Linklist p;
	visited[v]=1;
	cout<<"V"<<v<<"  ";
	p=AdjList[v].firstarc;
	p=p->nextarc;
	while(p)
	{ 
		if(!visited[p->to])
			DFS(p->to);
		p=p->nextarc;
	}
	
}
void DFSTraverse()//深度搜索
{
	cout<<"无向图的深度遍历:";
	int v;
	for(v=0;v<k;v++)
		visited[v]=0;
	for(v=0;v<k;v++)
		if(!visited[v])
			DFS(v);
		cout<<endl;
}

void BFSTraverse()//广度
{ 
	cout<<"无向图的广度遍历:";
	SqQueue Q;//定义队列
	InitQueue(Q);//初始化
	int v,e;
	Linklist p;
	for(v=0;v<k;v++)
		visited[v]=0;
	for(v=0;v<k;v++)
	{ 
		if(!visited[v])
		{ 
			cout<<"V"<<v<<"  ";
			EnQueue(Q,v);
			while(!QueueEmpty(Q))
			{ 
				e=DeQueue (Q);
				p=AdjList[e].firstarc;
				p=p->nextarc;
				while(p)
				{ 
					if(!visited[p->to])
					{ 
						visited[p->to]=1;
						cout<<"V"<<v<<"  ";
						EnQueue(Q,p->to);
					}
					p=p->nextarc;
				}	
			}
		}
	}
	cout<<endl;
}


void DaYin1()//邻接表
{ 
	cout<<"------------------------"<<endl;
	cout<<"|输入0:创建图          |"<<endl;
	cout<<"|输入1:输出图          |"<<endl;
	cout<<"|输入2:输出图的度      |"<<endl;
	cout<<"|输入3:对图进行拓扑排序|"<<endl;
	cout<<"|输入-1:退出           |"<<endl;
	cout<<"|请选择:               |"<<endl;
	cout<<"------------------------"<<endl;
	return ;
}
void DaYin2()//邻接表
{
	cout<<"------------------------"<<endl;
	cout<<"|输入0:创建图          |"<<endl;
	cout<<"|输入1:输出图          |"<<endl;
	cout<<"|输入2:输出图的度      |"<<endl;
	cout<<"|输入3:对图进行深度遍历|"<<endl;
	cout<<"|输入4:对图进行广度遍历|"<<endl;
	cout<<"|输入-1:退出           |"<<endl;
	cout<<"|请选择:               |"<<endl;
	cout<<"------------------------"<<endl;
	return;
	
}
///邻接矩阵
void JZGraph()//邻接矩阵的建立
{ 
	cout<<"邻接矩阵:有向图请输入0,无向图请输入1,请选择:";
	scanf("%d",&M.kind);
	cout<<"请输入顶点的的个数:";
	scanf("%d",&M.arcnum);  //  顶点数
	
	cout<<"请输入边的的个数:";
	scanf("%d",&M.vexnum);  //  边数
}


void MinRode(int v,int n)//dijsta
{
	int s[MAX];//判断是否已存入该点到S集合中
	int dist[MAX],pre[MAX],newdist;
	int i,j;
	for(i=0;i<M.arcnum;i++)
	{
		dist[i]=M.arcs[v][i];
		s[i]=0;
		pre[i]=v;
	}
	s[v]=1;
	for(i=1;i<M.arcnum;i++)
	{ 
		int temp=INFINITY;
		int u=v;
		for(j=0;j<M.arcnum;j++)
			if(!s[j]&&dist[j]<temp)
			{
				u=j;
				temp=dist[j];
			}
			s[u]=1;
			for(j=0;j<M.arcnum;j++)
				if(!s[j]&& M.arcs[u][j]<INFINITY)
				{
					newdist=temp+M.arcs[u][j];
					if(newdist<dist[j])
					{
						dist[j]=newdist;
						pre[j]=u;
					}
				}
	}
	
	
	
	if(dist[n]>=INFINITY)
		cout<<"V"<<v<<"与V"<<n<<"之间没有通路"<<endl;
	else
	{ 
		cout<<"V"<<v<<"与V"<<n<<"之间最短路径为:"<<endl;
		i=n;
		while(i!=v)
		{ 
			cout<<"V"<<i<<"<--";
			i=pre[i];
		}
		cout<<"V"<<v<<"\n"<<"最短路径长度为:"<<dist[n]<<endl;
		
	}
	
	
	
}
void MinTree()//最小生成树
{ 
	cout<<"最小生成树的权值为:";
	int s[MAX];//判断是否已存入该点到S集合中
	int dist[MAX],newdist,sum=0,pp;
	int i,j;
	for(i=0;i<M.arcnum;i++)
	{
		dist[i]=M.arcs[0][i];
		s[i]=0;
	}
	s[0]=1;
	for(i=1;i<M.arcnum;i++)
	{ 
		int temp=INFINITY;
		int u=0;
		for(j=0;j<M.arcnum;j++)
			if(!s[j]&&dist[j]<temp)
			{
				u=j;
				temp=dist[j];
			}
			s[u]=1;
			
			if(temp<INFINITY)
			{
				sum+=temp;
				if(!u)
					cout<<"("<<"0"<<","<<u<<")"<<temp<<"  ";
				
				else
				{ for(pp=0;pp<M.arcnum;pp++)
				if(s[pp]&&M.arcs[pp][u]==temp)
					cout<<"("<<pp<<","<<u<<")"<<temp<<"  ";
				
				}
			}
			else
			{ 
				cout<<"最小生成树,失败!!!";
				break;
			}
			for(j=0;j<M.arcnum;j++)
				if(!s[j]&& M.arcs[u][j]<INFINITY)
				{
					newdist=M.arcs[u][j];
					if(newdist<dist[j])
					{
						dist[j]=newdist;
					}
				}
	}
	if(sum<INFINITY)
		cout<<"\n"<<"最小生成树的权值和为:"<<sum<<endl;
	
}
void CreateJZGraph() 
{ 
	int i,j,a,b,w;
	int visit[MAX][MAX];
	for(i=0;i<M.arcnum;i++)
		for(j=0;j<M.arcnum;j++)
		{
			M.arcs[i][j]=INFINITY;
			visit[i][j]=0;
		}
		if(M.kind==0)//有向图
		{
			cout<<"请输入顶点和权值:"<<endl;
			for(i=0;i<M.vexnum;i++)
			{  
				scanf("%d%d%d",&a,&b,&w);
				M.arcs[a][b]=w;
			}
			int m,n;
			cout<<"计算任意两点的距离,请输入始末点,以起点为-1为结束标志:"<<endl;
            while(scanf("%d",&m))
			{
				if(m<0) break;
				cin>>n;
				MinRode(m,n);
				cout<<"计算任意两点的距离,请输入始末点,以起点为-1为结束标志:"<<endl;
			}
		}
		else//无向图
		{
			//cout<<"最小生成树为:";
			cout<<"请输入顶点和权值:"<<endl;
			for(i=0;i<M.vexnum;i++)//读入数据
			{  
				scanf("%d%d%d",&a,&b,&w);
				M.arcs[a][b]=w;
				M.arcs[b][a]=w;
			}
			MinTree();
			
		}		
}


//

int  main()
{
	int count;
	cout<<"存储方式:用邻接表存储请输入0,用邻接矩阵存储请输入1,请选择:";
	scanf("%d",&count);
	switch(count)
	{
	case 0:
		{
			cout<<"用邻接表存储:有向图请输入0,无向图请输入1,请选择:";
			scanf("%d",&Graph);
			int g1;
			if(Graph==0)//有向图
			{
				DaYin1();
				while(scanf("%d",&g1))
				{
					if(g1==-1)break;
					switch(g1)
					{
					case 0:CreateGraph();break;
					case 1:print();break;
					case 2:GraphDu();break;
					case 3:TuoPuSort();break;
						//cout<<"图的深度遍历:";
					}
					DaYin1();
				}
			}
			else//无向图
			{
				DaYin2();
				while(scanf("%d",&g1))
				{
					if(g1==-1)break;
					switch(g1)
					{
					case 0:CreateGraph();break;
					case 1:print();break;
					case 2:GraphDu();break;
					case 3:DFSTraverse();break;
					case 4:BFSTraverse();break;
					}
					DaYin2();
				}
			}
		}break;
	case 1: //邻接矩阵
		{
			JZGraph();
			CreateJZGraph();//最小生成树he最短路径	
		}
	}
	return 0;
}


/*
0 1 6
0 2 1
0 3 5
1 2 5
2 3 5
1 4 3
2 4 6
2 5 4
3 5 2
4 5 6
*/
/*
0 1 1
1 2 2
0 3 3
0 4 5
3 2 2
2 4 3
4 0 4
*/


(7)采用邻接矩阵存储实现无向图的最小生成树的PRIM算法。

(8)采用邻接矩阵存储一个有向图,输出单源点到其它顶点的最短路径。

(9)在主函数中设计一个简单的菜单,分别调试上述算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值