十字链表是邻接表和逆邻接表的一种结合,顶点结点和弧结点如图:
这样,求一个顶点的出度,入度都比较方便,一般用来存储有向图,下面便是实现部分了,大体和之前几种存储方式差不多,只是由于存储方式的不同而略有不同而已
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,广度遍历结果一样