I must be missing something very simple because this is blowing my mind!
I am trying to implement a Heap using a CompleteBinaryTree (which is implemented using an array). This CompleteBinaryTree is an array of Position<T> where each Position holds an element. I am writing the add(T t) method for the Heap, where t is inserted into the next free position of the CompleteBinaryTree, and then an upheap process is performed until the CompleteBinaryTree is ordered. Here is the method:
private CompleteBinaryTree<T> tree = new CompleteBinaryTree<T>();
private Position<T> entry = null;
public void add(T t) {
entry = tree.add(t);
if (entry.equals(tree.root())) {
return;
}
//continue to swap inserted element with its parent
//while it is smaller than its parent
while (entry.element().compareTo(tree.parent(entry).element()) < 0) {
Position<T> parent = tree.parent(entry);
Position<T> temp = entry;
entry = parent;
parent = temp;
}
}
The first element is added fine into the Heap, but when I try to add the second element, an InvalidPositionException is thrown at the while() line. This is where the exeption is being thrown from inside the CompleteBinaryTree class:
public Position<T> parent(Position<T> p) {
if (p == root()) throw new InvalidPositionException();
return array[((ArrayPosition) p).index/2];
}
And here are the two other methods used from CompleteBinaryTree:
public Position<T> root() {
if (isEmpty()) throw new InvalidPositionException();
return array[1];
}
public Position<T> add(T t) {
if (last == array.length) {
// extend array
ArrayPosition[] temp = (ArrayPosition[]) new Object[array.length*2];
for (int i=1; i < array.length; i++) {
temp[i] = array[i];
}
array = temp;
}
array[last] = new ArrayPosition(last, t);
return array[last++];
}
How am I getting an exception thrown because p == root(), when I first check if p is the root?
EDIT
Here is the CompleteBinaryTree toString(), which is returned by the Heap toString():
public String toString() {
StringBuffer buf = new StringBuffer();
for (int i = 1; i < last; i++) {
buf.append(" ").append(array[i]);
}
return buf.toString();
}
How am I getting an exception thrown because p == root(), when I first check if p is the root?
But you do not check every tree.parent() argument to see whether it is root. You check only the argument passed to the first invocation of that method. Every time the body of the while loop is executed, it sets entry to a new value, and when the loop cycles you pass that new, unchecked, value to tree.parent(). Indeed, each new value of entry is closer to the root than the previous one, because the whole point is to move up the tree from child to parent, i.e. toward the root. It is entirely likely that sometimes this procedure will reach the root, and that's more likely the fewer elements are already in the tree.
One way to solve this would be to move the root-check into the while condition:
while (!entry.equals(tree.root())
&& entry.element().compareTo(tree.parent(entry).element()) < 0) {
// ...
}
In that case, of course, you do not need the current one-time check that you perform outside the loop.
Related
For my class I have to create an iterator that will generate a power set of a LinkedSet. Per my professor, I have to iterate through a bitString of the int current. Where current is the subset to which we are adding elements of the main set. I keep having a NullPointerException. I think I am looping through the bitString correctly but when I want to move to the next node in the set, it is saying it is null. I've stared at this for 12 hours and cannot figure out what to do. My professor provided a framework, so I'll explain what is mine and what is his.
This is the framework:
private class LinkedSetPowerSetIterator implements Iterator<Set<T>> {
// cardinality of this set
int N;
// cardinality of the power set (2^N)
int M;
// the integer identifier of the current subset, i.e. the current element
// of the power set. Legal values range from 0..M-1 inclusive.
int current;
public LinkedSetPowerSetIteratorInt32BitString() {
// initialize N, M, and current here
}
public boolean hasNext() {
return current < M;
}
public Set<T> next() {
LinkedSet<T> s = new LinkedSet<T>();
char[] bitstring = Integer.toBinaryString(current).toCharArray();
// iterate from right to left over bitstring and the internal
// linked list to ensure that the call to add will insert a new
// first node (constant time)
current = current + 1;
return s;
}
public void remove() {
}
}
What I have so far:
private class myPowerIterator implements Iterator<Set<T>> {
// cardinality of set
int N;
// cardinality of power set (2^N)
int M;
//current subset in power set
int current;
// starting node, rear node
Node set = rear;
public myPowerIterator() {
N = size;
M = (int)Math.pow(2, N);
current = 0;
}
public boolean hasNext() {
return (current < M);
}
public Set<T> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
LinkedSet<T> result = new LinkedSet<T>();
char[] bitString = Integer.toBinaryString(current).toCharArray();
for (int i = bitString.length - 1; i >= 0; i--) {
if (bitString[i] == 1) {
result.add(set.element); // How do I make sure it is adding elements
set = set.prev; // from starting set? Keep getting Error:
} // NullPointerException: Cannot read field
else { // "prev" because this.set is null.
set = set.prev;
}
}
current = current + 1;
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
You need to implement the Iterable<T> interface in your LinkedSet<T>. If you don't do this then your next() method will not "reset" it's location, thus giving you the NullPointer.
I'm trying to remove an element from an array. I am running into an issue where when I run my program and remove a certain index. I get nulls in the place where the element/index should be removed entirely.
My output is when I execute list.display() in the main method is
Tom, Bob, Richard
However after I execute list.remove() and run the program. I get
null, null, Richard.
Any tips?
public class MyArrayList implements MyList {
private Object[] theList;
public MyArrayList()
{
theList = new Object[0];
}
public boolean add(Object toAdd){
if(toAdd != null) {
Object[] temp = new Object[theList.length + 1];
for(int i = 0; i < theList.length; i++) {
temp[i] = theList[i];
}
temp[theList.length] = toAdd;
theList = temp;
return true;
} else {
return false;
}
}
public Object remove(int index) {
if (index >= 0 && index < theList.length) {
Object[] temp = new Object[theList.length - 1];
theList[index] = null;
int j = 0;
for (int i = 0; i < theList.length; i++) {
if (i == index) {
continue;
}
temp[j++] = theList[i];
theList = temp;
}
return temp;
}
return null;
}
public class Main {
public static void main(String[] args) {
MyArrayList list = new MyArrayList();
list.add("Tom");
list.add("Bob");
list.add("Richard");
list.display();
list.remove(0);
list.remove(1);
list.display();
}
}
Where you call list.remove(0), you should be assigning the result back to list again. For example:
list = list.remove(0);
A couple of other things:
It's generally a bad idea to change the index variable within a loop. It's legal, but leads to logic errors that can be difficult to reason about and diagnose.
You're getting the null in your output because the remove method also mutates the theList when you execute:
theList[index] = null;
Since you're returning a copy of theList you don't need to also set that element of the theList array to null.
Since your code implements MyList which is not available in code, i could not run below sample on your code but you can have below logic in your code. You don't need extra temp array in remove method. Since it an array, you can start traversing array from index which has to be removed and start moving next element by one step before.
public Object remove(int index) {
if (theList == null || index < 0 || index >= theList.length) {
return theList;
}
for (int i = index; i < theList.length; i++) {
theList[i] = theList[i + 1];
}
return null;
}
You can trim array tail if it has more empty places based on some threshold.
the code is doing exactly what you asked it to do. Those removed values are null because you have this line
theList[index] = null;
Also think about what your intentions are.
list.remove(0); <- this will remove the first element so now list would be Rob, Richard
list.remove(1); <- this will remove the 2nd element of the modified list (Rob, Richard) so result would be Rob. This is probably not what you want.
instead of this
if (i == index) {
i++; // risk of out of bounds exception
}
you probably want this instead
if (i == index) {
continue;
}
I am trying to create a method that sets every instance of the variable elt in an array to null, and then shift every variable after it to the left. The current code that I have written only sets the first instance of the variable to null and shifts all other variable to the left, but does not set any other instance of elt to null. The code I have so far is below.
public T remove(T elt) {
boolean exist = false;
for (int i=0; i<data.length; i++) {
if (data[i] == elt) {
data[i] = null;
size--;
exist = true;
for (++i; i < data.length; i++) {
data[i-1] = data[i];
}
}
}
if (exist == true)
return elt;
else
return null;
}
In main, I have the following code:
public static void main(String[] args) {
Bag<String> sbag = new Bag<String>();
sbag.add("Noriko");
sbag.add("hello");
sbag.add("Buddy");
sbag.add("Mary");
sbag.add("Peter");
sbag.add("hello");
sbag.remove("hello");
When I print the array, I expect the following output:
Noriko
Buddy
Mary
Peter
Instead I get:
Noriko
Buddy
Mary
Peter
hello
This tells me it is only setting the first instance of elt to null, moving every variable to the left, and stopping. Can anyone tell me how I can fix my code so that it sets every instance of the variable elt null?
The common technique to the "remove all and shift" problem is to do it all in one loop with two separate indexes - one for reading, and one for writing:
int rd = 0, wr = 0;
while (rd != data.length) {
if (data[rd] != elt) { // Shouldn't you use equals() instead?
data[wr++] = data[rd++];
} else {
rd++;
}
}
while (wr != data.length) {
data[wr++] = null;
}
This technique is very useful in practice. I highly recommend working through an example or two with paper and pencil to make sure that you fully understand it.
Both your innner and outer loop use the variable i. When the first match is found, the record is removed and i is incremented to data.length (when shifting the remaining records to the left). When you get back to the outer loop, i = data.length and the outer loop terminates.
You should use a different variable for your inner loop.
From the looks of your code it would seem like you would want to use a "List" type.
With this you can then add and remove variables without having to write an entire new function to do it.
For the sake of excercise:
public T remove(T elt) {
boolean exist = false;
for (int i=0; i<size; i++) { // changed data.length to size to avoid unnecessary iterations over deleted positions
while (data[i] == elt) { // changed if to while
data[i] = null;
size--;
exist = true;
for (int j = i+1; j < data.length; j++) { // changed iteration variable, we don't want to move i
data[j-1] = data[j];
}
}
}
if (exist == true)
return elt;
else
return null;
}
I'm working with a LinkedList of customLinkedLists and I'm having some problems with the implementation of my AddFirst method.
Here's the method,
public void addFirst(GenericType data)
{
Node<GenericType> toAdd = new Node<GenericType>(data);
if(sizeCounter != 0)
{
toAdd.next = head;
head = toAdd;
sizeCounter++;
} else {
head = toAdd;
tail = toAdd;
toAdd.next = null;
sizeCounter++;
}
}
The problem is this increments the size correctly every time i call it, but when I try to print out the values, it throws a null pointer exception.
I know there's a problem in the way I'm setting the head/tail pointer but I cant figure out what it is exactly.
EDIT:
Basically I have a OuterList and a custom LinkedList class.
in the outer list class, i have an object that makes:
LinkedList<CustomList<GenericType>> oList = new LinkedList<CustomList<GenericType>>;
//method add in OuterList class that calls addFirst in customLinkedClass
public void add(GenericType x){
oList.get(0).addFirst(x);
}
//Prints the List
public void print(){
for(int i=0; i<oList.size(); i++){
for(int j=0; j<oList.get(i).size(); j++){
// first .get() is for the oList to get the first customLinkedList.
// second .get() returns the value of the Node in the customLinkedList
System.out.println(oList.get(i).get(j));
}
}
When I try to dump after adding an item it throws a null pointer. When I create the customLinkedList, is set head.next = tail. Could that be the cause of the problem? I do not see why it would be giving me errors
EDIT 2:
Stack Trace:
Exception in thread "main" java.lang.NullPointerException
at squarelist.CustomList.get(CustomList.java:187)
at squarelist.OuterList.dump(OuterList.java:94)
at squarelist.OuterList.main(OuterList.java:106)
Line it occurs at:
public GenericType get(int index){ return getNodeAt(index).value; }
getNodeAt() function:
private Node<GenericType> getNodeAt( int index ){
Node<GenericType> p = null;
p = head.next;
for( int i = 0; i < index; i++ ){
p = p.next;
}
return p;
}
Change this :
head = add;
tail = add;
to this :
head = toAdd;
tail = toAdd;
in the else block
EDIT
After posting the stack trace, the problem is that you are returning null from the getNodeAt method.
Let's say that you have only one element in the list; then p = head.next; will be null and you are returning that value.
Try setting p=head instead
I'm trying to build a lexicographically ordered linked list. I planned it all out on paper and thought I need everything right, but once I insert a second or third entry it returns with a null pointer exception.
Exception in thread "main" java.lang.NullPointerException
at DoublyLL.insert(DoublyLL.java:88)
If I enter, for examples:
"chris", "andy", then "bob", "bob" returns the excpetion.
"chris", "bob", then "andy", "andy" returns the exception
"andy", "bob", I get the same exception with the addition of at DoublyLL$Node.access$000(DoublyLL.java:148)
The code:
public boolean insert(StudentListing newListing)
{ Node n = new Node();
if(n == null) // out of memory
return false;
else
{
Node q = new Node();
q = h;
int lex;
if (q.next == null) // first inputed node
{
n.next = q.next;
q.next = n;
n.back = q;
n.l = newListing.deepCopy();
return true;
} else // not first node
{
q = q.next;
do
{
// This is the line the error is called vvv
lex = q.l.getKey().compareTo(newListing.getKey());
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (lex < 0)
{
// keep going
q = q.next;
} else if (lex > 0)
{
// place before q
n.back = q.back;
q.back = n;
n.next = q;
n.back.next = n;
return true;
} else if (lex == 0)
{
// q and listing match
}
} while (lex < 0);
}
}
return false;
}
Inner class
public class Node
{ private StudentListing l;
private Node next;
private Node back;
public Node()
{ }
}
The biggest problem here is that, when you're inserting a new StudentListing to a non-empty list, you iterate over the list until you find an element that's greater than the StudentListing you're inserting. But if the StudentListing that you're inserting is greater than any element in the list, then you never find such an element, so you run off the end of the list. Before writing q = q.next, you need to check if q.next == null, and handle that case appropriately.
(There are also various little non-Java-isms in your code — for example, if(n == null) // out of memory will never be true, because Java indicates an out-of-memory error by raising an exception rather than by returning null — but none of those looks like a major problem to me.)