//头文件
//以数组形式构造图
#pragma once
#include <iostream>
#include <queue>
using namespace std;
#define INFINITY INT_MAX
#define NAX_VERTEX_NUM 20
#define VRtype int
//#define InfoType char*
#define VertexType char*
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define INFEASIBLE -1
bool visited[NAX_VERTEX_NUM];
void(*VisitFunc)(VertexType);
typedef enum
{
DG,DN,UDG,UDN//有向图,有向网,无向图,无向网
}GraphKind;
typedef struct ArcCell
{
VRtype adj;//无权图,用0或1;带权图,即权值
//InfoType *info;
}ArcCell, AdjMatrix[NAX_VERTEX_NUM][NAX_VERTEX_NUM];
typedef struct //定义图的结构
{
VertexType vexs[NAX_VERTEX_NUM];//顶点向量
AdjMatrix arcs; //邻接矩阵
int vexnum,arcnum; //定点数,边(弧)数
GraphKind kind; //图的种类标记
}MGraph;
int CreateDG(MGraph &G);//构造有向图
int CreateDN(MGraph &G);//构造有向网
int CreateUDG(MGraph &G);//构造无向图
int CreateUDN(MGraph &G);//构造无向网
int CreateGraph(MGraph &G)//采用数组(邻接矩阵)表示法,构造图G
{
int n;
cout<<"创建有向图(0),有向网(1),无向图(2),无向网(3)"<<endl;
cin>>n;
switch(n)
{
case DG:
G.kind = DG;
return CreateDG(G);//有向图
case DN:
G.kind = DN;
return CreateDN(G);//有向网
case UDG:
G.kind = UDG;
return CreateUDG(G);//无向图
case UDN:
G.kind = UDN;
return CreateUDN(G);//无向网
default:
return ERROR;
}
}
int LocateVex(MGraph G, VertexType V)//顶点V在图中的位置
{
int i;
for(i=0; i<G.vexnum; i++)
{
if(strcmp(G.vexs[i],V) == 0)
return i;
}
return -1;//不存在,返回-1
}
int CreateUDG(MGraph &G)//构造无向图
{
cout<<"输入顶点数,边数:"<<endl;
cin>>G.vexnum>>G.arcnum;
int i,j,k;
for(i=0; i<G.vexnum; i++)//构造顶点向量
{
cout<<"输入第"<<i+1<<"个顶点的名称:";
G.vexs[i] = (VertexType)malloc( sizeof(char) );
cin>>G.vexs[i];
}
for(i=0; i<G.vexnum; i++)//初始化领接矩阵
{
for(j=0; j<G.vexnum; j++)
{
G.arcs[i][j].adj = 0;
//G.arcs[i][j].info = NULL;
}
}
char *v1, *v2;
v1 = (char*)malloc(sizeof(char));
v2 = (char*)malloc(sizeof(char));
for(k=0; k<G.arcnum; k++)//构造邻接矩阵
{
cout<<"输入相连的边(v1,v2):";
cin>>v1>>v2;
i = LocateVex(G,v1);//定位顶点v1及v2在图中的位置
j = LocateVex(G,v2);
G.arcs[i][j].adj = 1;//权值
G.arcs[j][i] = G.arcs[i][j];//无向图中,邻接矩阵对称
}
G.kind = UDG;//无向图
return OK;
}
int CreateDG(MGraph &G)//构造有向图
{
cout<<"输入顶点数,边数:"<<endl;
cin>>G.vexnum>>G.arcnum;
int i,j,k;
for(i=0; i<G.vexnum; i++)//构造顶点向量
{
cout<<"输入第"<<i+1<<"个顶点的名称:";
G.vexs[i] = (VertexType)malloc( sizeof(char) );
cin>>G.vexs[i];
}
for(i=0; i<G.vexnum; i++)//初始化领接矩阵
{
for(j=0; j<G.vexnum; j++)
{
G.arcs[i][j].adj = 0;
//G.arcs[i][j].info = NULL;
}
}
char *v1, *v2;
v1 = (char*)malloc(sizeof(char));
v2 = (char*)malloc(sizeof(char));
for(k=0; k<G.arcnum; k++)//构造邻接矩阵
{
cout<<"输入连接的边(v1,v2):";
cin>>v1>>v2;
i = LocateVex(G,v1);//定位顶点v1及v2在图中的位置
j = LocateVex(G,v2);
G.arcs[i][j].adj = 1;//权值
}
G.kind = DG;//有向图
return OK;
}
int CreateUDN(MGraph &G)//采用数组(邻接矩阵)表示法,构造无向网
{
//int IncInfo;
cout<<"输入顶点数,边数:"<<endl;
cin>>G.vexnum>>G.arcnum;
int i,j,k;
for(i=0; i<G.vexnum; i++)//构造顶点向量
{
cout<<"输入第"<<i+1<<"个顶点的名称:";
G.vexs[i] = (VertexType)malloc( sizeof(char) );
cin>>G.vexs[i];
}
for(i=0; i<G.vexnum; i++)//初始化领接矩阵
{
for(j=0; j<G.vexnum; j++)
{
G.arcs[i][j].adj = INFINITY;
//G.arcs[i][j].info = NULL;
}
}
char *v1, *v2;
v1 = (char*)malloc(sizeof(char));
v2 = (char*)malloc(sizeof(char));
int w;
for(k=0; k<G.arcnum; k++)//构造邻接矩阵
{
cout<<"输入边及其权重(v1,v2,w):";
cin>>v1>>v2>>w;
i = LocateVex(G,v1);//定位顶点v1及v2在图中的位置
j = LocateVex(G,v2);
G.arcs[i][j].adj = w;//权值
G.arcs[j][i] = G.arcs[i][j];//无向网中,邻接矩阵对称
}
G.kind = UDN;//无向网
return OK;
}
int CreateDN(MGraph &G)//采用数组(邻接矩阵)表示法,构造有向网
{
//int IncInfo;
cout<<"输入顶点数,边数:"<<endl;
cin>>G.vexnum>>G.arcnum;
int i,j,k;
for(i=0; i<G.vexnum; i++)//构造顶点向量
{
cout<<"输入第"<<i+1<<"个顶点的名称:";
G.vexs[i] = (VertexType)malloc( sizeof(char) );
cin>>G.vexs[i];
}
for(i=0; i<G.vexnum; i++)//初始化领接矩阵
{
for(j=0; j<G.vexnum; j++)
{
G.arcs[i][j].adj = INFINITY;
//G.arcs[i][j].info = NULL;
}
}
char *v1, *v2;
v1 = (char*)malloc(sizeof(char));
v2 = (char*)malloc(sizeof(char));
int w;
for(k=0; k<G.arcnum; k++)//构造邻接矩阵
{
cout<<"输入边及其权重(v1,v2,w):";
cin>>v1>>v2>>w;
i = LocateVex(G,v1);//定位顶点v1及v2在图中的位置
j = LocateVex(G,v2);
G.arcs[i][j].adj = w;//权值
}
G.kind = DN;//有向网
return OK;
}
VertexType GetVex(MGraph G, int v)//返回图中第V个顶点
{
if(v<1 || v>G.vexnum)
return NULL;
else
return G.vexs[v-1];//顶点数组以标号0开始
}
int PutVex(MGraph &G, VertexType v, VertexType value)//修改图中顶点v的名称为value
{
int i = LocateVex(G,v);
if(i<0)
return ERROR;
else
strcpy(G.vexs[i],value);
return OK;
}
VertexType FirstAdjVex(MGraph G, VertexType v)//返回顶点V的第一个邻接点
{
int i,j,k;
k = LocateVex(G,v);//定位顶点v在图中的位置
if(k<0)
return NULL;
if(G.kind % 2 == 1)//网
j = INFINITY;
else
j = 0;//图
for(i=0; i<G.vexnum; i++)
{
if(G.arcs[k][i].adj != j)//邻接矩阵中该行第一个不为j的分量所在的列号
return GetVex(G,i+1);
}
return NULL;
}
VertexType NextAdjVex(MGraph G, VertexType v, VertexType w)//返回顶点V的(相对于w)下一个邻接点
{
int i,j,k,p;
i = LocateVex(G,v);
j = LocateVex(G,w);
if(i<0 || j<0)
return NULL;
if(G.kind % 2 == 1)//网
k = INFINITY;
else
k = 0;//图
for(p=j+1; p<G.vexnum; p++)
{
if(G.arcs[i][p].adj != k)
return GetVex(G,p+1);
}
return NULL;
}
void InsertVex(MGraph &G, VertexType v)//插入顶点
{
int j,i;
if(G.kind % 2 == 1)
j = INFINITY;//网
else
j = 0;//图
G.vexs[G.vexnum] = (VertexType)malloc(sizeof(VertexType));
strcpy(G.vexs[G.vexnum],v);
for(i=0; i<=G.vexnum; i++)
G.arcs[G.vexnum][i].adj = G.arcs[i][G.vexnum].adj = j;//初始化权值
G.vexnum++;
}
int DeleteVex(MGraph &G, VertexType v)//删除顶点
{
int i,j,k,p;
k = LocateVex(G,v);
if(k<0)
return ERROR;
if(G.kind % 2 == 1)
j = INFINITY;//网
else
j = 0;//图
for(i=0; i<G.vexnum; i++)//入弧(出度)
if(G.arcs[k][i].adj != j)
G.arcnum--;
if(G.kind < 2)//有向
for(i=0; i<G.vexnum; i++)
if(G.arcs[i][k].adj != j)
G.arcnum--;
for(i=k+1; i<G.vexnum; i++)//顶点向量第k个之后的都往前移
strcpy(G.vexs[i-1],G.vexs[i]);
//free(G.vexs[i-1]);
G.vexs[i-1] = NULL;
for(i=0; i<G.vexnum; i++)//邻接矩阵中每行从第k列之后的都往前移
{
for(p=k+1; p<G.vexnum; p++)
G.arcs[i][p-1] = G.arcs[i][p];
G.arcs[i][p-1].adj = j;
}
G.arcs[i-1][p-1].adj = j;
for(i=k+1; i<G.vexnum; i++)//邻接矩阵中每列从第k行之后的都往上移
{
for(p=0; p<G.vexnum-1; p++)
{ G.arcs[i-1][p] = G.arcs[i][p];
if(i == G.vexnum-1)
G.arcs[i][p].adj = j;
}
}
G.vexnum--;
return OK;
}
int InsertArc(MGraph &G, VertexType v, VertexType w)//插入一条边或弧
{
int i,j,weight;
i = LocateVex(G,v);//尾
j = LocateVex(G,w);//头
if(i<0 || j<0)
return ERROR;
G.arcnum++;
if(G.kind % 2 == 1)
{
cout<<"输入权值:";
cin>>weight;
}
else
weight = 1;
if(G.kind < 2)//有向
G.arcs[i][j].adj = weight;
else//无向
G.arcs[j][i].adj= G.arcs[i][j].adj=weight;
return OK;
}
int DeleteArc(MGraph &G, VertexType v, VertexType w)//删除一条边
{
int i,j,weight;
i = LocateVex(G,v);//尾
j = LocateVex(G,w);//头
if(i<0 || j<0)
return ERROR;
G.arcnum--;
if(G.kind % 2 == 1)//网
weight = INFINITY;
else//图
weight = 1;
if(G.kind < 2)//有向
G.arcs[i][j].adj = weight;
else
G.arcs[i][j].adj = G.arcs[j][i].adj = weight;
return OK;
}
void Display(MGraph G)//输出邻接矩阵
{
int i,j;
for(i=0; i<G.vexnum; i++)
{
for(j=0; j<G.vexnum; j++)
{
cout<<"("<<G.vexs[i]<<"->"<<G.vexs[j]<<",";
if(G.arcs[i][j].adj == INFINITY)
cout<<"oo";
else
cout<<G.arcs[i][j].adj;
cout<<")"<<" ";
}
cout<<endl;
}
}
void Visit(VertexType e)
{
cout<<e;
}
void DFS(MGraph G, int v)
{
visited[v] = TRUE;//访问第v个结点
VisitFunc(G.vexs[v]);
VertexType w;
for(w=FirstAdjVex(G,G.vexs[v]); w!=NULL; w=NextAdjVex(G,G.vexs[v],w) )//对第v个顶点尚未访问的邻接结点w递归调用DFS
{
if(!visited[LocateVex(G,w)])
DFS(G,LocateVex(G,w));
}
}
void DFSTraverse(MGraph G, void(*Visit)(VertexType))//深度优先遍历
{
int v;
VisitFunc = Visit;
for(v=0; v<G.vexnum; v++)
visited[v] = FALSE;//访问标志数组
for(v=0; v<G.vexnum; v++)
if(!visited[v])//对尚未访问的顶点调用DFS
DFS(G,v);
cout<<endl;
}
void BFSTraverse(MGraph G, void(*Visit)(VertexType))//广度优先搜索算法
{
int i,u;
VertexType w;
for(i=0; i<G.vexnum; i++)//访问标记数组初始化
visited[i] = FALSE;
queue<int> Q; //置空的辅助队列
for(i=0; i<G.vexnum; i++)
{
if(!visited[i])
{
visited[i] = TRUE;
Visit(G.vexs[i]);
Q.push(i);
while(!Q.empty())
{
u = Q.front();//对头元素出队并置为u
Q.pop();
for(w=FirstAdjVex(G,G.vexs[u]); w!=NULL; w=NextAdjVex(G,G.vexs[u],w))
{ //w为u的尚未访问的邻接顶点
if(!visited[LocateVex(G,w)])
{
visited[LocateVex(G,w)] = TRUE;
Visit(w);
Q.push(LocateVex(G,w));
}
}
}
}
}
cout<<endl;
}
// Graph_Connectivity.cpp : Defines the entry point for the console application.
/*-----CODE FOR FUN---------------
-------CREATED BY Dream_Whui------
-------2015-2-11--------------------*/
//求无向图G的深度优先生成森林,孩子兄弟链表T
#include "stdafx.h"
#include "Graph.h" //引入图的头文件
typedef char* Elemtype;
typedef struct CSNode//树的存储结构:孩子兄弟链表结构
{
Elemtype data;
struct CSNode *firstchild, *nextsibling;
}CSNode, *CSTree;
void DFSTree(MGraph G, int i, CSTree &T)//从第i个顶点出发深度优先遍历图G,建立以T为根的生成树
{
int first;
VertexType w;
CSTree p,q;
visited[i] = TRUE;
first = TRUE;
for(w=FirstAdjVex(G,G.vexs[i]); w!=NULL; w=NextAdjVex(G,G.vexs[i],w))
{
if(!visited[LocateVex(G,w)])
{
p = (CSTree)malloc(sizeof(CSNode));//分配孩子结点,并赋值
p->data = (Elemtype)malloc(sizeof(char));
p->data = w;
p->firstchild = NULL;
p->nextsibling = NULL;
if(first) //w是v的第一个未被访问的邻接顶点
{
T->firstchild = p;
first = FALSE;
}
else
q->nextsibling = p; //是上一个邻接顶点的右兄弟结点
q = p;
DFSTree(G,LocateVex(G,w),q); //从第w个顶点出发深度优先遍历图G,建立子生成树q
}
}
}
void DFSForest(MGraph G, CSTree &T)//无向图G的深度优先生成森林,孩子兄弟链表T
{
T = NULL;
CSTree p,q;
int i;
for(i=0; i<G.vexnum; i++)
visited[i] = FALSE;
for(i=0; i<G.vexnum; i++)
{
if(!visited[i]) //第i个结点为新的生成树的根结点
{
p = (CSTree)malloc(sizeof(CSNode));//分配根结点,并赋值
p->data = (Elemtype)malloc(sizeof(char));
p->data = GetVex(G,i+1);//返回第i+1个顶点的名字(i以0起,即结点以i+1起)
p->firstchild = NULL;
p->nextsibling = NULL;
if(!T)
T = p; //第一颗生成树的根
else
q->nextsibling = p;//是其他生成树的根(前一颗的根的“兄弟”)
q = p; //q指示当前生成树的根
DFSTree(G,i,p);
}
}
}
void DFS_Traverse(CSTree T) //深度优先输出各顶点的名字
{
if(T)
{
cout<<T->data;
DFS_Traverse(T->firstchild);
DFS_Traverse(T->nextsibling);
}
}
int main(int argc, char* argv[])
{
MGraph G;
CSTree T;
CreateGraph(G);
DFSForest(G,T);
DFS_Traverse(T);
return 0;
}
数据结构---图的连通性
最新推荐文章于 2022-03-30 21:07:43 发布