• 邻接表的实现


    今天想练习一下图算法,有些图算法的基础数据结构是邻接表,于是想着用C实现一下,虽说wiki上有一个邻接表的实现,但是自己还是想练一下手,在网上也搜到了别人的邻接表实现,发现大同小

    异,然后就在别人的基础上修改了一下得到了这个版本,记录一下,供以后练习使用。


    1.邻接表概念

    一张图,如果不考虑空间占用问题的话,用邻接矩阵存储是最方便的了,但有时候,图很稀疏,用矩阵存储就不划算了,这时候可以考虑用邻接表来实现,另外,有些算法用邻接表比较合适。

    邻接表的图示如下(网络来源):

    image

    关于邻接表的概念,要清晰易懂的话上面的链接就很好,要详尽的话看wiki就好了,我的代码是在下面这个网页的基础上修改的。

    2.邻接表需注意的点

    • 一般需要一个顶点数组来保存顶点信息
    • 每个顶点数组后面跟着一个单链表,表示与该顶点直接相连的顶点
    • 顶点数组中保存有一个指向单链表头部的指针,以及顶点信息的相应描述

    3.邻接表的实现

    头文件:

    /*
    by areslipan@163.com
    filename: adjlist.h
    */

    #ifndef _ADJLIST_
    #define _ADJLIST_
    #include<iostream>
    using namespace std;

    #define MAXVEX 100 /* 最大顶点数,应由用户定义 */
    typedef int VertexType; /* 顶点类型应由用户定义 */
    typedef int EdgeType; /* 边上的权值类型应由用户定义 */

    typedef struct EdgeNode/* 边表结点 */
    {
    int adjvex;/* 邻接点域,存储该顶点对应的下标 */
    EdgeType weight;/* 用于存储权值,对于非网图可以不需要 */
    struct EdgeNode *next; /* 链域,指向下一个邻接点 */
    } EdgeNode;

    typedef struct VextexNode/* 顶点表结点 */
    {
    VertexType data;/* 顶点域,存储顶点信息 */
    EdgeNode *firstedge;/* 边表头指针 */
    } VextexNode, AdjList[MAXVEX];

    typedef struct
    {
    AdjList adjList;
    int numNodes, numEdges; /* 图中当前顶点数和边数 */
    } GraphAdjList;


    void create_adjlist_graph(GraphAdjList *Gp);
    void show_adjlist_graph(GraphAdjList *Gp);
    void destroy_adjlist_graph(GraphAdjList *Gp);

    #endif

    实现文件:

    /*
    by areslipan@163.com
    filename : adjlist.cpp
    */
    #include "adjlist.h"
    void create_adjlist_graph(GraphAdjList *Gp)
    {
    int i, j, k,w;
    EdgeNode *pe;
    cout << "输入顶点数和边数(空格分隔):" << endl;
    cin >> Gp->numNodes >> Gp->numEdges;

    cout << "输入顶点信息:" << endl;
    for (i = 0 ; i < Gp->numNodes; i++)
    {
    cin >> Gp->adjList[i].data;
    Gp->adjList[i].firstedge = NULL;/* 将边表置为空表 */
    }

    for (k = 0; k < Gp->numEdges; k++)/* 建立边表 */
    {
    cout << "输入边(vi,vj,w)的顶点序号i,j(空格分隔):" << endl;
    cin >> i >> j >> w;
    pe = (EdgeNode *)malloc(sizeof(EdgeNode));
    pe->adjvex = j;/* 邻接序号为j */
    pe->weight = w;
    /* 将pe的指针指向当前顶点上指向的结点 */
    pe->next = Gp->adjList[i].firstedge;
    Gp->adjList[i].firstedge = pe;/* 将当前顶点的指针指向pe */

    //如果是无向图可以加上下面这段代码
    /* pe = (EdgeNode *)malloc(sizeof(EdgeNode));
    pe->adjvex = i;
    pe->next = Gp->adjList[j].firstedge;
    Gp->adjList[j].firstedge = pe;*/

    }

    cout<<"有向图的邻接表创建成功..."<<endl;
    }

    void show_adjlist_graph(GraphAdjList *Gp)
    {
    cout<<"邻接表如下:"<<endl;
    if(Gp->numNodes == 0 || Gp->numEdges == 0)cout<<"The adjlist is empty!"<<endl;

    for(int v=0;v<Gp->numNodes;++v)
    {
    cout<<"V"<<v<<":";
    if(Gp->adjList[v].firstedge==NULL)cout<<"NULL"<<endl;
    else
    {
    EdgeNode *cur=Gp->adjList[v].firstedge;
    while(cur!=NULL)
    {
    cout<<"V"<<cur->adjvex<<"("<<cur->weight<<")"<<" ";
    cur=cur->next;
    }
    cout<<endl;
    }
    }
    }

    void destroy_adjlist_graph(GraphAdjList *Gp)
    {
    if(Gp->numNodes == 0 || Gp->numEdges == 0)return ;
    else
    {
    for(int v=0;v<Gp->numNodes;++v)
    {
    while(Gp->adjList[v].firstedge!=NULL)
    {
    EdgeNode *cur=Gp->adjList[v].firstedge;
    Gp->adjList[v].firstedge=cur->next;

    free(cur);
    }
    }
    }

    cout<<"邻接表销毁成功..."<<endl;
    }

    测试文件:

    /*
    by areslipan@163.com
    filename : test.cpp
    */

    #include "adjlist.h"
    using namespace std;

    int main()
    {
    GraphAdjList g;
    create_adjlist_graph(&g);
    show_adjlist_graph(&g);
    destroy_adjlist_graph(&g);
    show_adjlist_graph(&g);
    system("pause");
    }

  • 相关阅读:
    ASP.NET MVC 常用内置验证特性 简介
    为什么要有get方法?-多态内存分析的应用
    多态的内存分析-转载
    抽象类和接口
    多态
    通过序列化复制整个对象
    检查异常和非检查异常
    怎样抛出自己定义的异常
    try catch和throws怎么用?-结合使用
    两个对象整体内容的比较-重写对象的equals方法
  • 原文地址:https://www.cnblogs.com/obama/p/3347459.html
Copyright © 2020-2023  润新知