c++利用邻接矩阵存储方法实现图的存储与输出。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++利用邻接矩阵存储方法实现图的存储与输出。相关的知识,希望对你有一定的参考价值。
书上的都是c语言的写法,但是我要c++的写法的。各位大侠帮帮忙
1、输出图的深度优先搜索遍历序列
2、Prim算法的实现。
3、利用迪杰斯特拉算法求有向网的最短路径及其长度。
附带点注释,小弟在此先谢谢了
要的是程序的代码...
#include <iostream>
using namespace std;
//*****stack.h
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef int Status;
template<class QElemType>
class stack
public:
void InitStack();
void DestroyStack();
void ClearStack();
Status StackEmpty();
Status StackLength();
void GetTop(QElemType & e);
void Push(QElemType e);
void Pop(QElemType & e);
private:
struct SqStack
QElemType *base;
QElemType *top;
int stacksize;
S;
;
//******stack.cpp------
template<class QElemType>
void stack<QElemType>::InitStack()
S.base = (QElemType *)malloc(STACK_INIT_SIZE * sizeof(QElemType));
if(!S.base) exit(0);
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
template <class QElemType>
void stack<QElemType>::DestroyStack()
free(S.base);
template <class QElemType>
void stack<QElemType>::ClearStack()
S.top = S.base;
template <class QElemType>
Status stack<QElemType>::StackEmpty()
if(S.top == S.base) return 1;
else return 0;
template <class QElemType>
Status stack<QElemType>::StackLength()
return (S.top - S.base);
template <class QElemType>
void stack<QElemType>::GetTop(QElemType & e)
if(S.top != S.base)
e = *(S.top - 1);
else cout << "ERROR" << endl;
template <class QElemType>
void stack<QElemType>::Push(QElemType e)
if(S.top - S.base >= S.stacksize)
S.base = (QElemType *)realloc(S.base,(S.stacksize + STACKINCREMENT) * sizeof(QElemType));
if(!S.base) exit(0);
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
*S.top++ = e;
template <class QElemType>
void stack<QElemType>::Pop(QElemType & e)
if(S.top == S.base) cout << "ERROR" << endl;
else
e = * --S.top;
//**********stack.cpp End
template <class TElemType>
class Graph
public:
void CreateUDN();
void DestroyUDN();
void CreateAlgraph();
void DestroyAlgraph();
void DFS(int v,bool *visited);
void DFSTraverse();
void Minispantree_prim(); //PRIM算法求最小生成树
void Shortestpath_DIJ(TElemType data1,TElemType data2); //对环不适用,如从V1到V1就不适用
void Shortestpath_FLOYD(TElemType data1,TElemType data2);
private:
template <class TElemType>
struct Mgraph
int vexnum;
int arcnum;
TElemType *vertex;
int **AdjMatrix;
;
Mgraph<TElemType> gph; //邻接矩阵存储
struct Arcnode
int adjvex;
Arcnode *nextarc;
float weight;
;
template <class TElemType>
struct Vexnode
TElemType data;
Arcnode *firarc;
;
struct ALgraph
int vexnum;
int arcnum;
bool kind;
Vexnode<TElemType> *vex;
;
ALgraph algraph; //邻接表存储
;
//*********Graph.cpp
template <class TElemType>
void Graph<TElemType>::CreateUDN()
cout << "输入无向网的顶点数和边数:" << endl;
cin >> gph.vexnum >> gph.arcnum;
gph.vertex = (TElemType *)malloc(gph.vexnum * sizeof(TElemType));
int i,j,m,n; //m,n表示顶点信息对应的序号,w是权值
int w;
TElemType v1,v2;
cout << "输入顶点信息:" << endl;
for(i = 0;i < gph.vexnum;i++)
cin >> gph.vertex[i];
gph.AdjMatrix = (int **)malloc(gph.vexnum * sizeof(int *));
for(i = 0;i < gph.vexnum;i++)
gph.AdjMatrix[i] = (int *)malloc(gph.vexnum * sizeof(int));
for(i = 0;i < gph.vexnum;i++)
for(j = 0;j < gph.vexnum;j++)
gph.AdjMatrix[i][j] = INT_MAX; //INT_MAX
cout << "输入一条边依附的两点及权值:" << endl;
for(int k = 0;k < gph.arcnum;k++)
cin >> v1 >> v2 >> w;
for(i = 0;i < gph.vexnum;i++)
if(v1 == gph.vertex[i]) m = i;
if(v2 == gph.vertex[i]) n = i;
gph.AdjMatrix[m][n] = gph.AdjMatrix[n][m] = w;
template <class TElemType>
void Graph<TElemType>::DestroyUDN()
free(gph.vertex);
for(int i = 0;i < gph.vexnum;i++)
free(gph.AdjMatrix[i]);
free(gph.AdjMatrix);
template <class TElemType>
void Graph<TElemType>::CreateAlgraph()
int i,j,m,n;
float w;
TElemType v1,v2;
Arcnode *p;
cout << "输入图类型(1是无向图,0是有向图):" << endl;
cin >> algraph.kind;
cout << "输入顶点数和边数:" << endl;
cin >> algraph.vexnum >> algraph.arcnum;
algraph.vex = (Vexnode<TElemType> *)malloc(algraph.vexnum * sizeof(Vexnode<TElemType>));
cout << "输入顶点信息:" << endl;
for(i = 0;i < algraph.vexnum;i++)
cin >> algraph.vex[i].data;
algraph.vex[i].firarc = NULL;
if(algraph.kind)
cout << "输入各边依附的两点和权值:" << endl;
for(i = 0;i < algraph.arcnum;i++)
cin >> v1 >> v2 >>w;
for(j = 0;j < algraph.vexnum;j++)
if(v1 == algraph.vex[j].data) m = j;
if(v2 == algraph.vex[j].data) n = j;
p = (Arcnode *)malloc(2*sizeof(Arcnode));
p[0].adjvex = n;p[0].weight = w;
p[1].adjvex = m;p[1].weight = w;
p[0].nextarc = algraph.vex[m].firarc;algraph.vex[m].firarc = p;
p[1].nextarc = algraph.vex[n].firarc;algraph.vex[n].firarc = ++p;
else
cout << "输入各边的弧尾与弧头结点及有向边的权值:" << endl;
for(i = 0;i < algraph.arcnum;i++)
cin >> v1 >> v2 >> w;
for(j = 0;j < algraph.vexnum;j++)
if(v1 == algraph.vex[j].data) m = j;
if(v2 == algraph.vex[j].data) n = j;
p = (Arcnode *)malloc(sizeof(Arcnode));
p->adjvex = n;p->weight = w;
p->nextarc = algraph.vex[m].firarc;algraph.vex[m].firarc = p;
//构造完成
template <class TElemType>
void Graph<TElemType>::DestroyAlgraph()
int i;
Arcnode *p,*q;
for(i = 0;i < algraph.vexnum;i++)
p = algraph.vex[i].firarc;
if(p)
q = p->nextarc;
while(q)
free(p);
p = q;
q = q->nextarc;
free(p);
free(algraph.vex);
template <class TElemType>
void Graph<TElemType>::DFS(int v,bool *visited)
cout << algraph.vex[v].data << endl;
visited[v] = true;
Arcnode *p;
int v1;
for(p = algraph.vex[v].firarc;p;p = p->nextarc)
v1 = p->adjvex;
if(!visited[v1]) DFS(v1,visited);
template <class TElemType>
void Graph<TElemType>::DFSTraverse()
int i,v;
bool *visited = (bool *)malloc(algraph.vexnum * sizeof(bool));
for(i = 0;i < algraph.vexnum;i++)
visited[i] = false;
for(v = 0;v < algraph.vexnum;v++)
if(!visited[v]) DFS(v,visited);
free(visited);
//EndDFSTraverse
template <class TElemType>
void Graph<TElemType>::Minispantree_prim()
struct closedge
int adjvex;
int lowcost;
;
closedge *edge = (closedge *)malloc(gph.vexnum * sizeof(closedge));
int i,j,k = 0,u;
int min;
for(i = 0;i < gph.vexnum;i++)
if(i != k)
edge[i].adjvex = 0;
edge[i].lowcost = gph.AdjMatrix[k][i];
edge[k].lowcost = 0;
cout << "最小生成树的边如下:" << endl;
for(i = 1;i < gph.vexnum;i++)
min = INT_MAX;
for(j = 0;j < gph.vexnum;j++)
if(edge[j].lowcost != INT_MAX &&edge[j].lowcost != 0 && edge[j].lowcost < min)
min = edge[j].lowcost;
k = j;
u = edge[k].adjvex;
edge[k].lowcost = 0;
cout << "(" << gph.vertex[u] << "," << gph.vertex[k] << ")" << " ";
for(j = 0;j < gph.vexnum;j++)
if(gph.AdjMatrix[j][k] < edge[j].lowcost)
edge[j].lowcost = gph.AdjMatrix[j][k];
edge[j].adjvex = k;
free(edge);
cout << endl;
template <class TElemType>
void Graph<TElemType>::Shortestpath_DIJ(TElemType data1,TElemType data2)
int i,j,v,u,k,min;
stack<int> S;
S.InitStack();
int *spath = (int *)malloc(gph.vexnum * sizeof(int));
int *pathrecord = (int *)malloc(gph.vexnum * sizeof(int));
bool *visited = (bool *)malloc(gph.vexnum * sizeof(bool));
for(i = 0;i < gph.vexnum;i++) visited[i] = false;
for(i = 0;i < gph.vexnum;i++)
if(data1 == gph.vertex[i]) v = i;
if(data2 == gph.vertex[i]) u = i;
for(i = 0;i < gph.vexnum;i++)
spath[i] = gph.AdjMatrix[v][i];
pathrecord[i] = v;
spath[v] = 0;visited[v] = true;pathrecord[v] = -1;
for(i = 1;i < gph.vexnum;i++)
min = INT_MAX;
for(j = 0;j < gph.vexnum;j++)
if(!visited[j])
if(spath[j] < min) min = spath[j];k = j;
visited[k] = true;
for(j = 0;j < gph.vexnum;j++)
if(!visited[j] && gph.AdjMatrix[k][j] < INT_MAX && spath[k]+gph.AdjMatrix[k][j] < spath[j])
spath[j] = spath[k]+gph.AdjMatrix[k][j];
pathrecord[j] = k;
free(visited);
cout << spath[u] << endl;
S.Push(u);
for(v = pathrecord[u];v != -1;v = pathrecord[v])
S.Push(v);
while(!S.StackEmpty())
S.Pop(i);
cout << gph.vertex[i] << " ";
cout << endl;
S.DestroyStack();
free(spath);
free(pathrecord);
template <class TElemType>
void Graph<TElemType>::Shortestpath_FLOYD(TElemType data1,TElemType data2)
int i,j,k,v,u,m;
int **D = (int **)malloc(gph.vexnum * sizeof(int *));
bool ***path = (bool ***)malloc(gph.vexnum * sizeof(bool **));
for(i = 0;i < gph.vexnum;i++)
D[i] = (int *)malloc(gph.vexnum * sizeof(int));
path[i] = (bool **)malloc(gph.vexnum * sizeof(bool *));
if(data1 == gph.vertex[i]) v = i;
if(data2 == gph.vertex[i]) u = i;
for(i = 0;i < gph.vexnum;i++)
for(j = 0;j < gph.vexnum;j++)
path[i][j] = (bool *)malloc(gph.vexnum *sizeof(bool));
for(i = 0;i < gph.vexnum;i++)
for(j = 0;j < gph.vexnum;j++)
D[i][j] = gph.AdjMatrix[i][j];
for(k = 0;k < gph.vexnum;k++)
path[i][j][k] = false;
if(D[i][j] < INT_MAX)
path[i][j][i] = true;path[i][j][j] = true;
for(k = 0;k < gph.vexnum;k++)
for(i = 0;i < gph.vexnum;i++)
for(j = 0;j < gph.vexnum;j++)
if(D[i][k] != INT_MAX && D[k][j] != INT_MAX && D[i][k]+D[k][j] < D[i][j])
D[i][j] = D[i][k] + D[k][j];
for(m = 0;m < gph.vexnum;m++)
path[i][j][m] = path[i][k][m] || path[k][j][m];
cout << "从" << gph.vertex[v] << "到" << gph.vertex[u] << "的最短路径及经过的点如下:" << endl;
cout << D[v][u] << endl;
for(i = 0;i < gph.vexnum;i++)
if(path[v][u][i] == true) cout << i << " ";
cout << endl;
for(i = 0;i < gph.vexnum;i++)
free(D[i]);
free(path[i]);
free(D);
free(path);
//***********end Graph
int main()
Graph<int> gph;
gph.CreateUDN();
gph.Minispantree_prim();
int data1,data2;
cout << "输入起点和终点:" << endl;
cin >> data1 >> data2;
gph.Shortestpath_DIJ(data1,data2);
//gph.Shortestpath_FLOYD(data1,data2);
gph.DestroyUDN();
return 0;
功能函数都实现了,可以自己在源程序中调用函数实现各种功能。本回答被提问者采纳 参考技术B void dfs(adj,v)
visited[v-1]=1;//标志是否被访问过
visit(v);//cout<<v;
for(p=adj[v-1].firstarc;p!=NULL;p=p->nextarc)
if(!visited[p->adjvex-1]) dfs(adj,p->adjvex);
//prim
#define MAXINT (1<<(sizeof(int)*8-1) )-1
#define NUM 图顶点数
void prim1(g[][NUM],v0,n)//g-图, v0-起始点(1到n),n-图顶点数
for(i=0;i<n;i++) set[i]=0; //memset(set,’\0’,sizeof(set))
set[v0-1]=1;//v0在集合U中
for(k=1;k<=n-1;k++)
min=MAXINT;
for(i=0;i<n;i++)
if(set[i]==1)
for(j=0;j<n;j++)
if(set[j]==0 )
if(g[i][j]<min) p=i;q=j;min=g[i][j];
set[q]=1;
cout<<p+1<<‘ ‘<<q+1<<‘ ‘<<min<<endl;
//for k
//djk
#define NUM
void shortpath_dij(g[][NUM],v0) //v0为源点,值为1到NUM
for(i=0;i<NUM;i++)
set[i]=0;
dist[i]=g[v0-1][i];
set[v0-1]=1;
for(i=1;i<NUM;i++)
min=MAXINT;
for(w=0;w<NUM;w++)
if(set[w]= =0 && dist[w]<min)
v=w; min=dist[w];
set[v]=1;
for(w=0;w<NUM;w++)
if(set[w]= =0 && dist[v]+g[v][w]<dist[w])
dist[w]=dist[v]+g[v][w];
//for i
//shortpath_dij
/****这些是我数据结构的课件上的内容你稍作修改应该可以了,希望对你有帮助,最短路径的完整代码我这也有。你可以找我***/ 参考技术C 有很多现成的代码,不用浪费分数了。
参考资料:http://zhidao.baidu.com/question/99646264.html
图的理解:存储结构与邻接矩阵
存储结构
要存储一个图,我们知道图既有结点,又有边,对于有权图来说,每条边上还带有权值。常用的图的存储结构主要有以下二种:
- 邻接矩阵
- 邻接表
邻接矩阵
我们知道,要表示结点,我们可以用一个一维数组来表示,然而对于结点和结点之间的关系,则无法简单地用一维数组来表示了,我们可以用二维数组来表示,也就是一个矩阵形式的表示方法。
我们假设A是这个二维数组,那么A中的一个元素aij不仅体现出了结点vi和结点vj的关系,而且aij的值正可以表示权值的大小。
以下是一个无向图的邻接矩阵表示示例:
从上图我们可以看到,无向图的邻接矩阵是对称矩阵,也一定是对称矩阵。且其左上角到右下角的对角线上值为零(对角线上表示的是相同的结点)
有向图的邻接矩阵是怎样的呢?
对于带权图,aij的值可用来表示权值的大小,上面两张图是不带权的图,因此它们值都是1。
邻接表
我们知道,图的邻接矩阵存储方法用的是一个n*n的矩阵,当这个矩阵是稠密的矩阵(比如说当图是完全图的时候),那么当然选择用邻接矩阵存储方法。
可是如果这个矩阵是一个稀疏的矩阵呢,这个时候邻接表存储结构就是一种更节省空间的存储结构了。
对于上文中的无向图,我们可以用邻接表来表示,如下:
每一个结点后面所接的结点都是它的邻接结点。
邻接矩阵与邻接表的比较
当图中结点数目较小且边较多时,采用邻接矩阵效率更高。
当节点数目远大且边的数目远小于相同结点的完全图的边数时,采用邻接表存储结构更有效率。
以上是关于c++利用邻接矩阵存储方法实现图的存储与输出。的主要内容,如果未能解决你的问题,请参考以下文章
编程实现以邻接表或邻接矩阵为存储结构,图的广度和深度优先搜索