持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情
邻连表
领接表
领接表也是图的一种存储结构,之前的存储是领接矩阵。领接表是数组和链表的结合,其中有一个顶点数组和边表组成,如下图所示。对于稀疏图,如果用领接矩阵,有10个节点,则需要10*10的空间,但利用率很低,但是对于邻接表的存储可能需要的空间更少。
结合上图去抽象一个邻接表结点的对象
(1): 对于顶点数组中,每个结点存的是结点的值,而在边表中的每个结点存储的是顶点数组的下标位置 所以对结点的抽象数据就有一个column和一个next:
/**
* The column index.
*/
int column;
/**
* The next adjacent node.
*/
AdjacencyNode next;
/**
* The first constructor.
* @param paraColumn
*/
public AdjacencyNode(int paraColumn){
column = paraColumn;
next = null;
}
}
(2) 对于一个邻接表的构造,从代码中可以知道,对于headers数组的colun设置 为-1,并没有存放数据。我们是取的下标索引作为节点的值。在这个构造函数中,tempPreviousNode和tempNode两个变量让顶点数组和边表连接起来了。
AdjacencyNode[] headers;
public AdjacencyList(int[][] paraMatrix){
numNodes = paraMatrix.length;
//Step 1. Initialize. The data in the headers are not meaningful.
AdjacencyNode tempPreviousNode, tempNode;
headers = new AdjacencyNode[numNodes];
for (int i = 0; i < numNodes; i++){
headers[i] = new AdjacencyNode(-1);
tempPreviousNode = headers[i];
for (int j = 0; j < numNodes; j++){
if (paraMatrix[i][j] == 0){
continue;
}
// Create a new node.
tempNode = new AdjacencyNode(j);
// Link.
tempPreviousNode.next = tempNode;
tempPreviousNode = tempNode;
}
}
}
可以看一下这个在初始化后的结构:
AdjacencyList tempTable = new AdjacencyList(tempMatrix);
打断点看headers数据结构。
返回的headers数组和下图的表一样
(3)两种不同存储结构的广度优先遍历
对于矩阵的存储结构:我们对每一行数据for循环去判断结点是否被访问,结点是否相邻?之后再访问结点入队列
对于领接表存储结构:我们是对每一个hearders[i]所连接的链表,只需要判断结点是否访问,不用再判断结点相邻,因为这链表连接的就是领接点。 之后就访问结点入队列。
总结
今天主要是学习邻接表的存储结构。变换为邻接表的广度优先遍历