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

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]++;
}
}
}
}

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.

Linked List in a Array

I am currently doing a online Java course and am having a bit of trouble with a assignment. The assignment is to essentially create a Hashmap using just Arrays but no other Java Data Structures or methods. This is my code:
public class test {
static String[] array = new String[10];
class Cell<T> {
T first;
Cell<T> next;
Cell(T h, Cell<T> t) {
first = h;
next = t;
}
}
public static int hashFunction(String a) {
int sum = 1;
for (int i = 0; i < a.length(); i++) {
char b = a.charAt(i);
int value = (int) b;
sum *= value;
}
return sum % array.length;
}
public static void arraySetter(String a) {
int position = hashFunction(a);
if (array[position] == null) {
array[position] = a;
} else {
//Need a Linked List here for when there is already a item in the array at the same index.
}
}
public static void printArray() {
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
public static void main(String[] args) {
arraySetter("abc");
printArray();
}
}
My code essentially creates a list of lists. At each position in the Array I now need to create a list which is only initialised when there are two items with the same value for the hashFunction. I haven't written that function yet but my problem now is I don't know how to create a linkedList at each position in the array. Can someone help me out here?
This is the data structure in which you should store your data:
Cell[] array
When using an array such as String[] you will never be able to add any else than instances of String into that array.
When you get a new hashCode, you should create a new one:
array[position] = new Cell<>(a, null);
As it is the first element from the linkedList we will call it the head.
Every time a value with the same hashcode is provided, you will need to iterate from the head until a Cell whose next value is null, then you define it with a new instance of Cell.
This is generally called addLast method, and you ca find a good example here:
https://www.cs.cmu.edu/~adamchik/15-121/lectures/Linked%20Lists/linked%20lists.html
If you want a linked list to avoid collision then you have to declare array which will contain head of the linked list.
Node<K,V>[] table;
Sample code not fully implemented.
class Node<K,V> {
K key;
V value;
Node<K,V> next;
}
Node will contain current key and value .if key is same then you have to override and also next value if you want to use linked list.If you want to use array to avoid collision that time also use node which will contain key and value key is required to check equality and no next variable.

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.)

Determine index an Object is in an array from the object itself

Is there a way for objects inside an array to detect what slot they are in? If I had a Object array, could a Object inside the array detect what cell it is in without being explicitly told?
Nope, unfortunately, how arrays work in Java is that the array simply "points" to an object. As a Java array only stores references (to objects), but any number of variables can reference the same object, so an Object has no idea where it lives in an array. In fact, the same object can be pointed to from several indices in the array!
Consider
Object o = new Object(); // The variable o has a "reference" to the Object in memory
Object[] arr = new Object[3]; // empty array to hold Object types
arr[0] = o; // the first index points to the Object we created above
arr[1] = o; // the second index points to that same object!
arr[2] = o; // still the same object! If we modified the original object (assuming it's not immutable) in any way, all the indices in this array would point to the modified object.
Hope this helps!
The fastest (easiest to write) way to iterate through an array of objects is
for (Object o : arr) {
// do something to the local variable o, which you can think of as representing each object in your array
}
No. If you need to do this, you probably have a design flaw. Why does an Object need to know where it appears in the array? If the index is of some semantic meaning or interest to the object, then the object should have an int field containing this information. If you are trying to modify the original array based on one object then you probably have a poorly-factored class somewhere, e.g. if something such as this is happening:
class A {
Object data[];
}
class B {
remove(A a, Object instance) {
// how to remove instance from a.data??
}
}
Then really B.remove should be a method of A and hence have access to data in the first place. And so forth.
Furthermore an array may just not be the right data structure. If the index has much semantic value a Map<Integer, Object> may be more appropriate, although arrays are often used to represent this when the indices are continuous from 1..n and the array is immutable. In my silly example with remove, a List would be more appropriate. Etc.
try
int i = Arrays.asList(arr).indexOf(obj);
As #Aaron_H said, no dice. I'll add that you can work around it with something like this:
public class Test {
public static void main(String[] args) {
ZenArray<IndexedString> z = new ZenArray(10);
for (int i = 0; i < z.size(); i++) {
z.set(i, new IndexedString("String " + i));
}
for (int i = 0; i < z.size(); i++) {
System.out.println("I'm at index " + z.get(i).getIndex());
}
}
}
class ZenArray<T extends ZenArray.IndexedElement> {
private Object [] a;
interface IndexedElement {
void setIndex(int i);
int getIndex();
}
public ZenArray(int size) {
a = new Object[size];
}
public void set(int i, T val) {
val.setIndex(i);
a[i] = val;
}
public T get(int i) {
return (T)a[i];
}
public int size() {
return a.length;
}
}
// An example of an indexed element implementation.
class IndexedString implements ZenArray.IndexedElement {
int i;
String val;
public IndexedString(String val) {
this.val = val;
}
public String getVal() {
return val;
}
#Override
public void setIndex(int i) {
this.i = i;
}
#Override
public int getIndex() {
return i;
}
}

converting BST to array

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);
}
}

Categories

Resources