十字链表存储有向图

十字链表是邻接表和逆邻接表的一种结合,顶点结点和弧结点如图:这里写图片描述
这样,求一个顶点的出度,入度都比较方便,一般用来存储有向图,下面便是实现部分了,大体和之前几种存储方式差不多,只是由于存储方式的不同而略有不同而已
crossedList.h

#pragma once
# include<iostream>
# include"vertex.h"

typedef struct _arcNode//弧结点
{
    int tailVertex;//弧尾结点
    int headVertex;//弧头结点
    double info;//弧的信息,比如权重
    struct _arcNode *headLink=NULL;//指向弧头相同的弧结点的指针
    struct _arcNode *tailLink=NULL;//指向弧尾相同的弧结点的指针
}arcNode;
typedef struct _vertexNode//顶点结点
{
    int numOfVertex;//顶点的编号,从0开始
    arcNode *firstIn = NULL;//指向弧头相同的链表
    arcNode *firstOut = NULL;//指向弧尾相同的链表
}vertexNode;

class crossedList
{
public:
    crossedList(int iNumOfVertex, int iNumOfArc);//构造函数
    ~crossedList();//析构函数
    void create();
    void setVisitedFalse();//每次搜索前都将设置访问标志为false
    void DFS(int i);//深度优先搜索 从第i+1个结点开始 
    void BFS(int i);//广度优先搜索
private:
    vertex *vertexElem;//顶点元素
    int iVertex;//顶点个数
    int iArc;//弧的个数
    vertexNode *verNode;//顶点节点
    void addNode(int a, int b, double weight);//在链表中添加一个结点
};

crossedList.cpp

# include"crossedList.h"
# include<iostream>
# include"myQuene.h"
using namespace std;

crossedList::crossedList(int i = 0, int j = 0) :iVertex(i), iArc(j)
{
    vertexElem = new vertex[i];
    verNode = new vertexNode[i];
}

void crossedList::addNode(int a, int b, double weight)//在链表中添加一个结点
{
    arcNode *p = verNode[a].firstOut;
    arcNode *p1;
    arcNode*p2 = verNode[b].firstIn;

    if (p == NULL)//第一次添加结点
    {
        p1 = new arcNode;
        p1->tailVertex = a;
        p1->headVertex = b;
        p1->info = weight;
        verNode[a].firstOut = p1;
    }
    else
    {
        while (p->tailLink)
            p = p->tailLink;
        //此时p为尾结点
        p1 = new arcNode;
        p1->tailVertex = a;
        p1->headVertex = b;
        p1->info = weight;
        p->tailLink = p1;
    }
    if (p2 == NULL)
    {
        verNode[b].firstIn = p1;
    }
    else
    {
        while (p2->headLink)
            p2 = p2->headLink;
        p2->headLink = p1;
    }
}

void crossedList::create()
{
    cout << "请依次输入顶点信息:" << endl;

    for (int i = 0;i < iVertex;i++)
    {
        cin >> (vertexElem[i].data);
        verNode[i].numOfVertex = i;
    }

    cout << "请依次输入有向图中相关联的顶点(0表示第一个顶点)及弧的权值(第一个是弧尾,第二个是弧头):" << endl;
    int a, b;
    double weight;

    for (int i = 0;i < iArc;i++)
    {
        cin >> a >> b >> weight;
        addNode(a, b, weight);
    }
}

crossedList::~crossedList()
{
    arcNode*p;
    for (int i = 0;i < iVertex;i++)
    {
        p = verNode[i].firstOut;
        verNode[i].firstOut = NULL;
        while (p)
        {
            arcNode *p1 = p;
            p = p->tailLink;
            delete p1;
        }
    }
    delete []vertexElem;
    delete []verNode;
}

void crossedList::setVisitedFalse()
{
    for (int i = 0;i < iVertex;i++)
    {
        vertexElem[i].isVisited = false;
    }
}

void crossedList::DFS(int i)//深度优先搜索 从第i+1个结点开始 
{
    if (!vertexElem[i].isVisited)
    {
        vertexElem[i].visited();
        vertexElem[i].isVisited = true;
    }
    else return;

    arcNode*p = verNode[i].firstOut;
    while (p)
    {
        DFS(p->headVertex);
        p = p->tailLink;
    }
}
void crossedList::BFS(int i)//广度优先搜索
{
    if (!vertexElem[i].isVisited)
    {
        vertexElem[i].visited();
        vertexElem[i].isVisited = true;
    }
    else return;
    myQuene<int> q(30);
    q.in(i);
    int x;

    while (!q.empty())
    {
        q.out(x);
        arcNode*p = verNode[x].firstOut;
        while (p)
        {
            if (!vertexElem[p->headVertex].isVisited)
            {
                vertexElem[p->headVertex].visited();
                vertexElem[p->headVertex].isVisited = true;
                q.in(p->headVertex);
            }
            p = p->tailLink;
        }
    }
}

main.cpp

# include<iostream>
# include"crossedList.h"

using namespace std;

int main()
{
    crossedList cl(8,9);
    cl.create();
    cout << "深度优先遍历为:" << endl;
    cl.setVisitedFalse();
    cl.DFS(0);

    cout << "\n广度优先遍历为:\n";
    cl.setVisitedFalse();
    cl.BFS(0);
    cout << endl;
    system("pause");
    return 0;
}

这里写图片描述
上面是之前邻接表存储时用的图,可以看到结果是一样的

比如下面这个图,深度遍历:vo-v1,由于v1没有出度,所以接下来是v2,然后是v3,广度遍历结果一样
这里写图片描述
这里写图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值