# Level based Representation of a Binary Tree - Load the Tree

Suppose, you are given an index and level based representation of a binary tree. can you tell, what is the index of its left child and what is the index of its right index?

Let's see some examples :

Node index Left child index Right child index
0 1 2
1 3 4
1 5 6
3 7 8
4 9 10

Do you see the pattern? It is easy to see:

Node index Left child index Right child index
k 2*k+1 2*k+2

Now that we regonize the pattern, we can write:

`````` def loadByIndex(data: List[Union[int, None]], kk: int):
# if the node does not exist in the list
if kk >= len(data):
return None

# find the value stored in current Node
value = data[kk]

# if the item is None, there is no node at this position
if value is None:
return None

# load the left child subtree
left = loadByIndex(data, kk * 2 + 1)

# load the right child subtree
right = loadByIndex(data, kk * 2 + 2)

# create the new tree
return Node(value, left, right)
``````

So, using this function we can easily load the tree:

`````` def load( data : List[Union[int,None]] ) -> Node :
``````

Now, let's see that it works

run tests
`````` \$ python -m unittest tests.load
.....
----------------------------------------------------------------------
Ran 5 tests in 0.002s

OK
``````

Yes, we solved the first task. However, can we write a better code

We write a helper function that is used only in the load function, let's move this function as inner function of load

`````` def load(data: List[Union[int, None]])
def loadByIndex(data: List[Union[int, None]], kk: int):
# if the node does not exist in the list
if kk >= len(data):
return None

# find the value stored in current Node
value = data[kk]

# if the item is None, there is no node at this position
if value is None:
return None

# load the left child subtree
left = loadByIndex(data, kk * 2 + 1)

# load the right child subtree
right = loadByIndex(data, kk * 2 + 2)

# create the new tree
return Node(value, left, right)
``````

It seems the code is verbose. Let's fix it. first, there is no need to move data to the function as it is available by defualt from the outer function.

`````` def load(data: List[Union[int, None]]):
# if the node does not exist in the list
if kk >= len(data):
return None

# find the value stored in current Node
value = data[kk]

# if the item is None, there is no node at this position
if value is None:
return None

# load the left child subtree
left = loadByIndex(kk * 2 + 1)

# load the right child subtree
right = loadByIndex(kk * 2 + 2)

# create the new tree
return Node(value, left, right)

``````

Now, that we have tests, we can be confident in refactoring the code.

`````` def load(data: List[Union[int, None]]):
# if the node does not exist in the list
if kk >= len(data) or data[kk] is None:
return None
# load Node, the left node located kk*2+1 and right node located at kk*2+2
return Node(data[kk], loadByIndex(kk * 2 + 1), loadByIndex(kk * 2 + 2) )
``````

Let's run the unittest again, and check that new changes we made in the code still works

run tests
`````` \$ python -m unittest tests.load
.....
----------------------------------------------------------------------
Ran 5 tests in 0.002s

OK
``````

Now, can you write the tests for the dump functions and implement it?