目录
数据类型
存储结构
邻接矩阵表示法
无向图
邻接矩阵表示
有向图
网
实现
邻接矩阵表示
存储结构
创建无向图
优点
缺点
邻接表法表示
表示无向图
表示有向图
存储结构
无向网
特点
十字链表与多重表
十字链表
存储结构
多重表
存储结构
数据类型
存储结构
邻接矩阵表示法
无向图
无向图的度=矩阵中非0元素个数和的一半
邻接矩阵表示
有向图
因此,有向图的度为矩阵中非0元素个数总和
网
实现
邻接矩阵表示
存储结构
创建无向图
优点
缺点
邻接表法表示
表示无向图
表示有向图
示例
存储结构
先表示出所有边结点,再将边结点组成链表连接到各个对应顶点上。
示例
无向网
特点
十字链表与多重表
十字链表
为解决有向图求度不方便的问题
存储结构
firstin表示以data为弧头(终点,即指向data顶点-入)的边,firstout表示以data为弧尾(起点-出)的边。
tailvex表示弧的弧尾(起点)顶点序号,headvex表示弧的弧头(终点)顶点序号,
hlink指向下一个弧头相同的弧,tlink指向下一个弧尾相同的弧。
先列出所有弧,再连接到顶点。
多重表
存储结构
相关代码
#include <iostream>
using namespace std;
//图的存储
//1.邻接矩阵存储:边数+顶点数+顶点表-一维+边表-二维
#define maxn 20
#define infi 33333333
//类型定义
typedef struct {
char vexs[maxn];//顶点表
int arc[maxn][maxn];//边表
int vexnum,arcnum;//顶点数与边数
}adjgraph;
//创建无向图
//1.输入边数与顶点数,初始边表-无穷
//2.输入顶点,为顶点表赋值
//3.输入边的顶点及权值,为边表赋值:需要先确定顶点的下标才能确定边
int getvex(adjgraph *g,char v){
for(int i=1;i<=g->vexnum;i++)
if(g->vexs[i]==v) return i;
return 0;
}
//后期实现!!!!
//void print(adjgraph *g){
// for(int i=1;i<=g->vexnum;i++)
// if(g->vexs[i]==v) return i;
//}
void create(adjgraph *g){
char vex1,vex2;//存储边的顶点
int weigh;//存储边的权值
int v1,v2;//存储边的下标
cout<<"输入顶点数及边数:"<<endl;
cin>>g->vexnum>>g->arcnum;
for(int i=1;i<=g->vexnum;i++){//初始边表
for(int j=1;j<=g->arcnum;j++){
g->arc[i][j]=infi;
}
}
for(int i=1;i<=g->vexnum;i++){//存储顶点信息
cout<<"请输入第"<<i<<"个顶点信息:\n";
cin>>g->vexs[i];
}
for(int j=1;j<=g->arcnum;j++){//存储边表信息
cout<<"请输入第"<<j<<"条边的顶点信息:\n";
cin>>vex1>>vex2;
cout<<"请输入第"<<j<<"条边的权值:\n";
cin>>weigh;
v1=getvex(g,vex1);
v2=getvex(g,vex2);
g->arc[v1][v2]=weigh;//单向
g->arc[v2][v1]=weigh;//双向-无向图
}
}
//2.邻接表表示:顶点表+顶点数+边数
//顶点表:顶点信息+第一条边结点
//边结点:顶点编号+边权+下一条边
int getvex2(adjlist &g,char v){
for(int i=1;i<=g.vnum;i++)
if(g.vex[i].vex==v) return i;
return 0;
}
typedef struct acrnode{//边结点
int adjacr;//记录邻接顶点编号-弧尾
int weigh;//权值
acrnode *next;//有相同弧头顶点的下一个边结点
}acrnode;
typedef struct vnode{//顶点类型
char vex;
acrnode *first;
}vnode;
typedef struct {//邻接表
int vnum,acrnum;
vnode vex[maxn];//顶点表
}adjlist;
void create(adjlist &g){
char v1,v2;
int vex1,vex2;
acrnode n,m;
//1.输入顶点数、边数
cin>>g.vnum>>g.acrnum;
//2.初始邻接表:输入顶点,初始顶点表头指针为空
for(int i=1;i<=g.vnum;i++){
cin>>g.vex[i].vex;
g.vex[i].first=NULL;
}
//3.输入边顶点,构造边结点,记录弧头与弧尾顶点,头插边表
for(int i=1;i<=g.acrnum;i++){
cin>>v1>>v2;
vex1=getvex2(g,v1);//弧尾
vex2=getvex2(g,v2);//弧头
n=new acrnode;//构造边结点
//记录边v1->v2; 并插入到顶点v1的边表中
n->adjacr=vex2;//存储邻接v1的顶点v2的编号
n->next=g.vex[vex1].first;//下一个边结点存储原来v1顶点的第一个边结点
g.vex[vex1].first=n;//更新v1顶点的第一条边为n,实现插入
//记录边v2->v1:新边结点结构-左边记录邻接指点编号 权值 右边记录具有同样以v2为弧尾的下一条边结点
m=new acrnode;
m->adjacr=vex1;//记录邻接v2的顶点v1的编号
m->next=g.vex[vex2].first;//下一个边结点存储v2指向的第一个边结点
g.vex[vex2].first=m;//更新顶点v2的第一条边结点,实现插入
}
}
//3.十字链表表示:弧结点+顶点结点==>顶点表+弧数+顶点数-解决有向图找出入度的问题
//弧结点
typedef struct acrnode{
int tailvex,headvex;//弧头+弧尾编号
struct acrnode *tailacr,*headacr;//分别具有相同弧头和弧尾的下一条弧结点
}arcnode;
typedef struct vexnode{
char data;//顶点信息
acrnode *tail,*head;//以顶点为弧尾或为弧头的弧结点
}vexnode;
typedef struct node{
int vnum,acrnum;
vexnode v[maxn];
};
//4.多重表:顶点结点+边结点==>顶点表+边数+顶点数-解决无向图重复存边的问题
typedef struct acrnode{
int tailvex,headvex;//组成边结点的两顶点编号
struct acrnode *tailacr,*headacr;//与边结点顶点相同的边结点
int weigh;//边的权重
};
//顶点结点:顶点信息+指向第一条边的指针
typedef struct vexnode{
char data;
acrnode *first;//第一条边结点
};
typedef struct node{
int vnum,vacr;
vexnode v[maxn];//顶点表
};
int main(){
adjgraph g;
create(&g);
return 0;
}