邻接表&十字链表

邻接表&十字链表邻接表:每一行都可以看成一个单链表,第一行中,v0-1-3可以得到,v0的出度为v1和v3。邻接表完整代码:#include<iostream>usingnamespacestd;constintMAX_V=15;//边节点typedefstructEdge_node{chardata;Edge_node*next;}E…

大家好,又见面了,我是你们的朋友全栈君。

邻接表:

在这里插入图片描述
每一行都可以看成一个单链表,第一行中,v0-1-3可以得到,v0的出度为v1和v3。

邻接表完整代码:

#include <iostream>
using namespace std;

const int MAX_V = 15;

//边节点
typedef struct Edge_node {
    char data;
    Edge_node *next;
}Enode,*pEnode;

//表节点
typedef struct List_node {
    char data;
    Edge_node *firstEdge;
}Lnode, *pLnode;


int main()
{
    void AddEdge( char v1, char v2, pLnode list, int V );
    void display( pLnode list, int V );
    void clear( pLnode list, int V);

    int V,E;
    cout << "input vertex number and edge number:\n";//输入顶点数和边数
    cin >> V >> E;

    Lnode list[MAX_V];//建立数组
    for( int i=0; i<V; ++i ){
        list[i].firstEdge = NULL;
    }

    cout << "input vertex:\n";//输入顶点
    for( int i=0; i<V; ++i )
        cin >> list[i].data;

    cout << "input edges, eg: a b \n";
    char v1,v2;
    for( int i=0; i<E; ++i ){

        cin >> v1 >> v2;
        AddEdge( v1, v2, list, V);
    }

    //输出
    cout <<"display:\n";
    display( list, V );

    cout << "clear:\n";
    clear( list, V );

    return 0;
}

void AddEdge( char v1, char v2, pLnode list, int V ) {

    for( int i=0; i<V; ++i ){

        if( v1==list[i].data ){
            //生成新的边节点
            pEnode newEdge = new Enode;
            newEdge->data = v2;
            newEdge->next = NULL;

            newEdge->next = list[i].firstEdge;
            list[i].firstEdge = newEdge;

            break;
        }
    }
}

void display( pLnode list, int V ){

    for( int i=0; i<V; ++i ){
        cout << list[i].data <<": ";
        pEnode p = list[i].firstEdge;
        while( p ){
            cout << p->data << ' ';
            p = p->next;
        }
        cout <<endl;
    }
}

void clear( pLnode list, int V){

    for( int i=0; i<V; ++i ){
        pEnode p = list[i].firstEdge;
        pEnode todel;
        while( NULL!=p ){
            todel = p;
            cout <<"delete is "<< todel->data << ' ';
            p = p->next;
            delete todel;
        }
        cout << endl;
    }

}

但对于有向图来说,邻接表是有缺陷的,关心了出度问题,想了解入度就必须要遍历整个图才能知道,反之,逆邻接表解决了入度的情况。
而十字链表可以同时解决出度和入度的问题。

十字链表

重新定义表节点结构:增加了两个指针firstIn,firstOut。分别用来指向该顶点的入(出)边表中第一个结点。

在这里插入图片描述
firstin表示入边表头指针,指向该顶点的入边表中第一个结点;

firstout表示出边表头指针,指向该顶点的出边表中第一个结点;
邻接表&十字链表
tailvex是指弧起点在顶点的下标,

headvex是指弧终点在顶点表中的下标,

headlink是指入边表指针域,指向终点相同的一下条边

taillink是指出边表指针域,指向起点相同的下一条边。

对比

与邻接表相比,这里的 tailLink 指针就相当于邻接表里的那个指针,指向出度的下一个节点。而这里的 headLink 就是新增加的用来记录入度的指针。
在这里插入图片描述
首先,横着看:每一行都可以看出单链表,把从 firstOut 出来的串起来就是出度(类似邻接表);
竖着看(不太明显):从 headLink 出来的指针指向串起来,都是入度节点。

那为什么要重复存储节点信息呢?例如图中的0存了2次,1存了3次等。这是为了方便找入度节点。试想,邻接表用一个指针一个节点信息来存储方便找出度,那么要是出度入度都方便找,自然要给入度也加上一个指针(headLink)和一个数据域(tailVex)。这样当找到入度的边接节点,取出 headLink 就找到入度节点了。

将边节点结构分割:
入度:headLink + tailVex;
出度:tailLink + headVex;

十字链表代码:

#include <iostream>
#include <cstring>
using namespace std;

const int MAX_V = 15;
//边节点
typedef struct Edge_node {
    char tailVex,headVex;           //tailvex是指弧起点在顶点的下标,headvex是指弧终点在顶点表中的下标,
    Edge_node *tailLink, *headLink;//headlink指向弧头相同的下一条弧。taillink指向弧尾相同的下一条弧.
}Enode,*pEnode;

//表节点
typedef struct List_node {
    char data;
    Edge_node *firstIn, *firstOut;//firstin表示入边表头指针,指向该顶点的入边表中第一个结点.
}Lnode, *pLnode;

int main()
{
    void AddEdge( char v1, char v2, pLnode list, int V );
    void display( pLnode list, int V );
    void clear( pLnode list, int V);

    int V,E;
    cout << "input vertex number and edge number:\n";//输入顶点数和边数
    cin >> V >> E;

    Lnode list[MAX_V];//建立数组
    for( int i=0; i<V; ++i ){
        list[i].firstIn = NULL;
        list[i].firstOut = NULL;
    }

    //输入顶点
    cout << "input vertex:\n";
    for( int i=0; i<V; ++i )
        cin >> list[i].data;

    //输入边
    cout << "input edges, eg: a b \n";
    char v1,v2;
    for( int i=0; i<E; ++i ){

        cin >> v1 >> v2;
        AddEdge( v1, v2, list, V);
    }

    //输出
    cout <<"display:\n";
    display( list, V );

    cout << "clear:\n";
    clear( list, V );

    return 0;
}

void AddEdge( char v1, char v2, pLnode list, int V ){

    int getIndex( char x , pLnode list , int V );
    int v1_index = getIndex( v1 , list, V );
    int v2_index = getIndex( v2, list ,V );

    pEnode newEdge = new Enode;
    newEdge->tailVex = v1;
    newEdge->headVex = v2;

    //添加出度
    newEdge->tailLink = list[v1_index].firstOut;
    list[v1_index].firstOut = newEdge;

    //添加入度
    newEdge->headLink = list[v2_index].firstIn;
    list[v2_index].firstIn = newEdge;
}
int getIndex( char x, pLnode list, int V ){

    for( int i=0; i<V; ++i ){
        if( x==list[i].data )
            return i;
    }
}

void display( pLnode list, int V ){

    for( int i=0; i<V; ++i ){
        cout << list[i].data <<" out : ";
        pEnode p = list[i].firstOut;
        while( p ){
            cout << p->headVex << ' ';
            p = p->tailLink;
        }
        cout <<endl;

        cout << list[i].data <<" in : ";
        p = list[i].firstIn;
        while( p ){
            cout << p->tailVex << ' ';
            p = p->headLink;
        }
        cout <<endl;
    }

}

void clear( pLnode list, int V){

    for( int i=0; i<V; ++i ){
        pEnode p = list[i].firstOut;
        pEnode todel;
        while( NULL!=p ){
            todel = p;
            cout <<"delete is "<< todel->headVex << ' ';
            p = p->tailLink;
            delete todel;
        }
        cout << endl;
    }
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/150311.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • pycharm专业版下载安装教程_pycharm安装后无解释器

    pycharm专业版下载安装教程_pycharm安装后无解释器常见的pycharm是收费的,或者需要序列号,找起来很麻烦,现在介绍一款免费使用的pycharm–教育版。下面介绍一下pycharm的安装过程和使用中常见的一些问题。一、安装pycharm下载地址:https://www.jetbrains.com/pycharm-edu/ 。下载之后双击即可安装,安装过程中一直点击下一步即可。二、更换主题1.点击File-&gt;S…

  • 芯片架构–四大处理器架构「建议收藏」

    芯片架构–四大处理器架构「建议收藏」处理器分为复杂指令集计算机(CISC)和精简指令集计算机(RISC)。1、x86架构我们使用的电脑以及公司的服务器,大部分采用了x86架构的处理器,以intel和AMD的处理器为主。x86架构的处理器采用了CISC指令集(复杂指令集计算机),x86架构的CPU分为x86和x86-64两类,目前主流的是x86-64,即64位的处理器。2、ARM架构我们的手机几乎全部使用了ARM架构,采用了RISC指令集(精简指令集),ARM的优势在于低功耗,因此非常适合手机等终端使用,x86架构的处理器无

  • STM32 三极管继电器驱动电路设计「建议收藏」

    STM32 三极管继电器驱动电路设计「建议收藏」继电器线圈需要流过较大的电流(约50mA)才能使继电器吸合,一般的集成电路不能提供这样的大电流,因此,必须要进行扩流,即设计驱动电路。三极管氛围NPN与PNP型两种,在使用中,我选择PNP型的S8550型号三极管。百度三极管驱动继电器,可以得到大量的参考电路设计,虽然花样繁多,但是可用,靠谱的比较少,并且基本都是从两三篇转载而来,上图就是比较经典的一个设计。对于PCB的设计,要保持严…

  • phpMyAdmin完全安装配置步骤教程

    phpMyAdmin完全安装配置步骤教程phpMyAdmin完全安装配置步骤教程 phpMyAdmin就是一种MySQL数据库的管理工具,安装该工具后,即可以通过web形式直接管理MySQL数据,而不需要通过执行系统命令来管理,非常适合对数据库操作命令不熟悉的数据库管理者,下面详细说明该工具的安装方法。在上一篇文章《phpMyAdmin的介绍》中,我们只介绍了使用phpMyAdmin的介绍以及phpMyAdm…

  • Advanced SystemCare激活

    Advanced SystemCare激活AdvancedSystemCare6.x(x>=1)激活方案 1,请先在电脑上安装6.0版本。输入以下激活码激活:注册码:4A639-FD966-C5435-512C4[使用6.0版本用以上注册码可以激活]更多注册码CC52B-28CB1-DAF12-A96D6 65792-57FC4-5CEC1-677C4 4A639-FD966-C5435-512C

    2022年10月20日
  • 清晰的java代码初学者,一个不错的 java初学者手册

    清晰的java代码初学者,一个不错的 java初学者手册刚刚在网上看到有人在讨论java应注意的技巧已经整理好了本人太菜遇见这种菜鸟口粮自然不会放过不过也感觉其中有些不是特别的清楚不过作为参考至于是否准确工作中验证吧(1)使用Integer.valueOf()代替newInteger();(2)if(result.size()>0)returntrue;returnfalse;可以优化为returnres…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号