有向图使用邻接表存储方式时,顶点的出度通过遍历它的邻接单链表可以实现,但是入度需要遍历所有邻接单链表才能得到
逆邻接表则相反,逆邻接表中顶点的入度易得到,出度则需要遍历所有单链表
十字链表可解决这一问题,十字链表中的每个节点既有一个指针指向以它本身为尾的边的链表(出度),也有一个指针指向以它本身尾头的边的链表(入度)
这样统计一个顶点的度就很方便,典型的使用空间换取时间。
/**
* 有向图的十字链表存储方式
*/
public class AdjacencyCrossListGraph {
// 邻接表的顶点数组
VertexNode[] vexs;
int vexNums,arcNums;
class VertexNode{
// 数据域
char data;
// 存放由该结点的邻接点组成的单链表的头指针
// firstIn、firstOut只是为了方便操作的一个单链表头指针,其中不存放任何有意义的值,之后的结点存储的才是真正的邻接点域
// firstIn指向顶点的入度边的链表
ListNode firstIn;
// firstOut指向顶点的出度边的链表
ListNode firstOut;
public VertexNode(char data){
this.data=data;
this.firstIn=new ListNode();
this.firstOut=new ListNode();
}
}
class ListNode{
// 存放弧头顶点在顶点数组中的下标位置
int headPos;
// 存放弧尾顶点在顶点数组中的下标位置
int tailPos;
// 与这条边弧头顶点相同的边的指针
ListNode hLink;
// 与这条边弧尾顶点相同的指针
ListNode tLink;
// 存放权值
int info;
public ListNode(){
}
public ListNode(int headPos, int tailPos, ListNode hLink, ListNode tLink, int info) {
this.headPos = headPos;
this.tailPos = tailPos;
this.hLink = hLink;
this.tLink = tLink;
this.info = info;
}
}
public AdjacencyCrossListGraph(int n){
vexs=new VertexNode[n];
}
/**
* 初始化邻接表
* @param vexStr 邻接表的顶点
* @param arcStr 邻接表的边
*/
public void init(String vexStr, String[] arcStr){
for (int i = 0; i < vexs.length; i++) {
vexs[i]=new VertexNode(vexStr.charAt(i));
// 顶点的数量+1
vexNums++;
}
// 初始化邻接链表
// 先根据边的两个顶点的值,确定两个顶点在顶点表中的下标
for (String s : arcStr) {
// 顶点v1
char v1=s.charAt(0);
// 顶点v2
char v2=s.charAt(2);
// 权值
int w=s.charAt(4)-'0';
// 得到i,j
int i=locateVex(v1);
int j=locateVex(v2);
ListNode p = null;
// 给下标为i的顶点添加邻接点,邻接点下标为j
ListNode listNode_i = new ListNode(i,j,null,null,w);
// 出度<i,j>
p=vexs[i].firstOut;
listNode_i.tLink=p.tLink;
p.tLink=listNode_i;
// 入度<j,i>,给j顶点添加由i指向j的入度结点
ListNode listNode_j = new ListNode(j, i, null, null, w);
p=vexs[j].firstIn;
listNode_j.hLink=p.hLink;
p.hLink=listNode_j;
// 边的数量+1
arcNums++;
}
}
private int locateVex(char v){
for (int i = 0; i < vexs.length; i++) {
if(v==vexs[i].data){
return i;
}
}
return -1;
}
/**
* 统计顶点的入度个数
* @return
*/
public int inDegree(char v){
int vexPos = locateVex(v);
VertexNode vex = vexs[vexPos];
ListNode in = vex.firstIn;
int count=0;
while(in.hLink!=null){
count++;
in=in.hLink;
}
return count;
}
/**
* 统计顶点的出度个数
* @return
*/
public int outDegree(char v){
int vexPos = locateVex(v);
VertexNode vex = vexs[vexPos];
ListNode in = vex.firstOut;
int count=0;
while(in.tLink!=null){
count++;
in=in.tLink;
}
return count;
}
/**
* 统计顶点的度
* @param v
* @return
*/
public int degree(char v){
return this.inDegree(v)+this.outDegree(v);
}
}