Related
The error I believe starts on line 102: int treeDepth(Node Node) because when I run the code with a regular while loop with a count, it runs and displays a tree. But as soon as I change the while condition to while (treeDepth(this.root) <= 5) it runs but displays nothing, and I get no errors. Trying to make it so the tree that is created doesn't have a depth larger than 5.
import java.io.*;
import java.util.*;
class Node {
int value;
Node left;
Node right;
Node(int value) {
this.value = value;
right = null;
left = null;
}
}
public class treeStructureBinary{
Node root;
public static void main(String[] args) {
treeStructureBinary bn =new treeStructureBinary();
bn.appMain(args);
}
void appMain(String[] args) {
createBinaryTree();
}
private Node addRecursive(Node current, int value) {
if (current == null) {
return new Node(value);
}
if (value < current.value) {
current.left = addRecursive(current.left, value);
} else if (value > current.value) {
current.right = addRecursive(current.right, value);
} else {
return current;
}
return current;
}
public void add(int value) {
this.root = addRecursive(this.root, value);
}
public treeStructureBinary createBinaryTree() {
treeStructureBinary bt = new treeStructureBinary();
int [] array = new int[89];
int counter = 0;
boolean check = true;
while (treeDepth(this.root) <= 5)
{
Random rand = new Random();
int n = rand.nextInt(89) + 10;
for(int z = 0; z <= counter; z++)
{
if ( n == array[z])
{
check = false;
break;
}
}
if (check == true)
{
bt.add(n);
array[counter] = n;
counter++;
}
check = true;
}
bt.traverseLevelOrder();
return bt;
}
public void traverseLevelOrder() {
if (this.root == null) {
return;
}
Queue<Node> nodes = new LinkedList<>();
nodes.add(this.root);
while (!nodes.isEmpty()) {
Node node = nodes.remove();
System.out.print(" " + node.value);
if (node.left != null) {
nodes.add(node.left);
}
if (node.right != null) {
nodes.add(node.right);
}
}
}
int treeDepth(Node Node){
if (Node == null) {
return 0;
}else {
int lDepth = treeDepth(Node.left);
int rDepth = treeDepth(Node.right);
if (lDepth > rDepth) {
System.out.println("lDepth" + "\n");
return (lDepth + 1);
}else {
System.out.println("rDepth" + "\n");
return (rDepth + 1);
}
}
}
}
I think your addRecursive never actually adds the node to the tree--or always adds it? Anyway it looks funky. I'd focus on that for a bit.
This code in particular:
if (value < current.value) {
current.left = addRecursive(current.left, value);
} else if (value > current.value) {
current.right = addRecursive(current.right, value);
} else {
return current;
}
always forces an assign (even if it's not a leaf) and the final else will only execute when value == current.value which is probably not what you want.
I don't really want to go much further because it looks homeworky and you'll gain more figuring it out yourself.
It might work anyway (You just may be re-assigning every node at every level) but I'm not sure without running it.
Anyway, if this is a homework assignment I'd really like to commend you on your style, it's one of the best I've seen posted here for a homework-like question.
Main problem here is that you are working on two different trees.
First you create one tree in main function:
public static void main(String[] args) {
treeStructureBinary bn =new treeStructureBinary();
bn.appMain(args);
}
Then you create another one in createBinaryTree method:
public SthApplication createBinaryTree() {
treeStructureBinary bt = new treeStructureBinary();
See, you used new keyword twice, so there will be two objects.
Later in your app you refer to this.root (which is the one from main), but some methods use local variable bt.
In example, treeDepth(this.root) operates on different tree then the bt.add(n), so it goes into infinite loop.
If you solve that problem, you will know how to finish the rest.
Thanks guys I figured it out!
import java.io.*;
import java.util.*;
class Node {
int value;
int balancefactor;
int nodex;
Node left;
Node right;
Node(int value, int balancefactor, int nodex) {
this.value = value;
this.balancefactor = balancefactor;
this.nodex = nodex;
this.right = null;
this.left = null;
}
}
public class treeStructureBinary{
Node root;
public static void main(String[] args) {
treeStructureBinary bn =new treeStructureBinary();
bn.appMain(args);
}
void appMain(String[] args) {
int count = args.length;
if (count >1) {
count = 1;
}
String [] cmdln = {""};
for (int i=0;i<count;i++) {
cmdln[i]=args[i];
}
if (cmdln[0].equals("BT")){
createBinaryTree();
} else if (cmdln[0].equals("AVL")) {
} else {
System.out.println("Please enter BT or AVL to choose the type of
tree.");
}
}
private Node addRecursive(Node current, int value, int balancefactor, int
nodex) {
if (current == null) {
return new Node(value, balancefactor, nodex);
} if (value < current.value) {
balancefactor++;
nodex=(nodex*2);
current.left = addRecursive(current.left, value, balancefactor,
nodex);
} else if (value > current.value) {
balancefactor++;
nodex=(nodex*2)+1;
current.right = addRecursive(current.right, value, balancefactor,
nodex);
} else {
return current;
}
return current;
}
public void add(int value) {
int balancefactor=1;
int nodex=0;
this.root = addRecursive(this.root, value, balancefactor, nodex);
}
public treeStructureBinary createBinaryTree() {
treeStructureBinary bt = new treeStructureBinary();
int [] array = new int[89];
int counter = 0;
boolean check = true;
int temp = 0;
while (temp < 5) {
Random rand = new Random();
int n = rand.nextInt(89) + 10;
for(int z = 0; z <= counter; z++) {
if ( n == array[z]) {
check = false;
break;
}
}
if (check == true) {
bt.add(n);
array[counter] = n;
counter++;
}
check = true;
temp = bt.treeDepth();
}
bt.traverseLevelOrder();
Scanner reader =new Scanner(System.in);
System.out.println("\n\nEnter a number to delete or 0 to exit");
int input = reader.nextInt();
Boolean isMatch = true;
while (input!=0) {
for(int p = 0; p < counter; p++)
{
//System.out.println(array[p]);
if (input != array[p])
{
isMatch = false;
}
else
{
isMatch = true;
array[p] = 0;
break;
}
}
if (isMatch == false )
{
System.out.println("Error, number not found.");
}
bt.nodeDelete(input);
bt.traverseLevelOrder();
System.out.println("\n\nEnter a number to delete or 0 to exit");
input = reader.nextInt();
}
return bt;
}
public void traverseLevelOrder() {
int count = 0;
int outer = 31;
int inner = 30;
int lastnode= 0;
int check = 0;
if (this.root == null) {
return;
}
Queue<Node> nodes = new LinkedList<>();
nodes.add(this.root);
while (!nodes.isEmpty()) {
Node node = nodes.remove();
if (count < node.balancefactor) {
System.out.print("\n");
for (int i=0; i<outer; i++) {
System.out.print(" ");
}
inner=outer;
outer=outer/2;
count++;
lastnode=0;
check=0;
}
check=((node.nodex-lastnode));
for (int i=0; i<(inner*check*2);i++) {
System.out.print(" ");
}
if (check >1) {
for (int j=0;j<check;j++) {
System.out.print(" ");
}
}
lastnode=node.nodex;
System.out.print(node.value);
if (node.left != null) {
nodes.add(node.left);
}
if (node.right != null) {
if (node.right==null &&lastnode == 0) {
if (count==5) {
break;
}
System.out.print(" ");
}
nodes.add(node.right);
}
}
}
int treeDepth(){
int temp = treeDepthRecursive(this.root);
return temp;
}
int treeDepthRecursive(Node current) {
if (current == null) {
return 0;
} else {
int lDepth = treeDepthRecursive(current.left);
int rDepth = treeDepthRecursive(current.right);
if (lDepth > rDepth) {
return (lDepth + 1);
} else {
return (rDepth + 1);
}
}
}
public void nodeDelete(int value) {
nodeDeleteRecursive(root, value);
}
public Node nodeDeleteRecursive(Node current, int value) {
if (current == null) {
return null;
}
if (value == current.value) {
if (current.left ==null && current.right==null) {
return null;
}
if (current.right==null) {
return current.left;
}
if (current.left==null) {
return current.right;
}
int sValue = findSmall(current.right);
current.value = sValue;
current.right = nodeDeleteRecursive(current.right, sValue);
return current;
}
if (value < current.value) {
current.left = nodeDeleteRecursive(current.left, value);
return current;
}
current.right =nodeDeleteRecursive(current.right, value);
return current;
}
public int findSmall(Node root) {
return root.left == null?(root.value):(findSmall(root.left));
}
}
I'm stuck on this problem:
You have two numbers represented by a linked list, where each node contains a single digit. The digits are stored in reverse order, such that the 1’s digit is at the head of the list. Write a function that adds the two numbers and returns the sum as a linked list.
EXAMPLE
Input: (3 -> 1 -> 5), (5 -> 9 -> 2)
Output: 8 -> 0 -> 8
The problem is that my result is 8 8 while the result should be 8 0 8.
I printed out the sum and it is 8 10 8 so it should work.
Any ideas?
Here is my code:
public Node addNumbers(Node number1, Node number2) {
if(number1 == null && number2 == null)
return null;
Node sumOf = null;
int sum = 0;
int carry = 0;
while(number1 != null && number2 != null) {
sum = number1.data + number2.data + carry;
System.out.println(sum);
// update carry for next operation
if(sum > 9)
carry = 1;
else
carry = 0;
if(sum > 9) {
if(sumOf == null) {
sumOf = new Node(sum % 10);
} else {
sumOf.next = new Node(sum % 10);
}
} else {
if(sumOf == null) {
sumOf = new Node(sum);
} else {
sumOf.next = new Node(sum);
}
}
number1 = number1.next;
number2 = number2.next;
}
return sumOf;
}
public void toString(Node node) {
System.out.println();
while (node != null) {
System.out.print(node.data + " ");
node = node.next;
}
}
public static void main(String[] args) {
AddTwoNumbers add = new AddTwoNumbers();
number1 = new Node(3);
number1.next = new Node(1);
number1.next.next = new Node(5);
number2 = new Node(5);
number2.next = new Node(9);
number2.next.next = new Node(2);
System.out.println("numbers: ");
add.toString(number1);
add.toString(number2);
System.out.println();
System.out.println("after adding: ");
add.toString(add.addNumbers(number1, number2));
}
}
You only ever set sumOf (if it is null) and sumOf.next (if sumOf is not null). Your resulting list therefore never has more than two elements. You need to track the current tail of your list and append there, instead of always appending to sumOf.
Additionally, you need to handle the cases where one input number has more digits than the other, and where you have non-zero carry after exhausting all the input digits. You do not presently handle either.
Here is the solution, do note that i carry forward when the sum of two integers is greater than 9 else i continue with the sum of next integers from both the list.
class Node {
private Object data;
private Node next;
public Object getData() { return data; }
public void setData(Object data) { this.data = data; }
public Node getNext() { return next; }
public void setNext(Node next) { this.next = next; }
public Node(final Object data, final Node next) {
this.data = data;
this.next = next;
}
#Override
public String toString() { return "Node:[Data=" + data + "]"; }
}
class SinglyLinkedList {
Node start;
public SinglyLinkedList() { start = null; }
public void addFront(final Object data) {
// create a reference to the start node with new data
Node node = new Node(data, start);
// assign our start to a new node
start = node;
}
public void addRear(final Object data) {
Node node = new Node(data, null);
Node current = start;
if (current != null) {
while (current.getNext() != null) {
current = current.getNext();
}
current.setNext(node);
} else {
addFront(data);
}
}
public void deleteNode(final Object data) {
Node previous = start;
if (previous == null) {
return;
}
Node current = previous.getNext();
if (previous != null && previous.getData().equals(data)) {
start = previous.getNext();
previous = current;
current = previous.getNext();
return;
}
while (current != null) {
if (current.getData().equals(data)) {
previous.setNext(current.getNext());
current = previous.getNext();
} else {
previous = previous.getNext();
current = previous.getNext();
}
}
}
public Object getFront() {
if (start != null) {
return start.getData();
} else {
return null;
}
}
public void print() {
Node current = start;
if (current == null) {
System.out.println("SingleLinkedList is Empty");
}
while (current != null) {
System.out.print(current);
current = current.getNext();
if (current != null) {
System.out.print(", ");
}
}
}
public int size() {
int size = 0;
Node current = start;
while (current != null) {
current = current.getNext();
size++;
}
return size;
}
public Node getStart() {
return this.start;
}
public Node getRear() {
Node current = start;
Node previous = current;
while (current != null) {
previous = current;
current = current.getNext();
}
return previous;
}
}
public class AddNumbersInSinglyLinkedList {
public static void main(String[] args) {
SinglyLinkedList listOne = new SinglyLinkedList();
SinglyLinkedList listTwo = new SinglyLinkedList();
listOne.addFront(5);
listOne.addFront(1);
listOne.addFront(3);
listOne.print();
System.out.println();
listTwo.addFront(2);
listTwo.addFront(9);
listTwo.addFront(5);
listTwo.print();
SinglyLinkedList listThree = add(listOne, listTwo);
System.out.println();
listThree.print();
}
private static SinglyLinkedList add(SinglyLinkedList listOne, SinglyLinkedList listTwo) {
SinglyLinkedList result = new SinglyLinkedList();
Node startOne = listOne.getStart();
Node startTwo = listTwo.getStart();
int carry = 0;
while (startOne != null || startTwo != null) {
int one = 0;
int two = 0;
if (startOne != null) {
one = (Integer) startOne.getData();
startOne = startOne.getNext();
}
if (startTwo != null) {
two = (Integer) startTwo.getData();
startTwo = startTwo.getNext();
}
int sum = carry + one + two;
carry = 0;
if (sum > 9) {
carry = sum / 10;
result.addRear(sum % 10);
} else {
result.addRear(sum);
}
}
return result;
}
}
Sample Run
Node:[Data=3], Node:[Data=1], Node:[Data=5]
Node:[Data=5], Node:[Data=9], Node:[Data=2]
Node:[Data=8], Node:[Data=0], Node:[Data=8]
**#In Python:-**
class Node():
def __init__(self,value):
self.value=value
self.nextnode=None
class LinkedList():
def __init__(self):
self.head=None
def add_element(self,value):
node=Node(value)
if self.head is None:
self.head =node
return
crnt_node=self.head
while crnt_node.nextnode is not None:
crnt_node=crnt_node.nextnode
crnt_node.nextnode=node
def reverse_llist(self):
crnt_node=self.head
if crnt_node == None:
print('Empty Linkned List')
return
old_node = None
while crnt_node:
temp_node = crnt_node.nextnode
crnt_node.nextnode = old_node
old_node = crnt_node
crnt_node = temp_node
self.head = old_node
def converted_llist(self):
crnt_node=self.head
carry_value=0
while True:
#print(crnt_node.value)
if (crnt_node.value+1)%10==0:
carry_value=1
crnt_node.value=0
print(crnt_node.value,end='->')
else:
print(crnt_node.value+carry_value,end='->')
if crnt_node.nextnode is None:
break
crnt_node=crnt_node.nextnode
print('None')
def print_llist(self):
crnt_node=self.head
while True:
print(crnt_node.value,end='->')
if crnt_node.nextnode is None:
break
crnt_node=crnt_node.nextnode
print('None')
list_convert=LinkedList()
list_convert.add_element(1)
list_convert.print_llist()
list_convert.add_element(9)
list_convert.print_llist()
list_convert.add_element(9)
list_convert.print_llist()
list_convert.add_element(9)
list_convert.print_llist()
list_convert.reverse_llist()
list_convert.print_llist()
list_convert.converted_llist()
I need help making this toString method pass the tests at the bottom. I am currently getting the error (expected:<0:20, 1:[1]0> but was <0:20, 1:[2]0>). addFirst is working 100%, but I'm not sure what is wrong here.
public class LList
{
public Node head;
private int i;
private int size;
public void addFirst(int value)
{
Node n = new Node();
n.value = value;
n.next = head;
head = n;
}
public void removeFirst()
{
if (head != null)
{
// commone case: there is at least one node
head = head.next;
}
else
{
// no nodes
throw new Banana();
}
}
public int size()
{
Node current = head;
int count = 0;
while(current != null)
{
count++; // keep count of nodes
current = current.next; // move to next node
}
return count;
}
public int get(int index)
{
int count = 0;
Node current = head;
if (index < 0 || index >= size())
{
throw new Banana();
}
while(count != index)
{
count++;
current = current.next;
}
return current.value;
}
public String toString()
{
String s = "";
Node current = head;
//current = head;
if (size() == 0)
{
return s;
}
else
{
s = s + "" + i + ":" + current.value;
for (int i = 1; i < size(); i++)
{
s = s + ", " + i + ":" + current.value;
}
return s;
}
}
public class Node
{
public int value;
public Node next;
}
#Test
public void testToString()
{
LList a = new LList();
assertEquals("", a.toString());
a.addFirst(10);
assertEquals("0:10", a.toString());
a.addFirst(20);
assertEquals("0:20, 1:10", a.toString());
a.addFirst(30);
assertEquals("0:30, 1:20, 2:10", a.toString());
}
You should iterate (walk over) all Nodes.
Use while loop for that, e.g.:
public String toString() {
String s = "";
Node current = head;
// current = head;
if (size() != 0) {
int i = 0;
s = s + "" + i + ":" + current.value;
while(current.next != null) {
i++;
current = current.next;
s = s + ", " + i + ":" + current.value;
}
}
return s;
}
I'm practicing basic data structure stuff and I'm having some difficulties with recursion. I understand how to do this through iteration but all of my attempts to return the nth node from the last of a linked list via recursion result in null. This is my code so far:
public static int i = 0;
public static Link.Node findnthToLastRecursion(Link.Node node, int pos) {
if(node == null) return null;
else{
findnthToLastRecursion(node.next(), pos);
if(++i == pos) return node;
return null;
}
Can anyone help me understand where I'm going wrong here?
This is my iterative solution which works fine, but I'd really like to know how to translate this into recursion:
public static Link.Node findnthToLast(Link.Node head, int n) {
if (n < 1 || head == null) {
return null;
}
Link.Node pntr1 = head, pntr2 = head;
for (int i = 0; i < n - 1; i++) {
if (pntr2 == null) {
return null;
} else {
pntr2 = pntr2.next();
}
}
while (pntr2.next() != null) {
pntr1 = pntr1.next();
pntr2 = pntr2.next();
}
return pntr1;
}
You need to go to the end and then count your way back, make sure to pass back the node each time its passed back. I like one return point
public static int i = 0;
public static Link.Node findnthToLastRecursion(Link.Node node, int pos) {
Link.Node result = node;
if(node != null) {
result = findnthToLastRecursion(node.next, pos);
if(i++ == pos){
result = node;
}
}
return result;
}
Working example outputs 7 as 2 away from the 9th and last node:
public class NodeTest {
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
/**
* #param args
*/
public static void main(String[] args) {
Node first = null;
Node prev = null;
for (int i = 0; i < 10; i++) {
Node current = new Node(prev, Integer.toString(i),null);
if(i==0){
first = current;
}
if(prev != null){
prev.next = current;
}
prev = current;
}
System.out.println( findnthToLastRecursion(first,2).item);
}
public static int i = 0;
public static Node findnthToLastRecursion(Node node, int pos) {
Node result = node;
if (node != null) {
result = findnthToLastRecursion(node.next, pos);
if (i++ == pos) {
result = node;
}
}
return result;
}
}
No need for static variables.
public class List {
private Node head = null;
// [...] Other methods
public Node findNthLastRecursive(int nth) {
if (nth <= 0) return null;
return this.findNthLastRecursive(this.head, nth, new int[] {0});
}
private Node findNthLastRecursive(Node p, int nth, int[] pos) {
if (p == null) {
return null;
}
Node n = findNthLastRecursive(p.next, nth, pos);
pos[0]++;
if (pos[0] == nth) {
n = p;
}
return n;
}
}
You can do this a couple of ways:
recurse through the list once to find the list length, then write a recursive method to return the kth element (a much easier problem).
use an auxiliary structure to hold the result plus the remaining length; this essentially replaces the two recursions of the first option with a single recursion:
static class State {
Link.Node result;
int trailingLength;
}
public static Link.Node findnthToLastRecursion(Link.Node node, int pos) {
if(node == null) return null;
State state = new State();
findnthToLastRecursion(node, pos, state);
return state.result;
}
private static void findnthToLastRecursion(Link.Node node, int pos, State state) {
if (node == null) {
state.trailingLength = 0;
} else {
findnthToLastRecursion(node.next(), state);
if (pos == state.trailingLength) {
state.result = node;
}
++state.trailingLength;
}
}
I misunderstood the question. Here is an answer based on your iterative solution:
public static Link.Node findnthToLast(Link.Node head, int n) {
return findnthToLastHelper(head, head, n);
}
private static Link.Node findnthToLastHelper(Link.Node head, Link.Node end, int n) {
if ( end == null ) {
return ( n > 0 ? null : head);
} elseif ( n > 0 ) {
return findnthToLastHelper(head, end.next(), n-1);
} else {
return findnthToLastHelper(head.next(), end.next(), 0);
}
}
actually you don't need to have public static int i = 0; . for utill method the pos is :
pos = linked list length - pos from last + 1
public static Node findnthToLastRecursion(Node node, int pos) {
if(node ==null){ //if null then return null
return null;
}
int length = length(node);//find the length of the liked list
if(length < pos){
return null;
}
else{
return utill(node, length - pos + 1);
}
}
private static int length(Node n){//method which finds the length of the linked list
if(n==null){
return 0;
}
int count = 0;
while(n!=null){
count++;
n=n.next;
}
return count;
}
private static Node utill(Node node, int pos) {
if(node == null) {
return null;
}
if(pos ==1){
return node;
}
else{
return utill(node.next, pos-1);
}
}
Here node.next is the next node. I am directly accessing the next node rather than calling the next() method. Hope it helps.
This cheats (slightly) but it looks good.
public class Test {
List<String> list = new ArrayList<> (Arrays.asList("Zero","One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten"));
public static String findNthToLastUsingRecursionCheatingALittle(List<String> list, int n) {
int s = list.size();
return s > n
// Go deeper!
? findNthToLastUsingRecursionCheatingALittle(list.subList(1, list.size()), n)
// Found it.
: s == n ? list.get(0)
// Too far.
: null;
}
public void test() {
System.out.println(findNthToLastUsingRecursionCheating(list,3));
}
public static void main(String args[]) {
new Test().test();
}
}
It prints:
Eight
which I suppose is correct.
I have use List instead of some LinkedList variant because I do not want to reinvent anything.
int nthNode(struct Node* head, int n)
{
if (head == NULL)
return 0;
else {
int i;
i = nthNode(head->left, n) + 1;
printf("=%d,%d,%d\n", head->data,i,n);
if (i == n)
printf("%d\n", head->data);
}
}
public class NthElementFromLast {
public static void main(String[] args) {
List<String> list = new LinkedList<>();
Stream.of("A","B","C","D","E").forEach(s -> list.add(s));
System.out.println(list);
System.out.println(getNthElementFromLast(list,2));
}
private static String getNthElementFromLast(List list, int positionFromLast) {
String current = (String) list.get(0);
int index = positionFromLast;
ListIterator<String> listIterator = list.listIterator();
while(positionFromLast>0 && listIterator.hasNext()){
positionFromLast--;
current = listIterator.next();
}
if(positionFromLast != 0) {
return null;
}
String nthFromLast = null;
ListIterator<String> stringListIterator = list.listIterator();
while(listIterator.hasNext()) {
current = listIterator.next();
nthFromLast = stringListIterator.next();
}
return nthFromLast;
}
}
This will find Nth element from last.
My approach is simple and straight,you can change the array size depending upon your requirement:
int pos_from_tail(node *k,int n)
{ static int count=0,a[100];
if(!k) return -1;
else
pos_from_tail(k->next,n);
a[count++]=k->data;
return a[n];
}
You'll have make slight changes in the code:
public static int i = 0;
public static Link.Node findnthToLastRecursion(Link.Node node, int pos) {
if(node == null) return null;
else{
**Link.Node temp = findnthToLastRecursion(node.next(), pos);
if(temp!=null)
return temp;**
if(++i == pos) return node;
return null;
}
}
For an assignment, we were instructed to create a priority queue implemented via a binary heap, without using any built-in classes, and I have done so successfully by using an array to store the queued objects. However, I'm interested in learning how to implement another queue by using an actual tree structure, but in doing so I've run across a bit of a problem.
How would I keep track of the nodes on which I would perform insertion and deletion? I have tried using a linked list, which appends each node as it is inserted - new children are added starting from the first list node, and deleted from the opposite end. However, this falls apart when elements are rearranged in the tree, as children are added at the wrong position.
Edit: Perhaps I should clarify - I'm not sure how I would be able to find the last occupied and first unoccupied leaves. For example, I would always be able to tell the last inserted leaf, but if I were to delete it, how would I know which leaf to delete when I next remove the item? The same goes for inserting - how would I know which leaf to jump to next after the current leaf has both children accounted for?
A tree implementation of a binary heap uses a complete tree [or almost full tree: every level is full, except the deepest one].
You always 'know' which is the last occupied leaf - where you delete from [and modifying it is O(logn) after it changed so it is not a problem], and you always 'know' which is the first non-occupied leaf, in which you add elements to [and again, modifying it is also O(logn) after it changed].
The algorithm idea is simple:
insert: insert element to the first non-occupied leaf, and use heapify [sift up] to get this element to its correct place in the heap.
delete_min: replace the first element with the last occupied leaf, and remove the last occupied leaf. then, heapify [sift down] the heap.
EDIT: note that delete() can be done to any element, and not only the head, however - finding the element you want to replace with the last leaf will be O(n), which will make this op expensive. for this reason, the delete() method [besides the head], is usually not a part of the heap data structure.
I really wanted to do this for almost a decade.Finally sat down today and wrote it.Anyone who wants it can use it.I got inspired by Quora founder to relearn Heap.Apparently he was asked how would you find K near points in a set of n points in his Google phone screen.Apparently his answer was to use a Max Heap and to store K values and remove the maximum element after the size of the heap exceeds K.The approach is pretty simple and the worst case is nlog K which is better than n^2 in most sorting cases.Here is the code.
import java.util.ArrayList;
import java.util.List;
/**
* #author Harish R
*/
public class HeapPractise<T extends Comparable<T>> {
private List<T> heapList;
public List<T> getHeapList() {
return heapList;
}
public void setHeapList(List<T> heapList) {
this.heapList = heapList;
}
private int heapSize;
public HeapPractise() {
this.heapList = new ArrayList<>();
this.heapSize = heapList.size();
}
public void insert(T item) {
if (heapList.size() == 0) {
heapList.add(item);
} else {
siftUp(item);
}
}
public void siftUp(T item) {
heapList.add(item);
heapSize = heapList.size();
int currentIndex = heapSize - 1;
while (currentIndex > 0) {
int parentIndex = (int) Math.floor((currentIndex - 1) / 2);
T parentItem = heapList.get(parentIndex);
if (parentItem != null) {
if (item.compareTo(parentItem) > 0) {
heapList.set(parentIndex, item);
heapList.set(currentIndex, parentItem);
currentIndex = parentIndex;
continue;
}
}
break;
}
}
public T delete() {
if (heapList.size() == 0) {
return null;
}
if (heapList.size() == 1) {
T item = heapList.get(0);
heapList.remove(0);
return item;
}
return siftDown();
}
public T siftDown() {
T item = heapList.get(0);
T lastItem = heapList.get(heapList.size() - 1);
heapList.remove(heapList.size() - 1);
heapList.set(0, lastItem);
heapSize = heapList.size();
int currentIndex = 0;
while (currentIndex < heapSize) {
int leftIndex = (2 * currentIndex) + 1;
int rightIndex = (2 * currentIndex) + 2;
T leftItem = null;
T rightItem = null;
int currentLargestItemIndex = -1;
if (leftIndex <= heapSize - 1) {
leftItem = heapList.get(leftIndex);
}
if (rightIndex <= heapSize - 1) {
rightItem = heapList.get(rightIndex);
}
T currentLargestItem = null;
if (leftItem != null && rightItem != null) {
if (leftItem.compareTo(rightItem) >= 0) {
currentLargestItem = leftItem;
currentLargestItemIndex = leftIndex;
} else {
currentLargestItem = rightItem;
currentLargestItemIndex = rightIndex;
}
} else if (leftItem != null && rightItem == null) {
currentLargestItem = leftItem;
currentLargestItemIndex = leftIndex;
}
if (currentLargestItem != null) {
if (lastItem.compareTo(currentLargestItem) >= 0) {
break;
} else {
heapList.set(currentLargestItemIndex, lastItem);
heapList.set(currentIndex, currentLargestItem);
currentIndex = currentLargestItemIndex;
continue;
}
}
}
return item;
}
public static void main(String[] args) {
HeapPractise<Integer> heap = new HeapPractise<>();
for (int i = 0; i < 32; i++) {
heap.insert(i);
}
System.out.println(heap.getHeapList());
List<Node<Integer>> nodeArray = new ArrayList<>(heap.getHeapList()
.size());
for (int i = 0; i < heap.getHeapList().size(); i++) {
Integer heapElement = heap.getHeapList().get(i);
Node<Integer> node = new Node<Integer>(heapElement);
nodeArray.add(node);
}
for (int i = 0; i < nodeArray.size(); i++) {
int leftNodeIndex = (2 * i) + 1;
int rightNodeIndex = (2 * i) + 2;
Node<Integer> node = nodeArray.get(i);
if (leftNodeIndex <= heap.getHeapList().size() - 1) {
Node<Integer> leftNode = nodeArray.get(leftNodeIndex);
node.left = leftNode;
}
if (rightNodeIndex <= heap.getHeapList().size() - 1) {
Node<Integer> rightNode = nodeArray.get(rightNodeIndex);
node.right = rightNode;
}
}
BTreePrinter.printNode(nodeArray.get(0));
}
}
public class Node<T extends Comparable<?>> {
Node<T> left, right;
T data;
public Node(T data) {
this.data = data;
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class BTreePrinter {
public static <T extends Comparable<?>> void printNode(Node<T> root) {
int maxLevel = BTreePrinter.maxLevel(root);
printNodeInternal(Collections.singletonList(root), 1, maxLevel);
}
private static <T extends Comparable<?>> void printNodeInternal(
List<Node<T>> nodes, int level, int maxLevel) {
if (nodes.isEmpty() || BTreePrinter.isAllElementsNull(nodes))
return;
int floor = maxLevel - level;
int endgeLines = (int) Math.pow(2, (Math.max(floor - 1, 0)));
int firstSpaces = (int) Math.pow(2, (floor)) - 1;
int betweenSpaces = (int) Math.pow(2, (floor + 1)) - 1;
BTreePrinter.printWhitespaces(firstSpaces);
List<Node<T>> newNodes = new ArrayList<Node<T>>();
for (Node<T> node : nodes) {
if (node != null) {
String nodeData = String.valueOf(node.data);
if (nodeData != null) {
if (nodeData.length() == 1) {
nodeData = "0" + nodeData;
}
}
System.out.print(nodeData);
newNodes.add(node.left);
newNodes.add(node.right);
} else {
newNodes.add(null);
newNodes.add(null);
System.out.print(" ");
}
BTreePrinter.printWhitespaces(betweenSpaces);
}
System.out.println("");
for (int i = 1; i <= endgeLines; i++) {
for (int j = 0; j < nodes.size(); j++) {
BTreePrinter.printWhitespaces(firstSpaces - i);
if (nodes.get(j) == null) {
BTreePrinter.printWhitespaces(endgeLines + endgeLines + i
+ 1);
continue;
}
if (nodes.get(j).left != null)
System.out.print("//");
else
BTreePrinter.printWhitespaces(1);
BTreePrinter.printWhitespaces(i + i - 1);
if (nodes.get(j).right != null)
System.out.print("\\\\");
else
BTreePrinter.printWhitespaces(1);
BTreePrinter.printWhitespaces(endgeLines + endgeLines - i);
}
System.out.println("");
}
printNodeInternal(newNodes, level + 1, maxLevel);
}
private static void printWhitespaces(int count) {
for (int i = 0; i < 2 * count; i++)
System.out.print(" ");
}
private static <T extends Comparable<?>> int maxLevel(Node<T> node) {
if (node == null)
return 0;
return Math.max(BTreePrinter.maxLevel(node.left),
BTreePrinter.maxLevel(node.right)) + 1;
}
private static <T> boolean isAllElementsNull(List<T> list) {
for (Object object : list) {
if (object != null)
return false;
}
return true;
}
}
Please note that BTreePrinter is a code I took somewhere in Stackoverflow long back and I modified to use with 2 digit numbers.It will be broken if we move to 3 digit numbers and it is only for simple understanding of how the Heap structure looks.A fix for 3 digit numbers is to keep everything as multiple of 3.
Also due credits to Sesh Venugopal for wonderful tutorial on Youtube on Heap data structure
public class PriorityQ<K extends Comparable<K>> {
private class TreeNode<T extends Comparable<T>> {
T val;
TreeNode<T> left, right, parent;
public String toString() {
return this.val.toString();
}
TreeNode(T v) {
this.val = v;
left = null;
right = null;
}
public TreeNode<T> insert(T val, int position) {
TreeNode<T> parent = findNode(position/2);
TreeNode<T> node = new TreeNode<T>(val);
if(position % 2 == 0) {
parent.left = node;
} else {
parent.right = node;
}
node.parent = parent;
heapify(node);
return node;
}
private void heapify(TreeNode<T> node) {
while(node.parent != null && (node.parent.val.compareTo(node.val) < 0)) {
T temp = node.val;
node.val = node.parent.val;
node.parent.val = temp;
node = node.parent;
}
}
private TreeNode<T> findNode(int pos) {
TreeNode<T> node = this;
int reversed = 1;
while(pos > 0) {
reversed <<= 1;
reversed |= (pos&1);
pos >>= 1;
}
reversed >>= 1;
while(reversed > 1) {
if((reversed & 1) == 0) {
node = node.left;
} else {
node = node.right;
}
reversed >>= 1;
}
return node;
}
public TreeNode<T> remove(int pos) {
if(pos <= 1) {
return null;
}
TreeNode<T> last = findNode(pos);
if(last.parent.right == last) {
last.parent.right = null;
} else {
last.parent.left = null;
}
this.val = last.val;
bubbleDown();
return null;
}
public void bubbleDown() {
TreeNode<T> node = this;
do {
TreeNode<T> left = node.left;
TreeNode<T> right = node.right;
if(left != null && right != null) {
T max = left.val.compareTo(right.val) > 0 ? left.val : right.val;
if(max.compareTo(node.val) > 0) {
if(left.val.equals(max)) {
left.val = node.val;
node.val = max;
node = left;
} else {
right.val = node.val;
node.val = max;
node = right;
}
} else {
break;
}
} else if(left != null) {
T max = left.val;
if(left.val.compareTo(node.val) > 0) {
left.val = node.val;
node.val = max;
node = left;
} else {
break;
}
} else {
break;
}
} while(true);
}
}
private TreeNode<K> root;
private int position;
PriorityQ(){
this.position = 1;
}
public void insert(K val) {
if(val == null) {
return;
}
if(root == null) {
this.position = 1;
root = new TreeNode<K>(val);
this.position++;
return ;
}
root.insert(val, position);
position++;
}
public K remove() {
if(root == null) {
return null;
}
K val = root.val;
root.remove(this.position-1);
this.position--;
if(position == 1) {
root = null;
}
return val;
}
public static void main(String[] args) {
PriorityQ<Integer> q = new PriorityQ<>();
System.out.println(q.remove());
q.insert(1);
q.insert(11);
q.insert(111);
q.insert(1111);
q.remove();
q.remove();
q.remove();
q.remove();
q.insert(2);
q.insert(4);
}
}