I've started to learn about data structures at school and I have an homework where I have to implement an Binary Search Tree and tell the memory occupied by the data structures.
I've created my BST and I believe all is working as expected but I don't have a clue how to calculate the memory used.
This is the code I've created for the data structure and the code for inserting:
class Node {
int key, totalValue;
public Node left;
public Node right;
public Node (int key, int totalValue) {
this.key= key;
this.totalValue = totalValue;
this.left = null;
this.right = null;
}
public int getkey() {
return key;
}
public int getTotalValue() {
return totalValue;
}
}
class Tree {
private Node root;
public Tree() {
this.root = null;
}
public Node getRoot() {
return this.root;
}
public void setRoot(Node node) {
this.root = node;
}
}
And this is the code for inserting:
private static void addNode(Node node, Node tempNode) {
if (tempNode.getkey() < node.getkey()) {
if (node.left == null) {
node.left = tempNode;
} else {
addNode(node.left, tempNode);
}
} else if (tempNode.getkey() > node.getkey()){
if (node.right == null) {
node.right = tempNode;
} else {
addNode(node.right, tempNode);
}
}else{
node.totalValue += tempNode.getTotalValue();
}
}
I know that for each node I need 8 bytes for the 2 int, but I don't know how much each pointer occupies.
Second question. Imagine I insert 25000 entries from 10000 keys. Each insertion will be used recursively until the new node finds it's "position". How can I calculate the memory occupied?
The basic concept behind the recursive method would be
GetMemoryUsed(node)
{
if(node is leaf)
return (node.localMemory)
return(GetMemoryUsed(node.left) + GetMemoryUsed(node.right) + node.localMemory);
}
where node.localMemory is just the amount of memory that the specific node uses (not counting the child nodes)
As far as getting precise numbers, here are a couple of tools you might be interested in:
Java Instrumentation
JMap Memory Map
Related
I have written a program to find all valid parameter combination if an input N is given. There should be N number of parameters.
For example, if N = 2, the answer will be ()(), (()) and if N = 3 the answer will be ((())), (())(), ()(()), ()()(), (()()).
I have implemented the solution using binary tree in Java. Here is my solution.
class Node {
char value;
Node right;
Node left;
public Node(char value) {
this.value = value;
}
public void insertRight(char value) {
Node node = new Node(value);
this.right = node;
}
public void insertLeft(char value) {
Node node = new Node(value);
this.left = node;
}
}
public class App
{
private static final int N = 3;
public static void main (String[] args)
{
Node tree = new Node('(');
insertNodes(tree, N - 1, 1);
printParams("", tree);
}
private static void insertNodes(Node currentNode, int remainingOpen, int remainingClose) {
if (remainingOpen > 0) {
currentNode.insertLeft('(');
insertNodes(currentNode.left, remainingOpen - 1, remainingClose + 1);
}
if (remainingClose > 0) {
currentNode.insertRight(')');
insertNodes(currentNode.right, remainingOpen, remainingClose - 1);
}
}
private static void printParams(String paramStr, Node node) {
paramStr = paramStr + node.value;
if (node.left == null && node.right == null) {
System.out.println(paramStr);
return;
}
if (node.left != null)
printParams(paramStr, node.left);
if (node.right != null)
printParams(paramStr, node.right);
}
}
I want to know the complexity of this solution. What would be the complexity for creating the tree and what would be the complexity for traversing on each path?
I know that, there will be 2 * N nodes in each path and there will be at most 2^2N children. If we are traversing each path from root, complexity may be N * 2 ^ 2N. But, I'm not able to think of complexity when recursion is involved.
The complexity for creation is given by the number of nodes you create, which is intuitive enough. Traversal is the same, since you visit each node exactly once.
In your case, the number of nodes form a Catalan sequence: https://en.wikipedia.org/wiki/Catalan_number
.
I am trying to search a doubly-linked list in Java for a term, and return it if found. Here is my code so far:
private class Node {
public String content;
public Node up;
public Node left;
public Node right;
}
private Node searchList(String term, Node node) {
while (node != null) {
System.out.print(node.name + " - "); //To see process
if (node.content.equals(term)) {
return node;
} else if (node.right != null) {
return searchList(term, node.right);
}
node = node.left;
}
return null;
}
My algorithm is basically:
While the node is not null
Check if it matches the search term
If there is an element to he right, scan that with recursion
Both points are now null, item is not present
Edit with my question, sorry:
I cannot get it to search down to bottom levels and having trouble understanding where I have gone wrong.
Any help would be appreciated!
I got to agree with the comments that your question is unclear.
However, I assume you are just looking for a way to implement a recursive search on a double linked list (in which null elements are not allowed). As the other answer already mentions, I assume type Page to be a subtype of Node. In fact, I will substitute it in my example below.
Since there seems to be some misconception about implementing a double linked list and about recursion itself, I will give a condensed but running example.
The code you are presenting lacks a termination condition for the recursion. Which, unfortunately, also holds true for ikicha's solution. One way (amongst others) to accomplish this is to use a helper method to pass an invariant (eg. the start element) or counter from one iteration of the recursion to the next one.
The line node = node.left in your example has no effect. If you wanted to achieve a search in both directions (as ikicha sketched) I would be interested in why direction matters for you.
public class DoubleLinked {
private Node first;
private Node last;
private int size;
private class Node {
public String content;
public Node left;
public Node right;
public Node(String content) {
this.content = content;
}
}
private void addElement(Node addedNode) {
if (first == null) {
first = addedNode;
last = addedNode;
} else {
last.right = addedNode;
addedNode.left = last;
addedNode.right = first;
last = addedNode;
}
size++;
}
private Node searchList(String term, Node node) {
int tries = 0;
if (node != null) {
return searchHelper(term, node.right, tries);
}
return null;
}
private Node searchHelper(String term, Node node, int tries) {
if (node == null || tries >= size) {
return null;
}
if (node.content.equals(term)) {
return node;
} else {
return searchHelper(term, node.right, tries);
}
}
public static void main(String[] args) {
DoubleLinked list = new DoubleLinked();
list.addElement(list.new Node("first"));
Node startNode = list.new Node("second");
list.addElement(startNode);
list.addElement(list.new Node("third"));
list.addElement(list.new Node("forth"));
Node r = list.searchList("forth", startNode);
System.out.println(r!=null?r.content:"term not found");
}
}
I think your algorithm computes same node several times because move left and find all right nodes of the left one repeatedly.
You can find node by search two direction each from start node.
private Node internalSearchList(String term, Node node, int direction) {
if (node == null) {
return null;
}
if (term.equals(node.content)) {
return node;
} else {
return internalSearchList(term, direction == 0 ? node.left : node.right, direction);
}
}
private Node searchList(String term, Node node) {
// search to left side
Node result = internalSearchList(term, node, 0);
if (result != null) {
return result;
} else {
return internalSearchList(term, node, 1);
}
}
And also I think the type of Node.left and Node.right must be Node.
private class Node {
public String content;
public Node up;
public Node left;
public Node right;
}
Solution i am pasting comes from this Geek URL
Its written in C, so i tried converting it in JAVA as below - (please do correct me if m wrong, i am not c/c++ person)
Program
// A simple recursive function to convert a given Binary tree to Doubly
// Linked List
// root --> Root of Binary Tree
// head --> Pointer to head node of created doubly linked list
public void BinaryTree2DoubleLinkedList(BTNodes root, BTNodes head)
{
if(root == null)
return;
// Initialize previously visited node as NULL. This is
// declared outside the recursive function so that the same value
// is accessible in all recursive calls
prev = null;
// Recursively convert left subtree
BinaryTree2DoubleLinkedList(root.getLeft(), head);
//set head of LL if not set
if(orgHead == null)
orgHead = root;
// Now convert this node
if (prev == null)
head = root;
else
{
root.setLeft(prev);
prev.setRight(root);
}
prev = root;
// Finally convert right subtree
BinaryTree2DoubleLinkedList(root.getRight(), head);
}
Tree In Consideration
10
/ \
5 15
/ \ / \
2 7 12 18
/
1
/
0
Problem
This program returns output :
0 1 2 5 7 10 15 18
As you can see, 12 is missing from the code.I tried to dry run it many times but still not able to find out the real issue.....I tried searching for different solutions but most of them traverse in the part-converted-LL which increases the time complexity.
In original C code function prototype is following:
void BinaryTree2DoubleLinkedList(node *root, node **head)
**head mean double pointer, head value can be changed within function using *head. In java you can't modify function parameter because they are always copied, but you can modify array element.
So please try following code:
BTNode prev;
void BinaryTree2DoubleLinkedList(BTNodes root, BTNodes[] head)
{
// Base case
if (root == null) return;
// Initialize previously visited node as NULL. This is
// static so that the same value is accessible in all recursive
// calls
// Recursively convert left subtree
BinaryTree2DoubleLinkedList(roor.getLeft(), head);
// Now convert this node
if (prev == null)
head[0] = root;
else
{
root.setLeft(prev);
prev.setRight(root);
}
prev = root;
// Finally convert right subtree
BinaryTree2DoubleLinkedList(root.getRight(), head);
}
Initial call should look like:
BTNodes[] head = new BTNodes[1];
BinaryTree2DoubleLinkedList(root, head);
// result is in head[0]
To avoid ugly allocation for head element better to make additional function like following:
BTNodes BinaryTree2DoubleLinkedList(BTNodes root) {
BTNodes[] head = new BTNodes[1];
BinaryTree2DoubleLinkedList(root, head);
return head[0];
}
Converting Binary Search tree into Doubly Linked List is kind of easy task if we use left and right fields of Node.
Recursion helps us here.
First, go down till the left node. Assign the left most leaf node as prev and also as head of list.
Once control come back from leaf node to its parent, assign current node i.e. parent of left node as right of prev and left of current node as leaf node.
Same is goes for right leaf child of current node.
Once we are out of complete recursion, we will have our doubly linked list, with listHead and listTail.
{
Node prev = null;
Node listHead = null;
Node listTail = null;
public void convertToList(Node node)
{
if(node == null)
return;
convertToList(node.left);
if(listHead == null)
listHead = node;
if(prev == null)
prev = node;
else
{
node.left = prev;
prev.right = node;
}
prev = node;
convertToList(node.right);
if(node.right == null)
listTail = node;
}
public void printList()
{
Node node = listHead;
System.out.println("Doubly Linked List from Head: ");
while(node!= null)
{
System.out.print(node.data+" ");
node = node.right;
}
}
public void printListFromTail()
{
Node node = listTail;
System.out.println("Doubly Linked List from Tail: ");
while(node!= null)
{
System.out.print(node.data+" ");
node = node.left;
}
}
}
For any google visitor, i worked out a way to avoid head[0] - (this might pose problems if the program is called through different object for different trees, as head[0] may get overwritten)
Here is the implementation :
Trick is to remove prev = null; from the code and initialize tempHead = null and prev = null in the calling function, not in recursive call.
void BinaryTree2DoubleLinkedList(BTNodes root, BTNodes tempHead)
{
// Base case
if (root == null) return; //optional, not needed in fact
// Recursively convert left subtree
if(root.getLeft() != null) //purely to reduce number of traversed node
BinaryTree2DoubleLinkedList(root.getLeft(), tempHead);
//set Original Head of the List, this would be leftmost
//leaf in the tree
if(orgHead == null)
orgHead = root;
// Now convert this node
if (prev == null)
tempHead = root;
else
{
root.setLeft(prev);
prev.setRight(root);
}
prev = root;
// Finally convert right subtree
if(root.getRight() != null) //purely to reduce number of traversed node
BinaryTree2DoubleLinkedList(root.getRight(), tempHead);
}
Other helper Details :
Initial call :
BinaryTree2DoubleLinkedList(bst.root,tempHead); //root and null value
Traverse List
printList(orgHead); //pass original head to print function
Complexity :
Time = Space : O(n)
public void ConverttoList(Node root){
Node top = root;
top.left = GetLeftNode(top.left);
top.right = GetRightNode(top.right);
top.left.right= top;
top.right.left= top;
Node leftmost = top.left;
while(leftmost.left!=null){
leftmost = leftmost.left;
}
while(leftmost!= null) {
System.out.printf(leftmost.Data + "->");
leftmost = leftmost.right;
}
}
public Node GetLeftNode(Node root){
if(root.left == null){
return root;
}
else{
Node startnode = GetLeftNode(root.left);
startnode.right = root;
root.left = startnode;
root.right = GetRightNode(root.right);
root.right.left = root;
Node rightmost=root.right;
while (rightmost.right!=null){
rightmost=rightmost.right;
}
return rightmost;
}
}
public Node GetRightNode(Node root){
if(root.left == null){
return root;
}
else{
Node startnode = GetLeftNode(root.left);
startnode.right = root;
root.left = startnode;
root.right = GetRightNode(root.right);
root.right.left = root;
Node leftmost=root.left;
while (leftmost.left!=null){
leftmost=leftmost.left;
}
return leftmost;
}
}
// bst to dll will generate a sorted dll
public class TreeToDLL {
public static void main(String args[]){
TreeNode t = new TreeNode(5);
TreeNode t3 = new TreeNode(3);
TreeNode t1 = new TreeNode(1);
TreeNode t7 = new TreeNode(7);
TreeNode t9 = new TreeNode(9);
TreeNode t8 = new TreeNode(8);
t.setLeft(t3);
t3.setLeft(t1);
t.setRight(t7);
t7.setRight(t9);
t9.setLeft(t8);
DllNode dll = convert(t);
dll.print();
}
static class DllNode{
int data;
DllNode next;
DllNode prev;
public DllNode(int data) {
this.data = data;
}
public DllNode() {
}
public int getData() {
return data;
}
public DllNode getPrev() {
return prev;
}
public void setPrev(DllNode prev) {
this.prev = prev;
}
public void setData(int data) {
this.data = data;
}
public DllNode getNext() {
return next;
}
public void setNext(DllNode next) {
this.next = next;
}
public void print(){
DllNode t = this;
while(t!=null){
System.out.print(t.getData()+"->");
t = t.getNext();
}
}
}
static class TreeNode{
int data;
TreeNode left;
TreeNode right;
public TreeNode(int data) {
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public TreeNode getLeft() {
return left;
}
public TreeNode setLeft(TreeNode left) {
this.left = left;
return this;
}
public TreeNode getRight() {
return right;
}
public TreeNode setRight(TreeNode right) {
this.right = right;
return this;
}
}
private static DllNode convert(TreeNode t){
DllNode d =convert(t,new PreviousDLLNode());
while(d.prev!=null){
d = d.prev;
}
return d;
}
private static DllNode convert(TreeNode t, PreviousDLLNode d){
if(t==null) return null;
convert(t.getLeft(),d);
DllNode dn = new DllNode(t.getData());
if(d.val!=null){
d.val.setNext(dn);
}
dn.setPrev(d.val);
d.val = dn;
convert(t.getRight(),d);
return dn; // this node will be in the middle of the dll.
}
private static class PreviousDLLNode{
DllNode val;
}
}
I solved my problem inserting treenodes sorted in order in a DLL like that:
I added in my netBeans package the DoubleLinkedList and BinarySearchTree classes needed (including the TreeNode and the DoubleNode etc) and
I modified the BinarySearchTree as shown below:
public class BinarySearchTree {
DoubleLinkedList dL;
TreeNode root;
public BinarySearchTree() {
this.root = null;
this.dL=new DoubleLinkedList();
}
public void
tree2DList(TreeNode TN) {
if (TN == null) {
return ;
} else {
tree2DList(TN.left);
dL.insertLast((YourClassOfObjects)TN.getItem());
tree2DList(TN.right);
}
return;
}
I added a DoubleLinkedList field which I initialized in the default constructor of BST, calling the default constructor of DLL and I created the recursive method below, inspired from and following inOrderTraversal for the sorted input of tree nodes in the DLL
I am currently revising for my programming exam and I have came across a question from a past paper that has me rather confused.
I have two classes, Queue and Node, shown below.
The question states that I have to extend the behaviour of the Queue class by adding the necessary code to the inspectQueue method that prints to the console all the data stored within the queue.
The only solution I can think of, and it is very weak, is to have a simple ArrayList and every time an element is enqueued/dequeued then add/remove the node to/from the list.
Is there a better solution that I am glossing over? I'd really appreciate some guidance.
I've commented the code where I have implemented my "solution" the rest of the code is how it appears in the exam paper.
Thanks for your time.
Queue.java
public class Queue {
protected Node head;
protected Node last;
//added by me
private ArrayList<Node> nodes = new ArrayList<Node>();
//end my add
public boolean isEmpty() {
return (this.head == null);
}
public void enqueue(Object d) {
Node n = new Node();
n.setData(d);
nodes.add(n); //added by me
if (this.isEmpty()) {
head = n;
last = n;
}
else {
last.setNext(n);
last = n;
}
}
public Object dequeue() {
if(this.isEmpty()) {
this.last = null;
return null;
}
else {
Node h = this.head;
nodes.remove(h); //added by me
head = h.getNext();
return h.getData();
}
}
public Object peek() {
if(this.isEmpty()) {
return null;
}
else {
Node t = this.head;
return t.getData();
}
}
public void clearQueue() {
this.head = null;
this.last = null;
}
public void inspectQueue() {
//added by me (all below)
System.out.println("Inspecting Queue: (contains " + nodes.size() + " nodes)");
for(Node n : nodes) {
System.out.println(n.getData());
}
}
}
Node.java
public class Node {
protected Object data;
protected Node next;
public void setNext(Node e) {
this.next = e;
}
public Node getNext() {
return this.next;
}
public void setData(Object d) {
this.data = d;
}
public Object getData() {
return this.data;
}
}
Your nodes form a linked list, so just do
public void inspectQueue() {
Node n = head;
while (n != null) {
System.out.println(n.getData());
n = n.getNext();
}
}
This is a very basic data structure, called a LinkedList. In the your code for the Node class you can see the following:
protected Node next;
This means that every Node also holds a reference to the next Node in the list. If this Node is null, there are no more elements in the list. Knowing this, you can loop somewhat like this:
Node currentNode = this.head;
while(currentNode != null) {
System.out.println(currentNode.getData().toString());
currentNode = currentNode.getNext();
}
This eliminates the need for an ArrayList to store your references.
The LinkedList is a VERY frequently used data structure and very important to understand. If you have any questions, just go ahead and ask!
If you also want to have the size, keep a counter along, increment it each time you call getNext(), and print the size after the for loop.
You don't need the array, you have that information stored within the Node next property:
public void inspectQueue() {
Node current = head;
while(current != null) {
System.out.println(n.getData());
current = current.getNext();
}
}
That data structure is called linked list.
The simpler solution is to start with queue.head and traverse the linked list of nodes using node.next, printing the data as you go along.
I had to do some methods about BinaryTree (no Search Binary Tree). I'm not able to do 3 methods: reflect (reflect the tree, my code don't work beacuse reflect only a part of the tree), cut and cut2. The code is:
public class BinaryTree {
protected class Node {
Integer element;
Node left;
Node right;
Node(int element) {
this.element = element;
left = right = null;
}
Node(int element, Node left, Node right) {
this.element = element;
this.left = left;
this.right = right;
}
// is leaf?
boolean isLeaf() {
return left == null && right == null;
}
}
protected Node root;
public BinaryTree() {
root = null;
}
/* doesn't work */
public void reflect() {
if (root == null)
return;
reflect(root);
}
protected void reflect(Node node) {
reflect(node.left);
reflect(node.right);
Node temp = new Node(node.left.element);
node.left.element = node.right.element;
node.right.element = temp.element;
}
/* this method had to trim the tree at level h,
if h=0, it cut the whole tree. It change the original tree */
/* doesn't work */
public void cut(int h) {
}
/* i can change parameters */
protected void cut(Node node, int h) {
}
/* this method had to trim the tree at level h,
if h=0, it cut the whole tree. It doesn't change the original tree,
it returns a new tree */
/* doesn't work */
public BinaryTree cut2(int h) {
}
/* i can change parameters */
protected BinaryTree cut2(Node node, int h) {
}
}
}
I'm not able to do the methods reflect cut and cut2. Help me please, thank you!
This smells like homework, and even though the tag was pruned, I don't think us writing complete implementations of binary trees is the right thing.
Having said that, can you explain what isn't clear about implementing both of those methods? They're pretty much equal, except for the tree copying needed for cut2. I'd implement it via a recursive private method cutInternal(Node n, int currLevel, int h) passing in the level number that we're currently at. Then, when currLevel == h we just prune both nodes and return.
You almost had reflect right. Just avoid creating new Node objects:
protected void reflect(Node node) {
if (node != null) {
reflect(node.left);
reflect(node.right);
Node temp = node.left;
node.left = node.right;
node.right = temp;
}
}
As for cut:
public void cut(int h) {
if (h == 0) {
root = null;
} else {
cut(root, h - 1);
}
}
Then you can write cut(Node, int):
protected void cut(Node node, int h) {
if (node != null) {
if (h == 0) {
node.left = node.right = null;
} else {
cut(node.left, h - 1);
cut(node.right, h - 1);
}
}
}
See if you can work out cut2 on your own using the above as a start.