Pretty easy question:
Recursively how can I create an array of a binary search tree (in order) which uses this constructor:
public class OrderedSet<E extends Comparable<E>> {
private class TreeNode {
private E data;
private TreeNode left, right;
public TreeNode(E el) {
data = el;
left = null;
right = null;
}
}
private TreeNode root;
public int size = 0;
public OrderedSet() {
root = null;
}
In-Order means you first have to traverse the left part of the tree, so:
TreeNode tree // this is your tree you want to traverse
E[] array = new E[tree.size]; // the arrays length must be equivalent to the number of Nodes in the tree
int index = 0; // when adding something to the array we need an index
inOrder(tree, array, index); // thats the call for the method you'll create
The method itself could looks something like this:
public void inOrder(TreeNode node, E[] array, int index){
if(node == null){ // recursion anchor: when the node is null an empty leaf was reached (doesn't matter if it is left or right, just end the method call
return;
}
inOrder(node.getLeft(), array, index); // first do every left child tree
array[index++]= node.getData(); // then write the data in the array
inOrder(node.getRight(), array, index); // do the same with the right child
}
Somewhat like that. I am just not sure about the index and where it needs to be incremented. If you don't want to worry about the index or if you don't know how many nodes are in the tree, then use an ArrayList instead and transform it in the end to an array.
Normally a cleaner call method is build around the recursive method like this:
public E[] inOrderSort(TreeNode tree){
E[] array = new E[tree.size];
inOrder(tree, array, 0);
return array;
}
Thanks, that worked great. Java wouldn't allow me to make an array of generics so using your algorithm I made it work with an ArrayList (like you suggested) Here's the method (using the above constructor) just incase someone else asks the same question. (Ref is my reference to the current tree node)
public ArrayList<E> toArray() {
ArrayList<E> result = new ArrayList<E>();
toArrayHelp(root, result);
return result;
}
private void toArrayHelp(TreeNode ref, ArrayList<E> result) {
if (ref == null) {
return;
}
toArrayHelp(ref.left, result);
result.add(ref.data);
toArrayHelp(ref.right, result);
}
Related
In my case, I want to create a binary tree by taking the depth as the input.
For example, if I do tree.create(3), there will generate a binary tree when the depth of the deepest left is three, which means there will be 2^3 - 1 nodes in the tree and the value of all of them will be 0. The index will be 0 - 6 accorndingly.
class Tree<T> {
int depth;
int index;
T value;
public Tree(int index,T value) {
this.index = index;
this.value = value;
}
public static <K> Tree<K> create(int depth){
if(depth >= 1) {
//return a tree with the inputting depth,
//but I don't know how to do in this step
return new Tree(...?)
}
}
}
Which part of knowledge shall I use to achieve this in Java? Thanks!
Usually when working with a binary tree data structure you need to write recursive methods. When writing a recursive method, you need to write a condition that terminates the recursion. In your case, the recursion will end if we have reached the desired depth. In order to determine if we have reached the desired depth, we need to know what that desired depth is and what the current depth is. I will assume that the depth of the root node in the binary tree is zero. This means that for a maximum depth of 3 (as in the example in your question), the deepest level will be level 2. If we have not reached the desired depth, then I need to add a left and a right child node and then call the same method on each of those children and make sure that the depth of the child nodes is one greater than the depth of the parent. So my recursive method needs three parameters:
a node to (possibly) add child nodes to
the current depth
the maximum depth
Note that I don't need to handle the value (or data) that each node contains because you state, in your question, that each node will have the same value. Hence I can simply copy the value from the parent node to each of its children.
Here is a complete example. Note that when I tested it, a depth greater than 25 causes an OutOfMemoryError because there is a limit on how many recursive method invocations can be done.
import java.util.ArrayList;
import java.util.List;
public class BinTree<T> {
BinTreeNode<T> root;
public static <T> BinTree<T> create(int depth, T val) {
if (depth > 0) {
BinTree<T> theTree = new BinTree<>();
theTree.root = new BinTreeNode<>(val);
theTree.addLevel(theTree.root, 0, depth);
return theTree;
}
else {
throw new IllegalArgumentException("Invalid depth: " + depth);
}
}
public void getAllElements(BinTreeNode<T> aNode, List<T> list) {
if (aNode == null) {
return;
}
else {
getAllElements(aNode.left, list);
list.add(aNode.genericObject);
getAllElements(aNode.right, list);
}
}
private void addLevel(BinTreeNode<T> theNode, int level, int deepest) {
if (level == deepest - 1) {
return;
}
theNode.left = new BinTreeNode<>(theNode.genericObject);
theNode.right = new BinTreeNode<>(theNode.genericObject);
addLevel(theNode.left, level + 1, deepest);
addLevel(theNode.right, level + 1, deepest);
}
public static void main(String[] args) {
BinTree<String> aTree = BinTree.create(3, "George"); // max depth = 25
List<String> list = new ArrayList<>();
aTree.getAllElements(aTree.root, list);
System.out.println(list.size());
}
}
class BinTreeNode<T> {
BinTreeNode<T> left, right;
T genericObject;
public BinTreeNode(T obj) {
genericObject = obj;
}
}
Note that I added method getAllElements as a test to see whether the correct number of nodes were created.
I'm trying to figure out how to create a sublist of a linked list without using the standard library for a practice exercise.
I have a solution coded but I'm not sure if this is working properly. I don't have any compile errors that are coming up but wanted a second opinion if there is a better way to do this or if corrections should be made.
LinkedList class basic instance variables
public class LinkedList<E> implements DynamicList<E> {
LLNode<E> head;
LLNode<E> tail;
int llSize;
LinkedList(){
this.head = null;
this.tail = null;
this.llSize =0;
}
get method addressing LinkedList index
#Override
public E get(int index) {
LLNode<E> current = this.head;
while(current.nextPointer != null){
if(index == current.getIndex()){
return current.getObj();
}else{
current = current.nextPointer;
}
}
return null;
}
Node class
public class LLNode<E>{
E obj;
LLNode<E> previousPointer;
LLNode<E> nextPointer;
int index;
public LLNode(E obj){
this.obj = obj;
this.index=0;
}
public E getObj() {
return obj;
}
public LLNode<E> getPreviousPointer() {
return previousPointer;
}
public LLNode<E> getNextPointer() {
return nextPointer;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
Sublist method
#Override
public DynamicList<E> subList(int start, int stop) {
DynamicList<E> newDynamicList = new LinkedList<>();
for(int i = start; i<stop; i++){
newDynamicList.add(get(i));
}
return newDynamicList;
}
As I'm seeing, that is a double linked list. As is suggested in comments, avoid using an index as part of the node itself, the index is part of the List, because the list controls the way each node is traversed to perform any operation (add, remove, find, etc)
My suggestion (for sublist):
Check if the sublist is within the size of your list (you can throw some exception or return some default data, it depends on your design)
Move the index control to the list
For getting the sublist, you might have something like get the start node of the sublist, and then, use the nextPointer to traverse through the next nodes. You can calculate the size of the sublist and use that to control when you have to stop
public DynamicList<E> subList(int start, int stop) {
DynamicList<E> newDynamicList = new LinkedList<>();
//here, you can validate the subList conditions to work (size, boundaries, etc)
//an exception may be thrown if parameters do not meet some criteria
int subListSize = stop - start;
LLNode<E> current = get(start);
while(newDynamicList.size() < subListSize){
//Consider cloning the node and add it to the sublist
newDynamicList.add(current);
current = current.nextPointer;
}
return newDynamicList;
}
The main reason for not using the get method for retrieve each node is that get operation search for the node from the beginning each time you call it. It is better to get the start node and start traversing the nodes from there.
Don't forget that created Sublist will contain a reference to the original list nodes. I suggest to clone the elements for avoiding affect the original node
When given an array of integers, I'm trying to change each element with the product of the integers before it.
For example, int[] array = {2,2,3,4}; is now: {2, 4, 12, 48};
I added each element to a LinkedList, and I'm trying to do this recursively.
This is what I have:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
if(curr == null)
{
return;
}
else
{
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node(data);
curr.setNext(newNode);
// product(curr);
}
}
The first product works: {2,4}, but when I try to put in the recursion, I get a stackoverflow. Any suggestions??
Edit: So the reason that I'm either getting a stackoverflow or null pointer exception is because I'm updating the list, and then trying to get the next integer(but since there's only two elements in the list, there isn't a getNext()). I'm not sure how to fix this.
It looks like you were getting a bit tied up in the recursion. I modified your method to accept a Node along with the product from the previous iteration. At each step of the iteration I update the value in the already-existing List, so there is no need for using the new operator.
public static void product(Node curr, int value) {
if (curr == null) {
return;
}
else {
int data = value * curr.getData(); // compute current product
curr.setData(data); // update Node
product(curr.getNext(), data); // make recursive call
}
}
There are actually two issues with the code.
The recursion never ends, i.e. it is not actually moving to a smaller "subproblem" as the recursion is calling the same node again
and again.
After creating a new node and modifying the next we also need to connect the node "after" the next node otherwise the link will be
lost. Please check the below method which addresses both the issues.
Although I didn't do an excessive testing it is working for simple dataset.
Original List:
2->4->5->6->8->null
Multiplied List:
2->8->40->240->1920->null
public void product(Node curr) {
if (curr.getNext() == null) {
return;
} else {
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node();
newNode.setData(data);
Node nodeAfterNextNode = curr.getNext().getNext();
newNode.setNext(nodeAfterNextNode);
curr.setNext(newNode);
product(newNode);
}
}
It is because you call recursive method on the current node, so it is actually never move forward in the LinkedList. You can simply update the next node's data and call the recursive method on it. See the code below:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
Node next = curr.getNext();
if(next == null)
{
return;
}
else
{
int data = curr.getData() * next.getData();
next.setData(data);
product(next);
}
}
So I was wondering how I could create a new empty linked list, using my class definition of List and node, with a first head node pointing to null without having to hold any integer value. The thing is I'm not allowed to change the given methods or add any to the definition, so whenever I create a list, in the constructor I'm not sure how I'm supposed to asign head to null. Here's part of the codes:
public class Node {
private Node next;
private int key;
Node(Node nxt, int keyValue) {
key = keyValue;
next = nxt;
}
Node getNext() {
return next;
}
int getKey() {
return key;
}
void putNext(Node nxt) {
next = nxt;
}
}
Class List
public class List {
private Node head;
List() {
head = new Node(null, -1); // arbitary value for head
head.putNext(null);
}
This is what I came up with. I just assign a random value to variable key in head node. But if I do this, it will kinda mess up with my later methods that used recursive like deletion or finding sum or find max, min, etc
Is there any other way around I can do to deal with this issue?
In an Empty Linked List Head is Just a pointer which points to Nothing. You dont need to worry about creating an object to which current head points. Just create a head pointer and assign it to NULL. When you are actually adding a Node assign the address of first node to Head. Thats it...
public class List {
private Node *head;
List() {
head = NULL;
}
}
Working on creating linked lists for an assignment and one requirement is a method named concat which takes a list parameter and appends it to the end of the current list. It's not necessary for this method to use recursion, but our programs are supposed to use recursion heavily. I'm just wondering if it's even possible to come up with a recursive algorithm for this. Our list classes only have a head node, nothing else, and they're not doubly linked.
My current attempt can only append the first value recursively. I know what it's doing wrong, but I can't come up with a solution. The first method is what's actually called on a list with a list being passed in to "concatenate". I then attempt to find the tail of the list and pass these in to the recursive method. This "wrapper" method is a mandatory requirement for our recursive methods. Here's my attempt, but it's obviously failing since I'm having trouble advancing the node reference "pt" to the next node in the list once all of the calls pop off the stack and then re-entering recursive calls to concat. If this is possible with recursion, can you please give me an idea of how to advance this value down the first list and re-enter the recursive calls or maybe just a better general approach towards this problem? Thanks for your time.
public void concat(MyString list1) {
CharacterNode tail = null, pt = list1.head;
// Find the tail of the list
if (pt == null) {
} else if (pt.getNext() == null) {
tail = pt;
} else {
while (pt.getNext() != null) {
pt = pt.getNext();
}
tail = pt;
}
list1.head = concat(list1.head, tail, list1.head);
}
private static CharacterNode concat(CharacterNode lhead, CharacterNode tail, CharacterNode pt) {
// Pass in smaller list every time
// Head traverses down list till the end
// Add new node with (pt's letter, null link)
if (lhead == null) {
// If head is null, we need to add the node
lhead = new CharacterNode(pt.getCharacter(),null);
} else if (tail.getNext() == lhead) {
// If the head is past tail, stop
} else {
// Call concat on a smaller list
lhead.setNext(concat(lhead.getNext(),tail,pt));
}
return lhead;
}
Here's CharacterNode:
class CharacterNode {
private char letter;
private CharacterNode next;
public CharacterNode(char ch, CharacterNode link) {
letter = ch;
next = link;
}
public void setCharacter(char ch) {
this.letter = ch;
}
public char getCharacter() {
return letter;
}
public void setNext(CharacterNode next) {
this.next = next;
}
public CharacterNode getNext() {
return next;
}
}
MyString:
class MyString {
// member variable pointing to the head of the linked list
private CharacterNode head;
// default constructor
public MyString() {
}
// copy constructor
public MyString(MyString l) {
}
// constructor from a String
public MyString(String s) {
}
// for output purposes -- override Object version
// no spaces between the characters, no line feeds/returns
public String toString() {
}
// create a new node and add it to the head of the list
public void addHead(char ch) {
}
// create a new node and add it to the tail of the list -- "wrapper"
public void addTail(char ch) {
}
// Recursive method for addTail
private static CharacterNode addTail(CharacterNode L, char letter) {
}
// modify the list so it is reversed
public void reverse() {
}
// remove all occurrences of the character from the list -- "wrapper"
public void removeChar(char ch) {
}
// Recursive removeChar method
private static CharacterNode removeChar(CharacterNode n, char letter) {
}
// "wrapper" for recursive length()
public int length() {
}
// Returns the length of the linked list
private static int length(CharacterNode L) {
}
// concatenate a copy of list1 to the end of the list
public void concat(MyString list1) {
}
// recursive method for concat
private static CharacterNode concat(CharacterNode lhead, CharacterNode tail, CharacterNode pt) {
}
}
To concatenate two linked lists, you have to make the last node of first list to point to first node of the second list.
Node first_list = ... // head node
Node second_list = ... // head node
...
Node last_node = first_list.getLastNode()
last_node.setNext(second_list)
Now concentrate on implementing getLastNode(). It can be done very simply by using either recursion or iteration, literally in 2 lines.