图
线性表特性;
明显层次关系, 1对多关系
图的结构, 结点之间关系任意.
二叉树有空树(只有根结点),但是图没有空图的概念。
图的结点可以形成闭环也可以不形成闭环,同样也可以不连接
带方向的叫有向图,没有方向的叫无向图
二、图的存储
连接线:无向图叫边,有向图叫弧
自己用0,没有关系就用无穷大表示(代码中用最大值表示),有关系有权重就用权重,没有权重就用1.没有
多少个顶点就多大的数组
1、邻接矩阵(顺序存储)
#include <stdio.h>
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#define OK 1
#define ERROR 0
#define TURE 1
#define FALSE 0
#define MAXVEX 100
#define INFINTTYC 0
//邻接矩阵
//二维数组
/*
图的度,一行的总和
代码里用INT_MAX 最大值用来代表无穷
*/
typedef int Status;//函数类型,其值是返回结果状态码
typedef char VertexType;
//typedef CElemType SqBiTree[MAX_TREE_SIZE];//0号存储单元根结点
//CElemType Nil = 0;//设整形以0 为空 或 INT_MAX(65535)
typedef int EdgeType;
typedef struct {
VertexType vexs[MAXVEX];//结点层
EdgeType arc[MAXVEX][MAXVEX];
int numNodes, numEdges;//图中当前的顶点数和边数 本层的序号(按照满二叉树给定序号规则)
}MGraph;
void CreateMGraph(MGraph *G){
int i,j,k,w;
printf("输入顶点数和边数:\n");
//1、输入顶点数/边数
scanf("%d,%d",&G->numNodes,&G->numEdges);
printf("顶点数:%d,边数:%d\n",G->numNodes,G->numEdges);
//2、输入顶点信息/顶点表
for (i=0; i<= G->numNodes; i++) {
scanf("%c",&G->vexs[i]);
}
//3、初始化邻接矩阵
//全部标记为0
for (i=0; i<G->numNodes; i++) {
for (j=0; j<G->numNodes; j++) {
G->arc[i][j] = INFINTTYC;
}
}
//4、输入边表信息
for (k = 0; k<G->numEdges; k++) {
printf("输入边(vi,vj)上的下标i,下标j,权w\n");
scanf("%d,%d,%d",&i,&j,&w);
G->arc[i][j] = w;
//如果无向图,矩阵对称
G->arc[j][i] = G->arc[i][j];
}
//5、打印邻接矩阵
for (int i=0; i<G->numNodes; i++) {
printf("\n");
for (int j=0; j<G->numNodes; j++) {
printf("%d ",G->arc[i][j]);
}
}
printf("\n");
}
int main(int argc, const char * argv[]) {
printf("邻接矩阵实现图的存储\n");
/*图的存储-邻接矩阵*/
MGraph G;
CreateMGraph(&G);
return 0;
}
邻接矩阵实现图的存储
输入顶点数和边数:
4,5
顶点数:4,边数:5
abcd
输入边(vi,vj)上的下标i,下标j,权w
0,1,1
输入边(vi,vj)上的下标i,下标j,权w
0,2,1
输入边(vi,vj)上的下标i,下标j,权w
0,3,1
输入边(vi,vj)上的下标i,下标j,权w
1,2,1
输入边(vi,vj)上的下标i,下标j,权w
2,3,1
0 1 1 1
1 0 1 0
1 1 0 1
1 0 1 0
Program ended with exit
2、邻接表(链式存储)
如果说如下图这种情况,用邻接矩阵来存储的话就太浪费内存空间了
这个时候我们就用邻接表
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#define M 100
#define true 1
#define false 0
连接表结点解析
思路
typedef char Element;
typedef int BOOL;
//邻接表的节点
typedef struct Node{
int adj_vex_index; //弧头的下标,也就是被指向的下标
Element data; //权重值
struct Node * next; //边指针
}EdgeNode;
//顶点节点表
typedef struct vNode{
Element data; //顶点的权值
EdgeNode * firstedge; //顶点下一个是谁?
}VertexNode, Adjlist[M];
//总图的一些信息
typedef struct Graph{
Adjlist adjlist; //顶点表
int arc_num; //边的个数
int node_num; //节点个数
BOOL is_directed; //是不是有向图
}Graph, *GraphLink;
void creatGraph(GraphLink *g){
int i,j,k;
EdgeNode *p;
//1. 顶点,边,是否有向
printf("输入顶点数目,边数和有向?:\n");
scanf("%d %d %d", &(*g)->node_num, &(*g)->arc_num, &(*g)->is_directed);
//2.顶点表
printf("输入顶点信息:\n");
for (i = 0; i < (*g)->node_num; i++) {
getchar();
scanf("%c", &(*g)->adjlist[i].data);
(*g)->adjlist[i].firstedge = NULL;
}
//3.
printf("输入边信息:\n");
for (k = 0; k < (*g)->arc_num; k++){
getchar();
scanf("%d %d", &i, &j);
//①新建一个节点
p = (EdgeNode *)malloc(sizeof(EdgeNode));
//②弧头的下标
p->adj_vex_index = j;
//③头插法插进去,插的时候要找到弧尾,那就是顶点数组的下标i
p->next = (*g)->adjlist[i].firstedge;
//④将顶点数组[i].firstedge 设置为p
(*g)->adjlist[i].firstedge = p;
//j->i
if(!(*g)->is_directed)
{
// j -----> i
//①新建一个节点
p = (EdgeNode *)malloc(sizeof(EdgeNode));
//②弧头的下标i
p->adj_vex_index = i;
//③头插法插进去,插的时候要找到弧尾,那就是顶点数组的下标i
p->next = (*g)->adjlist[j].firstedge;
//④将顶点数组[i].firstedge 设置为p
(*g)->adjlist[j].firstedge = p;
}
}
}
void putGraph(GraphLink g){
int i;
printf("邻接表中存储信息:\n");
//遍历一遍顶点坐标,每个再进去走一次
for (i = 0; i < g->node_num; i++) {
EdgeNode * p = g->adjlist[i].firstedge;
while (p) {
printf("%c->%c ", g->adjlist[i].data, g->adjlist[p->adj_vex_index].data);
p = p->next;
}
printf("\n");
}
}
int main(int argc, const char * argv[]) {
// insert code here...
printf("邻接表实现图的存储\n");
/*
邻接表实现图的存储
输入顶点数目,边数和有向?:
4 5 0
输入顶点信息:
0 1 2 3
输入边信息:
0 1 0 2 0 3 2 1 2 3
邻接表中存储信息:
0->3 0->2 0->1
1->2 1->0
2->3 2->1 2->0
3->2 3->0
*/
/*
邻接表实现图的存储
输入顶点数目,边数和有向?:
4 5 1
输入顶点信息:
0 1 2 3
输入边信息:
1 0 1 2 2 1 2 0 0 3
邻接表中存储信息:
0->3
1->2 1->0
2->0 2->1
*/
GraphLink g = (Graph *)malloc(sizeof(Graph));
creatGraph(&g);
putGraph(g);
return 0;
}