Implementing Consolidate in Fibonacci heap - algorithm

The pseudocode from Introduction to Algorithms states:
for each node w in the root list of H
link trees of the same degree
But how to efficiently implement the for each root node part? Original roots are linked to other roots of the same degree throughout the process of consolidation, which makes it difficult to just pass through the circular list of root nodes. How can I decide whether I have checked every root node or not?

One simple way that you could do this would be to use a three-step process:
Break the circular link so that the list is now just a normal doubly-linked list.
Iterate over the doubly-linked list and process each tree. This is tricky because, as you've mentioned, the forward and next pointers on each node might change during the iteration.
Close the cycle.
Here's how you might do each step:
Break the circular link:
rootList->prev->next = NULL;
rootList->prev = NULL;
Iterate over the doubly-linked list.
Node* current = rootList;
while (current != NULL) {
/* Cache the next node to visit so that even if the list changes, we can still
* remember where to go next.
*/
Node* next = current->next;
/* ... main Fibonacci heap logic ... */
current = next;
}
Repair the doubly-linked list:
Node* curr = rootList;
if (curr != NULL) { // If list is empty, no processing necessary.
while (curr->next != NULL) {
curr = curr->next;
}
curr->next = rootList;
rootList->prev = curr;
}
Hope this helps!

Related

To find loop in a singly linked list without using slow and fast pointer

As we know that for detecting loop in a linked list, we use slow pointer and fast pointer in which firstly we initialize two node slow and fast with head nodethen we traverse fast pointer two step ahead and slow with one step ahead.If we find both addresses are equal, then, there is loop otherwise if fast==null || fast.next==null then there is no loop. Now my question is "Is there any possibility to detect loop in singly linked list without using fast and slow pointer ?"
Any idea will be appreciated.
Thanks in advance.
There are at least two other solutions.
An O(n^2) solution is to keep track of the node numbers. At each node, go back to the head and count how many next operations it takes to reach the current node. If you get to the nth node before you do n next operations, then there's a loop in your list. That is:
// assuming head is not null, and head doesn't point to itself
nodeNumber = 1
current = head.next
while (current != null)
{
p = head
counter = 0
while (p != current && counter < nodeNumber)
{
p = p.next
counter = counter + 1
}
if (p != current)
there's a loop
nodeNumber = nodeNumber + 1
}
A destructive method is to reverse the links as you go. If there's a loop in the linked list, then when your pointer is equal to null it will be at the root. That is:
if (head == null) || (head.next == null)
no loop
prev = head
current = head.next
while (current != null)
{
// save next position
next = current.next
// reverse the link
current.next = prev
// and move to the next node
prev = current
current = next
}
if (prev == head)
there is a loop
That does have the disadvantage of destroying the list if there's a loop in it. If there's not a loop, you can go back through the list and reverse the links.
Yes, of course. Most intuitive way is to traverse each node and check if you have visited this node. If you would have visited this node earlier, this means that there is a cycle and this particular node is the start of cycle.
To check if you have visited this node earlier you can maintain a hash-set which allows you to check for presence of an element in O(1) time complexity.
Check the below pseudo code.
Time Complexity - O(n)
Space Complexity - O(n)
boolean isCyclic(Node head){
HashSet<Node> set = new HashSet<Node>();
while(head != NULL){
if(set.contains(head))
return true;
set.add(head)
head = head.next
}
return false;
}

Flattening a multilevel linked list

Question
Given a linked list where in addition to the next pointer, each node
has a child pointer, which may or may not point to a separate list.
Given the head of the first list flatten the list so that all the
nodes appear in a single-level linked list.
Goal.
We need to flatten the list in such a way that all nodes at first level
should come first, then
nodes of second level, and so on.
The above list should be converted to
10->5->12->7->11->4->20->13->17->6->2->16->9->8->3->19->15
My approach:
1) Create an empty queue
2) while(Queue is not empty AND head.next!=null AND head.child!=null)
2a) while(head!=null)
if(head.child!=null)
Enqueue(head.child)
newList = head;
head = head.next;
newList = newList.next;
2b)head = deQ();
Is this approach correct?
Here's a simple two-finger breadth-first (level-order) traverse which does an in-place flattening. (Efficiency freaks might want to rearrange the loops because some tests are done twice, but it hardly makes a difference.) The basic idea is that there is an implicit queue consisting of the nodes between finger2 and finger1. finger1 walks forward across the level and every time it reaches a node with no right sibling, the "queue" is advanced by walking finger2 to the right until it finds a child, which is then appended at finger1 so that finger1 can keep moving to the right.
finger1 = finger2 = head;
while finger2 is not Null:
while finger1.next is not Null: finger1 = finger1.next
while finger2 is not Null and finger2.child is Null: finger2 = finger2.next
if finger2 is not Null:
finger1.next = finger2.child
finger2.child = Null
Simple stack based solution which traverses till next ends, then attaches the children from stack.
node *flatten(node *head) {
stack<node *> s;
node *curr = root;
while (1) {
if (curr->next) { // keep moving in current streak
if (curr->child)
s.push(curr);
curr = curr->next;
}
else { // attach child branch and continue from there
if (s.empty())
return head;
curr->next = s.top()->next;
s.top()->next = NULL;
s.pop();
curr = curr->next;
}
}
}

Connect nodes at same level using constant extra space

Objective:To write a function to connect all the adjacent nodes at the same level in a binary tree. Structure of the given Binary Tree node is like following.
struct node{
int data;
struct node* left;
struct node* right;
struct node* nextRight;
}
Initially, all the nextRight pointers point to garbage values. Function should set these pointers to point next right for each node.
Solution:
void connectRecur(struct node* p);
struct node *getNextRight(struct node *p);
// Sets the nextRight of root and calls connectRecur() for other nodes
void connect (struct node *p)
{
// Set the nextRight for root
p->nextRight = NULL;
// Set the next right for rest of the nodes (other than root)
connectRecur(p);
}
/* Set next right of all descendents of p. This function makes sure that
nextRight of nodes ar level i is set before level i+1 nodes. */
void connectRecur(struct node* p)
{
// Base case
if (!p)
return;
/* Before setting nextRight of left and right children, set nextRight
of children of other nodes at same level (because we can access
children of other nodes using p's nextRight only) */
if (p->nextRight != NULL)
connectRecur(p->nextRight);
/* Set the nextRight pointer for p's left child */
if (p->left)
{
if (p->right)
{
p->left->nextRight = p->right;
p->right->nextRight = getNextRight(p);
}
else
p->left->nextRight = getNextRight(p);
/* Recursively call for next level nodes. Note that we call only
for left child. The call for left child will call for right child */
connectRecur(p->left);
}
/* If left child is NULL then first node of next level will either be
p->right or getNextRight(p) */
else if (p->right)
{
p->right->nextRight = getNextRight(p);
connectRecur(p->right);
}
else
connectRecur(getNextRight(p));
}
/* This function returns the leftmost child of nodes at the same level as p.
This function is used to getNExt right of p's right child
If right child of p is NULL then this can also be used for the left child */
struct node *getNextRight(struct node *p)
{
struct node *temp = p->nextRight;
/* Traverse nodes at p's level and find and return
the first node's first child */
while(temp != NULL)
{
if(temp->left != NULL)
return temp->left;
if(temp->right != NULL)
return temp->right;
temp = temp->nextRight;
}
// If all the nodes at p's level are leaf nodes then return NULL
return NULL;
}
What will be the time complexity of this solution?
It is O(n^2) because of the getNextRight.
Easiest to see is to consider you have a complete binary tree. The number of leafs is O(n/2) so O(n). You get to call getNextRight for each leaf.
The first getNextRight is going to be for the last leaf on the right. That takes no passes through the while loop.
Next, you call getNextRight for the next to last leaf on the right. That takes 1 pass through the while loop.
For the next leaf you get 2 passes through the while loop. And so on... you get O(1 + 2 + 3 + ... + n/2) which is O(n^2).
Also the space complexity is not really constant. It is O(log n) if the tree is balanced because of the recursion. You may have a log n sized stack. If the tree is not balanced it will be even worst.
What appears to me is that you are connecting the nodes level-wise starting from the root node.
At any level since the parents have already been connected, you simply reach out to the next branch through the parents. Hence you are accessing each node only once (or twice through a child) at most.
Hence to me, the order of time complexity seems to be O(n) where n is the total number of elements in the tree.
I provided an answer to a similar question here on stackoverflow, using level-order traversal. Space and time complexity is O(n)

Efficient algorithm to determine if an alleged binary tree contains a cycle?

One of my favorite interview questions is
In O(n) time and O(1) space, determine whether a linked list contains a cycle.
This can be done using Floyd's cycle-finding algorithm.
My question is whether it's possible to get such good time and space guarantees when trying to detect whether a binary tree contains a cycle. That is, if someone gives you a struct definition along the lines of
struct node {
node* left;
node* right;
};
How efficiently can you verify that the given structure is indeed a binary tree and not, say, a DAG or a graph containing a cycle?
Is there an algorithm that, given the root of a binary tree, can determine whether that tree contains a cycle in O(n) time and better than O(n) space? Clearly this could be done with a standard DFS or BFS, but this requires O(n) space. Can it be done in O(√n) space? O(log n) space? Or (the holy grail) in just O(1) space? I'm curious because in the case of a linked list this can be done in O(1) space, but I've never seen a correspondingly efficient algorithm for this case.
You can't even visit each node of a real, honest-to-god, cycle-free tree in O(1) space, so what you are asking for is clearly impossible. (Tricks with modifying a tree along the way are not O(1) space).
If you are willing to consider stack-based algorithms, then a regular tree walk can be easily modified along the lines of Floyd's algorithm.
it is possible to test in logarithmic space if two vertices of a graph belong to the same connected component (Reingold, Omer (2008), "Undirected connectivity in log-space", Journal of the ACM 55 (4): Article 17, 24 pages, doi:10.1145/1391289.1391291). A connected component is cyclic; hence if you can find two vertices in a graph that belong to the same connected component there is a cycle in the graph. Reingold published the algorithm 26 years after the question of its existence was first posed (see http://en.wikipedia.org/wiki/Connected_component_%28graph_theory%29). Having an O(1) space algorithm sounds unlikely given that it took 25 years to find a log-space solution. Note that picking two vertices from a graph and asking if they belong to a cycle is equivalent to asking if they belong to a connected component.
This algorithm can be extended to a log-space solution for graphs with out-degree 2 (OP: "trees"), as it is enough to check for every pair of a node and one of its immediate siblings if they belong to the same connect component, and these pairs can be enumerated in O(log n) space using standard recursive tree descent.
If you assume that the cycle points to a node at the same depth or smaller depth in the "tree", then you can do a BFS (iterative version) with two stacks, one for the turtle (x1) and one for the hare (x2 speed). At some point, the Hare's stack will be either empty (no cycle), or be a subset of the turtle's stack (a cycle was found). The time required is O(n k), and the space is O(lg n) where n is the number of used nodes, and k the time required to check the subset condition which can be upper bounded by lg(n). Note that the initial assumption about the cycle does not constraints the original problem, since it is assumed to be a tree but for a finite number of arcs that form a cycle with previous nodes; a link to a deeper node in the tree will not form a cycle but destroy the tree structure.
If it can be further assumed that the cycle points to an ancestor, then, the subset condition can be changed by checking that both stacks are equal, which is faster.
Visited Aware
You would need to redefine the structure as such (I am going to leave pointers out of this):
class node {
node left;
node right;
bool visited = false;
};
And use the following recursive algorithm (obviously re-working it to use a custom stack if your tree could grow big enough):
bool validate(node value)
{
if (value.visited)
return (value.visited = false);
value.visited = true;
if (value.left != null && !validate(value.left))
return (value.visited = false);
if (value.right != null && !validate(value.right))
return (value.visited = false);
value.visited = false;
return true;
}
Comments: It does technically have O(n) space; because of the extra field in the struct. The worst case for it would also be O(n+1) if all the values are on a single side of the tree and every value is in the cycle.
Depth Aware
When inserting into the tree you could keep track of the maximum depth:
struct node {
node left;
node right;
};
global int maximumDepth = 0;
void insert(node item) { insert(root, item, 1); }
void insert(node parent, node item, int depth)
{
if (depth > maximumDepth)
maximumDepth = depth;
// Do your insertion magic, ensuring to pass in depth + 1 to any other insert() calls.
}
bool validate(node value, int depth)
{
if (depth > maximumDepth)
return false;
if (value.left != null && !validate(value.left, depth + 1))
return false;
if (value.right != null && !validate(value.right, depth + 1))
return false;
return true;
}
Comments: The storage space is O(n+1) because we are storing the depth on the stack (as well as the maximum depth); the time is still O(n+1). This would do better on invalid trees.
Managed to get it right!
Runtime: O(n). I suspect it goes through an edge at most a constant number of times. No formal proof.
Space: O(1). Only stores a few nodes. Does not create new nodes or edges, only rearranges them.
Destructive: Yes. It flattens the tree, every node has the inorder successor as its right child, and null as the left.
The algorithm tries to flatten the binary tree by moving the whole left subtree of the current node to above it, making it the rightmost node of the subtree, then updating the current node to find further left subtrees in the newly discovered nodes. If we know both the left child and the predecessor of the current node, we can move the entire subtree in a few operations, in a similar manner to inserting a list into another. Such a move preserves the in-order sequence of the tree and it invariably makes the tree more right slanted.
There are three cases depending on the local configuration of nodes around the current one: left child is the same as the predecessor, left child is different from the predecessor, or no left subtree. The first case is trivial. The second case requires finding the predecessor, the third case requires finding a node on the right with a left subtree. Graphical representation helps in understanding them.
In the latter two cases we can run into cycles. Since we only traverse a list of the right childs, we can use Floyd's cycle detection algorithm to find and report loops. Sooner or later every cycle will be rotated into such a form.
#include <cstdio>
#include <iostream>
#include <queue>
#define null NULL
#define int32 int
using namespace std;
/**
* Binary tree node class
**/
template <class T>
class Node
{
public:
/* Public Attributes */
Node* left;
Node* right;
T value;
};
/**
* This exception is thrown when the flattener & cycle detector algorithm encounters a cycle
**/
class CycleException
{
public:
/* Public Constructors */
CycleException () {}
virtual ~CycleException () {}
};
/**
* Biny tree flattener and cycle detector class.
**/
template <class T>
class Flattener
{
public:
/* Public Constructors */
Flattener () :
root (null),
parent (null),
current (null),
top (null),
bottom (null),
turtle (null),
{}
virtual ~Flattener () {}
/* Public Methods */
/**
* This function flattens an alleged binary tree, throwing a new CycleException when encountering a cycle. Returns the root of the flattened tree.
**/
Node<T>* flatten (Node<T>* pRoot)
{
init(pRoot);
// Loop while there are left subtrees to process
while( findNodeWithLeftSubtree() ){
// We need to find the topmost and rightmost node of the subtree
findSubtree();
// Move the entire subtree above the current node
moveSubtree();
}
// There are no more left subtrees to process, we are finished, the tree does not contain cycles
return root;
}
protected:
/* Protected Methods */
void init (Node<T>* pRoot)
{
// Keep track of the root node so the tree is not lost
root = pRoot;
// Keep track of the parent of the current node since it is needed for insertions
parent = null;
// Keep track of the current node, obviously it is needed
current = root;
}
bool findNodeWithLeftSubtree ()
{
// Find a node with a left subtree using Floyd's cycle detection algorithm
turtle = parent;
while( current->left == null and current->right != null ){
if( current == turtle ){
throw new CycleException();
}
parent = current;
current = current->right;
if( current->right != null ){
parent = current;
current = current->right;
}
if( turtle != null ){
turtle = turtle->right;
}else{
turtle = root;
}
}
return current->left != null;
}
void findSubtree ()
{
// Find the topmost node
top = current->left;
// The topmost and rightmost nodes are the same
if( top->right == null ){
bottom = top;
return;
}
// The rightmost node is buried in the right subtree of topmost node. Find it using Floyd's cycle detection algorithm applied to right childs.
bottom = top->right;
turtle = top;
while( bottom->right != null ){
if( bottom == turtle ){
throw new CycleException();
}
bottom = bottom->right;
if( bottom->right != null ){
bottom = bottom->right;
}
turtle = turtle->right;
}
}
void moveSubtree ()
{
// Update root; if the current node is the root then the top is the new root
if( root == current ){
root = top;
}
// Add subtree below parent
if( parent != null ){
parent->right = top;
}
// Add current below subtree
bottom->right = current;
// Remove subtree from current
current->left = null;
// Update current; step up to process the top
current = top;
}
Node<T>* root;
Node<T>* parent;
Node<T>* current;
Node<T>* top;
Node<T>* bottom;
Node<T>* turtle;
private:
Flattener (Flattener&);
Flattener& operator = (Flattener&);
};
template <class T>
void traverseFlat (Node<T>* current)
{
while( current != null ){
cout << dec << current->value << " # 0x" << hex << reinterpret_cast<int32>(current) << endl;
current = current->right;
}
}
template <class T>
Node<T>* makeCompleteBinaryTree (int32 maxNodes)
{
Node<T>* root = new Node<T>();
queue<Node<T>*> q;
q.push(root);
int32 nodes = 1;
while( nodes < maxNodes ){
Node<T>* node = q.front();
q.pop();
node->left = new Node<T>();
q.push(node->left);
nodes++;
if( nodes < maxNodes ){
node->right = new Node<T>();
q.push(node->right);
nodes++;
}
}
return root;
}
template <class T>
void inorderLabel (Node<T>* root)
{
int32 label = 0;
inorderLabel(root, label);
}
template <class T>
void inorderLabel (Node<T>* root, int32& label)
{
if( root == null ){
return;
}
inorderLabel(root->left, label);
root->value = label++;
inorderLabel(root->right, label);
}
int32 main (int32 argc, char* argv[])
{
if(argc||argv){}
typedef Node<int32> Node;
// Make binary tree and label it in-order
Node* root = makeCompleteBinaryTree<int32>(1 << 24);
inorderLabel(root);
// Try to flatten it
try{
Flattener<int32> F;
root = F.flatten(root);
}catch(CycleException*){
cout << "Oh noes, cycle detected!" << endl;
return 0;
}
// Traverse its flattened form
// traverseFlat(root);
}
As said by Karl by definition a "Tree" is free of cycles. But still i get the spirit in which the question is asked. Why do you need fancy algorithms for detecting cycle in any graph. You can simply run a BFS or DFS and if you visit a node which is visited already it implies a cycle. This will run in O(n) time but the space complexity is also O(n), dont know if this can be reduced.
As mentioned by ChingPing, a simple DFS should do the trick. You would need to mark each node as visited(need to do some mapping from Reference of Node to Integer) and if an reentry is attempted on an already visited Node, that means there is a cycle.
This is O(n) in memory though.
At first glance you can see that this problem would be solved by a non-deterministic application of Floyd's algorithm. So what happens if we apply Floyd's in a split-and-branch way?
Well we can use Floyd's from the base node, and then add an additional Floyd's at each branch.
So for each terminal path we have an instance of Floyd's algorithm which ends there. And if a cycle ever arises, there is a turtle which MUST have a corresponding hare chasing it.
So the algorithm finishes. (and as a side effect, each terminal node is only reached by one hare/turtle pair so there are O(n) visits and thus O(n) time. (store the nodes which have been branched from, this doesn't increase the order of magnitude of memory and prevents memory blowouts in the case of cycles)
Furthermore, doing this ensures the memory footprint is the same as the number of terminal nodes. The number of terminal nodes is O(log n) but O(n) in worst case.
TL;DR: apply Floyd's and branch at each time you have a choice to make:
time: O(n)
space: O(log n)
I don't believe there exists an algorithm for walking a tree with less than O(N) space. And, for a (purported) binary tree, it takes no more space/time (in "order" terms) to detect cycles than it does to walk the tree. I believe that DFS will walk a tree in O(N) time, so probably O(N) is the limit in both measures.
Okay after further thought I believe I found a way, provided you
know the number of nodes in advance
can make modifications to the binary tree
The basic idea is to traverse the tree with Morris inorder tree traversal, and count the number of visited nodes, both in the visiting phase and individual predecessor finding phases. If any of these exceeds the number of nodes, you definitely have a cycle. If you don't have a cycle, then it is equivalent to the plain Morris traversal, and your binary tree will be restored.
I'm not sure if it is possible without knowing the number of nodes in advance though. Will think about it more.

How to determine if a linked list has a cycle using only two memory locations

Does anyone know of an algorithm to find if a linked list loops on itself using only two variables to traverse the list. Say you have a linked list of objects, it doesn't matter what type of object. I have a pointer to the head of the linked list in one variable and I am only given one other variable to traverse the list with.
So my plan is to compare pointer values to see if any pointers are the same. The list is of finite size but may be huge. I can set both variable to the head and then traverse the list with the other variable, always checking if it is equal to the other variable, but, if I do hit a loop I will never get out of it. I'm thinking it has to do with different rates of traversing the list and comparing pointer values. Any thoughts?
I would suggest using Floyd's Cycle-Finding Algorithm aka The Tortoise and the Hare Algorithm. It has O(n) complexity and I think it fits your requirements.
Example code:
function boolean hasLoop(Node startNode){
Node slowNode = Node fastNode1 = Node fastNode2 = startNode;
while (slowNode && fastNode1 = fastNode2.next() && fastNode2 = fastNode1.next()){
if (slowNode == fastNode1 || slowNode == fastNode2) return true;
slowNode = slowNode.next();
}
return false;
}
More info on Wikipedia: Floyd's cycle-finding algorithm.
You can use the Turtle and Rabbit algorithm.
Wikipedia has an explanation too, and they call it "Floyd's cycle-finding algorithm" or "Tortoise and hare"
Absolutely. One solution indeed can be traversing the list with both pointers, one travelling at twice the rate of the other.
Start with the 'slow' and the 'fast' pointer pointing to any location in the list. Run the traversal loop. If the 'fast' pointer at any time comes to coincide with the slow pointer, you have a circular linked list.
int *head = list.GetHead();
if (head != null) {
int *fastPtr = head;
int *slowPtr = head;
bool isCircular = true;
do
{
if (fastPtr->Next == null || fastPtr->Next->Next == null) //List end found
{
isCircular = false;
break;
}
fastPtr = fastPtr->Next->Next;
slowPtr = slowPtr->Next;
} while (fastPtr != slowPtr);
//Do whatever you want with the 'isCircular' flag here
}
I tried to solve this myself and found a different (less efficient but still optimal) solution.
The idea is based on reversing a singly linked list in linear time. This can be done by doing two swaps at each step in iterating over the list. If q is the previous element (initially null) and p is the current, then swap(q,p->next) swap(p,q) will reverse the link and advance the two pointers at the same time. The swaps can be done using XOR to prevent having to use a third memory location.
If the list has a cycle then at one point during the iteration you will arrive at a node whose pointer has already been changed. You cannot know which node that is, but by continuing the iteration, swapping some elements twice, you arrive at the head of the list again.
By reversing the list twice, the list remains unchanged in result and you can tell if it had a cycle based on whether you arrived at the original head of the list or not.
int isListCircular(ListNode* head){
if(head==NULL)
return 0;
ListNode *fast=head, *slow=head;
while(fast && fast->next){
if(fast->next->next==slow)
return 1;
fast=fast->next->next;
slow=slow->next;
}
return 0;
}
boolean findCircular(Node *head)
{
Node *slower, * faster;
slower = head;
faster = head->next;
while(true) {
if ( !faster || !faster->next)
return false;
else if (faster == slower || faster->next == slower)
return true;
else
faster = faster->next->next;
}
}
Taking this problem to a next step will be identifying the cycle (that is, not just that the cycle exists, but where exactly it is in the list).
Tortoise and Hare algorithm can be used for the same, however, we will require to keep track of the head of the list at all times. An illustration of this algorithm can be found here.

Resources