*2.3. k*2*-Tree*

Originally proposed for compressing Web graphs, *k*2-tree is a LOUDS variant compact data structure [22]. The tree represents a binary adjacency matrix of a graph (see Figure 2). It is constructed by recursively partitioning the matrix into square submatrices of equal size until each submatrix reaches a size of *k* x *k* where *k* ≥2. During the process of partitioning, if there is at least one cell in the submatrix that has a value of 1, the node in the tree will be set to 1. Otherwise, it will be set to 0 (i.e., it is a leaf and has no children) and this particular submatrix will not be partitioned any further. Figure 2 illustrates an example of a graph of 6 nodes, its 8 × 8 binary adjacency matrix at various stages of recursive partitioning, and the *k*2-tree that is constructed from the matrix.

The values of *k*2-trees are basically stored in two bitmaps denoted by *T* (tree) and *L* (leaves). The values are traversed in a breadth-first fashion starting with the first level. The *T* bitmap stores the bits at all levels except the last one where its bits will be stored in the *L* bitmap. Note that the bit values of *T* which are either 0 or 1 will be stored as a bit vector. To illustrate this with an example, we again make use of the binary matrix in Figure 2. The *T* bitmap contains all the bits from levels 1 and 2. Thus the *T* bitmap has the following bits: 1001 1101 1000 (see Figure 6). The bits from the last level, level 3, will be stored in the *L* bitmap with the following bits: 1001 0001 1011 1111.

Consider a set *S* with elements from 1 to *n*, to find the child's or the parent's position of a certain node *m* in a *k*2-tree, we perform the following operations:

first-child(*m*) <sup>←</sup> rank(*m*) · *<sup>k</sup>*<sup>2</sup> where 1 <sup>≤</sup> *<sup>m</sup>* ≤ *S* parent(*m*) <sup>←</sup> select(*m*/*k*2) where 1 <sup>≤</sup> *<sup>m</sup>* ≤ *S*

Once again using the *k*2-tree in Figure 2 as an example, with the *T* bitmap (Figure 6) and the rank and select functions, we can navigate the tree and obtain the positions of the first child and the parent. Figure 7 shows how the nodes of the *k*2-tree are numbered.

Ex. Locate the first child of node 8: rank1(8) \* 4 = 6 \* 4 = 24

(There are 6 one bits in the *T* bitmap starting from node 0 up to and including node 8.)

	- select1(11/4) = select1(2) = 3

(Start counting from node 0, skipping all nodes with '0' bits, and node 3 is the first node that gives a total number of 1-bit count of 2. Therefore, node 3 is the parent.


**Figure 6.** A *T* bitmap with the first node labeled as 0.

**Figure 7.** An example showing how the rank function is computed to obtain the children's position on a *k*2-tree node (k=2) based on the tree in Figure 2. It starts with 0 on the first child of the root (first level) and the numbering traverses from left to right and from top to bottom.

It was shown that *k*2-tree gave the best performance when the matrix was sparse with large clusters of 0's or 1's [20].
