Suppose I have an array as an input, say
array = -1 0 0 1 2 1 3 5 5 6 6
(This is actually a parent array representation of a binary tree)
The tree looks like this in this case:
0
/ \
1 2
/ \ /
3 5 4
/ / \
6 7 8
/ \
9 10
And I have another input, say
input = 1
(this is a node to be deleted from the tree)
What I want to achieve is basically:
- Delete array[input]
- Search for the input variable in the remaining array
- Delete all the elements with value = input
- Store the indices of the deleted values
- Search the remaining array for value = indices
- Delete those elements and store their indices
- Repeat from step 5 until nothing more can be deleted
This is the algorithm I have thought of to delete a node and all of its children.
So basically for the sample input given above, the output should be:
-1 0 2
I have opted not to use a tree data structure because I feel that constructing the tree from the parent array, then searching for the node and deleting it might be slower (although I may be wrong).
I haven't been able to achieve this in code though, I just have the logic. Whenever I am trying to write the pseudo code, one or more problems in my logic become visible. Which is why I have no concrete code to post here yet. So I have no idea how long this will take.
This is a question for a class assignment and just using a tree data structure will work, but I want to implement a better solution in this case if possible.
Any help is appreciated. No need to give me complete code. Just some pointers would be enough.
1 Answer 1
Here is an implementation of a slightly modified version of your algorithm.
The difference is that we do not do the purging one level after the other, but instead all in one go. This uses the fact that children always are to the right of their parents, so if we just go through the list once and mark everything that is to delete as we go, we do not miss anything.
This leaves the tree in a non canonical state, because the removed nodes are still there, they just are marked as to remove (by having their parent set at -2).
Therefore I have also added an opotional compression step that removes these nodes and renumbers the remaining ones, so that the remaining nodes are numbered 0, 1, 2, ... without gaps.
from itertools import islice, count
def delete_branch_from_tree(parents, branch_root,
compress=False, inplace=False):
n = len(parents)
if not inplace: # make a copy
parents = parents[:]
if branch_root == 0:
parents[:] = [] if compress else n * [-2]
return parents
# -2 will indicate missing nodes
parents[branch_root] = -2
for node in range(branch_root+1, n):
if parents[parents[node]] == -2:
parents[node] = -2
if compress: # remove nodes marked as missing, renumber the other ones
c = count()
new_number = [None if parent==-2 else next(c) for parent in parents]
parents[:] = [new_number[parent] for parent in parents if parent != -2]
# -1 was not in the lookup table (new_number), must fix manually
parents[0] = -1
return parents
Demo:
>>> tree = [-1, 0, 0, 1, 2, 1, 3, 5, 5, 6, 6]
>>>
>>> delete_branch_from_tree(tree, 1)
[-1, -2, 0, -2, 2, -2, -2, -2, -2, -2, -2]
>>> delete_branch_from_tree(tree, 1, compress=True)
[-1, 0, 1]
>>> delete_branch_from_tree(tree, 5)
[-1, 0, 0, 1, 2, -2, 3, -2, -2, 6, 6]
>>> delete_branch_from_tree(tree, 5, compress=True)
[-1, 0, 0, 1, 2, 3, 5, 5]
Comments
Explore related questions
See similar questions with these tags.
5, what to you put at index5in your list? Do you need to update7and8, or can they still point to the removed node afterwards? If "deleting" a node renumbers all the successive node names (by shifting their indexes in the list), you're going to need to do a bunch of cleanup work to make everything else still fit together.-1 0 2doesn't seem to be a valid representation, since by the position equals child id convention it would have to be read as 0: no parent, 1: parent is 0, 2: parent is 2.