一、邻接矩阵
<编译通过正常运行>
#include<stdio.h>
#include<stdlib.h>
#define MAXVEX 100 最大顶点数
typedef char VertexType; //顶点类型
typedef int EdgeType; //权值类型
#define INFINITY 65535 //用65535来表 ∞
typedef struct
{
VertexType vexs [MAXVEX]; //顶点表
EdgeType arc [MAXVEX][MAXVEX]; //邻接矩阵(边表)
int numVertexes ,numEdges; //当前的顶点数和边数。
}Graph; //后面也常写作MGraph。。。。sorry
void CreateGraph ( Graph *G )
{
int i , j , k , w ;
printf("请输入顶点数和边数(中间加逗号):\n");
scanf( "%d , %d",&G->numVertexes , &G->numEdges );
for ( i=0 ; i<G->numVertexes ; i++)
scanf("%c",&G->vexs[i]); //读入顶点信息
for ( i = 0 ; i<G->numVertexes ; i++)
for ( j = 0 ; j < G->numVertexes ; j++)
G->arc[i][j] = INFINITY; //邻接矩阵全初始化
for ( k = 0 ; k < G->numEdges ; k++ ) //1、
{
printf ( "输入边(vi,vj)上的下标i , j 和 权w:");
//如果是有向图,就按照方向输入下标
scanf("%d%d%d",&i,&j,&w);
G->arc[i][j]=w;
G->arc[j][i]=G->arc[i][j] ;
//无向图是对称矩阵。有向图去掉这句。
}
}
// 1、 无向图循环G->numEdges次,有向图要把所有循环条件改成2*G->numEdges次
/*我们总结:创建一个有向图的邻接表需要的元素有很多,
包括:
过称是:输入 : 顶点个数, 边的条数,
arc[numvertexes][numvertexes]邻接矩阵(边表)
全部初始化为 INFINITY:∞
输入邻接矩阵的下标和权值。*/
/*n个顶点e条边的无向网图的构建时间复杂度为O(n+n*n+e),其中邻接矩阵初始化花费O(n*n)的时间*/
void printGraph(Graph g) //打印“图”
{
int i, j;
for(i = 0 ; i < g.numVertexes; i++)
{
for(j = 0 ; j < g.numVertexes; j++) //1、
{
printf( " %d ", g.arc[i][j]);
}
printf("\n");
}
}
int main( ) {
Graph G;
CreateGraph(&G);
printGraph(G);
return 0;
}
// 1、 无向图循环G->numEdges次,有向图要把所有循环条件改成2*G->numEdges次 。
用邻接矩阵表示有向图时,
若 ai -> aj 的权值 =8
aj -> ai 的权值 =∞
那我们自然可知这条边有方向。
二、邻接表
邻接表的创建 w(゚Д゚)w<正常运行>
#include<stdio.h>
#include<stdlib.h>
typedef char VertexType; //顶点类型
typedef int EdgeType; //权值类型
#define INFINITY 65535 //用65535来表∞
#define MAXVEX 100 最大顶点数
typedef struct node //边表节点
{
int adjvex; //邻接点域
EdgeType weight;
struct node *next; //链域,指向下一个邻接点。
}EdgeNode ;
typedef struct VertexNode //顶点表节点。
{
VertexType data; //顶点域存储定顶点信息。
EdgeNode *firstedge; //边表头指针。
}VertexNode , AdjList[ MAXVEX ] ;
typedef struct
{
AdjList adjlist; //
int numVertexes,numEdges; //图中当前顶点数和边数
}GraphAdjList;
//无向图的邻接表创建代码
void CreateALGraph(GraphAdjList *G)
{
int i , j , k ;
EdgeNode *e;
printf("输入顶点数和边数\n");
scanf("%d%d",&G->numVertexes,&G->numEdges);
for (i = 0; i < G->numVertexes; i++)
{
scanf("%d",&G->adjlist[i].data); //顶点的标号
G->adjlist[i].firstedge = NULL;
//将边表置为空表
}
for (k = 0; k < G->numEdges; k++)
{
printf("输入边(Vi,Vj)上的顶点序号:\n");
scanf("%d %d",&i,&j);
e = (EdgeNode *)malloc(sizeof(EdgeNode));
/*向内存申请空间,生成边表节点*/
e->adjvex = j; //邻接序号为j
e->next = G->adjlist[i].firstedge;
/*将e指针指向当前顶点指向的节点*/
G->adjlist[i].firstedge = e;
//将当前结点的指针指向e
e = (EdgeNode *)malloc(sizeof(EdgeNode));
/*向内存申请空间,生成边表节点*/
e->adjvex = i ; //邻接序号为 i
e->next = G->adjlist[j].firstedge;
//将e指针指向当前顶点指向的节点
G->adjlist[j].firstedge = e;
/*将当前顶点的指针指向e;*/
}
}
/*经典头插法,无向图一条边对应两个顶点,所以在循环中,一次就针对i j 分别进行了插入。n个顶点e条边,
所以时间复杂度是O(n+e) */
“再说一遍” 每个顶点Vi的所有邻接点构成一个线性表,用单链表存储,无向图称链表为顶点vi的边表,有向图则称为顶点Vi作为弧尾(头)的出(入)边表。
图中的每一个节点都是表头(顶点)节点,在十字链表中,顶点节点后面连接的是弧节点。/*经典头插法,无向图一条边对应两个顶点,所以在循环中,一次就针对i j 分别进行了插入。n个顶点e条边,
所以时间复杂度是O(n+e) */
一、十字链表
//有向图的十字链表表存储表示-------编译正常运行>
#include<stdio.h>
#include<stdlib.h>
#define MAX_VERTEXT_NUM 20
typedef int InfoType;
typedef char VertextType;
typedef struct ArcBox { //边表节点信息
int headVex ;
int tailVex ;
struct ArcBox *headLink;
struct ArcBox *tailLink;
InfoType *info;
} ArcBox;
typedef struct VexNode {
VertextType data;
ArcBox *firstIn;
ArcBox *firstOut;
} VexNode;
typedef struct {
VexNode xList[MAX_VERTEXT_NUM];
int vexNum;
int arcNum;
} OLGraph;
void CreateGraphic(OLGraph *G) {
int i,j,k;
ArcBox *arcBox;
printf_s("请输入顶点数和弧数:");
scanf_s("%d,%d",&G->vexNum, &G->arcNum);
//建立顶点表
printf_s("建立顶点表\n");
for (i = 0; i < G->vexNum; i++) {
printf_s("请输入第%d个顶点:", i);
fflush(stdin);//刷新缓冲区
G->xList[i].data = getchar();//输入顶点值
G->xList [i].firstIn = NULL;//初始化指针
G->xList[i].firstOut = NULL;//初始化指针
}
//建立弧表
printf_s("建立弧表\n");
for (k = 0; k < G->arcNum; k++) {
printf_s("请输入(headVex,tailVex)的顶点对序号");
scanf_s("%d,%d", &i, &j); //输入时注意加逗号
arcBox = (ArcBox *)malloc(sizeof(ArcBox));
//对弧结点赋值
arcBox->headVex = j;
arcBox->tailVex = i;
arcBox->headLink = G->xList[j].firstIn;
arcBox->tailLink = G->xList[i].firstOut;
arcBox->info = NULL;
//完成在入弧和出弧链表表头的插入
G->xList[j].firstIn = arcBox;
G->xList[i].firstOut = arcBox;
}
}
void DisplayGraphic(OLGraph *G) {
int i;
ArcBox *arcBox;
printf("共%d个顶点,%d条弧\n",G->vexNum, G->arcNum);
for (i = 0; i < G->vexNum; i++) {
printf_s("顶点%c:", G->xList[i].data);
arcBox = G->xList[i].firstIn;
printf_s("入度:");
while (arcBox) {
printf_s("%c->%c ", G->xList[arcBox->tailVex].data,G->xList[i].data);
arcBox = arcBox->headLink;
}
arcBox = G->xList[i].firstOut;
printf_s("出度:");
while (arcBox) {
printf_s("%c->%c ", G->xList[i].data,G->xList[arcBox->headVex].data);
arcBox = arcBox->tailLink;
}
printf_s("\n");
}
}
int main() {
OLGraph *Graph;
Graph = (OLGraph *)malloc(sizeof(OLGraph));
CreateGraphic(Graph);
DisplayGraphic(Graph);
}