Insertion in Heap in java - java

Here is an implementation of a Heap in java without using array but I have some problem in inserting data in it for example when i insert 1,3,2,5,8 it inserts 5,8 two times one as subtree of 3 and another one as subtree of 2.
public class Heap {
private class Node {
private Node left, right,parent;
private int key;
private Node(int key) {
this.key = key;
}
}
private Node root;
public void insert(int key) {
root = insert(root,key,null);
}
private Node insert(Node x, int key,Node parent) {
if(x == null){
x = new Node(key);
x.parent = parent;
return x;
}if(x.left == null){
x.left = insert(x.left, key,x);
}else if (x.right == null) {
x.right = insert(x.right, key,x);
}else{
x.left = insert(x.left, key,x);
x.right = insert(x.right, key,x);
}
return x;
}
}

Problem is
x.left = insert(x.left, key,x);
x.right = insert(x.right, key,x);
you are simply inserting to both sub heaps...
This is not how heap works...

else {
x.left = insert(x.left, key, x);
x.right = insert(x.right, key, x);
}
inserts the key in both sub-trees of x.
You have to decide which branch to take, e.g. by comparing the key to the key at x, and using the right branch if key >= x.key, otherwise take the left branch (if done properly you'll get an ordered tree), or take the branch which is the smallest sub-tree of x.

Related

Red Black Trees getting merged?

I have 6 Red Black trees filled with different data, but the further down I go, the more my trees get mixed up. I've commented out all but two of them, here's my code for those two trees.
Scanner co2DateFile = new Scanner(new File("co2.csv"));
Scanner co2NumFile = new Scanner(new File("co2.csv"));
RedBlackBST co2DateKey = new RedBlackBST();
RedBlackBST co2NumKey = new RedBlackBST();
while (co2DateFile.hasNextLine()) {
String[] line3 = co2DateFile.nextLine().split(",");
if (line3[0].equals("World")) {
LocalDate date = parseDateString(line3[2]);
String stringDate = date.toString();
co2DateKey.root = co2DateKey.put(co2DateKey.root, stringDate, line3[3]);
}
}
while (co2NumFile.hasNextLine()) {
String[] line4 = co2NumFile.nextLine().split(",");
if (line4[0].equals("World")) {
co2NumKey.root = co2NumKey.put(co2NumKey.root, line4[3], line4[2]);
}
}
co2DateKey.inorder(co2DateKey.root);
I'm using the same file for both trees, but using different pieces of data for the keys and values. If I print co2DateKey inorder, then it prints the keys/values for co2DateKey and co2NumKey, but if I comment out the code for co2NumKey, then co2DateKey only prints its own keys/values. I'm not sure where they're getting crossed, so any help would be appreciated.
Here's my RedBlackBST class:
import java.util.Scanner;
import java.util.LinkedList;
import java.util.Queue;
import java.io.File;
import java.io.FileNotFoundException;
class Node
{
Node left;
Node right; // initializing Nodes and variables
String key;
String value;
String type;
boolean color; // true means color is red, false is black
Node(String key, String value)
{
this.key = key;
this.value = value;
left = null;
right = null;
color = true; // new nodes are always red
}
}
public class RedBlackBST {
public static Node root = null; // root initialized
public Node rotateLeft(Node myNode)
{
Node child = myNode.right;
Node childLeft = child.left; // assigning variables
child.left = myNode;
myNode.right = childLeft; // rotating nodes to the left
return child;
}
public Node rotateRight(Node myNode)
{
Node child = myNode.left; // assigning variables
Node childRight = child.right;
child.right = myNode; // rotating nodes to the right
myNode.left = childRight;
return child;
}
public void flipColors(Node x, Node y) // flipping colors of two given nodes
{
boolean temp = x.color; // uses temp to store color of first node
x.color = y.color; // first node takes second node's color
y.color = temp; // second node takes first node's color
}
public String get(String key) {
return get(root, key); // this function is called from main, which calls recursive get
}
private String get(Node x, String key) {
while (x != null) {
int cmp = key.compareTo(x.key); // compares current key with the one we are searching for
if (cmp < 0)
x = x.left;
else if (cmp > 0)
x = x.right; // recursively searches through tree until key is found
else
return x.value; // returns value associated with said key
}
return null;
}
public boolean getColor(String key) {
return getColor(root, key); // this function is called from main, which calls recursive getColor
}
private boolean getColor(Node x, String key) {
while (x != null) {
int cmp = key.compareTo(x.key); // same idea as get
if (cmp < 0)
x = x.left;
else if (cmp > 0) // recursively searches through tree to find key
x = x.right;
else
return x.color; // returns color of node associated with said key
}
return false;
}
public boolean isRed(Node myNode)
{
if (myNode == null) // checks color of node passed into function, returns true if red
return false;
return (myNode.color == true);
}
// insertion into Left Leaning Red Black Tree.
public Node put(Node myNode, String key, String value)
{
// inserting node, checks for violations to left leaning red black tree come next
if (myNode == null)
return new Node(key, value);
if (key.compareTo(myNode.key) < 0) // compares keys, recursive calls to find proper spot
myNode.left = put(myNode.left, key, value);
else if (key.compareTo(myNode.key) > 0)
myNode.right = put(myNode.right, key, value);
else if (key.equals(myNode.key) == true) // if key is already in tree, numeric value is replaced
myNode.value = value;
else
return myNode;
// case 1.
// when right child is Red but left child is
// Black or doesn't exist.
if (isRed(myNode.right) && !isRed(myNode.left))
{
myNode = rotateLeft(myNode); // left rotate the node to make it into valid structure.
flipColors(myNode, myNode.left); // swap the colors as the child node should always be red
}
// case 2
// when left child as well as left grand child are Red
if (isRed(myNode.left) && isRed(myNode.left.left))
{
myNode = rotateRight(myNode); // right rotate the current node to make it into a valid structure, then flip colors
flipColors(myNode, myNode.right);
}
// case 3
// when both left and right child are Red in color.
if (isRed(myNode.left) && isRed(myNode.right))
{
myNode.color = !myNode.color; // invert the color of node as well it's left and right child
myNode.left.color = false; // change the color to black
myNode.right.color = false;
}
return myNode;
}
public Iterable<String> keys(Node node, Queue<String> queue) { // uses inorder traversal to put keys in right order
if (node != null)
{
keys(node.left, queue);
queue.add(node.key); // adds each key to queue in correct order
keys(node.right, queue);
}
return queue; // returns queue after all keys have been added
}
public String highest(Node node) {
Node current = node;
while (current.right != null) {
current = current.right;
}
return current.key;
}
void inorder(Node node)
{
if (node != null)
{
inorder(node.left);
System.out.println(node.key + " " + node.value);
inorder(node.right);
}
}
Problem is here:
public static Node root = null; // root initialized
The root is declared static, which means it is shared between all instances of RedBlackBST. They all have the same root. Sure they will be mixed up.
Remove the static keyword.

How to find max value(not key) in an AVL tree?

I build a simple AVL tree as following, each node has key and value. Now I want to implement a method that could return the key of node which has the largest value. For example, if I have a tree like:
(7,1)
/ \
(4,3) (13,8)
/ \ / \
(2,4) (6,3) (11,8) (15,2)
/ \ / / \ / \
(1,9)(3,0)(5,16)(9,2)(12,3)(14,3)(16,5)
/ \
(8,19)(10,4)
The method would return 8, as the node (8,19) has the largest value. Following is my avl tree and node constructor. I do try to implement this method by hand but somehow it doesn't work. I'd be grateful if someone coule help me.
public class AVLTreeImp<T extends Comparable<? super T>,V> implements AVLTree<T,V>{
private Node<T, V> root;
public class Node<T extends Comparable<? super T>,V> implements AVLTree.Node{
T key;
V value;
Node<T,V> left;
Node<T,V> right;
Node<T,V> parent;
int height;
public Node(){
this.key = null;
this.left = null;
this.right = null;
this.parent = null;
this.height = 0;
this.value = null;
}
public Node(T key, V value, Node<T,V> left, Node<T,V> right){
this.key = key;
this.left = left;
this.right = right;
this.parent = null;
this.height = 0;
this.value = value;
}
}
public AVLTreeImp(){
this.root = null;
}
#Override
public void insert(T key, V value){
root = insert(root,key,value);
}
private Node<T,V> insert(Node<T,V> node, T key, V value){
if (node == null){
node = new Node<T,V>(key, value,null,null);
}else{
if (key.compareTo(node.key) < 0){
node.left = insert(node.left, key, value);
if (!(isBalanced(node))) {
if (key.compareTo(node.left.key) < 0) {
node = leftLeftRotation(node);
} else {
node = leftRightRotation(node);
}
}
}else if (key.compareTo(node.key) > 0){
node.right = insert(node.right,key,value);
if (!(isBalanced(node))){
if (key.compareTo(node.right.key) > 0){
node = rightRightRotation(node);
}else{
node = rightLeftRotation(node);
}
}
}
}
regenerateHeight(node);
return node;
}
Below is my implementation of this method, I'm not sure what's wrong with this.
public Integer findMax(){
Node<Integer,Integer> result = (Node<Integer,Integer>)root;
result.value = 0;
return findMax((Node<Integer, Integer>) root,result);
}
private Integer findMax(Node<Integer,Integer> node,Node<Integer,Integer> result){
if (node == null){
return result.key;
}
if (node.value > result.value ||
(node.value == result.value && node.key.compareTo(result.key) < 0)){
result = node;
}
findMax(node.left,result);
findMax(node.right,result);
return result.key;
}
You have a balanced BST! That means operations like the following are efficient,
Insert/Remove
Max/Min key
Membership Query
But turns out, as comment suggested, you’d have to traverse the entire tree to find an element matching your criteria, which is a O(N) op, not optimal. Worse, your structure is recursive!
You can,
Maintain a priority queue keyed by your “value”
Build another tree keyed by your “value”
They are both far more efficient than a full tree look up.
However, without further context, I find you usage of the tree questionable? Why is your tree keyed by something you’re not operating on?
Your recursive findMax method is incorrect. You are assigning result = node;
but this is only local assignment not updating result when calling findMax(node.left,result); and findMax(node.right,result);
. This should work:
public Integer findMax(){
Node<Integer,Integer> result = (Node<Integer,Integer>)root;
result = findMax((Node<Integer, Integer>) root,result);
return result.key;
}
private Node<Integer,Integer> findMax(Node<Integer,Integer> node,Node<Integer,Integer> result){
if (node == null){
return result;
}
if (node.value > result.value ||
(node.value == result.value && node.key.compareTo(result.key) < 0)){
result = node;
}
result = findMax(node.left,result);
result = findMax(node.right,result);
return result;
}
More about passing java parameters here Is Java "pass-by-reference" or "pass-by-value"?

what's the purpose of variable val in this algo

it's an algo from internet about Red-Black BST Java implementation. I am confused about the variable named val in this program. Here is the code:
package tools;
public class redBlack2 {
private static final boolean RED = true;
private static final boolean BLACK = false;
private Node root;
public redBlack2() {}
private class Node {
private int key;
private int val;
private Node left, right;
private boolean color;
public Node(int key, int val, boolean color) {
this.key = key;
this.val = val;
this.color = color;
}
}
private boolean isRed(Node x) {
if (x == null) return false;
return x.color == RED;
}
public int get(int key) {
return get(root, key);
}
private int get(Node x, int key) {
while (x != null) {
if (key < x.key) x = x.left;
else if (key > x.key) x = x.right;
else return x.val;
}
System.out.println("There is no such key.");
return 0;
}
public boolean contains(int key) {
return get(key) != 0;
}
public void put(int key, int val) {
root = put(root, key, val);
root.color = BLACK;
}
private Node put(Node h, int key, int val) {
if (h == null) return new Node(key, val, RED);
if (key<h.key) h.left = put(h.left, key, val);
else if (key>h.key) h.right = put(h.right, key, val);
else if (key == h.key) h.val = val;
if (isRed(h.right) && !isRed(h.left)) h = rotateLeft(h);
if (isRed(h.left) && isRed(h.left.left)) h = rotateRight(h);
if (isRed(h.left) && isRed(h.right)) flipColors(h);
return h;
}
private Node rotateRight(Node h) {
Node x = h.left;
h.left = x.right;
x.right = h;
x.color = x.right.color;
x.right.color = RED;
return x;
}
private Node rotateLeft(Node h) {
Node x = h.right;
h.right = x.left;
x.left = h;
x.color = x.left.color;
x.left.color = RED;
return x;
}
private void flipColors(Node h) {
h.color = !h.color;
h.left.color = !h.left.color;
h.right.color = !h.right.color;
}
public static void main(String[] args) {
redBlack2 r = new redBlack2();
r.put(34,1);
r.put(23,2);
r.put(65,3);
r.put(73, 4);
System.out.print(r.get(73));
}
}
is that just a mark we give to the number we put inside the Tree? then don't we already have key as a mark? why we still need variable val?
Yes, you're right, it's just like a mark. We can indeed implement this algorithm with just one variable, i.e., key. In this algo, val is something that is being stored as a type of data for which we need to keep track.
For example consider this
You have several numbered boxes like 34, 23, 65, 73 and you want to
implement RB Tree operations on them. So these number on boxes
resembles the key in your algorithm.
Now consider each box contains a number of balls in it. These balls
can be seen as a data which is stored inside the box and you need to
keep a track of it. So this can be considered as val.
You can even go a step further and keep a track of several things that are inside a box by changing the data-type of val to List or Map or even user-defined objects. It will still work the same way.
In this implementation, this data structure acts like a Map, which means it maps keys to values. That val is a common abbreivation of value, which is quite self-explainatory. It could be of any type existing in Java, be it primitive or reference.

Turning a regular Binary Search Tree into an Balanced Binary Search Tree

I was able to write my own Binary Search Tree, but I am having a lot of trouble figuring out how to turn that into a Balanced Binary Search tree.
Could someone help me implement a Balanced binary search tree code with the regular binary tree.
I think I was successful in changing my TreeNode class to have the necessary changes.
I added another key and another value along with another TreeNode middle to hold the middle pointer when you get to a 3 node in the tree.
I then added another constructor to hold the case if it was a 3 node. I believe I did this right.
public class TreeNode<V>
{
public int key;
public int key1;
public V value;
public V value1;
public TreeNode<V> left;
public TreeNode<V> right;
public TreeNode<V> middle;
public TreeNode(int key, V value)
{
this.key = key;
this.value = value;
this.left = null;
this.right = null;
}
public TreeNode(int key, V value, int key1, V value1)
{
this.key = key;
this.key1 = key1;
this.value = value;
this.value1 = value1;
this.left = null;
this.right = null;
this.middle = null;
}
The tough part comes to when I need to change the actual BST Class. I know the put is going to change quite a bit because we have to check and see if it is a 2 node or a 3 node, as well as check for what the parent node is.
Here is what I have so far:
public class BST<V>
{
private TreeNode<V> root;
public BST()
{
this.root = null;
}
public V get(int key)
{
return get(root, key);
}
private V get(TreeNode<V> current, int key)
{
if (current == null)
return null;
else if (key == current.key)
return current.value;
else if (key < current.key)
return get(current.left, key);
else
return get(current.right, key);
}
public void put(int key, V value)
{
if (root == null)
root = new TreeNode<>(key, value);
else
put(root, key, value);
}
private void put(TreeNode<V> current, int key, V value)
{
if (key == current.key)
{
current.value = value;
return;
}
else if (key < current.key)
{
if (current.left == null)
{
current.left = new TreeNode<>(key, value);
return;
}
else
put(current.left, key, value);
}
else
{
if (current.right == null)
{
current.right = new TreeNode<>(key, value);
return;
}
else
put(current.right, key, value);
}
}
}
My difficultly comes most with the recursion. I understand how basic recursion works, but using it to implement a balanced binary search tree is seeming a much more difficult talk than originally thought.
You only want a binary search tree, correct? If so, there isn't really a need for keys (Which are used for M-ary trees).
This isn't exactly an answer, but hopefully this will help simplify your code at least a little bit.

How do I implement a priority queue with explicit links (using a triply linked datastructure)?

I am trying to implement a priority queue, using a triply linked data structure. I want to understand how to implement sink and swim operations, because when you use an array, you can just compute the index of that array and that's it. Which doesn't make sense when you use a triply-linked DS.
Also I want to understand how to correctly insert something in the right place, because when you use an array, you can just insert in the end and do a swim operation, which puts everything in the right place, how exactly do I compute that "end" in a linked DS?
Another problem would be removing the element with the biggest priority. To do that, for an array implementation, we just swap the last element with the first (the root) one and then, after removing the last element, we sink down the first one.
(This is a task from Sedgewick).
I posted this in case someone gets stuck doing this exercise from Sedgewick, because he doesn’t provide a solution for it.
I have written an implementation for maximum oriented priority queue, which can be modified according for any priority.
What I do is assign a size to each subtree of the binary tree, which can be defined recursively as size(x.left) + size(x.right) + 1. I do this do be able to find the last node inserted, to be able to insert and delete maximum in the right order.
How sink() works:
Same as in the implementation with an array. We just compare x.left with x.right and see which one is bigger and swap the data in x and max(x.left, x.right), moving down until we bump into a node, whose data is <= x.data or a node that doesn’t have any children.
How swim() works:
Here I just go up by doing x = x.parent, and swapping the data in x and x.parent, until x.parent == null, or x.data <= x.parent.
How max() works:
It just returns root.data.
How delMax() works:
I keep the last inserted node in a separate field, called lastInserted. So, I first swap root.data with lastInserted.data. Then I remove lastInserted by unhooking a reference to it, from its parent. Then I reset the lastInserted field to a node that was inserted before. Also we must not forget to decrease the size of every node on the path from root to the deleted node by 1. Then I sink the root data down.
How insert() works:
I make a new root, if the priority queue is empty. If it’s not empty, I check the sizes of x.left and x.right, if x.left is bigger in size than x.right, I recursively call insert for x.right, else I recursively call insert for x.left. When a null node is reached I return new Node(data, 1). After all the recursive calls are done, I increase the size of all the nodes on the path from root to the newly inserted node.
Here are the pictures for insert():
And here's my java code:
public class LinkedPQ<Key extends Comparable<Key>>{
private class Node{
int N;
Key data;
Node parent, left, right;
public Node(Key data, int N){
this.data = data; this.N = N;
}
}
// fields
private Node root;
private Node lastInserted;
//helper methods
private int size(Node x){
if(x == null) return 0;
return x.N;
}
private void swim(Node x){
if(x == null) return;
if(x.parent == null) return; // we're at root
int cmp = x.data.compareTo(x.parent.data);
if(cmp > 0){
swapNodeData(x, x.parent);
swim(x.parent);
}
}
private void sink(Node x){
if(x == null) return;
Node swapNode;
if(x.left == null && x.right == null){
return;
}
else if(x.left == null){
swapNode = x.right;
int cmp = x.data.compareTo(swapNode.data);
if(cmp < 0)
swapNodeData(swapNode, x);
} else if(x.right == null){
swapNode = x.left;
int cmp = x.data.compareTo(swapNode.data);
if(cmp < 0)
swapNodeData(swapNode, x);
} else{
int cmp = x.left.data.compareTo(x.right.data);
if(cmp >= 0){
swapNode = x.left;
} else{
swapNode = x.right;
}
int cmpParChild = x.data.compareTo(swapNode.data);
if(cmpParChild < 0) {
swapNodeData(swapNode, x);
sink(swapNode);
}
}
}
private void swapNodeData(Node x, Node y){
Key temp = x.data;
x.data = y.data;
y.data = temp;
}
private Node insert(Node x, Key data){
if(x == null){
lastInserted = new Node(data, 1);
return lastInserted;
}
// compare left and right sizes see where to go
int leftSize = size(x.left);
int rightSize = size(x.right);
if(leftSize <= rightSize){
// go to left
Node inserted = insert(x.left, data);
x.left = inserted;
inserted.parent = x;
} else{
// go to right
Node inserted = insert(x.right, data);
x.right = inserted;
inserted.parent = x;
}
x.N = size(x.left) + size(x.right) + 1;
return x;
}
private Node resetLastInserted(Node x){
if(x == null) return null;
if(x.left == null && x.right == null) return x;
if(size(x.right) < size(x.left))return resetLastInserted(x.left);
else return resetLastInserted(x.right);
}
// public methods
public void insert(Key data){
root = insert(root, data);
swim(lastInserted);
}
public Key max(){
if(root == null) return null;
return root.data;
}
public Key delMax(){
if(size() == 1){
Key ret = root.data;
root = null;
return ret;
}
swapNodeData(root, lastInserted);
Node lastInsParent = lastInserted.parent;
Key lastInsData = lastInserted.data;
if(lastInserted == lastInsParent.left){
lastInsParent.left = null;
} else{
lastInsParent.right = null;
}
Node traverser = lastInserted;
while(traverser != null){
traverser.N--;
traverser = traverser.parent;
}
lastInserted = resetLastInserted(root);
sink(root);
return lastInsData;
}
public int size(){
return size(root);
}
public boolean isEmpty(){
return size() == 0;
}
}

Categories