/* * 合并斐波那契堆的根链表中左右相同度数的树 */ static void fib_heap_consolidate(FibHeap *heap) { int i, d, D; FibNode *x, *y, *tmp; fib_heap_cons_make(heap);//开辟哈希所用空间 D = heap->maxDegree + 1; for (i = 0; i < D; i++) heap->cons[i] = NULL; // 合并相同度的根节点,使每个度数的树唯一 while (heap->min != NULL) { x = fib_heap_remove_min(heap); // 取出堆中的最小树(最小节点所在的树) d = x->degree; // 获取最小树的度数 // heap->cons[d] != NULL,意味着有两棵树(x和y)的"度数"相同。 while (heap->cons[d] != NULL) { y = heap->cons[d]; // y是"与x的度数相同的树" if (x->key > y->key) // 保证x的键值比y小 { tmp = x; x = y; y = tmp; } fib_heap_link(heap, y, x); // 将y链接到x中 heap->cons[d] = NULL; d++; } heap->cons[d] = x; } heap->min = NULL; // 将heap->cons中的结点重新加到根表中 for (i=0; i<D; i++) { if (heap->cons[i] != NULL) { if (heap->min == NULL) heap->min = heap->cons[i]; else { fib_node_add(heap->cons[i], heap->min); if ((heap->cons[i])->key < heap->min->key) heap->min = heap->cons[i]; } } } }
/** * Transform the root list into a list of binonmial heaps. * It makes the amortized cost so good for a secuence of mixed insert() and deleteMin() calls. * Cost: O(log n) * Pre: this fib_heap has at least 1 element. * Post: list of binomial heaps **/ void fib_heap::consolidate() { const int max_bin_heaps = 1.5 * (log2(n) + 1) ; //1.5*log n node_t* aux_array[max_bin_heaps]; //Init array: for (int i = 0; i<max_bin_heaps; ++i) { aux_array[i] = nullptr; } node_t *aux1, *aux2; //correspondence with MAR notes x <=> aux1 & y <=> aux2 D(std::cerr << "Debug: consolidate loop starts" << std::endl); //We've gotta go over every node in the root list while (root_list != nullptr) { aux1 = root_list; remove_from_list(root_list,aux1); //Make aux1 an unitary circular list (link to itself only) aux1->right = aux1; aux1->left = aux1; //Inside this while, we make sure we are creating only one bin heap of every degree while (aux_array[aux1->degree] != nullptr) { D(std::cerr << "bin heap of degree " << aux1->degree << " already taken by " << aux_array[aux1->degree]->key << std::endl); D(std::cerr << "consolidate loop" << std::endl << std::endl); aux2 = aux_array[aux1->degree]; //Another node with the same degree as aux1 //if aux1 is greater, it swaps them so that aux1 is always <= aux2 if (aux1->key > aux2->key) { swap(aux1,aux2); } aux_array[aux1->degree] = nullptr; fib_heap_link(aux2,aux1); } aux_array[aux1->degree] = aux1; } //Now, we restore the heap and the min pointer for (int i = 0; i<max_bin_heaps; ++i) { node_t *x = aux_array[i]; if (x != nullptr) { if (this->isEmpty()) { root_list = x; } else { concatenate_circular_lists(root_list,x); if (x->key < min->key) min = x; } } } D(std::cerr << "Debug: consolidate ok" << std::endl); D(std::cout << *this << std::endl); }