图G由两个集合V和E组成,记为G=(V,E),其中V是顶点的有限集合,记为V(G), E是连接V中两个不同顶点(顶点对)的边的有限集合,记为E(G)
#include
#include
#include
using namespace std;
#define MAXV 100
#define INF 32767
typedef struct {
int num; // 序号
int data;
}VertexType; // 顶点类型
typedef struct {
int edges[MAXV][MAXV]; // 邻接矩阵数组
int n,e; // 顶点数,边数
VertexType vertex[MAXV]; // 顶点
}MatGraph;
// 图的邻接表表示
typedef struct ANode { //边结点类型
int adjvex; //该边邻接点编号
struct ANode *nextarc;
int weight;
}ArcNode;
typedef struct Vnode{ // 头结点类型
VertexType data; // 顶点信息
int count; // 增加数据域:存放顶点入度
ArcNode *firstarc;
}VNode;
typedef struct {
VNode adjlist[MAXV];
int n;
int e;
}AdjGraph; // 用一个头节点数组构造的图
// 用邻接表创建图
void CreateAdj(AdjGraph *&G,int A[MAXV][MAXV], int n, int e)
{
int i,j;
ArcNode* p;
G = (AdjGraph*)malloc(sizeof(AdjGraph));
for(i=0;i<n;i++)
G->adjlist[i].firstarc = NULL;
for(i=0;i<n;i++)
for(j=n-1;j>=0;j--)
{
if(A[i][j] !=0&&A[i][j]!=INF)
{
p = (ArcNode*)malloc(sizeof(ArcNode));
p->adjvex = j;
p->weight = A[i][j];
p->nextarc = G->adjlist[i].firstarc;
G->adjlist[i].firstarc = p;
}
}
G->n = n , G->e = e;
}
// 输出图G
void DispAdj(AdjGraph *G)
{
int i;
ArcNode *p;
for(i=0;i<G->n;i++)
{
p = G->adjlist[i].firstarc;
printf("%3d:",i);
while(p!=NULL)
{
printf("%3d[%d]->",p->adjvex,p->weight);
p = p->nextarc;
}
cout << "^\n";
}
}
// 销毁图
void DestroyAdj(AdjGraph *&G)
{
int i;
ArcNode *pre, *p;
for(i=0;i<G->n;i++)
{
pre = G->adjlist[i].firstarc;
if(pre!=NULL)
{
p = pre->nextarc;
while(p!=NULL)
{
free(pre);
pre = p;
p = p->nextarc;
}
free(pre);
}
}
free(G);
}
// 邻接矩阵转邻接表 复杂度:O(n^2)
void MatToList(MatGraph g, AdjGraph *&G)
{
int i,j;
ArcNode *p;
G = (AdjGraph*)malloc(sizeof(AdjGraph));
for(i=0;i<G->n;i++)
G->adjlist[i].firstarc = NULL;
for(i=0;i<g.n;i++)
for(j=g.n-1;j>=0;j--)
if(g.edges[i][j]!=0&&g.edges[i][j]!=INF)
{
p = (ArcNode*)malloc(sizeof(ArcNode));
p->adjvex = j;
p->weight = g.edges[i][j];
p->nextarc = G->adjlist[i].firstarc;
G->adjlist[i].firstarc = p;
}
G->n = g.n;
G->e = g.e;
}
// 邻接表转邻接矩阵 复杂度 O(n+e)
void ListToMat(AdjGraph *G, MatGraph &g)
{
int i;
ArcNode *p;
for(i=0;i<G->n;i++)
{
p = G->adjlist[i].firstarc;
while(p!=NULL)
{
g.edges[i][p->adjvex] = p->weight;
p = p->nextarc;
}
}
g.n = G->n;
g.e = G->e;
}
int visited[MAXV]={0};
// 深度优先搜索 DFS O(n+e)
void DFS(AdjGraph *G,int v) // 遍历连通图
{
ArcNode *p;
visited[v] = 1;
printf("%2d",v);
p = G->adjlist[v].firstarc;
while(p!=NULL)
{
if(visited[p->adjvex] == 0)
DFS(G,p->adjvex);
p = p->nextarc;
}
}
void DFS1(AdjGraph *G) // 遍历非连通图
{
for(int i=0;i<G->n;i++)
if(visited[i]==0) DFS(G,i);
}
// 广度优先搜索 O(n^2)
void BFS(AdjGraph *&G, int v) // 遍历连通图
{
int w;
ArcNode *p;
int visited[MAXV] ={0};
visited[v] = 1;
printf("%2d",v);
deque<int> de;
de.push_back(v);
while(!de.empty())
{
w = *de.begin();
de.pop_front();
p = G->adjlist[w].firstarc;
while(p!=NULL){
if(visited[p->adjvex] == 0)
{
printf("%2d",p->adjvex);
visited[p->adjvex] = 1;
de.push_back(p->adjvex);
}
p = p->nextarc;
}
}
cout << endl;
}
void BFS1(AdjGraph *G) // 遍历非连通图
{
for(int i=0;i<G->n;i++)
if(visited[i]==0) BFS(G,i);
}
bool Connect(AdjGraph *G)
{
int i;
bool flag = true;
for(int i=0;i<G->n;i++)
visited[i] = 0;
DFS(G,0);
for(int i=0;i<G->n;i++)
if(visited[i]==0)
{
flag = false;
break;
}
return flag;
}
int main()
{
int A[MAXV][MAXV] = {
{0,28,INF,INF,INF,10,INF},
{26,0,16,INF,INF,INF,14},
{INF,16,0,12,INF,INF,INF},
{INF,INF,12,0,22,INF,18},
{INF,INF,INF,22,0,25,24},
{10,INF,INF,INF,25,0,INF},
{INF,14,INF,18,24,INF,0}
};
AdjGraph *G;
int n = 7,e = 18;
CreateAdj(G,A,n,e);
DispAdj(G);
cout << "广度优先搜索产生的序列为: ";
BFS(G,0);
cout << "深度优先搜索产生的序列为: ";
DFS(G,0);
cout << endl;
//cout << "图G是否连通: ";
//printf(" %d",Connect(G));
DestroyAdj(G);
return 0;
}
P.S:马上考试了,我还在写博客,但我觉得这才是正确的复习方式,hahahha太真实了…