Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paring heap without shared_ptr #1707

Closed
wants to merge 1 commit into from
Closed

Conversation

jere8184
Copy link
Contributor

@jere8184 jere8184 commented Nov 7, 2024

fixes #1675

@jere8184

This comment was marked as duplicate.

@jere8184
Copy link
Contributor Author

jere8184 commented Nov 8, 2024

@heinezen @TheJJ Hopefully this is along the right lines, One issue I've noticed is that unlink_node will leave the user of the function with a node that they will have to then manually delete unless the node is pushed back into the heap at least with my current implementation.

@jere8184 jere8184 force-pushed the paring_heap branch 7 times, most recently from a18ba68 to fb52b9f Compare November 10, 2024 14:34
@jere8184
Copy link
Contributor Author

jere8184 commented Nov 10, 2024

unlink_node is now private. remove_node method added. 32% performance increase observed.

@heinezen heinezen linked an issue Nov 18, 2024 that may be closed by this pull request
2 tasks
Copy link
Member

@heinezen heinezen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found a few problems.

std::shared_ptr<this_type> prev_sibling;
std::shared_ptr<this_type> next_sibling;
std::shared_ptr<this_type> parent; // for decrease-key and delete
this_type* child = nullptr;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you rename the member?

Copy link
Contributor Author

@jere8184 jere8184 Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I felt it made more sense as a node can only have one child. Happy to change it back.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the code yes, but from a conceptual view, each node still has many children. The reason it's done this way is so that the pairing heap can be represented as a binary tree. You can read more about the concept here: https://en.wikipedia.org/wiki/Left-child_right-sibling_binary_tree

So first_child (or left_child) is more accurate.

Comment on lines 323 to 321
#if OPENAGE_PAIRINGHEAP_DEBUG
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code block does nohing now

}

this->node_count -= 1;
size_t erase_result = this->nodes.erase(ret);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are never using erase_result if OPENAGE_PAIRINGHEAP_DEBUG is false.

* Ω(log log n), O(2^(2*√log log n'))
* caller must eventually either add node back to heap or delete it
*/
element_t pop_node() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like pop_node() no longer deletes the node from the pointer, so this may cause issues. Especially if other methods like unlink_node() expect that pop_node() does deletion.

If you look back at 4ab602a#diff-84a922def1ded03f0d8849cb1c1d56e758f9ae47a06cb78fc40b193294d40ab9R380 where the shared:ptr implementation was introduced, you can see that there originally was no pop_node() (only pop()). Maybe it makes sense to merge the methods again.

Copy link
Contributor Author

@jere8184 jere8184 Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed as well, that's why I made pop_node() and unlink_node() private, I thought maybe as long as their callers handle the node correctly, it should be fine. I have merged both the methods.

In the ptr raw implementation that was changed by 4ab602a there's both pop_node() and pop().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the old implementation, pop_node was technically only a delete (more akin to remove_node now). It's a bit confusing bcause of the renames. Merging the functions is the right call I think.

@heinezen heinezen added improvement Enhancement of an existing component lang: c++ Done in C++ code area: util Utilitis and data structures labels Nov 19, 2024
@TheJJ TheJJ changed the title Paring heap Paring heap without shared_ptr Nov 19, 2024
@jere8184 jere8184 force-pushed the paring_heap branch 2 times, most recently from 03571e7 to b286c0c Compare November 20, 2024 19:30
Copy link
Member

@heinezen heinezen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have one addtional suggestion and then we can merge.

The rest of the code seems to work out fine :)

Comment on lines -639 to -641
#if OPENAGE_PAIRINGHEAP_DEBUG
std::unordered_set<element_t> nodes;
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we could keep this set only when OPENAGE_PAIRINGHEAP_DEBUG is true, so that the eap becomes even more efficient. Looks like it's only necessary for clearing up the nodes on deletion right now. I suggest we could try this solution:

  1. From clear(), use iter_all to iterate through all the nodes and call delete on them.
  2. Wrap all interactions of nodes with the #if OPENAGE_PAIRINGHEAP_DEBUG preprocessor thing again.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright sound like a plan :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@heinezen requested changes Implemented at #1713

@jere8184 jere8184 closed this by deleting the head repository Nov 24, 2024
@jere8184
Copy link
Contributor Author

I think I may have made a small mistake :/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: util Utilitis and data structures improvement Enhancement of an existing component lang: c++ Done in C++ code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement pairing heap without shared_ptr
2 participants