/* * Extend a priority search tree so that it can store a node with heap_index * max_heap_index. In the worst case, this algorithm takes O((log n)^2). * However, this function is used rarely and the common case performance is * not bad. */ static struct prio_tree_node *prio_tree_expand(struct prio_tree_root *root, struct prio_tree_node *node, unsigned long max_heap_index) { struct prio_tree_node *prev; if (max_heap_index > prio_tree_maxindex(root->index_bits)) root->index_bits++; prev = node; INIT_PRIO_TREE_NODE(node); while (max_heap_index > prio_tree_maxindex(root->index_bits)) { struct prio_tree_node *tmp = root->prio_tree_node; root->index_bits++; if (prio_tree_empty(root)) continue; prio_tree_remove(root, root->prio_tree_node); INIT_PRIO_TREE_NODE(tmp); prio_set_parent(prev, tmp, true); prev = tmp; } if (!prio_tree_empty(root)) prio_set_parent(prev, root->prio_tree_node, true); root->prio_tree_node = node; return node; }
/* * Extend a priority search tree so that it can store a node with heap_index * max_heap_index. In the worst case, this algorithm takes O((log n)^2). * However, this function is used rarely and the common case performance is * not bad. */ static struct prio_tree_node *prio_tree_expand(struct prio_tree_root *root, struct prio_tree_node *node, unsigned long max_heap_index) { struct prio_tree_node *first = NULL, *prev, *last = NULL; if (max_heap_index > prio_tree_maxindex(root->index_bits)) root->index_bits++; while (max_heap_index > prio_tree_maxindex(root->index_bits)) { root->index_bits++; if (prio_tree_empty(root)) continue; if (first == NULL) { first = root->prio_tree_node; prio_tree_remove(root, root->prio_tree_node); INIT_PRIO_TREE_NODE(first); last = first; } else { prev = last; last = root->prio_tree_node; prio_tree_remove(root, root->prio_tree_node); INIT_PRIO_TREE_NODE(last); prev->left = last; last->parent = prev; } } INIT_PRIO_TREE_NODE(node); if (first) { node->left = first; first->parent = node; } else last = node; if (!prio_tree_empty(root)) { last->left = root->prio_tree_node; last->left->parent = last; } root->prio_tree_node = node; return node; }
/* * Insert a prio_tree_node @node into a radix priority search tree @root. The * algorithm typically takes O(log n) time where 'log n' is the number of bits * required to represent the maximum heap_index. In the worst case, the algo * can take O((log n)^2) - check prio_tree_expand. * * If a prior node with same radix_index and heap_index is already found in * the tree, then returns the address of the prior node. Otherwise, inserts * @node into the tree and returns @node. */ struct prio_tree_node *prio_tree_insert(struct prio_tree_root *root, struct prio_tree_node *node) { struct prio_tree_node *cur, *res = node; unsigned long radix_index, heap_index; unsigned long r_index, h_index, index, mask; int size_flag = 0; get_index(node, &radix_index, &heap_index); if (prio_tree_empty(root) || heap_index > prio_tree_maxindex(root->index_bits)) return prio_tree_expand(root, node, heap_index); cur = root->prio_tree_node; mask = 1UL << (root->index_bits - 1); while (mask) { get_index(cur, &r_index, &h_index); if (r_index == radix_index && h_index == heap_index) return cur; if (h_index < heap_index || (h_index == heap_index && r_index > radix_index)) { struct prio_tree_node *tmp = node; node = prio_tree_replace(root, cur, node); cur = tmp; /* swap indices */ index = r_index; r_index = radix_index; radix_index = index; index = h_index; h_index = heap_index; heap_index = index; } if (size_flag) index = heap_index - radix_index; else index = radix_index; if (index & mask) { if (prio_tree_right_empty(cur)) { INIT_PRIO_TREE_NODE(node); cur->right = node; node->parent = cur; return res; } else cur = cur->right; } else { if (prio_tree_left_empty(cur)) { INIT_PRIO_TREE_NODE(node); cur->left = node; node->parent = cur; return res; } else cur = cur->left; } mask >>= 1; if (!mask) { mask = 1UL << (BITS_PER_LONG - 1); size_flag = 1; } } /* Should not reach here */ assert(0); return NULL; }