有向图的十字链表表示

本文主要讨论有向图的十字链表表示,包括建图,添加弧,删除弧,以邻接表的格式打印图(其中包括两种形式:1,同尾的弧构成条链 2,同头的弧构成条链)c ++ 描述。
参考《数据结构 c语言版》清华大学出版社
类 ArcBox 包含弧的信息:分别对应如下
弧的尾节点序号,弧的头结点序号,指针域(指向与这条弧具有相同头结点的下一条弧),指针域(指向与这条弧具有相同尾结点的下一条弧),弧的信息(权重)
这里写图片描述
类VexNode 包含每个顶点的信息
顶点的名称(v1,v2,,,),指针域(指向以该顶点为弧头的第一条弧),指针域(指向以该顶点为弧尾的第一条弧)

这里写图片描述

class ArcBox
{
public:
    ArcBox();
    ArcBox(int from, int to, int inf);
    ~ArcBox(){};
    friend class OLGraph;
    int getTailvex() { return tailvex; }
    int getHeadvex() { return headvex; }
    ArcBox *getHlink() { return hlink; }
    ArcBox *getTlink() { return tlink; }
    int getInfo() { return info; }
    void setInfo(int in) { info = in; }
    void setTailvex(int tv) { tailvex = tv; }
    void setHeadvex(int hv) { headvex = hv; }
    void setHlink(ArcBox *hl) { hlink = hl; }
    void setTlink(ArcBox *tl) { tlink = tl; }

private:
    int tailvex;
    int headvex;
    ArcBox *hlink;
    ArcBox *tlink;
    int info  ; // 权重,距离。。。
};
ArcBox::ArcBox()
{
    tailvex = -1;
    headvex = -1;
    hlink = NULL;
    tlink = NULL;
    info = -1;
}
ArcBox::ArcBox(int tail,int head,int inf)
{
    tailvex = tail;
    headvex = head;
    info = inf;
    hlink = NULL;
    tlink = NULL;
}

class Vexnode
{
public:
    Vexnode();
    ~Vexnode() {};
    friend class OLGraph;
    void setNodeNum(int noden) { nodeNum = noden; }
    void setFirstin(ArcBox *firsti) { firstin = firsti; }
    void setFirstout(ArcBox *firsto) { firstout = firsto; }
    int getNideNum() { return nodeNum; }
    ArcBox *getFirstin() { return firstin; }
    ArcBox *getFirstout() { return firstout; }
private:
    int nodeNum;
    ArcBox *firstin;
    ArcBox *firstout;
};
Vexnode::Vexnode()
{
    nodeNum = 0;
    firstin = NULL;
    firstout = NULL;
}


class OLGraph
{
public:
    OLGraph();
    ~OLGraph();

    int getVexnum() { return vexnum; }
    int getArcnum() { return vexnum; }
    Vexnode getVList(int vexIndex) { return xList[vexIndex]; }
    int addArc(int tail, int head, int inf); // 参数 tail 和 head 表示弧的尾节点和头结点的数据,而不是节点编号
    int deleteArc(int tail, int head); // 参数 tail 和 head 表示弧的尾节点和头结点的数据,而不是节点编号
    int createOLGraph();

    int vexLoc(int vexNum);
    int ftPrint();
    int tfPrint();
private:
    Vexnode xList[ MAX ];
    int vexnum;
    int arcnum;
};

OLGraph::OLGraph()
{
    vexnum = 0;
    arcnum = 0;
}

OLGraph::~OLGraph()
{
}
int OLGraph::vexLoc(int vexNum)
{
    for (int i = 0; i < this->vexnum; i++)
    {
        if (xList[i].nodeNum == vexNum)
        {
            return i;
        }
    }
    return -1;
}

int OLGraph::ftPrint()
{
    ArcBox *tempArc = new ArcBox();
    for (int index = 0; index < this->vexnum; index++)
    {
        cout << index << " : ";
        tempArc = xList[index].firstout;
        while (tempArc)
        {
            cout << "--> [ " << tempArc->headvex << "," << tempArc->info << " ]";
            tempArc = tempArc->tlink;

        }
        cout << "--> ^" << endl;
    }
    cout << "-------------------" << endl;
    return 0;
}
int OLGraph::tfPrint()
{
    ArcBox *tempArc = new ArcBox();
    for (int index = 0; index < this->vexnum; index++)
    {
        cout << index << " : ";
        tempArc = xList[index].firstin;
        while (tempArc)
        {
            cout << "--> [ " << tempArc->tailvex << "," << tempArc->info << " ]";
            tempArc = tempArc->hlink;
        }
        cout << "--> ^" << endl;
    }
    cout << "-------------------" << endl;
    return 0;
}
int OLGraph::addArc(int tail, int head, int inf)
{
    int tailIndex, headIndex;
    tailIndex = vexLoc(tail); // 弧尾节点在表头链表中的位置
    headIndex = vexLoc(head); // 弧头节点在表头链表中的位置
    ArcBox *ftArc = new ArcBox(tailIndex, headIndex, inf);
    ftArc->hlink = xList[headIndex].firstin; // 弧头节点相同
    xList[headIndex].firstin = ftArc;
    ftArc->tlink = xList[tailIndex].firstout; // 弧尾节点相同
    xList[tailIndex].firstout = ftArc;
    return 0;

}

int OLGraph::deleteArc(int tail, int head)
{
    int tailIndex, headIndex;
    tailIndex = vexLoc(tail); // 弧尾节点在表头链表中的位置
    headIndex = vexLoc(head); // 弧头节点在表头链表中的位置
    ArcBox *ftArc = new ArcBox(),*preArc = new ArcBox();
    // 先删同 tail 的链接
    ftArc = xList[tailIndex].firstout;
    if (ftArc && ftArc->headvex == headIndex) //特殊情况:判断第一个出节点是否为要找的
    {
        xList[tailIndex].firstout = ftArc->tlink;
        //delete ftArc;  // 易错点,只有把四条指向全部删掉之后才可以删除此 ArcBox对象,因为下文在删除另一个方向的两条指向时要用到这个 ArcBox对象
    }
    else
    {
        preArc = ftArc;
        ftArc = preArc->tlink;
        while (ftArc)
        {
            if (ftArc->headvex == headIndex)
            {
                preArc->tlink = ftArc->tlink;
                //delete ftArc;  // 易错点,只有把四条指向全部删掉之后才可以删除此 ArcBox对象,因为下文在删除另一个方向的两条指向时要用到这个 ArcBox对象
                break;

            }
            else
            {
                preArc = ftArc;
                ftArc = preArc->tlink;
            }
        }
    }


    // 再删同 head 的链接
    ftArc = xList[headIndex].firstin;
    if (ftArc && ftArc->tailvex == tailIndex) //特殊情况:判断第一个出节点是否为要找的
    {
        xList[headIndex].firstin = ftArc->hlink;
        delete ftArc;
    }
    else
    {
        preArc = ftArc;
        ftArc = preArc->hlink;
        while (ftArc)
        {
            if (ftArc->tailvex == tailIndex)
            {
                preArc->hlink = ftArc->hlink;
                delete ftArc;
                break;

            }
            else
            {
                preArc = ftArc;
                ftArc = preArc->hlink;
            }
        }
    }
    
    return 0;
}
int OLGraph::createOLGraph()
{
    cout << "请输入节点数目:" << endl;
    cin >> this->vexnum; 
    cout << "请输入弧的数目:" << endl;
    cin >> this->arcnum;
    cout << "请输入顶点信息:" << endl;
    for (int i = 0; i < this->vexnum; i++)
    {
        cin >> this->xList[i].nodeNum ;
    }
    cout << "请输入弧的信息" << endl;
    int tail,head,info;
    for (int i = 0; i < this->arcnum ; i++)
    {
        cin >> tail >> head >> info;
        addArc(tail, head, info);
    }
    return 0;
}

int main()
{
    OLGraph *olGraph = new OLGraph();
    olGraph->createOLGraph();
    olGraph->ftPrint();
    olGraph->tfPrint();
    cout << "添加边(2,1,0)" << endl;
    olGraph->addArc(2, 1, 0);
    olGraph->ftPrint();
    olGraph->tfPrint();
    cout << "删除边(1,2)" << endl;
    olGraph->deleteArc(1, 2);
    olGraph->ftPrint();
    olGraph->tfPrint();
}

举例子:
原图:
这里写图片描述
添加边(2,1,0)
这里写图片描述
删除边(1,2)
这里写图片描述
结果:
这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值