-1

so i guess you are all fimilliar with a binary heap data structure if not.. Brilliant. org say

i.e. a binary tree which obeys the property that the root of any tree is greater than or equal to (or smaller than or equal to) all its children (heap property). The primary use of such a data structure is to implement a priority queue.

will one of the properties of a binary heap is that it must be filled from top to bottom (from root) and from right to left

I coded this algorithm to find the next available spot to insert the next number I add (I hard coded the first nodes so I can track more further down the tree

this search method is inspired by BFS(Breadth First Search) algorithm

note that in this code I only care about finding the next empty node without the need to keep the heap property

I tested the code but I don't think I tested it enough so if you spot problems, bugs or suggest any ideas, every comment is welcomed

    def insert(self, data):
        if self.root.data == None:
            self.root.data = data
            print('root', self.root.data)
        else:
            self.search()

    def search(self):
        print('search..L31')
        queue = [self.root]

        while queue:
            curr = queue.pop(0)
            print(curr.data)
            if curr.right_child == None:
                print('made it')
                return
            else:
                queue.append(curr.left_child)
                queue.append(curr.right_child)



h = Min_heap(10)
h.insert(2)
h.root.left_child = Node(3)
h.root.right_child = Node(5)
h.root.left_child.left_child = Node(8)
h.root.left_child.right_child = Node(7)
h.root.right_child.left_child = Node(9)

# The tree I am building...
#                       __2__
#                      /     \
#                     3       5
#                    / \     / \
#                   8   7   9   ⨂
#                               ↑
#                            what am
#                          looking for
h.search()

there is another way to figuring this out which is basically translating the tree into an array/list using special formulas and then we just assume that the next data we want to insert is the last element in the previous array and then work back through the same formulas but I already know that algorithm and I thought why not trying to solve it as a graph soooo...

Ali
  • 439
  • 1
  • 4
  • 14
ii3Boodi
  • 1
  • 2
  • I think is inefficient to use a queue. To insert a new node you should visit your structure according to the rule of the heap and insert the new Node when you find the null (None in your pseudocode) node – Nick Sep 17 '22 at 21:24
  • 1
    The way a binary heap is implemented is with an array, not with nodes that have explicit left/right properties. Any advantage you would have from a heap is lost when you have to perform a BFS traversal over **all** nodes to find the insertion spot. You might as well throw the whole heap idea away and use a simple unsorted list where each time you need the minimum value, you scan the array, and remove the found minimum from it. Same time complexity as this broken heap, but much simpler. – trincot Sep 17 '22 at 21:37
  • 1
    If you know the number of nodes in the heap, you can find the next insertion spot using the binary representation of the count. See https://stackoverflow.com/a/49557487/56778 for an explanation. – Jim Mischel Sep 18 '22 at 04:17
  • What is your [answerable programming question](https://stackoverflow.com/help/on-topic)? – greybeard Sep 18 '22 at 05:15
  • https://brilliant.org/wiki/binary-heap/#:~:text=A%20binary%20heap%20is%20a,to%20implement%20a%20priority%20queue. @greybeard – ii3Boodi Sep 18 '22 at 16:55
  • I could just use a an array instead of al of this and it will be just fine.. I am learning python so I found it will be so useful to try to implement this (alot of syntax working, functions, logics and algorithms) @trincot – ii3Boodi Sep 18 '22 at 16:59

2 Answers2

0

If you want to guarantee balanced, just add to each node how many items are there or below. Maintain that with the heap. And when placing an element, always go to where there are the fewest things.

If you just want a simple way to place, just randomly place it. You don't have to be perfect. You will still on average be O(log(n)) levels, just with a worse constant.

(Of course your constants are better with the array approach, but you say you know that one and are deliberately not implementing it.)

btilly
  • 43,296
  • 3
  • 59
  • 88
  • you are saying that ad a variable to the node class to keep track of how many total nodes are below that one (children/children of children/...etc) and when i want to add a node (element) I just go for whenever this number is smaller.. but wouldn't this leads to random possessions when there is 0 to n-1 nodes in the last layer (considering it only fits to n nodes) ?? @btilly – ii3Boodi Sep 18 '22 at 16:28
  • If you break ties with always going left, then it won't be random. It won't be exactly the usual order, but it will work well. – btilly Sep 18 '22 at 16:33
  • okay now I got it, I will consider implementing that as I see it will be interesting to figure out.. just to check the code I wrote above was working or not? – ii3Boodi Sep 18 '22 at 17:02
0

You should better implement a binary heap as a list (array). But if you want to do it with node objects that have left/right attributes, then the position for the next node can be derived from the size of the tree.

So if you enrich your heap class instances with a size attribute and maintain that attribute to reflect the current number of nodes in the tree, then the following method will tell you where the next insertion point is, in O(logn) time:

Take the binary representation of the current size plus 1. So if the tree currently has 4 nodes, take the binary representation of 5, i.e. 101. Then drop the leftmost (most significant) bit. The bits that then remain are an encoding of the path towards the new spot: 0 means "left", 1 means "right".

Here is an implementation of a method that will return the parent node of where the new insertion spot is, and whether it would become the "left" or the "right" child of it:

    def next_spot(self):
        if not self.root:
            raise ValueError("empty tree")
        node = self.root
        path = self.size + 1
        sides = bin(path)[3:-1]  # skip "0b1" and final bit
        for side in sides:
            if side == "0":
                node = node.left
            else:
                node = node.right
        # use final bit for saying "left" or "right"
        return node, ("left", "right")[path % 2]
trincot
  • 317,000
  • 35
  • 244
  • 286
  • I had that idea but I didnt know how to turn into binary and drop final bit (as in line 6 in ur code) that idea came to me when i tried to represent the tree nodes (when they have values 1-2-3-4-5-6.. in order) in binary.. appreciated – ii3Boodi Sep 19 '22 at 18:38