当前位置:文档之家› 数据结构中图的全部操作

数据结构中图的全部操作

#include<stdio.h>#include<stdlib.h>#include<malloc.h>#include<stack>#include <iostream>#include<iomanip>using namespace std;#define MAX_VERTEX_NUM 100#define INFINITY INT_MAX#define EXTERN 10#define OK 1#define ERROR -1#define MAX -1#define MAXW 10000typedef int Status;typedef bool VisitIf;typedef char VertexType;//顶点数据类型typedef int VRType; //顶点关系( 表示是否相邻) typedef int InfoType; //弧相关信息typedef enum{DG,DN,UDG,UDN} GraphKind;//图的类型bool visited[MAX_VERTEX_NUM];//邻接矩阵typedef struct ArcCell{VRType adj;//权值InfoType *info;}ArcCell,AdjMartix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedef struct{VertexType vexs[MAX_VERTEX_NUM]; //顶点向量AdjMartix arcs; //邻接矩阵int vexnum,arcnum; //图当前顶点数,弧数 GraphKind Kind; //图的类型}MGraph;bool VexExist(MGraph G,VertexType v)//判断定点是否在图中{int i;for(i=0;i<G.vexnum;i++)//遍历所有顶点if(G.vexs[i]==v)return true;return false;}Status CreatUDN(MGraph &G) //构造无向网{int i,j,w;char ch;VertexType v1,v2;Status LocateVex(MGraph G,VertexType v); //函数声明cout<<"输入顶点数,弧数:"<<endl;cin>>G.vexnum>>G.arcnum; //输入当前顶点数弧数是否有弧信息cout<<"输入顶点(字符型):"<<endl;for(i=0;i<G.vexnum;i++) //初始化邻接矩阵{for(j=0;j<G.vexnum;j++){G.arcs[i][j].adj=MAX;G.arcs[i][j].info=NULL;}}for(i=0;i<G.vexnum;i++) //顶点信息{cout<<"输入第"<<i+1<<"个顶点:";cin>>ch;if(VexExist(G,ch)) //判断是否存在 {cout<<"顶点输入有误!"<<endl;i--;}else G.vexs[i]=ch;}for(int k=0;k<G.arcnum;){cout<<"输入第"<<k+1<<"条弧:"<<endl;cin>>v1>>v2;cout<<"输入弧的权值:"<<endl;cin>>w;if((i=LocateVex(G,v1))!=-2)//if((j=LocateVex(G,v2))!=-2){G.arcs[i][j].adj=w;//对弧写入权值G.arcs[j][i].adj=w;//对称弧赋值k++;continue;};cout<<"顶点输入错误!";}return OK;}Status LocateVex(MGraph G,VertexType v) //若图中存在v,返回v在图中的位置{for(int i=0;i<G.vexnum;i++){if(v==G.vexs[i])return i;}return -2;}//对无向图求每个顶点的度,或对有向图求每个顶点的入度和出度(5分)Status GetDegree(MGraph G,VertexType v){int i=0;int degree=0;i=LocateVex(G,v);////若图中存在v,返回v在图中的位置if(i!=-2)//如果存在for(int j=0;j<G.vexnum;j++)if(G.arcs[i][j].adj>0) degree++;if(i==-2){cout<<"顶点输入有误!"<<endl;return ERROR;}return degree;}// 完成插入顶点和边(或弧)的功能(5分)Status InsertVex(MGraph &G,VertexType v) //图中插入顶点{int k=G.vexnum;if(G.vexnum<MAX_VERTEX_NUM){G.vexs[k]=v;G.vexnum++;for(int i=0;i<G.vexnum;i++){G.arcs[k][i].adj=MAX;G.arcs[k][i].info=NULL;G.arcs[i][k].adj=MAX;G.arcs[i][k].info=NULL;}cout<<"插入成功!"<<endl;}return ERROR;}Status InsertArc(MGraph &G,VertexType v1,VertexType v2) //图中插入弧{int w,i,j;i=LocateVex(G,v1);j=LocateVex(G,v2);if(i!=-2)if(j!=-2){cout<<"输入弧的权值:";cin>>w;G.arcs[i][j].adj=w;G.arcs[j][i]=G.arcs[i][j];return OK;}cout<<"输入有误,插入失败!";return ERROR;}//完成删除顶点和边(或弧)的功能(5分)Status DelVex(MGraph &G,VertexType v) //图中删除顶点{int i,j;i=LocateVex(G,v);if(i!=-2){for(j=0;j<G.vexnum-i-1;j++)G.vexs[i+j]=G.vexs[i+j+1]; //顶点的删除if(i<G.vexnum) //与顶点相关的弧的删除{for(j=0;j<G.vexnum-i-1;j++)for(int k=0;k<G.vexnum;k++){G.arcs[i+j][k].adj=G.arcs[i+j+1][k].adj;G.arcs[i+j][k].info=G.arcs[i+j+1][k].info;}for(j=0;j<G.vexnum-i-1;j++)for(int k=0;k<G.vexnum;k++){G.arcs[k][i+j].adj=G.arcs[k][i+j+1].adj;G.arcs[k][i+j].info=G.arcs[k][i+j+1].info;}G.vexnum--;return OK;}G.vexnum--;}return ERROR;}Status DelArc(MGraph &G,VertexType v1,VertexType v2) //删除弧{int i,j;i=LocateVex(G,v1);j=LocateVex(G,v2);if(i!=-2)if(j!=-2){G.arcs[i][j].adj=MAX;G.arcs[j][i].adj=MAX;G.arcs[i][j].info=NULL;G.arcs[j][i].info=NULL;cout<<"删除成功!";return OK;}return ERROR;}void ScanAll(MGraph G)//显示图的所有信息{int i;cout<<"图中顶点信息如下:"<<endl;for(i=0;i<G.vexnum;i++)cout<<G.vexs[i]<<" ";cout<<"邻接矩阵如下:"<<endl;cout<<setw(5)<<"矩阵:";for(i=0;i<G.vexnum;i++)cout<<setw(5)<<G.vexs[i];cout<<endl;for(i=0;i<G.vexnum;i++){cout<<setw(6)<<G.vexs[i];for(int j=0;j<G.vexnum;j++)cout<<setw(5)<<G.arcs[i][j].adj; cout<<endl;}}////////////////////////////////////////////////////////// ///////////////////////////////////////定义图的邻接多重表结构typedef struct Ebox{VisitIf mark; //访问标志int ivex,jvex;//该边依附的两个顶点位置int weight;struct Ebox *ilink,*jlink;//分别指向依附这两个顶点的下一条边InfoType info; //弧信息指针}Ebox;typedef struct VexBox//顶点定义{VertexType data;Ebox *firstedge;//指向第一条依附该顶点的边}VexBox;typedef struct//图定义{VexBox vexes[MAX_VERTEX_NUM];int vexnum,edgenum;//无向图的当前顶点数和边数}UdGraph;////////////////////////////////////////////////////////// //////////////////////////////////////以邻接多重表创建无向网Status CreatUdGraph(UdGraph &G){int i;int m,n,w;Ebox *p;VertexType v1,v2;Status UdGLocateVex(UdGraph &G,VertexType v);//声明cout<<"输入图顶点的个数和边的数目:"<<endl;cin>>G.vexnum>>G.edgenum;for(i=0;i<G.vexnum;i++) //顶点信息的输入{cout<<"输入第"<<i+1<<"顶点:";cin>>G.vexes[i].data;G.vexes[i].firstedge=NULL;}for(i=0;i<G.edgenum;i++) //边信息输入 {cout<<"共"<<G.edgenum<<"条边"<<"输入第"<<i+1<<"条边:";cin>>v1>>v2;cout<<"输入权值:";cin>>w;if((m=UdGLocateVex(G,v1))!=-2)if((n=UdGLocateVex(G,v2))!=-2){p=(Ebox*)malloc(sizeof(Ebox));if(!p) return ERROR;p->ivex=m;p->jvex=n;p->weight=w;p->ilink=G.vexes[m].firstedge; //插入顶点m表头G.vexes[m].firstedge=p;p->jlink=G.vexes[n].firstedge; //插入顶点n的表头G.vexes[n].firstedge=p;};}return OK;}Status UdGLocateVex(UdGraph &G, VertexType v) //返回v在图G中的位置{for(int i=0;i<G.vexnum;i++){if(v==G.vexes[i].data)return i;}return -2;}Status UdGInsertVex(UdGraph &G) //插入顶点{if(G.vexnum<MAX_VERTEX_NUM){cout<<"输入要插入的顶点的信息:";cin>>G.vexes[G.vexnum].data;G.vexnum++;G.vexes[G.vexnum-1].firstedge=NULL;return OK;}return ERROR;}Status UdGInsertEadge(UdGraph &G,VertexType v1,VertexType v2,int w) //插入边{int m,n;m=UdGLocateVex(G,v1);n=UdGLocateVex(G,v2);Ebox *p;if(m!=-2)//如果点v1存在,并返回值给mif(n!=-2){p=(Ebox*)malloc(sizeof(Ebox));//申请一个结点if(!p) return ERROR;p->ivex=m;p->jvex=n;p->weight=w;p->ilink=G.vexes[m].firstedge; //插入顶点m表头G.vexes[m].firstedge=p;p->jlink=G.vexes[n].firstedge; //插入顶点n的表头G.vexes[n].firstedge=p;return OK;};cout<<"边信息输入有误!";return ERROR;}Status UdGGetDegree(UdGraph G,VertexType v) //返回v的度数{int degree=0;int i;Ebox *p;if((i=UdGLocateVex(G,v))==-2){cout<<"输入的顶点信息有误!";return ERROR;}p=G.vexes[i].firstedge;while(p){degree++;if(p->ivex==i) p=p->ilink;else p=p->jlink;}return degree;}Status UdGFirstVex(UdGraph G,int i) //返回v的第一个邻接点{if(i>G.vexnum||i<0){cout<<"输入的顶点有误!";return ERROR;}if(G.vexes[i].firstedge==NULL) return -2; //没有邻接点if(G.vexes[i].firstedge->ivex==i) return G.vexes[i].firstedge->jvex; //返回邻接点else return G.vexes[i].firstedge->ivex;}//返回i相对于j的下一个邻接点Status UdGNextVex(UdGraph G,int i,int j){Ebox *p;if(i>G.vexnum||i<0||j>G.vexnum||j<0){cout<<"输入的两个顶点有误!";return ERROR;}p=G.vexes[i].firstedge;while(p){if(p->ivex==j){p=p->jlink;break;}if(p->jvex==j){p=p->ilink;break;}if(p->ivex==i) p=p->ilink;else p=p->jlink;}if(!p) return -2; //没有邻接点 if(p->ivex==i) return p->jvex;else return p->ivex;}//邻接多重表转换为邻接矩阵MGraph StructTransform(UdGraph G1){int i,j;MGraph G;Ebox *p;G.vexnum=G1.vexnum;for(i=0;i<G1.vexnum;i++){G.vexs[i]=G1.vexes[i].data; //复制顶点数组}for(i=0;i<G.vexnum;i++) //初始化邻接矩阵for(j=0;j<G.vexnum;j++)G.arcs[i][j].adj=MAX;for(i=0;i<G1.vexnum;i++)visited[i]=false; //访问标记初始化for(i=0;i<G1.vexnum;i++) //邻接矩阵赋值{p=G1.vexes[i].firstedge;while(p){G.arcs[p->ivex][p->jvex].adj=G.arcs[p->jvex][p->ivex].adj= p->weight;if(p->ivex==i) p=p->ilink;else p=p->jlink;}}return G;}//邻接矩阵转换为邻接多重表UdGraph StructTransform(MGraph G1){int i,j;UdGraph G;//顶点数组的复制G.vexnum=G1.vexnum;for(i=0;i<G1.vexnum;i++)G.vexes[i].data=G1.vexs[i];for(i=0;i<G.vexnum;i++) G.vexes[i].firstedge=NULL;//根据邻接矩阵构造边for(i=0;i<G.vexnum;i++)for(j=i+1;j<G.vexnum;j++)if(G1.arcs[i][j].adj>0)UdGInsertEadge(G,G.vexes[i].data,G.vexes[j].data,G1.arcs[i ][j].adj);return G;}/********二叉树*******/typedef struct CSNode{VertexType v;CSNode *lchild;CSNode *nextsibling;} CSNode,*CSTree;//输出图的深度优先遍历序列或广度优先遍历序列(5分)Status DFSTraverse(UdGraph G) //返回连通分量{int i;int count=0;void DFS(UdGraph G,int i);for(i=0;i<G.vexnum;i++)visited[i]=false; //访问标志初始化 cout<<"深度优先遍历结果:"<<endl;for(i=0;i<G.vexnum;i++){if(!visited[i]){count++; //连通分量计数器 DFS(G,i);}}cout<<endl;return count;}void DFS(UdGraph G,int i){int w;visited[i]=true;cout<<G.vexes[i].data;for(w=UdGFirstVex(G,i);w!=-2;w=UdGNextVex(G,i,w)) if(!visited[w]) DFS(G,w);}Status ScanUdGraph(UdGraph G)//输出无向网{int i;Ebox *p;cout<<"图中顶点信息:"<<endl;for(i=0;i<G.vexnum;i++)cout<<"编号"<<i<<"\t"<<G.vexes[i].data<<endl;for(i=0;i<G.vexnum;i++){p=G.vexes[i].firstedge;if(!p){cout<<"没有与该顶点相关的边";continue;}cout<<"与顶点"<<G.vexes[i].data<<"相连的边:"<<endl;while(p){cout<<p->ivex<<"-"<<p->jvex<<" 权值:"<<p->weight<<endl;if(p->ivex==i) p=p->ilink;else p=p->jlink;}}return OK;}//求图的深度优先或广度优先的生成树(或生成森林)(存储结构为孩子-兄弟链表),并对生成树进行遍历(15分)//深度优先遍历生成树void DFSForest(UdGraph G,CSTree &T){int v;T=NULL;CSTree p=NULL;CSTree q=NULL;void DFSTreeSet(UdGraph G,int v,CSTree &T);for(v=0;v<G.vexnum;++v)visited[v]=false;for(v=0;v<G.vexnum;++v)if(!visited[v]){p=(CSTree)malloc(sizeof(CSNode)); if(!p){cout<<"内存分配失败";return;}p->v=G.vexes[v].data;p->lchild=p->nextsibling=NULL;if(!T) T=p;else q->nextsibling=p;q=p;DFSTreeSet(G,v,p);}}void DFSTreeSet(UdGraph G,int v,CSTree &T) {int w;bool first;visited[v]=true;first=true;CSTree p,q=T->lchild;for(w=UdGFirstVex(G,v);w!=-2;w=UdGNextVex(G,v,w)) if(!visited[w]){p=(CSTree)malloc(sizeof(CSNode));if(!p){cout<<"内存分配失败!";return;}p->v=G.vexes[w].data;p->lchild=p->nextsibling=NULL;if(first){T->lchild=p;first=false;}else{q->nextsibling=p;}q=p;DFSTreeSet(G,w,q);}}//深度优先遍历孩子兄弟链表Status DFSTree(CSTree T){if(!T) return OK;cout<<T->v<<" ";if(T->lchild) DFSTree(T->lchild);if(T->nextsibling) DFSTree(T->nextsibling); return OK;}//判断图中有没有环bool UdGLoopJudge(UdGraph G){int VD[ MAX_VERTEX_NUM];bool flag=false; //数组中点空标志int i,j,m;int count; //记录数组中为-1的数目Ebox *p;//VexDegree VD[MAX_VEX_NUM];for(i=0;i<G.vexnum;i++) //保存顶点的度数VD[i]=UdGGetDegree(G,G.vexes[i].data);while(!flag){count=1;for(j=0;j<G.vexnum;j++) //遍历数组检测度数为的点 {if(VD[j]==1){VD[j]=-1;m=j;break;}if(VD[j]==-1) count++;if(j==G.vexnum-1)m=-1;}//cout<<"-1点:"<<count<<endl;if(m==-1){if(count==G.vexnum) break;flag=true;break;}p=G.vexes[m].firstedge;while(p){if(p->ivex==m){if(VD[p->jvex]<0) p=p->ilink; else{VD[p->jvex]--;p=p->ilink;}}else{if(VD[p->ivex]<0) p=p->jlink; else{VD[p->ivex]--;p=p->jlink;}}}}return flag;}//普利姆算法求最小生成树void MiniSpanTree(MGraph G,VertexType u) {int k;int j,i;int count=0,min;struct{VertexType adjvex;int lowcost;}closedge[ MAX_VERTEX_NUM];k=LocateVex(G,u);for(j=0;j<G.vexnum;j++)if(j!=k){closedge[j].adjvex=u;closedge[j].lowcost=G.arcs[k][j].adj;};closedge[k].lowcost=0;count=1;cout<<"最小生成树的各个边信息如下:"<<endl;while(count!=G.vexnum){min=1000;for(i=0;i<G.vexnum;i++){if(closedge[i].lowcost==MAX||closedge[i].lowcost==0) continue;if(closedge[i].lowcost<min){min=closedge[i].lowcost;k=i;}}//cout<<"花费最小边对应点:"<<G.vexs[k]<<endl;// 求出加入生成树的下一个顶点(k)cout<<closedge[k].adjvex<<"-"<<G.vexs[k]<<":"<<closedge[k] .lowcost<<endl;// 输出生成树上一条边closedge[k].lowcost = 0; // 第k顶点并入U集count++;for (i=0; i<G.vexnum; ++i)//修改其它顶点的最小边{if(closedge[i].lowcost==-1){closedge[i].adjvex = G.vexs[k];closedge[i].lowcost = G.arcs[k][i].adj; continue;}if(closedge[i].lowcost==0) continue;if (G.arcs[k][i].adj ==-1 ) continue;if(G.arcs[k][i].adj<closedge[i].lowcost){closedge[i].adjvex = G.vexs[k];closedge[i].lowcost = G.arcs[k][i].adj; continue;}}}}//10、求顶点u到v的一条简单路径(10分)//m到n的简单路径char path[100];int count1=0;int flag=false;int easy_way(UdGraph G,int m,int n){int i;int DFSway(UdGraph g,int m,int n);for(i=0;i<100;i++) //路径设为空path[i]=' ';count1=0;flag=false;for(i=0;i<G.vexnum;i++) //访问标志数组初始化visited[i]=false;DFSway(G,m,n);if(!flag) return -1;for(i=0;i<count1;i++){if(path[i]==G.vexes[n].data) break;cout<<path[i];}cout<<G.vexes[n].data;return 0;}int DFSway(UdGraph g,int m,int n){//从第m个顶点出发递归地深度优先遍历图Gint w;int i=1;visited[m]=true;path[count1]=g.vexes[m].data;for(w=UdGFirstVex(g,m);w>=0;w=UdGNextVex(g,m,w)){if(!visited[w]){i++;if(w==n)flag=true;count1++;if(!flag){DFSway(g,w,n);//对未被访问的邻接顶点w递归调用DFS}}}if(!flag){if(i==UdGGetDegree(g,g.vexes[m].data))path[count1]=' ';count1--;}return flag;}//求两点的简单路径void print_easy_way(UdGraph G){char ch1,ch2;int i,j;cout<<"输入需要求简单路径的两个顶点:"<<endl; cin>>ch1>>ch2;i=UdGLocateVex(G,ch1);j=UdGLocateVex(G,ch2);cout<<"简单路径为:";if(easy_way(G,i,j)==-1)cout<<"不存在路径";cout<<endl;}//堆栈的基本操作typedef char SElemType;#define STACK_INIT_SIZE 100#define STACKINCREMENT 10typedef struct {int *base; //栈底指针int *top; //栈顶指针int stacksize; //栈的大小} SqStack;int InitStack (SqStack &S){S.base=(int *)malloc(STACK_INIT_SIZE * sizeof(int)); if (!S.base)return(0);S.stacksize = STACK_INIT_SIZE ;S.top = S.base;return(1);}bool StackEmpty (SqStack S){if(S.base==S.top)return(true);//栈空的条件return(false);}int Pop(SqStack &S, int &e){if(S.base==S.top)return(0);//栈空//e=*--S.top;S.top--;e=*S.top;return(1);}int Push(SqStack &S, int e){if(S.top-S.base>= S.stacksize) {//栈满,申请存储空间S.base=(int*)realloc(S.base,(S.stacksize+STACKINCREMENT) * sizeof(int));if (!S.base)return (0);S.stacksize += STACKINCREMENT ;}*S.top=e ;S.top++;return(1);}//求顶点u到其余各点的最短路径int prev[MAXW];//prev[v]表示从源s到顶点v的最短路径上顶点的前驱顶点。

相关主题