本文主要讨论有向图的十字链表表示,包括建图,添加弧,删除弧,以邻接表的格式打印图(其中包括两种形式: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)
结果: