Print binary tree nodes - c++

I'm programming a BinaryTree project. I finished all (insert, delete, create, find) but one function, the printing operation. I'm supposed to print it like this:
5
46
X557
XXX6XXX9
Basically print all the nodes, but print an X if the node is empty. I've been trying to figure out how to do this and I keep hitting a dead end. Would this be something like inorder-traversal?? Thank you

Use a Level-Order traversal (Breadth First Search) printing each node as you go through a level, with a newline at the end of each level.
You can find BFS pseudo-code here

You can use BFS but with a slight modification:
In simple BFS, after visiting a node you add its children to the queue. If no children,
nothing is added.
For your problem, if there are no children for a node that is visited, add a special node to the queue with its value as "x" so that it will print the "X" in your output correspondingly. Print a newline after each level.

As Dream Lane said, BFS would work here. I offered my own JAVA implementation here for your reference.
public static void printBST(Node root) {
// empty tree
if (root == null)
return;
Queue<Node> que = new LinkedList<Node>();
que.add(root);
boolean allChildNull = false;// end condition
while (que.size() > 0 && !allChildNull) {
allChildNull = true;
Queue<Node> childQue = new LinkedList<Node>();
for (Node n : que) {
// print out noe value, X for null
if (n == null)
System.out.printf("%1$s", "X");
else
System.out.printf("%1$s", n.value);
// add next level child nodes
if (n == null) {
childQue.add(null);
childQue.add(null);
} else {
childQue.add(n.left);
childQue.add(n.right);
if (n.left != null || n.right != null)
allChildNull = false;
}
}
System.out.printf("\n");// newline
que = childQue;
}
}

Related

segmentation fault while finding merge node?

I'm working on this find merge node method on hackerrank. My approach is: while both of the nodes are not null, I want to move one of the list to their next node, that's what flag variable is for. But somehow it's giving me segmentation fault? Did I accidentally access a null variable? Someone please enlighten me. Below is my method code.
Constraint: Both lists will converge and both lists are non-NULL
int FindMergeNode(Node *headA, Node *headB)
{
// Complete this function
// Do not write the main method.
bool flag = true;
while(headA != headB){
if(flag) headA=headA->next;
else headB=headB->next;
flag = !flag;
}
return headA->data; //or headB->data;
}
You make two assumptions:
1. There exists such node.
2. The distance of this node from the beginning of each list differs by at most 1 between the two lists. You alternately move forward in one list and then check to see if you got to the same node (by address). so if list1 has no nodes before the one you are looking for, and list2 has 2 nodes before it, you won't find a match.
If I understand your question correctly, the truth is that the distance from the end of the list is the same (because their tails are the same).
Why to use flag directly use the condition to check if it is the last node
if(headA->next ==NULL)
headA=headA->next;
else if (headB->next== NULL )
headB=headB->next;
Complete solution would be something
int FindMergeNode(Node *headA, Node *headB) {
Node *currentA = headA;
Node *currentB = headB;
//Do till the two nodes are the same
while(currentA != currentB){
//If you reached the end of one list start at the beginning of the other one
//currentA
if(currentA->next == NULL){
currentA = headB;
}else{
currentA = currentA->next;
}
//currentB
if(currentB->next == NULL){
currentB = headA;
}else{
currentB = currentB->next;
}
}
return currentB->data;
}

AVLTree implementation (C++): Can I describe a deletion() as a case of insertion(), to re-use code?

Bear with me on this one because I think it's moderately hard to explain:
I have built the following AVLTree::Insert() proc, as per R.Coleman's implementation:
void AVLTree::Insert(AVLTreeNode *newNode) ///MARKER: ####### REMINDER ######
{ ///This implementation REQUIRES that newNode has its #left, #right and #parent pointers set to NULL *BEFORE* sending him here, as a parameter
AVLTreeNode *temp, *prev, *ancestor;
temp = root; //Our temp starts at the root, and keeps heading down the tree until it "falls out".
prev = NULL; //#prev will "follow" #temp, one step behind it. It will, in the end, mark the point where we'll add newNode at.
ancestor = NULL; //Ancestor marks the position of the closest #ancestor that will drop out of balance after we insert newNode.
if(root == NULL ) //Check if the tree is empty before you do anything else.
{
root = newNode;
return;
}
//Looks like it isn't empty. Let's start the main loop.
while(temp != NULL)
{
prev = temp;
if(temp->balanceFactor != '=') //We found a node that is unbalanced, it'll drop out of balance completelly when we add the new node.
{ //Let's have the #ancestor variable point at it so we can restore the AVL property from the bottom to this node.
ancestor = temp;
}
if(newNode->value < temp->value) //These two ifs will throw #temp out of the tree at the end of the loop
{ //while #prev will be pointing at the node below which we'll be adding newNode
temp = temp->left;
}
else
{
temp = temp->right;
}
}
///The loop finished, #temp is now null. Time to insert newNode.
newNode->parent = prev;
if(newNode->value < prev->value) //If it's smaller than #prev, place it on its left, else do it at #prev's right.
{
prev->left = newNode;
}
else
{
prev->right = newNode;
}
///Now to restore the AVL property of the tree, starting from the inserted node up towards #ancestor, the last known unbalanced node that has now completely fallen out of balance.
restoreAVL(ancestor,newNode);
}
Notice that in the end, I call RestoreAVL that takes as parameters the newNode and ancestor (the last node back up the tree that needs adjust because he has fallen out of balance - it gets pointed to a node during the while(temp!=null) loop.)
This is AVLTree::restoreAVL(): If you bother reading it all, it takes in account every case that can happen by inserting a new node to an an AVLTree and takes care to restore the AVL property, if needed, with rotations and re-set the balance factors (L, R or =)
void AVLTree::restoreAVL(AVLTreeNode *ancestor, AVLTreeNode *newNode)
{ ///This process restores the AVL property in the tree, from the bottom
//-------------------------------------------------------
// Case 1: ancestor is NULL, that means the balanceFactor of all ancestors is '='
//-------------------------------------------------------
if(ancestor == NULL)
{
if(newNode->value < root->value)
{
root->balanceFactor = 'L'; //newNode was inserted at the left of our root
} //during our previous Insert
else
{
root->balanceFactor = 'R'; //Here it's on our right
}
///Adjust the balanceFactor for all nodes from newNode back up to root
adjustBalanceFactors(root, newNode);
}
//-------------------------------------------------------
// Case 2: Insertion in opposite subtree of ancestor's balance factor, i.e.
// ancestor.balanceFactor == 'L' AND Insertion made in ancestor's RIGHT subtree
// OR
// ancestor.balanceFactor == 'R' AND Insertion made in ancestor's LEFT subtree
// (In short, the insertion "neutralises" the balance of ancestor.)
//-------------------------------------------------------
else if( ( (ancestor->balanceFactor == 'L') && (newNode->value > ancestor->value) )
||
( (ancestor->balanceFactor == 'R') && (newNode->value < ancestor->value) )
)
{
ancestor->balanceFactor = '='; //Ancestor's balance factor is now neutralised.
///Adjust the balanceFactor for all nodes up to the ancestor,
///not up to the root like we did in Case 1.
adjustBalanceFactors(ancestor,newNode);
}
//-------------------------------------------------------
// Case 3: #ancestor's balance is 'R' and the new node was inserted in the right subtree of #ancestor's right child.
// As expected, the balance is now broken and we need to rotate left, once.
//-------------------------------------------------------
else if( (ancestor->balanceFactor == 'R') && (newNode->value > ancestor->right->value) )
{
ancestor->balanceFactor = '='; //We reset #ancestor's balance, it will be adjusted by #adjustBalanceFactors()
rotateLeft(ancestor); //Single left rotation with ancestor as the pivot.
///Let's adjust the balanceFactor for all nodes up to #ancestor's PARENT.
adjustBalanceFactors(ancestor->parent, newNode);
}
//-------------------------------------------------------
// Case 4: #ancestor's balance is 'L' and the node inserted is in the left subtree of #ancestor's left child.
// Here we have to rotate right, once. (Mirror case of Case 3 - See above)
//-------------------------------------------------------
else if( (ancestor->balanceFactor == 'L') && (newNode->value < ancestor->left->value) )
{
ancestor->balanceFactor = '='; //As before, #ancestor's balance needs to be reset.
rotateRight(ancestor);
///Again, we adjust the balanceFactor for all nodes up to #ancestor's PARENT.
adjustBalanceFactors(ancestor->parent, newNode);
}
//-------------------------------------------------------
// Case 5: #ancestor's balance factor is "L" and the new node is inserted
// in the RIGHT subtree of ancestor's LEFT child
//-------------------------------------------------------
else if( (ancestor->balanceFactor == 'L') && (newNode->value > ancestor->left->value) )
{
rotateLeft(ancestor->left);
rotateRight(ancestor);
adjustLeftRight(ancestor,newNode);
}
//-------------------------------------------------------
// Case 6 (final case): #ancestor's balance factor is "R" and the new node is inserted
// in the LEFT subtree of ancestor's RIGHT child
//-------------------------------------------------------
else
{
rotateRight(ancestor->right);
rotateLeft(ancestor);
adjustRightLeft(ancestor,newNode);
}
}
So my question is: I want to implement AVLTree::Delete(AVLTreenode *n). Instead of busting my head thinking of every possible outcome if you delete a node in an AVLTree, can I reduce a Deletion() into an Insertion() case and call RestoreAVL() with some node set as newNode and one set as ancestor? Can I recycle restoreAVL()?
Some examples:
The result is the same if I think that, after ignoring 00, 20 is inserted in the subtree.
But let's add node 70 on the left tree, and try reducing the Deletion() into an Insertation.
I can't think of any algorithmic way of reducing this situation into an Insertation(), so I know who can act as newNode and who can be the ancestor, and call restoreAVL().
Is what I'm saying feasible? Is there a failsafe way of reducing the problem and thus reducing the code I have to rewrite?
If you can code insertion operator, you will be possible to code deletion. Because deletion is simplier than insertion. It is really true because you don't need to rebalance in deletion operator. Complexity is still O(log N) for each query.
My code is not too efficient but it is short enough to code.
void doDelete(node* a){
if (a==0) return ;
if (a->ll==0) {
if (a->pp==0 || a->pp->ll==a)
lljoin(a->rr, a->pp);
else rrjoin(a->rr, a->pp);
delete a;
}
else if (a->rr==0){
if (a->pp==0 || a->pp->ll==a)
lljoin(a->ll, a->pp);
else rrjoin(a->ll, a->pp);
delete a;
}
else {
node *b = rightMost(a->ll);
swap(b->value, a->value);
doDelete(b);
}
}
Obviously you can find some common actions for deletion and insertion (for example searching), but I think that's not worth trying. There are still a lot uncommon between this algorithms. You definetely will reuse restoreAVL for AVL property recovery.
As I understand, the problem in your examples is that when you delete node from one subtree, you want to balance another subtree of the last balanced node on the path to the deleted node from root (where balanced node is node with balancedFactor='='). To me It has no sense, because it is not correct on the first place and much trickier to code.

Explain Morris inorder tree traversal without using stacks or recursion

Can someone please help me understand the following Morris inorder tree traversal algorithm without using stacks or recursion ? I was trying to understand how it works, but its just escaping me.
1. Initialize current as root
2. While current is not NULL
If current does not have left child
a. Print current’s data
b. Go to the right, i.e., current = current->right
Else
a. In current's left subtree, make current the right child of the rightmost node
b. Go to this left child, i.e., current = current->left
I understand the tree is modified in a way that the current node, is made the right child of the max node in right subtree and use this property for inorder traversal. But beyond that, I'm lost.
EDIT:
Found this accompanying c++ code. I was having a hard time to understand how the tree is restored after it is modified. The magic lies in else clause, which is hit once the right leaf is modified. See code for details:
/* Function to traverse binary tree without recursion and
without stack */
void MorrisTraversal(struct tNode *root)
{
struct tNode *current,*pre;
if(root == NULL)
return;
current = root;
while(current != NULL)
{
if(current->left == NULL)
{
printf(" %d ", current->data);
current = current->right;
}
else
{
/* Find the inorder predecessor of current */
pre = current->left;
while(pre->right != NULL && pre->right != current)
pre = pre->right;
/* Make current as right child of its inorder predecessor */
if(pre->right == NULL)
{
pre->right = current;
current = current->left;
}
// MAGIC OF RESTORING the Tree happens here:
/* Revert the changes made in if part to restore the original
tree i.e., fix the right child of predecssor */
else
{
pre->right = NULL;
printf(" %d ",current->data);
current = current->right;
} /* End of if condition pre->right == NULL */
} /* End of if condition current->left == NULL*/
} /* End of while */
}
If I am reading the algorithm right, this should be an example of how it works:
X
/ \
Y Z
/ \ / \
A B C D
First, X is the root, so it is initialized as current. X has a left child, so X is made the rightmost right child of X's left subtree -- the immediate predecessor to X in an inorder traversal. So X is made the right child of B, then current is set to Y. The tree now looks like this:
Y
/ \
A B
\
X
/ \
(Y) Z
/ \
C D
(Y) above refers to Y and all of its children, which are omitted for recursion issues. The important part is listed anyway.
Now that the tree has a link back to X, the traversal continues...
A
\
Y
/ \
(A) B
\
X
/ \
(Y) Z
/ \
C D
Then A is outputted, because it has no left child, and current is returned to Y, which was made A's right child in the previous iteration. On the next iteration, Y has both children. However, the dual-condition of the loop makes it stop when it reaches itself, which is an indication that it's left subtree has already been traversed. So, it prints itself, and continues with its right subtree, which is B.
B prints itself, and then current becomes X, which goes through the same checking process as Y did, also realizing that its left subtree has been traversed, continuing with the Z. The rest of the tree follows the same pattern.
No recursion is necessary, because instead of relying on backtracking through a stack, a link back to the root of the (sub)tree is moved to the point at which it would be accessed in a recursive inorder tree traversal algorithm anyway -- after its left subtree has finished.
The recursive in-order traversal is : (in-order(left)->key->in-order(right)). (this is similar to DFS)
When we do the DFS, we need to know where to backtrack to (that's why we normally keep a stack).
As we go through a parent node to which we will need to backtrack to -> we find the node which we will need to backtrack from and update its link to the parent node.
When we backtrack? When we cannot go further. When we cannot go further? When no left child's present.
Where we backtrack to? Notice: to SUCCESSOR!
So, as we follow nodes along left-child path, set the predecessor at each step to point to the current node. This way, the predecessors will have links to successors (a link for backtracking).
We follow left while we can until we need to backtrack. When we need to backtrack, we print the current node and follow the right link to the successor.
If we have just backtracked -> we need to follow the right child (we are done with left child).
How to tell whether we have just backtracked? Get the predecessor of the current node and check if it has a right link (to this node). If it has - than we followed it. remove the link to restore the tree.
If there was no left link => we did not backtrack and should proceed following left children.
Here's my Java code (Sorry, it is not C++)
public static <T> List<T> traverse(Node<T> bstRoot) {
Node<T> current = bstRoot;
List<T> result = new ArrayList<>();
Node<T> prev = null;
while (current != null) {
// 1. we backtracked here. follow the right link as we are done with left sub-tree (we do left, then right)
if (weBacktrackedTo(current)) {
assert prev != null;
// 1.1 clean the backtracking link we created before
prev.right = null;
// 1.2 output this node's key (we backtrack from left -> we are finished with left sub-tree. we need to print this node and go to right sub-tree: inOrder(left)->key->inOrder(right)
result.add(current.key);
// 1.15 move to the right sub-tree (as we are done with left sub-tree).
prev = current;
current = current.right;
}
// 2. we are still tracking -> going deep in the left
else {
// 15. reached sink (the leftmost element in current subtree) and need to backtrack
if (needToBacktrack(current)) {
// 15.1 return the leftmost element as it's the current min
result.add(current.key);
// 15.2 backtrack:
prev = current;
current = current.right;
}
// 4. can go deeper -> go as deep as we can (this is like dfs!)
else {
// 4.1 set backtracking link for future use (this is one of parents)
setBacktrackLinkTo(current);
// 4.2 go deeper
prev = current;
current = current.left;
}
}
}
return result;
}
private static <T> void setBacktrackLinkTo(Node<T> current) {
Node<T> predecessor = getPredecessor(current);
if (predecessor == null) return;
predecessor.right = current;
}
private static boolean needToBacktrack(Node current) {
return current.left == null;
}
private static <T> boolean weBacktrackedTo(Node<T> current) {
Node<T> predecessor = getPredecessor(current);
if (predecessor == null) return false;
return predecessor.right == current;
}
private static <T> Node<T> getPredecessor(Node<T> current) {
// predecessor of current is the rightmost element in left sub-tree
Node<T> result = current.left;
if (result == null) return null;
while(result.right != null
// this check is for the case when we have already found the predecessor and set the successor of it to point to current (through right link)
&& result.right != current) {
result = result.right;
}
return result;
}
I've made an animation for the algorithm here:
https://docs.google.com/presentation/d/11GWAeUN0ckP7yjHrQkIB0WT9ZUhDBSa-WR0VsPU38fg/edit?usp=sharing
This should hopefully help to understand. The blue circle is the cursor and each slide is an iteration of the outer while loop.
Here's code for morris traversal (I copied and modified it from geeks for geeks):
def MorrisTraversal(root):
# Set cursor to root of binary tree
cursor = root
while cursor is not None:
if cursor.left is None:
print(cursor.value)
cursor = cursor.right
else:
# Find the inorder predecessor of cursor
pre = cursor.left
while True:
if pre.right is None:
pre.right = cursor
cursor = cursor.left
break
if pre.right is cursor:
pre.right = None
cursor = cursor.right
break
pre = pre.right
#And now for some tests. Try "pip3 install binarytree" to get the needed package which will visually display random binary trees
import binarytree as b
for _ in range(10):
print()
print("Example #",_)
tree=b.tree()
print(tree)
MorrisTraversal(tree)
I found a very good pictorial explanation of Morris Traversal.
public static void morrisInOrder(Node root) {
Node cur = root;
Node pre;
while (cur!=null){
if (cur.left==null){
System.out.println(cur.value);
cur = cur.right; // move to next right node
}
else { // has a left subtree
pre = cur.left;
while (pre.right!=null){ // find rightmost
pre = pre.right;
}
pre.right = cur; // put cur after the pre node
Node temp = cur; // store cur node
cur = cur.left; // move cur to the top of the new tree
temp.left = null; // original cur left be null, avoid infinite loops
}
}
}
I think this code would be better to understand, just use a null to avoid infinite loops, don't have to use magic else. It can be easily modified to preorder.
I hope the pseudo-code below is more revealing:
node = root
while node != null
if node.left == null
visit the node
node = node.right
else
let pred_node be the inorder predecessor of node
if pred_node.right == null /* create threading in the binary tree */
pred_node.right = node
node = node.left
else /* remove threading from the binary tree */
pred_node.right = null
visit the node
node = node.right
Referring to the C++ code in the question, the inner while loop finds the in-order predecessor of the current node. In a standard binary tree, the right child of the predecessor must be null, while in the threaded version the right child must point to the current node. If the right child is null, it is set to the current node, effectively creating the threading, which is used as a returning point that would otherwise have to be on stored, usually on a stack. If the right child is not null, then the algorithm makes sure that the original tree is restored, and then continues traversal in the right subtree (in this case it is known that the left subtree was visited).
Python Solution
Time Complexity : O(n)
Space Complexity : O(1)
Excellent Morris Inorder Traversal Explanation
class Solution(object):
def inorderTraversal(self, current):
soln = []
while(current is not None): #This Means we have reached Right Most Node i.e end of LDR traversal
if(current.left is not None): #If Left Exists traverse Left First
pre = current.left #Goal is to find the node which will be just before the current node i.e predecessor of current node, let's say current is D in LDR goal is to find L here
while(pre.right is not None and pre.right != current ): #Find predecesor here
pre = pre.right
if(pre.right is None): #In this case predecessor is found , now link this predecessor to current so that there is a path and current is not lost
pre.right = current
current = current.left
else: #This means we have traverse all nodes left to current so in LDR traversal of L is done
soln.append(current.val)
pre.right = None #Remove the link tree restored to original here
current = current.right
else: #In LDR LD traversal is done move to R
soln.append(current.val)
current = current.right
return soln
PFB Explanation of Morris In-order Traversal.
public class TreeNode
{
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val = 0, TreeNode left = null, TreeNode right = null)
{
this.val = val;
this.left = left;
this.right = right;
}
}
class MorrisTraversal
{
public static IList<int> InOrderTraversal(TreeNode root)
{
IList<int> list = new List<int>();
var current = root;
while (current != null)
{
//When there exist no left subtree
if (current.left == null)
{
list.Add(current.val);
current = current.right;
}
else
{
//Get Inorder Predecessor
//In Order Predecessor is the node which will be printed before
//the current node when the tree is printed in inorder.
//Example:- {1,2,3,4} is inorder of the tree so inorder predecessor of 2 is node having value 1
var inOrderPredecessorNode = GetInorderPredecessor(current);
//If the current Predeccessor right is the current node it means is already printed.
//So we need to break the thread.
if (inOrderPredecessorNode.right != current)
{
inOrderPredecessorNode.right = null;
list.Add(current.val);
current = current.right;
}//Creating thread of the current node with in order predecessor.
else
{
inOrderPredecessorNode.right = current;
current = current.left;
}
}
}
return list;
}
private static TreeNode GetInorderPredecessor(TreeNode current)
{
var inOrderPredecessorNode = current.left;
//Finding Extreme right node of the left subtree
//inOrderPredecessorNode.right != current check is added to detect loop
while (inOrderPredecessorNode.right != null && inOrderPredecessorNode.right != current)
{
inOrderPredecessorNode = inOrderPredecessorNode.right;
}
return inOrderPredecessorNode;
}
}

How to check whether a linked list is circular or not? [duplicate]

This question already has answers here:
How to detect a loop in a linked list?
(29 answers)
Closed 5 years ago.
How can I find whether a singly linked list is circular/cyclic or not? I tried to search but couldn't find a satisfactory solution. If possible, can you provide a pseudo-code or Java-implementation?
For instance:
1 → 3 → 5 → 71 → 45 → 7 → 5, where the second 5 is actually the third element of the list.
The standard answer is to take two iterators at the beginning, increment the first one once, and the second one twice. Check to see if they point to the same object. Then repeat until the one that is incrementing twice either hits the first one or reaches the end.
This algorithm finds any circular link in the list, not just that it's a complete circle.
Pseudo-code (not Java, untested -- off the top of my head)
bool hasCircle(List l)
{
Iterator i = l.begin(), j = l.begin();
while (true) {
// increment the iterators, if either is at the end, you're done, no circle
if (i.hasNext()) i = i.next(); else return false;
// second iterator is travelling twice as fast as first
if (j.hasNext()) j = j.next(); else return false;
if (j.hasNext()) j = j.next(); else return false;
// this should be whatever test shows that the two
// iterators are pointing at the same place
if (i.getObject() == j.getObject()) {
return true;
}
}
}
A simple algorithm called Floyd's algorithm is to have two pointers, a and b, which both start at the first element in the linked list. Then at each step you increment a once and b twice. Repeat until you either reach the end of the list (no loop), or a == b (the linked list contains a loop).
Another algorithm is Brent's algorithm.
Three main strategies that I know of:
Starting traversing the list and keep track of all the nodes you've visited (store their addresses in a map for instance). Each new node you visit, check if you've already visited it. If you've already visited the node, then there's obviously a loop. If there's not a loop, you'll reach the end eventually. This isn't great because it's O(N) space complexity for storing the extra information.
The Tortoise/Hare solution. Start two pointers at the front of the list. The first pointer, the "Tortoise" moves forward one node each iteration. The other pointer, the "Hare" moves forward two nodes each iteration. If there's no loop, the hare and tortoise will both reach the end of the list. If there is a loop, the Hare will pass the Tortoise at some point and when that happens, you know there's a loop. This is O(1) space complexity and a pretty simple algorithm.
Use the algorithm to reverse a linked list. If the list has a loop, you'll end up back at the beginning of the list while trying to reverse it. If it doesn't have a loop, you'll finish reversing it and hit the end. This is O(1) space complexity, but a slightly uglier algorithm.
I you count your Nodes and get to the *head again.
How about following approach:
Sort the link list in ascending order by following any standard algorithms.
Before sort: 4-2-6-1-5
After Sort: 1-2-4-5-6
Once sorted, check for each node data and compare with link node's data, something like this:
if(currentcode->data > currentnode->link->data)
i.e. circular = true;
At any comparison, if any of "currentnode->data" is greater than "currentcode->link->data" for a sorted link list, it means current node is pointed to some previous node(i.e circular);
Guys, i dont have setup to test the code.Let me now if this concept works.
Use the Tortoise-Hare algorithm.
A algorithm is:
Store the pointer to the first node
Traverse through the list comparing each node pointer to this pointer
If you encounter a NULL pointer, then its not circularly linked list
If you encounter the first node while traversing then its a circularly linked list
#samoz has in my point of view the answer! Pseudo code missing. Would be something like
yourlist is your linked list
allnodes = hashmap
while yourlist.hasNext()
node = yourlist.next()
if(allnodes.contains(node))
syso "loop found"
break;
hashmap.add(node)
sorry, code is very pseudo (do more scripting then java lately)
Start at one node and record it, then iterate through the entire list until you reach a null pointer or the node you started with.
Something like:
Node start = list->head;
Node temp = start->next;
bool circular = false;
while(temp != null && temp != start)
{
if(temp == start)
{
circular = true;
break;
}
temp = temp->next;
}
return circular
This is O(n), which is pretty much the best that you will able to get with a singly linked list (correct me if I'm wrong).
Or to find any cycles in the list (such as the middle), you could do:
Node[] array; // Use a vector or ArrayList to support dynamic insertions
Node temp = list->head;
bool circular = false;
while(temp != null)
{
if(array.contains(temp) == true)
{
circular = true;
break;
}
array.insert(temp);
temp = temp->next;
}
return circular
This will be a little bit slower due to the insertion times of dynamic arrays.
Here is a nice site on which the different solutions can copied.
find loop singly linked list
This is the winner on that site
// Best solution
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;
}
This solution is "Floyd's
Cycle-Finding Algorithm" as published
in "Non-deterministic Algorithms" by
Robert W. Floyd in 1967. It is also
called "The Tortoise and the Hare
Algorithm".
It will never terminate from the loop, it can also be done in following solution:
bool hasCircle(List l)
{
Iterator i = l.begin(), j = l.begin();
while (true) {
// increment the iterators, if either is at the end, you're done, no circle
if (i.hasNext()) i = i.next(); else return false;
// second iterator is travelling twice as fast as first
if (j.hasNext()) j = j.next(); else return false;
if (j.hasNext()) j = j.next(); else return false;
// this should be whatever test shows that the two
// iterators are pointing at the same place
if (i.getObject() == j.getObject()) {
return true;
}
if(i.next()==j)
break;
}
}
Try this
/* Link list Node */
struct Node
{
int data;
struct Node* next;
};
/* This function returns true if given linked
list is circular, else false. */
bool isCircular(struct Node *head)
{
// An empty linked list is circular
if (head == NULL)
return true;
// Next of head
struct Node *node = head->next;
// This loop would stope in both cases (1) If
// Circular (2) Not circular
while (node != NULL && node != head)
node = node->next;
// If loop stopped because of circular
// condition
return (node == head);
}

Binary Search Tree node removal

I've been trying to implement a delete function for a Binary Search Tree but haven't been able to get it to work in all cases.
This is my latest attempt:
Node* RBT::BST_remove(int c)
{
Node* t = get_node(c);
Node* temp = t;
if(t->get_left() == empty)
*t = *t->get_left();
else if(t->get_right() == empty)
*t = *t->get_right();
else if((t->get_left() != empty) && (t->get_right() != empty))
{
Node* node = new Node(t->get_data(), t->get_parent(), t->get_colour(), t->get_left(), t->get_right());
*t = *node;
}
return temp;
}
Node* RBT::get_node(int c)
{
Node* pos = root;
while(pos != empty)
{
if(c < pos->get_data())
pos = pos->get_left();
else if(c == pos->get_data())
return pos;
else
pos = pos->get_right();
}
return NULL;
}
t is a node and empty is just a node with nothing in it.
I'm just trying to swap the values but I'm getting a runtime error. Any ideas?
edit: I'm returning temp to delete it afterwards.
Thanks
First, your last else if conditional clause is redundant. Swap it with an else clause.
Secondly, I think it would make things easier for you if you'd take as parameter a pointer to the node to remove. You can write a find() function which would find a node given its key. I'm assuming of course that you can change the function signature. If you can take as parameter the node to remove you can focus on removing the node rather than add logic for finding the node. Otherwise, still write that find() function and use that for getting the pointer to the relevant node.
When you remove a node in a binary search tree you must maintain the ordering so the tree doesn't lose its integrity. Recall that there is a specific ordering in the tree that supports the fast retrieval of elements. So, enumerate the possible cases:
The node to delete has no children. That's easy: just release its resources and you're done.
The node has a single child node. That's fairly simple too. Release the node and replace it with its child, so the child holds the removed node's place in the tree.
The node has two children. Let's call the node D. Find the right-most child of D's left subtree. Let's call this node R. Assign the value of R to D, and delete R (as described in this algorithm). Notice that R can have zero or one children.
The third scenario, illustrated:
.
.
.
/
D
/ \
/\ .
/ \
/ \
+------+
\
R
/
?