5/5/12

Convert data in adjacency list model to tree


This is my very first blog post so I hope you will share your feeling about my post. Is it helpful? Am I talking too detailed or too general? Is the font easy for you to read? If there is any problem you think that would help me in later posts, please send me a message or comment on this post. Thank you!

I’m going to our topic now. This article addresses the following issues:

If you know well about one issue, you should bypass it and read the part that is suitable for you.

One of a common task is to insert data in tree-form into database, such as the navigation tree like

--Drink

----Coke

----Pepsi

--Food

----Pork

----Beef

Example 1
You’re finding a way so that when you retrieving the data back from the database, you can represent it in nested <ul> and <li> form. If this is your case, then there’re some options for you:
Perhaps the third solution has more advantage over the other two, but if you choose ALM (or sometimes your co-worker ask you to use ALM) then this article is a simple solution for it.
Here I’m simply giving the presentation of Example 1 in relational database if you choose ALM:
Table 1
That’s it. That’s how your data would look like in your database for ALM. Now I’m gonna give you my library to convert that type of data to tree in php and java. For those who would like to do quick work, read part 2. Who want to know more about my method before implementing it please read part 3 and 4 first.
Please follow download link to download the library.
The ALM2Tree.7z should be extract by 7zip. Now you got 4 files:
  • Base_category.php: It is the data structure as in Table1. Each Base_category object represent one row in Table 1.
  • Node: It is the combination of a Base_category, a pointer to the Node’s father and an array of pointer to the Node’s children.
  • CTree: It contains one Node named $root and 2 stack: $stack1 and $stack2. 
My algorithm is that we try to get one-by-one element from $stack1 to insert to the tree. If the insertion is not successful (We cannot find the element’s father in our tree) then we should push the element to $stack2 and come back to it later.
We also have array $orphan. If finally the new element cannot insert to our tree, then it has no father and we push it to $orphan array.
I will explain it in detail in part 3.

To use the library, you should:

1) Code some line to get data from your database. Supposed that you have your data in $your_data
2) Code some line to convert it to an array of Base_category object. An example of how to initialize Base_category object is as follow: 
$bc = new Base_category(7, “Food”, 1) ; // 7: ID of Food. 1: parent_id of Food
 2) After the 2) step you should have array $arr. Now you should initialize a CTree object by  
$tree = new Ctree() ;
4) To Convert $arr to tree, simply use:$tree->build_tree($arr) ;
That’s it. It’s quite simple, huh. Now how can you use your tree? I have prepare some methods for you:

Get_root() // Return the Node $root

Get_orphan() // Return array of Base_category $orphan

Get_leaves( $id ) // Get all id of leave Nodes in sub-tree rooting from the node that has id = $id

Get_descendants( $id ) //Get all descendants (Node) of the node that has id = $id

My advice is to run my test.php file and see the result. You could print_r the result to see the data structure to write new function if you need. I have commented all my code so have a look at it. Hope it helps!
I am not saying that I’ve devised new algorithm. It’s quite a simple and common problem thus I think there are bunch of solution for it. But the fact that I didn’t read the algorithm anywhere and I now publish my code, I should explain how the code runs.

ALM2Tree Algorithm

Input: An array of Base_category object $arr

Output: A Ctree object which contains Node $root and array of Base_category $orphan

1. Create $stack1 and $stack2

2. Transfer all element from $arr to $stack1

3. While $stack1 and $stack2 is not empty

            3.1 If size of $stack1 and size of $stack2 are equal

                        Return

            3.2 Try to insert each element from $stack1 to the tree until $stack1 is empty

            3.3 Recalculate the size of $stack1

            3.4 Try to insert each element of $stack2 to the tree untial $stack2 is empty
            3.3 Recalculate the size of $stack2



The condition in 3.1 is when we have orphans and the tree has been built as fullest as possible.
The steps 3.2 and 3.4 use the add( $c ) function ( $c: Base_category object ). It is called by a Node object, i.e the $root.


The algorithm for a Node to add a Base_category

Input: An object whose type is Base_category: $c

Output: void. Either $c will be added to the Node’s descendants or $c will be add to opposite stack. With “opposite”, I mean, for example, $c is poped from $stack1 then $stack2 is the opposite stack. $stack1 and $stack2 are static variables.

  1. Find descendants of the current Node, supposed we have $des array
  2. If $c->pid is not equal to any ids of Nodes in $des, then $c is orphan (at this moment only – may be $c’s father will be inserted later. See Figure 1)
  3. Else
    1. Find current node's direct child that leads to the father of $c, we call it node A (See Figure 2)
    2. when node A found, recursively call add() function at node A (i.e use $A.add($c) )


Figure 1


Figure 2
Figure 3

The worse situation for ALM2Tree Algorithm is as Figure 3. If it happens, we only insert one element to the tree for each round. Thus the complexity is O(n!) with n is the number of elements which need to be inserted to the tree.
In fact, when I applied this algorithm, my website provided a way such that a sub-category could only be created if it belongs to another valid category. Thus in my database, data was in “right” order: father first, then comes it children. The complexity in my case was O(n).

5/4/12

About me

Thank you for visiting my page!

I am Dao Minh Tung, a student in UCD Michael Smurfit School. Currently I am studying Msc. iBusiness, so this blog is used as a medium to express my thinking on my subjects at school.

Previously, I'm a software engineer. I use some languages such as php, java, objective C. Therefore, this blog also talks about programming techniques and new technology.

I love learning new technology and business knowledge, sharing and discussing them with people.

I hope you find something helpful in my blog.

About Me

My photo
Dublin, Ireland
I am a Master student in UCD Michael Smurfit School. With broad experience in start-up, research, software industry and sale, I am actively seeking employment in consulting industry.