Solution 1: Keep a pointer to the last node
In this approach, a pointer to the last node is stored, and parent pointers are required.
When pasting, starting from the last node, go to node, under which the new last node will be inserted. Insert a new node and remember it as the last node. Move the heap as needed.
When deleting, starting from the last node, go to the second last node. Delete the original last node and remember the new last node just found. Move the source last node to the location of the remote node, and then, if necessary, move it up or down.
You can go to the indicated nodes in O (log (n)) time and O (1) space. The following is a description of the algorithms, but the code is available below:
: node , node . ... node. , node . , sibling node ( ). ( , ), . node node.
: node , , . ... node. , node . , node ( ). ( , ), . node.
, :
- . - , . ( - ), , , .
2. node
node count ( node). ( -) node .
, 1, . node . ( ) 1 . node; "", "".
, node 11 (= 1011b), , (0), (1), (1).
, , node ( node node_count + 1), --node ( node node_count-1).
libuv ; . .
, . , , , , , , , - .
, libuv ( ) , .
, Linux ( ) - , , ( , libuv). , .
1 2 , ( - node), , , . , node N, highest_bit(X) 0 N (0 LSB).
, ( ) , ( ) , .
highest_bit, . , - . , , 1, N, 1, 2N ).
, 1 , 2, , -, , 2. , , ( ) 2; 1 , .
1
, , , .
struct Node {
Node *parent;
Node *link[2];
};
struct Heap {
Node *root;
Node *last;
};
void init (Heap *h)
{
h->root = NULL;
h->last = NULL;
}
void insert (Heap *h, Node *node)
{
if (h->root == NULL) {
h->root = node;
h->last = node;
node->parent = NULL;
node->link[0] = NULL;
node->link[1] = NULL;
return;
}
Node *cur = h->last;
while (cur->parent != NULL && cur == cur->parent->link[1]) {
cur = cur->parent;
}
if (cur->parent != NULL) {
if (cur->parent->link[1] != NULL) {
cur = cur->parent->link[1];
while (cur->link[0] != NULL) {
cur = cur->link[0];
}
} else {
cur = cur->parent;
}
} else {
while (cur->link[0] != NULL) {
cur = cur->link[0];
}
}
assert(cur->link[1] == NULL);
h->last = node;
cur->link[cur->link[0] != NULL] = node;
node->parent = cur;
node->link[0] = NULL;
node->link[1] = NULL;
while (node->parent != NULL && value(node->parent) > value(node)) {
move_one_up(h, node);
}
}
void remove (Heap *h, Node *node)
{
if (node->parent == NULL && node->link[0] == NULL && node->link[1] == NULL) {
h->root = NULL;
h->last = NULL;
return;
}
Node *cur = h->last;
while (cur->parent != NULL && cur == cur->parent->link[0]) {
cur = cur->parent;
}
if (cur->parent != NULL) {
assert(cur->parent->link[0] != NULL);
cur = cur->parent->link[0];
}
while (cur->link[1] != NULL) {
cur = cur->link[1];
}
assert(h->last->parent != NULL);
h->last->parent->link[h->last == h->last->parent->link[1]] = NULL;
if (node == h->last) {
h->last = cur;
} else {
Node *srcnode = h->last;
replace_node(h, node, srcnode);
if (node != cur) {
h->last = cur;
}
if (srcnode->parent != NULL && value(srcnode) < value(srcnode->parent)) {
do {
move_one_up(h, srcnode);
} while (srcnode->parent != NULL && value(srcnode) < value(srcnode->parent));
} else {
while (srcnode->link[0] != NULL || srcnode->link[1] != NULL) {
bool side = srcnode->link[1] != NULL && value(srcnode->link[0]) >= value(srcnode->link[1]);
if (value(srcnode) > value(srcnode->link[side])) {
move_one_up(h, srcnode->link[side]);
} else {
break;
}
}
}
}
}
: move_one_up a node , replace_node node (srcnode) , node. , . , .