converting BST to array - java

I've looked all over and can't seem to find any help for this.. for a school project I have a BST tree and I have to put all the ints from the tree into an int array called BSTarray. This is what I have so far:
public int [] toBSTArray() {
int size = 20;
int [] BSTarray = new int [size];
for(int i = 0; i <size; i++) {
makeArray(root);
BSTarray[i] = root.getValue();
}
return BSTarray;
}
//helper method called by toBSTArray
public void makeArray(BinarySearchTreeNode node) {
if (node != null) {
makeArray(node.getLeft());
makeArray(node.getRight());
// System.out.print(node.getValue() + " ");
}
}
I thought this method was supposed to go through the tree and add in the values it finds into different indexes in the BSTarray, but all it's doing is adding the same number into all the indexes in the array. Am I doing something wrong with the recursion?

Try this:
Integer[] values = extractValues(n).toArray(new Integer[] {});
with that method definition:
private static List<Integer> extractValues(Node n) {
List<Integer> result = new ArrayList<>();
if (n.getLeft() != null) {
result.addAll(extractValues(n.getLeft()));
}
if (n.getRight() != null) {
result.addAll(extractValues(n.getRight()));
}
result.add(n.getValue());
return result;
}
I assumed a node structure that is similar to yours. Of course, the method doesn't have to be static if you don't use it in a static way.
This method might not be the most efficient due to the list conversion but you don't have to bother with any array sizes. If you really need the function to return an array, just wrap it into another function or let the proposed function return an array (this would make it necessary to convert the list to an array before each return).
Concerning your code, you iterate over the ito fill the entire array (no matter where you know the size from) but you always set the value to the value of the root node. That's why you always have the same value. Your makeArray function calls itself recursively but it doesn't do anything (even if you add a sysout statement ;) )
Update:
And for the constraint of using no lists, here is another version that uses only arrays:
int size = 20;
int[] results = new int[size];
extractValues(n, results, 0);
with the method definition:
private static int extractValues(Node n, int[] results, int index) {
if (n.getLeft() != null) {
index = extractValues(n.getLeft(), results, index);
}
if (n.getRight() != null) {
index = extractValues(n.getRight(), results, index);
}
results[index] = n.getValue();
return index + 1;
}
Note, that the result will be in results, then. The size has to be either assumed to be larger the number of nodes or it has to be counted by traversing the tree, before.

How about this: (Your recursion does not make any changes to the array)
public int [] toBSTArray() {
int size = 20; //ASSUMING THIS IS LESS THAN OR EQUAL TO NUMBER OF NODES IN THE TREE
int [] BSTarray = new int [size];
makeArray(root, 0, BSTarray);
return BSTarray;
}
//helper method called by toBSTArray
public void makeArray(BinarySearchTreeNode node, int i, int [] BSTarray ) {
if (node != null) {
BSTarray[i] = root.getValue();
makeArray(node.getLeft(), 2*i+1, BSTarray);
makeArray(node.getRight(), 2*i+2, BSTarray);
}
}

Related

Implement a method as a pure function to get size of a custom data structure iteratively (no recursion) and with space complexity O(1), so no copying

in a course I am doing, here is an example of the IntList class. With one recursive method to get the size of the list, getSizeRecursive() and one iterative method getSizeIterative().
public class IntList {
public int first;
public IntList rest;
public IntList(int first, IntList L){
this.first = first;
this.rest = L;
}
public int getSizeIterative(){
int size = 1;
while (this.rest != null){
size += 1;
this.rest = this.rest.rest;
}
return size;
}
public int getSizeRecursive(){
if (this.rest == null)
return 1;
else return 1 + rest.getSizeRecur();
}
}
Now the iterative method gives the desired result too, like the recursive method, but only if I run it once, as it's changing the pointer to rest variable when it calls getSizeIterative(). So, I don't get the same result when I call the method twice. e.g.
IntList l = new IntList(10, null);
l = new IntList(15, l);
l = new IntList(5, l);
System.out.println(l.getSize()); // Outputs 3 as expected.
System.out.println(l.getSize()); // Outputs 1! <-- Wrong.
Now, I want to implement this method as a pure function, so I create a copy of the list in the getSizeIterative() method, like this:
public int getSizeIterative(){
IntList copy = new IntList(first, rest); <-- Added this line.
int size = 1;
if (copy.rest != null){
while (copy.rest != null){
size += 1;
copy.rest = copy.rest.rest;
}
}
return size;
}
But now it takes up more space. Is there a way to not use extra space? Thanks.
Try this one
public int getSize(){
IntList copy = this;
int size = 1;
while (copy.rest != null){
size += 1;
copy = copy.rest;
}
return size;
}
UPD. A bit of explanation. When you create new pointer to an object, like
IntList copy = this;
It's still one object in memory, but 2 different pointers on it. You can do something like
copy = null;
and it will not break this pointer, because you changed only pointer, not an object. However, if you change a field in copy, it changes field in this also. So, if you do like
copy.rest = copy.rest.rest;
this line changes this.rest also, because you changed real in-memory object, not only a pointer.

Sorting String array gives NullPointerException

Hello I have implemented this basic program which should sort out the strings that are inserted however it somehow is failing to insert the strings .
For example if I implement :
TestSort t = new TestSort();
t.i("abc");
t.i("aab");
Can anybody see the error and help me fix this error please ?
Thank you
Here is the code :
public class TestSort {
private int length;
String[] data;
public TestSort() {
length = 0;
}
public void i(String value) {
data[length] = value;
setSorted(data);
length++;
}
public void setSorted(String data[]) {
for(int i = data.length-1; i >= 0; i--) {
for(int j = 0; j < i; j++) {
if(data[j].compareTo(data[j + 1]) > -1) {
String temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
}
for(int i = 0; i < data.length; i++) {
System.out.print(data[i] +" ");
}
}
}
You don't initialize the array data. So it is set null, and accesses with data[i] will get you an NullPointerException. Even if you initialize this field, it will not work, as Arrays in Java have a fixed size, you have to reallocate the Array, if you insert a new value. You should try a List-implementation instead.
So the code should initialize in the constructor:
data = new ArrayList<String>();
and insertion would change to
data.add(value);
you can change your constructor code as (String array max length can be taken as input parameter):
public testsort()
{
data = new String[10];
length = 0;
}
But if you are not sure with the size of array you can use ArrayList.
You are getting exception because you are comparing with data[j+1] that is still null.
first time when you call
t.i("abc");
there is only one reference in data array that is pointing to String literal "abc" and that is at index 0. index 1 is still referring to null.
first String is already sorted so no need to sort that. if you are having more than one string then you should call setSorted() method.
to solve this you can put your condition in loop as:
if((data[j] != null && data[j+1] != null) &&(data[j].compareTo(data[j + 1]) > -1))
A working example but still: use a List and life is much easier :-)
public class Test {
private int length;
private String[] data;
public Test(int arrayLength) {
// INITIALIZE YOU ARRAY --> No NULLPOINTEREXCEPTION!
data = new String[arrayLength];
length = 0;
}
public void i(String value) {
data[length] = value;
length++;
}
public void setSorted() {
for (int j = 0; j < data.length - 1; j++) {
if (data[j].compareTo(data[j + 1]) > -1) {
String temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
for (String s : data) {
System.out.println(s);
}
}
public static void main(String[] args) {
Test t = new Test(5);
t.i("bbb");
t.i("aaa");
t.i("ccc");
t.i("zzz");
t.i("ddd");
// USE SETSORTED HERE --> else you fill your array with the same elements
t.setSorted();
}
}
The variable 'data' is null since it is nowhere initialized hence giving null pointer exception. Since 'data' is an array and as per the rule whenever an array is defined, it has to be of defined length. for e.g if we consider your case. 'data' can be initialized as :-
String[] data = new String[any numerical value]
the numerical value will be its length i.e. the maximum number of elements it can hold.
Secondly, as per your program statement :-
data[length] = value;
is trying to assign value at data's [length] index which is completely wrong since you haven't defined the length therefore how could you guess the index's value. Therefore your this approaoch is logically wrong.
For such situation i.e. whenever we're unaware about the length of the array, use of ArrayList is suggested. Therefore your program can be re-written by two ways:-
1) Either define the length of the array
String[] data = new String[n];
where n ranges from at least 1 to any positive integer.
2) By using ArrayList
public class Main {
List<String> data;
public Main(){
data = new ArrayList<String>();
}
public static void main(String... q){
Main m = new Main();
m.insertData("abc");
m.insertData("zxy");
m.insertData("aab");
m.insertData("aaa");
m.showData();
}
public void insertData(String str){
data.add(str);
Collections.sort(data);
}
public void showData(){
if(data!=null && !data.isEmpty()){
for(String s : data){
System.out.println(s);
}
}
}
}
output:-
aaa
aab
abc
zxy
Hope this helps.
as Mnementh suggested, the reason for NPE is that you have created the field data of type String[] but you never initialized it.
Other answers have provided every reason on why your code throwing ugly errors; I have just improved your code by replacing your String[] with List<String> so you don't have to worry about the size of your array anymore.
Sorting is also simplified now using Collections.sort().
have a look,
class test1 {
public static void main(String[] args) {
Test sorting = new Test();
sorting.input("abc");
sorting.input("cba");
sorting.input("aab");
sorting.setSorted();
}
}
class Test {
private List<String> data = new ArrayList<String>();
public void input(String value) {data.add(value);}
public void setSorted() {
Collections.sort(data);
for (String current : data) {
System.out.println(current);
}
}
}
if you are using Java 8, then you can use Arrays.parallerSort(), it performs sorting the same way as Collection.sort but with a parallel implementation.
Current sorting implementations provided by the Java Collections Framework > (Collections.sort and Arrays.sort) all perform the
sorting operation sequentially in the calling thread. This enhancement
will offer the same set of sorting operations currently provided by
the Arrays class, but with a parallel implementation that utilizes the
Fork/Join framework. These new API's are still synchronous with regard
to the calling thread as it will not proceed past the sorting
operation until the parallel sort is complete.
to implement it, replace Collections.sort with Arrays.parallelSort in the above code,
Replace,
Collections.sort(data);
with,
Arrays.parallelSort(data.toArray(new String[data.size()]));

Using a data structure to solve this in O(n)

we have sequence of 4 characters (A,B,C and D)that map to numbers form 1 to n.
we define components to be:
Component(k) :
A {cell[k]}
if Color(left_k) = Color(k)
then
A <-- A U Component(left_k)
if Color(right_k) = Color(k)
then
A <-- A U Component(left_k)
return A
there is 3 types of operations(the numbers in list indicate the input):
by giving index it should remove the component in that index(the numbers mapping to characters are fixed)
example : AABBBDA is the string. if index is 3 it should return AADA
by giving index it should rotate the string based on the component on that index(the numbers mapping to characters are fixed)
example : AABBBDA is the string. if index is 3 it should return DABBBAA
it should print the string.
inputs are like:
1 2 --> first operation with index=2
2 3 --> second operation with index=3
3 --> third operation
It's an assignment, happy to get help.
this is what i've tried so far:
public static void main(String[] args)
{
int numberOfOps;
String[] print = new String[30];
List list = new List();
Scanner input = new Scanner(System.in);
int count = input.nextInt();
String colors = new String();
colors = input.next();
for(int i = 0; i < count; i++)
{
list.add(colors.charAt(i));
}
numberOfOps = input.nextInt();
list.printElement();
for (int i = 0; i < numberOfOps; i++)
{
int op = input.nextInt();
if(op == 1)
{
int index = input.nextInt();
char c = list.item[index];
int temp = index;
int prevIndex = index;
int nexIndex = index;
if(index != 0)
{
while (list.item[--index] == c)
{
prevIndex--;
}
while (list.item[++temp] == c)
{
nexIndex++;
}
list.setNext(prevIndex-1, nexIndex+1);
}
else
{
while (list.item[++temp] == c)
{
nexIndex++;
}
list.setNext(prevIndex, nexIndex+1);
}
}
if(op == 2)
{
int index = input.nextInt();
}
if(op == 3)
{
print[i] = list.printElement();
}
}
}
here is my List class:
public class List {
// reference to linked list of items
public static final int MAX_LIST = 20;
public static final int NULL = -1;
public char item[] = new char[MAX_LIST]; // data
public int avail;
public int next[] = new int[MAX_LIST]; // pointer to next item
private int numItems; // number of items in list
public List()
{
int index;
for (index = 0; index < MAX_LIST-1; index++)
next[index] = index + 1;
next[MAX_LIST-1] = NULL;
numItems = 0;
avail = 0;
} // end default constructor
public void add(char e)
{
item[avail] = e;
avail = next[avail];
numItems++;
}
public String printElement()
{
String temp = null;
int index = 0;
while(index<avail)
{
temp += item[index];
System.out.println(item[index]);
index = next[index];
}
return temp;
}
public int size()
{
return numItems;
}
public void setNext(int i, int value)
{
next[i] = value;
}
}
if you test it you'll get, it has lots of problems, such as, I have no idea to do the rotate operation, and it has problem with connecting two components when the middle component has been removed.
This is a difficult question to answer, because the requirements are not properly stated.
For example the first bunch of pseudo-code does not make it clear whether A is a set, a multi-set or a list. The notation (use of curly brackets, and U (union?)) seems to say set ... but the output seems to be a list. Or maybe it is supposed to be a schema for a data structure??
And even the inputs are not clearly described.
But putting that on one side, there is still room for some (hopefully) helpful advice.
Make sure that >>you<< understand the requirements. (I imagine that the real requirements for the assignment are better stated than this, and the details have been "lost in translation".)
I would actually use an array list (or a StringBuilder) rather than a linked list for this. (But a properly implemented linked list ... implementing the List API ... would work.)
But whatever data structure you chose, there is no point in implementing it from scratch ... unless you are specifically required to do that. There are perfectly good list classes in the Java standard libraries. You should reuse them ... rather than attempting to reinvent the wheel (and doing a bad job).
If you are required to implement your own data structure type, then your current attempt is a mess. It looks like a hybrid between an array list and a linked list ... and doesn't succeed in being either. (For example, a decent array list implementation does not need a MAX_LIST, and doesn't have next pointers / indexes. And a linked list does not have any arrays inside it.)

How to store each set in a disjoint-set forest?

Trying to code this up myself in Java... I have created a GraphNode class to represent nodes that have a pointer to their parent.
I have also created a DisjointSet class that includes a MakeSet method that creates a GraphNode object and has its parent reference refer to itself.
The question is: how do I then store each node so I can easily access it later in Union and FindSet? My first thought it to store it in a BST, but I'd have to create a custom TreeNode class that stores not only the value, but also the reference to the GraphNode. Is there an easier way?
There is absolutely an easier way: forget about all the node-business. The nodes are just conceptual, it's not required to implement them literally, and it's easier not to.
All you need is two arrays of ints. One that stores the parents and one that stores the ranks. So in a sort of pseudo-code, it would look something like this:
disjoint_set {
int[] parent, rank;
makeset(int n)
{
rank = new int[n];
parent = new int[n];
for(int i = 0; i < n; i++)
parent[i] = i;
}
int find(int i)
{
if (parent[i] != i)
parent[i] = find(parent[i]);
return parent[i];
}
void union(int x, int y)
{
x_root = find(x);
y_root = find(y);
if (x_root != y_root) {
if (rank[x_root] < rank[y_root])
parent[x_root] = y_root;
else if (rank[x_root] > rank[y_root])
parent[y_root] = x_root;
else {
parent[y_root] = x_root;
rank[x_root]++;
}
}
}
}

how to get random item from an arraylist without any repeatation in android

I have an ArrayList of an object from where I want items of a particular position, but everytime I launch the Activity the retrieved position should be randomize and also won't repeat until every position Item is completely retrieved. I used this method:
public static int getRandomNumber(ArrayList<Integer> arr)
throws IllegalArgumentException {
try {
Random random = new Random();
int select = random.nextInt(arr.size());
int randomnum = arr.get(select);
GlobalData.randList.remove(select);
return randomnum;
} catch (IllegalArgumentException e) {
for (int i = 0; i < arr.size(); i++) {
GlobalData.randList.add(i);
}
return 0;
}
but its not working,like duplicate number is coming, there may be a reason because everytime I am re launching the activity. I did it in oncreate instead of onResume but its not working as I expected? Is there any other way to work with it? Any solution?
Use Collections.shuffle() to shuffle the array. Use another variable to track the current position in the array. Each time you retrieve a new value increment the variable. Once you reach the end of the array re-shuffle it.
Reference:
Shuffling algorithms
public class RandomArray {
ArrayList<Integer> array = null;
int position = 0;
public RandomArray(ArrayList<Integer> arr) {
array = arr;
position = arr.size();
}
public int getNext() {
if (position == array.size()) {
position = 0;
Collections.shuffle(array);
}
return array.get(position++);
}
}
If you don't care about the original order, you can try this:
Object[] array = new Object[10]; // say 10 objects
int remain = array.length;
Random rnd = new Random();
public Object next () {
if (remain == 0) {
return null;
} else {
int i = rnd.nextInt(remain--);
Object tmp = array[i];
array[i] = array[remain];
array[remain] = tmp;
return tmp;
}
}
You can also do similar thing with ArrayList.
Well, in this way, it is faster than shuffle() method. shuffle() has the time complexity of O(n) while my code is O(1).

Categories

Resources