有向图的邻接表实现

图的邻接表表示法类似于树的孩子链表表示法。对于图G中的每个顶点vi,该方法把所有邻接于vi的顶点vj链成一个带头结点的单链表,这个单链表就称为顶点vi的邻接表(Adjacency List)。

1. 邻接表的结点结构


(1)表结点结构
    
┌────┬───┐ 
    
│adjvex  │next  │
    └────┴───┘
     邻接表中每个表结点均有两个域:
 ① 邻接点域adjvex
  存放与vi相邻接的顶点vj的序号j。
 ② 链域next
  将邻接表的所有表结点链在一起。
  注意:
     若要表示边上的信息(如权值),则在表结点中还应增加一个数据域。

(2)头结点结构
    
┌────┬─────┐ 
    
│vertex  │firstedge │
    └────┴─────┘
     顶点vi邻接表的头结点包含两个域:
 ① 顶点域vertex
  存放顶点vi的信息
 ② 指针域firstedge
  vi的邻接表的头指针。
  注意:
     ① 为了便于随机访问任一顶点的邻接表,将所有头结点顺序存储在一个向量中就构成了图的邻接表表示。

     ② 有时希望增加对图的顶点数及边数等属性的描述,可将邻接表和这些属性放在一起来描述图的存储结构。

代码:

#include<iostream>  
using namespace std;  
#define MAX_VERTEX_NUM 50//定义图的最大顶点数  
typedef char VertexData; 
 
typedef struct EdgeNode  //表结点  
{  
    int adjvex;          //邻接点域  
    EdgeNode *next;      //边结点所对应的下一个边结点
} EdgeNode; 
 
typedef struct VertexNode//头结点  
{  
    VertexData data;  
    EdgeNode *firstedge; //头结点所对应的第一个边结点  
}VertexNode; 
 
typedef struct AdjList  
{  
    int VexNum,ArcNum;   //定义图的顶点数和边数
    VertexNode vertex[MAX_VERTEX_NUM];     //定义头结点数组
}AdjList;  

void CreateGraph(AdjList *adj,int *n)      //n为指针传值  
{  
    int e,s,d;  
    cout<<"输入顶点数和边数"<<endl;  
    cin>>*n>>e;//输入顶点数和边数。  
    adj->VexNum=*n;  
    adj->ArcNum=e;  
    EdgeNode *q=NULL;    //定义一个指向边节点的指针,并初始化为NULL
    //初始化表头结点  
    int i;  
    for(i=1;i<=*n;i++)  
    {  
        cout<<"输入第"<<i<<"个结点的顶点名称"<<endl;  
        cin>>adj->vertex[i].data;          //顶点名称,是一个字符  
        adj->vertex[i].firstedge=NULL;  
    }  
    for(i=1;i<=e;i++)  
    {  
        cout<<"输入第"<<i<<"条边的起点和终点"<<endl;  
        cin>>s>>d;//输入边的起始和终止   
        q=(EdgeNode *)malloc(sizeof(EdgeNode));//创建一个表结点  
        if(q==NULL)  
            return;  
        q->adjvex=d;  
        q->next=adj->vertex[s].firstedge;     //新加入的节点都是在头结点之后,原来在头结点之后的节点要后移。  
        adj->vertex[s].firstedge=q;  
    }  
} 
 
void DisplayGraph(AdjList *adj)  
{  
    int n=adj->VexNum;//顶点个数,后面要遍历每一个点点  
    EdgeNode *q=NULL; //定义一个指向边节点的指针,并初始化为NULL
    int i;  
    for( i=1;i<=n;i++)  
    {  
        q=adj->vertex[i].firstedge;  
        if(q==NULL) //表示头结点后面没有跟其他结点  
        {  
            cout<<"没有从"<<adj->vertex[i].data<<"出发的节点"<<endl;  
        }  
        else  
        {  
            cout<<"从结点"<<adj->vertex[i].data<<"出发的边有"<<endl;  
            while(q!=NULL)  
            {         
                cout<<adj->vertex[i].data<<"->"<<adj->vertex[q->adjvex].data<<endl; //在“初始化表头结点”时已经将每个顶点的序号与名字对应起来,通过q->adjvex确定对应的(头)结点及其名字
                q=q->next;  
            }  
        }  
    }  
}  

void main( )  
{  
    int n;  
    AdjList *adj=(AdjList *)malloc(sizeof(AdjList));  
    CreateGraph(adj,&n);  
    DisplayGraph(adj);  
} 


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值