Java: Recursive methods for heap ADT operations - java

I have 2 iterative methods used in my heap implementation, one called reheapUp(for enqueue), one called reheapDown(for dequeue) and a helper method called newhole which manipulates the hole in the heap structure used in the reheapUp/reheapDown methods.
I'm trying to make a recursive versions of reheapUp/reheapDown but I keep running into a variety of issues, namely stack overflows. I've tried different approaches but have not had much luck. Here are the iterative versions, followed by my latest attempt at a recursive reheapDown, called recReheapdown:
private void reheapUp(T element)
// Current lastIndex position is empty.
// Inserts element into the tree and ensures shape and order properties.
{
int hole = lastIndex;
while ((hole > 0) // hole is not root and element > hole's parent
&&
(element.compareTo(elements.get((hole - 1) / 2)) > 0))
{
// move hole's parent down and then move hole up
elements.set(hole,elements.get((hole - 1) / 2));
hole = (hole - 1) / 2;
}
elements.set(hole, element); // place element into final hole
}
private void reheapDown(T element)
// Current root position is "empty";
// Inserts element into the tree and ensures shape and order properties.
{
int hole = 0; // current index of hole
int newhole; // index where hole should move to
newhole = newHole(hole, element); // find next hole
while (newhole != hole)
{
elements.set(hole,elements.get(newhole)); // move element up
hole = newhole; // move hole down
newhole = newHole(hole, element); // find next hole
}
elements.set(hole, element); // fill in the final hole
}
And finally:
private void recReheapDown(T element)
{
int hole = 0; // current index of hole
int newhole; // index where hold should move to
newhole = newHole(hole, element); //find next hole
if(newhole == hole)//base condition
{
elements.set(hole, element); //fill in the final hole
return;
}
elements.set(hole,elements.get(newhole));
hole = newhole; //move hole down
recReheapDown(element);
}
My recReheapUp is similar, so I won't post it. I would appreciate it greatly if someone could help me solve this problem. I've never been great at recursion, but i'm doing my best to learn. If someone would like to see the newHole method ill post it in an edit.
Lastly (just because i'm curious) what would be the complexity differences between the iterative and recursive versions? Thanks.
EDIT: Here is the newHole method as requested.
private int newHole(int hole, T element)
// If either child of hole is larger than element, return the index
// of the larger child; otherwise, return the index of hole.
{
int left = (hole * 2) + 1;
int right = (hole * 2) + 2;
if (left > lastIndex)
// hole has no children
return hole;
else
if (left == lastIndex)
// hole has left child only
if (element.compareTo(elements.get(left)) < 0)
// element < left child
return left;
else
// element >= left child
return hole;
else
// hole has two children
if (elements.get(left).compareTo(elements.get(right)) < 0)
// left child < right child
if (elements.get(right).compareTo(element) <= 0)
// right child <= element
return hole;
else
// element < right child
return right;
else
// left child >= right child
if (elements.get(left).compareTo(element) <= 0)
// left child <= element
return hole;
else
// element < left child
return left;
}

Related

Finding minimum depth of BST ... findHeight function won't work

Trying to solve this LC Easy: https://leetcode.com/problems/minimum-depth-of-binary-tree/
Which is to find the minimum depth (number of nodes on shortest path) of a tree.
I was able to create a "findheight" function which gives me the height of a tree.
My logic was to use findheight to find the height of both subtrees (left and right) of a root node, and then return the minimum between the two heights.
class Solution {
public int minDepth(TreeNode root) {
if(root == null){return 0;}
int left = findHeight(root.left);
int right = findHeight(root.right);
//unbalanced tree, only one subtree
if(left == 0 || right == 0){
return Math.max(left,right) + 1;
}
return Math.min(left,right) + 1 ;
}
public int findHeight(TreeNode root){
if(root == null){return 0;}
int left = findHeight(root.left);
int right = findHeight(root.right);
return Math.max(left,right) + 1;
}
}
It won't pass the test case:
[-9,-3,2,null,4,4,0,-6,null,-5]
Or:
Output:
4
Expected:
3
My thought process right now is that when I use "findHeight", I'm returning back the 'max' height per left and right subtree. In this test case, I should be returning back the minimum height.
I changed my code to "Math.min" in another iteration, but that doesn't work either.
Any ideas or theories why? So confused!! Should I just abandon this approach altogether?
Issue in current code
//unbalanced tree, only one subtree
if(left == 0 || right == 0){
return Math.max(left,right) + 1;
}
The above lines of code checks the imbalance only at root level. It does not recursively check imbalance at lower levels.
Check imbalance at every level
public int minDepth(final TreeNode node) {
if (node == null) {
return 0;
}
final int left = minDepth(node.left);
final int right = minDepth(node.right);
// if both paths exist, then return the minimum
if (node.left != null && node.right != null) {
return Math.min(left, right) + 1;
} else {
// if zero or one path exists return that path (so take maximum)
return Math.max(left, right) + 1;
}
}

Array Index Out of Bounds In Array Based Heap Sort

I'm trying to write an array based implementation of the heap sort algorithm. The goal is to build a heap in an array and then remove the minimum element at the root of the array and put it back into the original array. This is done until the array is sorted.
The replacement for the root is supposed to come from the last element in the array, which is then removed and put in the root. The new root element is swapped with one its children if necessary. This continues until it is in the correct location
However I keep getting array index out of bounds exception and I just cannot find the problem. I've been working on this for way too long.
I would really appreciate it if someone could help me.
public class ImprovedHeapSort<T>
{
/**
* #param unsortedArr Array to be sorted
* #return sortedArr The sorted array
*
* Static method which is an improved version of the HeapSort algorithm. The array
* is used to create a sorted array, which is treated as a minheap.
*
* The root is at index 0 and the last element is at index length-1.
* Each element is compared to its children, which are at positions 2n+1 and 2(n+1).
* Swapping and comparison continues until the root is reached.
*
*
*/
public static <T extends Comparable<T>> T[] HeapSort (T[] unsortedArr)
{
/*
* Throw exception if array is empty.
*/
if (unsortedArr[0] == null)
{
throw new EmptyCollectionException("Array");
}
/*
* If array only contains one element.
*/
if (unsortedArr.length == 1)
{
return unsortedArr;
}
T[] heapArr = Arrays.copyOf(unsortedArr, unsortedArr.length);
for(int i = 0; i < unsortedArr.length; i++)
{
heapArr[i] = unsortedArr[i];
/*
* Swapping to put element in appropriate location, if necessary.
*/
int cur = i;
T temp = heapArr[i];
/*
* Swapping until root isn't reached and the element being added
* would no longer be less than its parent.
*/
while(cur > 0 && temp.compareTo(heapArr[(cur-1)/2]) < 0)
{
heapArr[cur] = heapArr[(cur-1)/2]; //Swap cur with parent
cur = (cur-1)/2; //Move up to parent
}
heapArr[cur] = temp; //Insert at appropriate spot.
}
/*
* Remove the root element from the heap array and add it to unsortedArr
*
*/
for (int y = 0; y < unsortedArr.length; y++)
{
int count = heapArr.length - (y+1); //Count decreased after every pass.
T rootElem = heapArr[0]; //Store root
heapArr[0] = heapArr[heapArr.length- (y+1)]; //Set root to last element.
unsortedArr[y] = rootElem; //Add root to unsortedArr
int node = 0;
int left = 1;
int right = 2;
int next;
if ((heapArr[left] == null) && (heapArr[right] == null))
next = count-1;
else if (heapArr[right] == null)
next = left;
else if (heapArr[left].compareTo(heapArr[right]) < 0)
next = left;
else
next = right;
T temp = heapArr[node];
/*
* Swap until appropriate location is found. Least child is shifted up.
*/
while ((next < count) &&
(heapArr[next]).compareTo(temp) < 0)
{
heapArr[node] = heapArr[next];
node = next;
left = 2 * node + 1;
right = 2 * (node + 1);
if ((heapArr[left] == null) && (heapArr[right] == null))
next = count-2;
else if (heapArr[right] == null)
next = left;
else if (heapArr[left].compareTo(heapArr[right]) < 0)
next = left;
else
next = right;
}
heapArr[node] = temp; //Insert node at appropriate location
}
return unsortedArr;
You have a few bounds errors in your code.
First, let's look here:
/*
* Throw exception if array is empty.
*/
if (unsortedArr[0] == null)
{
throw new EmptyCollectionException("Array");
}
This code won't actually throw an exception if the array is empty. Instead, it tries to look at index 0, see if that value is null, and, if so, throw an exception. Therefore, if you try to pass in an array of size 0 or an empty array, you'll get either a bounds error or a null pointer exception. To fix this, try rewriting it as
if (unsortedArr == null) {
...
}
You probably don't want to automatically fail on an array of length 0. It's perfectly well-defined how to sort it: it's already sorted!
Additionally, I'm not sure what you meant to do here, but I'm almost positive this isn't what you intended:
int node = 0;
int left = 1;
int right = 2;
int next;
if ((heapArr[left] == null) && (heapArr[right] == null))
next = count-1;
else if (heapArr[right] == null)
next = left;
else if (heapArr[left].compareTo(heapArr[right]) < 0)
next = left;
else
next = right;
Notice that node, left, and right are always indices 0, 1, and 2, regardless of how big the array is. If you pass in a small array (say, size 2), this will read off the end.
Going forward, the sense I get is that you need to learn how to debug your programs a bit more. The exceptions raised here when I ran the code took me right to the line of the program that caused the problem, and from there it wasn't too hard to figure out where something unusual was going on. I hope this helps point you in the right direction, and good luck!

How should I implement removal of rightmost half of my custom Linkedlist

Write the method removeRightmostHalf member of the class LinkedList. Do not call any methods of the class and do not use any auxiliary data structures.
If l contains A! B! C! D! E, then after calling l.removeRightmostHalf(), l becomes A! B! C.
int size = 0 ;
int halfSize = 0;
current = head;
while (current.next != null) {
++size;
current=current.next;
}
++size;
if (size % 2 == 0) {
halfSize = (size / 2);
for (int i = halfSize + 1; i < size; i++) {
}
}
I do not know how I will remove inside for loop.
Any help!
I would suggest you to use two pointers, slow and fast pointer. Initially both will be pointing to the start of the linked list.
The slow pointer will move one node at a time.
The fast will move two node a time.
The moment you see that fast pointer has reached the end of the list, just mark the slow pointer node as end of the list, by setting next=null;
Important note that, the discovery of the end of the list will be depend on the even/odd size of the list. So design and test with both cases.
This will work , when you reach the half of the list just cut the link with the rest of it.
public void removeRightMost() {
int size = 0;
int halfSize = 0;
current = head;
while (current!= null) {
size++;
current = current.next;
}
if (size % 2 == 0) {
halfSize = (size / 2);
int count = 0;
current = head;
/* if the number of elements is even you need to decrease the halfSize 1 because
you want the current to reach the exactly half if you have 4 elements the current
should stop on the element number 2 then get out of the loop */
while (count < halfSize-1) {
current = current.next;
count++;
}
current.next=null; //here the process of the deletion when you cut the rest of the list , now nothing after the current (null)
}
else {
halfSize = (size / 2);
int count = 0;
current = head;
while (count < halfSize) {
current = current.next;
count++;
}
current.next=null;
}
current=head; // return the current to the first element (head)
}
good luck

detecting a cycle from a Graph

How to detect if a graph has a cycle or not from this part of code which shows the depth-first search an the graph is implemented in an adjacency matrix
// ------------------------------------------------------------
public void dfs() // depth-first search
{ // begin at vertex 0
int k = 0;
vertexList[0].wasVisited = true; // mark it
displayVertex(0); // display it
theStack.push(0); // push it
while (!theStack.isEmpty()) // until stack empty,
{
// get an unvisited vertex adjacent to stack top
int v = getAdjUnvisitedVertex(theStack.peek());
int x = nAdjVisitedVertex(v);
if (v == -1) // if no such vertex,
theStack.pop();
else // if it exists,
{
vertexList[v].wasVisited = true; // mark it
displayVertex(v); // display it
if (x == 2)
k++;
theStack.push(v); // push it
}
} // end while
// stack is empty, so we’re done
for (int j = 0; j < nVerts; j++)
// reset flags
vertexList[j].wasVisited = false;
if(k != 0)
System.out.println("not a cycle");
else
System.out.println("cycle");
} // end dfs
While traversing the graph, you need to keep looking for already visited node. If you come across a node which is already visited, you have found a loop. If traversal finishes without getting any visited node, there is no loop in the graph. And regarding implementation, try first, if you face any problem, come back with the problem.

How to calculate the depth of a binary search tree

I would like to calculate the summation of the depths of each node of a Binary Search Tree.
The individual depths of the elements are not already stored.
Something like this:
int countChildren(Node node)
{
if ( node == null )
return 0;
return 1 + countChildren(node.getLeft()) + countChildren(node.getRight());
}
And to get the sum of the depths of every child:
int sumDepthOfAllChildren(Node node, int depth)
{
if ( node == null )
return 0; // starting to see a pattern?
return depth + sumDepthOfAllChildren(node.getLeft(), depth + 1) +
sumDepthOfAllChildren(node.getRight(), depth + 1);
}
Now for a hopefully informative explanation in case this is homework. Counting the number of nodes is quite simple. First of all, if the node isn't a node (node == null) it returns 0. If it is a node, it first counts its self (the 1), plus the number of nodes in its left sub-tree plus the number of nodes in its right sub-tree. Another way to think of it is you visit every node via BFS, and add one to the count for every node you visit.
The Summation of depths is similar, except instead of adding just one for each node, the node adds the depth of its self. And it knows the depth of its self because its parent told it. Each node knows that the depth of it's children are it's own depth plus one, so when you get the depth of the left and right children of a node, you tell them their depth is the current node's depth plus 1.
And again, if the node isn't a node, it has no depth. So if you want the sum of the depth of all the root node's children, you pass in the root node and the root node's depth like so: sumDepthOfAllChildren(root, 0)
Recursion is quite useful, it's just a very different way of thinking about things and takes practice to get accustomed to it
int maxDepth(Node node) {
if (node == null) {
return (-1); // an empty tree has height −1
} else {
// compute the depth of each subtree
int leftDepth = maxDepth(node.left);
int rightDepth = maxDepth(node.right);
// use the larger one
if (leftDepth > rightDepth )
return (leftDepth + 1);
else
return (rightDepth + 1);
}
}
This solution is even more simpler.
public int getHeight(Node root)
{
if(root!=null)
return 1+ Math.max(getHeight(root.leftchild),getHeight(root.rightchild));
else
return 0;
}
For any given tree, the number of nodes is 1 for the root plus the number of nodes in the left subtree plus the number of nodes in the right subtree :)
Details, like making sure there actually is a left or right subtree, are "left to the reader".
private static int getNumberOfNodes(Node node) {
if (node == null) {
return 0;
}
return 1 + getNumberOfNodes(node.left) + getNumberOfNodes(node.right);
}
public int countNodes(Node root)
{
// Setup
// assign to temps to avoid double call accessors.
Node left = root.getLeft();
Node right = root.getRight();
int count = 1; // count THIS node.
// count subtrees
if (left != null) count += countNodes(left);
if (right != null) count += countNodes(right);
return count;
}
public class Node {
private Node left;
private Node right;
public int size() { return 1+ (left==null?0:left.size())+ (right==null?0:right.size());}
}
int depth(treenode *p)
{
if(p==NULL)return(0);
if(p->left){h1=depth(p->left);}
if(p=>right){h2=depth(p->right);}
return(max(h1,h2)+1);
}
public int numberOfNodes()
{
// This node.
int result = 1;
// Plus all the nodes from the left node.
Node left = getLeft();
if (left != null)
result += left.numberOfNodes();
// Plus all the nodes from the right node.
Node right = getRight();
if (right != null)
result += right.numberOfNodes();
return result;
}
public int getDepthHelper( TreeNode< T > node ) {
int treeHeightLeft;
int treeHeightRight;
//get height of left subtree
if( node.leftNode == null )
treeHeightLeft = 1;
else {
treeHeightLeft = getDepthHelper( node.leftNode) + 1;
}
//get height of right subtree
if( node.rightNode == null )
treeHeightRight = 1;
else {
treeHeightRight = getDepthHelper( node.rightNode) + 1;
}
return Math.max(treeHeightLeft, treeHeightRight);
}

Categories

Resources