图的基本操作主要包括图的建立,图的广度遍历跟图的深度遍历。图的建立就相当于将一副图存储起来,有两种方式,一种是邻接矩阵,一种是邻接链表。
1.邻接矩阵
个人认为邻接矩阵就是一个将顶点行列化的存储方式,用来存储图。比如一个有n个顶点的图,那么它用邻接矩阵表示的时候就是一个n行n列的矩阵!而它的边就是矩阵中有序点置1。
如图所示
![tu tu](https://images.cnblogs.com/cnblogs_com/march_seven/WindowsLiveWriter/7bc980b02a8b_F043/tu_thumb.png)
图还分有向,跟无向!这个就关系到存储的时候,矩阵是否对称!比如顶点1到顶点2有一条边,
则矩阵有序点(1,2)第一行第二列那个点是被置1 的;
同时无向的时候,矩阵有序点(2,1)第二行第一列那个点也是被置1 的,如果是有向,则改点不会被置1 ;
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
march_seven
/*邻接矩阵建立法*/
#define n 8
#define MAXSIZE 32 /*广度优先遍历时所使用的队列的最大容量*/
#define MaxNum 10000 /*定义一个最大数*/
/* 定义邻接矩阵类型 */
typedef int adjmatrix[n+1][n+1]; /* 0号单元没用*/
int visited[n+1]; /* 0号单元没用*/
int arcnum; /*边的个数*/
/* 建立图的邻接矩阵 */
void CreatMatrix(adjmatrix GA)
{
int i,j,k;
printf("图中有%d个顶点\n",n);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i==j) GA[i][j]=0; /*对角线的值置为0*/
else GA[i][j]=MaxNum; /*其它位置的值初始化为一个最大数*/
printf("请输入边的个数(限制在1到32的范围内):");
scanf("%d",&arcnum);
printf("请输入图的所有边(一条边的两个端点中间用,分隔): , \n");
for(k=1;k<=arcnum;k++)
{
scanf("%d,%d",&i,&j); /*读入边的信息*/
GA[i][j]=1;
GA[j][i]=1;
}
}
/* 从初始点v出发深度优先搜索邻接矩阵GA表示的图 */
void DfsMatrix(adjmatrix GA,int v)
{
int j;
visited[v]=1; printf("%d,",v);
for(j=1;j<=n;j++)
if(v!=j&&GA[v][j]!=MaxNum&&!visited[j]) DfsMatrix(GA,j);
}
void BfsMatrix(adjmatrix GA,int v)
{
int i,k,j,Q[MAXSIZE],front=0,rear=0;
for(i=1;i<=n;i++) visited[i]=0;
visited[v]=1;
printf("%d ",v);
rear=(rear+1)%MAXSIZE; /*开始遍历的顶点入队列*/
Q[rear]=v;
while(front!=rear)
{front=(front+1)%MAXSIZE; /*队头元素出队*/
k=Q[front];
for(j=1;j<=n;j++)
if((!visited[j])&&(GA[k][j]==1)) /*访问与队头元素邻接的还未被访问的结点*/
{visited[j]=1;
printf("%d ",j);
rear=(rear+1)%MAXSIZE;
Q[rear]=j;
}
}
}
main()
{adjmatrix GA;
int v;
CreatMatrix(GA);
printf("请输入深度优先遍历的开始结点:");
scanf("%d",&v);
printf("深度优先遍历序列是:");
DfsMatrix(GA,v);
printf("\n");
printf("请输入广度优先遍历的开始结点:");
scanf("%d",&v);
printf("广度优先遍历序列是:");
BfsMatrix(GA,v);
}
2.邻接链表
邻接链表就是将图通过链表的方式存储起来,这相对矩阵的存储方式比较复杂,但是实际意义更为明显,比如链表可以存储顶点更多的信息,(边的权值,顶点的数据域)相比之下它的工程意义更大。
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
march_seven#define MAXNODE 10
#define NULL 0
typedef struct arc
{int adjvex;
struct arc *next;}ArcNode;
typedef struct VexNode
{int vertex;
ArcNode *firstarc;
}VerNode;
typedef VerNode AdjList[MAXNODE];
int visited[MAXNODE];
int vexnum,arcnum;
void creatgraph(AdjList GL)
{int i,j,k;
ArcNode *p;
printf("请输入顶点个数和边的个数:");
scanf("%d,%d",&vexnum,&arcnum);
printf("请输入顶点(顶点用整型数代表):\n");
for(i=1;i<=vexnum;i++)
{scanf("%d",&GL[i].vertex);
GL[i].firstarc=NULL;
}
printf("请输入图的所有边(一条边的两个端点中间用,分隔): , \n");
for(k=1;k<=arcnum;k++)
{scanf("%d,%d",&i,&j);
if(i&&j)
{p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=j;p->next=GL[i].firstarc;GL[i].firstarc=p;
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=i;p->next=GL[j].firstarc; GL[j].firstarc=p;
}
}
}
void DfsAdjlist(AdjList GL,int v)
{int i;
for(i=1;i<=vexnum;i++) visited[i]=0;
if(!visited[v]) dfs(GL,v);
}
int dfs(AdjList G,int v)
{ArcNode *q;
if(!visited[v]) printf("%d,",G[v].vertex);
visited[v]=1;
q=G[v].firstarc;
while(q!=NULL)
{if(!visited[q->adjvex]) dfs(G,q->adjvex);
q=q->next;
}
}
int BfsAdjlist(AdjList GL,int v)
{int k,i,j,Q[MAXNODE],front=0,rear=0;
ArcNode *p;
for(i=1;i<=vexnum;i++) visited[i]=0;
visited[v]=1;
printf("%d ",GL[v].vertex);
rear=(rear+1)%MAXNODE;
Q[rear]=v;
while(front!=rear)
{front=(front+1)%MAXNODE;
k=Q[front];
p=GL[k].firstarc;
while(p!=NULL)
{if(!visited[p->adjvex])
{visited[p->adjvex]=1;
printf("%d ",p->adjvex);
rear=(rear+1)%MAXNODE;
Q[rear]=p->adjvex;
}
p=p->next;
}
}
}
main()
{AdjList GL;
int v;
creatgraph(GL);
printf("请输入深度优先遍历的开始结点:");
scanf("%d",&v);
printf("深度优先遍历序列是:");
DfsAdjlist(GL,v);
printf("\n");
printf("请输入广度优先遍历的开始结点:");
scanf("%d",&v);
printf("广度优先遍历序列是:");
BfsAdjlist(GL,v);
}
具体输入操作
深度遍历,概念比较模糊,解释不清楚!略!!!见谅!!!
广度遍历!
用下面一副图来说明!
就是一层一层的遍历!当然结果也有可能是:1,2,3,4,5,6,7关键还是看建立邻接链表时的顺序!
具体输入操作