十字链表定义
之前的邻接表对于有向图来说,可分为邻接表和逆邻接表,对于出入度要求不同时,生成的邻接表也不同
十字链表的出现就是将 邻接表和逆邻接表整合在一起
在同一个代码中,对于一个顶点可以找到其出度也可以找到其入度
在十字链表存储结构中,有向图中的顶点表的结点结构如下所示:
data存储数据,firstIn指向入边表头指针,firstOut指向出边表头指针。
边表结点结构如下
其中的tailVex表示该弧的弧尾顶点在顶点数组xList中的位置
headVex表示该弧的弧头顶点在顶点数组中的位置
hLink则表示指向弧头相同的下一条弧
tLink则表示指向弧尾相同的下一条弧。
如下图所示的一个有向图:
十字链表结构体定义
里面那个inof不知道啥意思
#include<iostream>
using namespace std;
#define MAX 25
typedef char Vertype;
typedef int infotype;//这是权重吗
typedef int Status;
typedef struct Arc_node//弧结点结构
{
int tailvex, headvex;
struct Arc_node *hlink, *tlink;
infotype *info;//这是权重的意思吗?
int weight;
}Arc_node;
typedef struct Vex_Node//顶点结构
{
Vertype data;
Arc_node *firstIn, *firstOut;
}Vex_Node;
typedef struct Or_list//十字链表
{
Vex_Node list[MAX];//顶点列表
int Vexnum, Arcnum;//顶点数目 和 边的数目
}Or_list;
//被调用的函数要声明
Status locateVertex(Or_list &G, Vex_Node node);
Status inserArc(Or_list &G, Vex_Node node1, Vex_Node node2);
Status inserArction(Or_list &G, int index1, int index2);
//生成图
Status CreatOr_list(Or_list &G)
{
cout <<"输入顶点数目和边的数目: " << endl;
cin >> G.Vexnum;
cin >> G.Arcnum;
//初始化
cout <<"输入"<<G.Vexnum<<"个顶点内容: " << endl;
for (int i = 0; i < G.Vexnum; i++)
{
cin >> G.list[i].data;
G.list[i].firstIn = NULL;
G.list[i].firstOut = NULL;
}
//增加弧
for (int j = 0; j < G.Arcnum; j++)
{
//此时,只有初始化的十字链表 弧还没有形成,所以这里将形成弧
Vex_Node node1, node2;
cout << "请输入第"<<j+1<<"条弧的两个顶点"<< endl;
cin >> node1.data >> node2.data;
inserArc(G,node1,node2);
}
return 0;
}
//获取两个顶点下标 并生成弧
Status inserArc(Or_list &G, Vex_Node node1, Vex_Node node2)
{
int index1 = locateVertex(G,node1);//获取下标
int index2 = locateVertex(G,node2);
if (index1 == -1 || index2 == -1)
{
cout << "顶点不存在"<< endl;
return NULL;
}
inserArction(G,index1,index2);
return 0;
}
//寻找某一顶点的下标
Status locateVertex(Or_list &G, Vex_Node node)//获取该顶点下标
{
int i,index=-1;
for (i = 0; i < G.Vexnum; i++)
{
if (G.list[i].data == node.data)
{
index = i;
break;//如果有重复的呢
}
}
return index;
}
//生成弧
Status inserArction(Or_list &G, int index1, int index2)
{
Arc_node *pArc = new Arc_node;
pArc->tailvex = index1;
pArc->headvex = index2;
pArc->info = NULL;//这一段是什么,
pArc->tlink = G.list[index1].firstOut;
pArc->hlink = G.list[index2].firstIn;
G.list[index1].firstOut = pArc;
G.list[index2].firstIn = pArc;
cout << "输入权重: "<< endl;
cin>>pArc->weight;
return 0;
}
//输出图
Status DispGhaph(Or_list &G)
{
for (int i = 0; i < G.Vexnum; i++)
{
//ptail 和phead 可以指向弧的前后顶点位置
Arc_node *ptail = G.list[i].firstOut;//以i位置顶点为出指针
Arc_node *phead = G.list[i].firstIn;//以i位置顶点为入指针
cout << i << " 位置顶点元素为: " << G.list[i].data << endl;
cout << "输出以" << G.list[i].data << "弧尾结构: " << endl;
while (ptail)
{
cout << G.list[ptail->tailvex].data <<'\t'<< "->" << '\t' << ptail->weight << '\t' << G.list[ptail->headvex].data << endl;
ptail = ptail->tlink;
}
cout << "输出以" << G.list[i].data << "弧头结构" << endl;
while (phead)
{
cout << G.list[phead->headvex].data << '\t' << phead->weight << '\t' << "<-" << '\t' << G.list[phead->tailvex].data << endl;
phead = phead->hlink;
}
}
return 0;
}
//增加弧
Status ADDGhaphARC(Or_list &G)
{
//增加新的弧 如果弧原本存在,提示。如果不存在就生成这条弧
Vex_Node node1, node2;
int I1=-1, I2=-1;
cout << "输入两个顶点以便生成弧"<< endl;
cin >> node1.data >> node2.data;
for (int i = 0; i < G.Vexnum; i++)
{
if (G.list[i].data == node1.data)
{
I1 = i;
break;
}
}
for (int i = 0; i < G.Vexnum; i++)
{
if (G.list[i].data == node2.data)
{
I2 = i;
break;
}
}
if (I1 == -1 || I2 == -1)
{
cout << "没有这个值"<< endl;
return NULL;
}
else if (G.list[I1].firstOut ==G.list[I2].firstIn)
{
cout << "弧原本存在"<< endl;
return NULL;
}
else
{
cout << "顶点合法,将生成弧"<< endl;
inserArction(G,I1,I2);
}
return 0;
}
int main()
{
Or_list G;
CreatOr_list(G);
DispGhaph(G);
ADDGhaphARC(G);
DispGhaph(G);
system("pause");
return 0;
}
在写这个的时候发现前面的额数据结构 都是在顺利的条件下生成 那么如果遇到输入格式或者范围超过时应该写一个提示输入不合规,重新输入的循环体,,,记得下次循环回头时重新编,我打算先将数据结构基础的都过一遍,用c给它写出来,现在开始入门JAVA的坑了,等学了基本的,在将数据结构用JAVA编写,一来练练JAVA 二来巩固完善数据结构