#include<stdio.h>
#include<stdlib.h>
//定义边
typedef struct Enode
{
int v1,v2;
int weight;
} *Edge;
//定义邻接点(构造边表)
typedef struct Adjvnode
{
int sign;
int weight;
struct Adjvnode *next;
} *Adjv;
//定义顶点表列
struct Hnode
{
char Data;
Adjv FirstEdge;
};
//定义一个图(含有100个顶点表列,Nv,Ne)
struct Gnode
{
int Nv;
int Ne;
struct Hnode AdjvList[100];
};
typedef struct Gnode* Graph;
Graph CreateGraph(int VerNum)
{//新建一个有VerNum个顶点但没有图的边(VerNum<=100)
int v;
Graph G;
G=(Graph)malloc(sizeof(struct Gnode));
G->Nv=VerNum;
G->Ne=0;
//注意,这种做法表示顶点编号应该从0开始,到Nv-1。
for(v=0;v<=VerNum;v++)
{
G->AdjvList[v].FirstEdge=NULL;
}
return G;
}
//插入边函数
void InsertEdge(Graph G,Edge E)
{
Adjv NewNode;//新建一个邻接点
NewNode=(Adjv)malloc(sizeof(struct Adjvnode));
NewNode->sign=E->v2;//这个邻接点代表的是v1所指向的v2
NewNode->weight=E->weight;//这条路径上的权重也要放进去新的邻接点里面
/*将代表v2的邻接点放入空图中*/
NewNode->next=G->AdjvList[E->v1].FirstEdge;
G->AdjvList[E->v1].FirstEdge=NewNode;
/*
Q1:为什么要让新的节点指向头节点(原来的节点)
A1:这样子方便我们后面进行遍历
Q2:那么FirstEdge中的next什么时候会用到
A2:在遍历的时候会用到
*/
//如果是无向图,还有以下操作
NewNode=(Adjv)malloc(sizeof(struct Adjvnode));
NewNode->sign=E->v1;
NewNode->weight=E->weight;
NewNode->next=G->AdjvList[E->v2].FirstEdge;
G->AdjvList[E->v2].FirstEdge=NewNode;
}
//创造一个图
Graph BuildGraph()
{
Graph G;
Edge E;
int Nv,i,v;
printf("正在读入顶点个数");
scanf("%d",&Nv);
G=CreateGraph(Nv);
printf("读入边个数");
scanf("%d",&(G->Ne));
if(G->Ne!=0)
{
E=(Edge)malloc(sizeof(struct Enode));
for(i=0;i<G->Ne;i++)
{
printf("请输入边的起点,终点,以及权重信息");
scanf("%d %d %d",&E->v1,&E->v2,&E->weight);
InsertEdge(G,E);
}
}
printf("输入顶点数据");
for(v=0;v<G->Nv;v++)
{
scanf("%d",&(G->AdjvList[v].Data));
}
return G;
}
c语言图的邻接表(没有main函数)
最新推荐文章于 2024-04-21 19:51:15 发布