I have this code for a heap tree and I'm stuck with the iterators.
I need in-order, pre-order and post-order iterators, but I have no idea how to do it.
If someone has an idea or example please help.
class Numbers implements Comparable<Numbers> {
private int value;
public Numbers(int value) {
this.value = value;
}
public String toString() {
return Integer.toString(value);
}
public int getValue() {
return this.value;
}
public int compareTo(Numbers o) {
int tmp = o.getValue();
if (value > tmp)
return 1;
if (value < tmp)
return -1;
return 0;
}
}
class BinaryHeapIsFull extends Exception {
BinaryHeapIsFull() {
super("There is no more place in the heap!");
}
}
public class BinaryHeap<E extends Comparable> {
E[] elements;
int count;
public BinaryHeap(int maxSize) {
elements = (E[]) new Comparable[maxSize];
this.count = 0;
}
public void enqueue(E elem) throws BinaryHeapIsFull {
if (count == elements.length)
throw new BinaryHeapIsFull();
int i = count++;
while (i > 0 && elements[(i - 1) / 2].compareTo(elem) == 1) {
elements[i] = elements[(i - 1) / 2];
i = (i - 1) / 2;
}
elements[i] = elem;
}
public E findMin() {
return elements[0];
}
public E dequeueMin() {
if (count == 0)
return null;
E result = elements[0];
E last = elements[--count];
int i = 0;
while (2 * i + 1 <= count) {
int child = 2 * i + 1;
if (child < count
&& elements[child + 1].compareTo(elements[child]) == -1)
child++;
if (last.compareTo(elements[child]) == -1
|| last.compareTo(elements[child]) == 0)
break;
elements[i] = elements[child];
i = child;
}
elements[i] = last;
return result;
}
public String toString() {
String print = "";
for (int i = 0; i < count; i++)
print += elements[i].toString() + " ";
return print;
}
public void sort() {
int a = count;
for (int i = 0; i < a; i++) {
System.out.print(findMin() + " ");
dequeueMin();
}
}
public static void main(String[] args) throws BinaryHeapIsFull {
BinaryHeap<Numbers> b = new BinaryHeap<Numbers>(10);
b.enqueue(new Numbers(6));
System.out.println(b.toString());
b.enqueue(new Numbers(3));
System.out.println(b.toString());
b.enqueue(new Numbers(4));
System.out.println(b.toString());
b.enqueue(new Numbers(1));
System.out.println(b.toString());
b.enqueue(new Numbers(5));
System.out.println(b.toString());
b.enqueue(new Numbers(0));
System.out.println(b.toString());
b.enqueue(new Numbers(2));
System.out.println(b.toString());
b.dequeueMin();
System.out.println(b.toString());
b.dequeueMin();
System.out.println(b.toString());
System.out.println(b.findMin());
b.sort();
}
}
I'd start with three classes, one for each case, that implements the Iterator interface. Give those iterators an instance of your binary heap and let them do their thing.
public class BinaryHeapPreOrderIterator implements Iterator {
// constructor and methods for Iterator here.
}
Related
I have a homework that the teacher test if it's corrects by checking it's output using this website moodle.caseine.org, so to test my code the program execute these lines and compare the output with the expected one, this is the test :
Tas t = new Tas();
Random r = new Random(123);
for(int i =0; i<10000;i++)t.inser(r.nextInt());
for(int i =0;i<10000;i++)System.out.println(t.supprMax());
System.out.println(t);
And my Heap (Tas) class:
package td1;
import java.util.ArrayList;
import java.util.List;
public class Tas {
private List<Integer> t;
public Tas() {
t = new ArrayList<>();
}
public Tas(ArrayList<Integer> tab) {
t = new ArrayList<Integer>(tab);
}
public static int getFilsGauche(int i) {
return 2 * i + 1;
}
public static int getFilsDroit(int i) {
return 2 * i + 2;
}
public static int getParent(int i) {
return (i - 1) / 2;
}
public boolean estVide() {
return t.isEmpty();
}
#Override
public String toString() {
String str = "";
int size = t.size();
if (size > 0) {
str += "[" + t.get(0);
str += toString(0);
str += "]";
}
return str;
}
public boolean testTas() {
int size = t.size();
int check = 0;
if (size > 0) {
for (int i = 0; i < t.size(); i++) {
if (getFilsGauche(i) < size) {
if (t.get(i) < t.get(getFilsGauche(i))) {
check++;
}
}
if (getFilsDroit(i) < size) {
if (t.get(i) < t.get(getFilsDroit(i))) {
check++;
}
}
}
}
return check == 0;
}
public String toString(int i) {
String str = "";
int size = t.size();
if (getFilsGauche(i) < size) {
str += "[";
str += t.get(getFilsGauche(i));
str += toString(getFilsGauche(i));
str += "]";
}
if (getFilsDroit(i) < size) {
str += "[";
str += t.get(getFilsDroit(i));
str += toString(getFilsDroit(i));
str += "]";
}
return str;
}
//insert value and sort
public void inser(int value) {
t.add(value);
int index = t.size() - 1;
if (index > 0) {
inserCheck(index); // O(log n)
}
}
public void inserCheck(int i) {
int temp = 0;
int parent = getParent(i);
if (parent >= 0 && t.get(i) > t.get(parent)) {
temp = t.get(parent);
t.set(parent, t.get(i));
t.set(i, temp);
inserCheck(parent);
}
}
//switch position of last element is list with first (deletes first and return it)
public int supprMax() {
int size = t.size();
int max = 0;
if (size > 0) {
max = t.get(0);
t.set(0, t.get(size - 1));
t.remove(size - 1);
supprMax(0);
}
else {
throw new IllegalStateException();
}
return max;
}
public void supprMax(int i) {
int size = t.size();
int temp = 0;
int index = i;
if (getFilsGauche(i) < size && t.get(getFilsGauche(i)) > t.get(index)) {
index = getFilsGauche(i);
}
if (getFilsDroit(i) < size && t.get(getFilsDroit(i)) > t.get(index)) {
index = getFilsDroit(i);
}
if (index != i) {
temp = t.get(index);
t.set(index, t.get(i));
t.set(i, temp);
supprMax(index);
}
}
public static void tri(int[] tab) {
Tas tas = new Tas();
for (int i = 0; i < tab.length; i++) {
tas.inser(tab[i]);
}
for (int i = 0; i < tab.length; i++) {
tab[i] = tas.supprMax();
}
}
}
The last 3 lines of the test are :
-2145024521
-2147061786
-2145666206
But the last 3 of my code are :
-2145024521
-2145666206
-2147061786
The problem are probably with the inser and supprMax methods.
I hate to get a bad grade just because of 3 lines placement, because it is a program that verify the code, it dosn't care the the solution was close, it's still says it's wrong.
I have generated a minheap to this file but I think something I have missed but I can't identify what are the things I have missed. I have missed something on --private void bubbleDown() { }-- section but I can't find what are the things missed by me.
private int default_size = 100; // how big the heap should be
private T[] array;
private int size;
public Heap() {
#SuppressWarnings("unchecked")
T[] tmp = (T[]) (new Comparable[default_size]);
array = tmp;
size = 0;
}
boolean isRoot(int index) { return (index == 0); }
int leftChild(int index) { return 2 * index + 1; }
int parent(int index) { return (index - 1) / 2; }
int rightChild(int index) { return 2 * index + 2; }
T myParent(int index) { return array[parent(index)]; }
T myLeftChild(int index) { return array[leftChild(index)]; }
T myRightChild(int index) { return array[rightChild(index)]; }
boolean hasLeftChild(int i) { return leftChild(i) < size-1; }
boolean hasRightChild(int i){ return rightChild(i) < size-1; }
private void swap(int a, int b) {
T tmp = array[a];
array[a] = array[b];
array[b] = tmp;
}
public boolean isEmpty() { return (size == 0); }
/* adding heap */
public void add(T value) {
if(size == default_size) throw new IllegalStateException("Full array");
array[size++] = value;
bubbleUp();
}
public void bubbleUp() {
if(size == 0) throw new IllegalStateException("Shape error");
int index = size - 1;
while(!isRoot(index)) {
if(myParent(index).compareTo(array[index]) <= 0) break;
/* else part */
swap(parent(index), index);
index = parent(index);
}
}
/* removing */
public T remove() {
if(isEmpty()) return null;
T res = array[0]; /* root */
array[0] = array[size-1];
size --;
bubbleDown();
return res;
}
// i think this section having wrong something
private void bubbleDown() {
int parent = 0;
int leftChild = 2*parent + 1;
int rightChild = 2*parent + 2;
int choice = compareAndPick(leftChild, rightChild);
while (choice != -1)
{
swap(choice, parent);
parent = choice;
choice = compareAndPick(2*choice+1, 2*choice+2);
}
}
private int compareAndPick(int leftChild, int rightChild)
{
if (leftChild >= default_size || array[leftChild] == null) return -1;
if (array[leftChild].compareTo(array[rightChild]) <= 0 || (array[rightChild] == null))
return leftChild;
return rightChild;
}
public void show() {
for(int i=0; i<size; i++)
System.out.print(array[i] + " ");
System.out.println("=======");
}
public static void main(String [] args) {
Heap<Integer> heap = new Heap<Integer>();
for(int i=0; i<10; i++) {
heap.add((Integer)(int)(Math.random() * 100));
heap.show();
}
System.out.println("You should see sorted numbers");
while(!heap.isEmpty()) {
System.out.print(heap.remove());
System.out.print(" ");
heap.show();
}
System.out.println();
}
}
this code used generics and min heap functions.. i need to identify what is the wrong thing did by me on bubbleDown() section
Explanation
The bubbleDown() method is not a different way to insert a node and move it to it's correct position in the Heap. When bubbleDown() is called it's job is to Heapify the Binary Tree from any state. So your attempt to write the method just by changing the condition from the bubbleUp() method isn't gonna help you.
Extra
Here is a video that can give you the idea of how bubbleDown is supposed to work.
Problem desc:
i seem to have a problem with my MIN-heap structure. I get the nullpointer in the min-heapify method in the first if-statement. The test class doesnt matter in this case
Can anyone spot the error? Here is the code for the minHeap (Line 31 is the first IF statement in the minHeapify method):
public class PQHeap implements PQ {
private PriorityQueue pq;
private Element[] heapArray;
private int heapSize;
public PQHeap(int maxElms) {
pq = new PriorityQueue(maxElms);
heapArray = new Element[maxElms];
heapSize = 0;
}
public void minHeapify(int index) {
int left = getLeft(index);
int right = getRight(index);
int smallest = index;
if (left < heapSize && heapArray[left].getKey() < heapArray[index].getKey()) {
smallest = left;
}
if (right < heapSize && heapArray[right].getKey() < heapArray[smallest].getKey()) {
smallest = right;
}
if (smallest != index) {
exchangeKey(heapArray[index].getKey(), heapArray[smallest].getKey());
minHeapify(smallest);
}
}
public int getLeft(int index) {
return index * 2;
}
public int getRight(int index) {
return index * 2 + 1;
}
public int getParent(int index) {
return index / 2;
}
public void exchangeKey(int a, int b) {
int temp = a;
a = b;
b = temp;
}
#Override
public Element extractMin() {
Element min = heapArray[0];
heapArray[0] = heapArray[heapArray.length - 1];
minHeapify(0);
return min;
}
#Override
public void insert(Element e) {
heapSize++;
int i = heapSize;
heapArray[i] = e;
while (i > 1 && heapArray[getParent(i)].getKey() > heapArray[i].getKey()) {
exchangeKey(heapArray[i].getKey(), getParent(heapArray[i].getKey()));
i = getParent(i);
}
}
//SKAL FJERNES
public void print() {
for (int i = 1; i <= heapSize / 2; i++) {
System.out.print(" PARENT : " + heapArray[i].getKey()
+ " LEFT CHILD : " + heapArray[2 * i].getKey()
+ " RIGHT CHILD :" + heapArray[2 * i + 1].getKey());
System.out.println();
}
}
//SKAL FJERNES
public void minHeap() {
for (int pos = (heapSize / 2); pos >= 1; pos--) {
minHeapify(pos);
}
}
}
i want to use an Iterator on a class that has a collection (defined by me as a dictionary) on which I implemented the Iterator. How can I do? Do I have to call back the private field of the class when I have to do a for-each loop?
Here is the code of the collection class:
public class ArrayDict<K, V> implements Dictionary<K, V> {
Coppia<K, V>[] dict = new Coppia[1];
int n = 0;
#Override
public Iterator<K> iterator() {
return new Iterator<K>() {
private int i = 0;
#Override
public boolean hasNext() {
return i < n;
}
#Override
public K next() {
int pos = i;
i++;
return(K) dict[pos].key;
}
};
}
#Override
public void insert(K key, V value) {
if(search(key)==null)
throw new EccezioneChiavePresente("Chiave giĆ presente");
dict[n] = new Coppia<K,V>(key, value);
n++;
if (n == dict.length) {
Coppia<K,V>[] tmp = new Coppia[dict.length * 2];
for (int i = 0; i < n; i++)
tmp[i] = dict[i];
dict = tmp;
}
}
#Override
public void delete(K key) {
if (n == 0)
throw new EccezioneDizionarioVuoto("Dizionario vuoto");
if (search(key) == null)
throw new EccezioneChiaveNonPresente("Chiave non presente");
int i;
for (i = 0; i < n; i++)
if (dict[i].key.equals(key))
break;
for (int j = i; j < n - 1; j++)
dict[j] = dict[j + 1];
n--;
if (n > 0 && n < dict.length / 4) {
Coppia<K,V>[] tmp = new Coppia[dict.length / 2];
for (i = 0; i < n; i++)
tmp[i] = dict[i];
dict = tmp;
}
}
#Override
public V search(K key) {
if(n==0)
throw new EccezioneDizionarioVuoto("Dizionario vuoto");
for (int i = 0; i < n; i++)
if (dict[i].key.equals(key))
return dict[i].value;
return null;
}
}
And here is a part of the class that use the collection as private field:
public abstract class BibliotecaAbs {
protected Dictionary<String, Record> volumi;
public boolean bibliotecaVuota() {
try {
volumi.delete("");
} catch (EccezioneDizionarioVuoto e) {
return true;
}
return false;
}
public void addVol(String posizione, Volume volume) {
try {
volumi.insert(posizione, new Record(volume, false));
} catch (EccezioneChiavePresente e) {
throw new EccezioneScaffaleOccupato();
}
}
Naturally I have a derived class that makes BibliotecaAbs concrete.
I want to do something like this:
for(Object s : b){
String intpos = s.toString();
But it gaves me the error:
Can only iterate over an array or an instance of java.lang.Iterable
How can I do to solve this problem? Any help would be appreciated
Add implements Iterable<SomeType> to the class declaration of BibliotecaAbs, and implement the required method public Iterator<SomeType> iterator().
There seems to be a problem in add method of the class I have written.. I want to make a SortedList using an array, but I can't figure out what the problem is. This is my code:
public class SortedList {
private Integer[] elements;
private int size;
private int capacity;
public SortedList(int cap) {
elements = new Integer[cap];
if (cap > 0)
{
cap = capacity;
}
else
capacity = 10;
}
public boolean isEmpty()
{
return size == 0;
}
public boolean isFull()
{
return size == capacity;
}
public int size()
{
return size;
}
public void doubleCapacity()
{
capacity = capacity * 2;
}
public void add(Integer el)
{
if(this.isEmpty())
{
elements[0] = el;
size++;
}
else if(this.isFull())
{
this.doubleCapacity();
for(int i = 0; i<this.size(); i++)
{
if(el >= elements[i])
{
elements[i+2] = elements[i+1];
elements[i+1] = el;
}
else
{
elements[i+1] = elements[i];
elements[i] = el;
}
}
size++;
}
else
{
for(int i = 0; i<this.size(); i++)
{
if(el >= elements[i])
{
elements[i+2] = elements[i+1];
elements[i+1] = el;
}
else
{
elements[i+1] = elements[i];
elements[i] = el;
}
}
size++;
}
}
public String toString()
{
String s = "";
s = s + "<SortedList[";
for(int i = 0; i < this.size(); i++)
{
s = s + elements[i];
if(i < this.size()-1)
s = s + ",";
}
s = s + "]>";
return s;
}
public static void main(String[] args)
{
SortedList sl = new SortedList(5);
sl.add(3);
//sl.add(2);
sl.add(4);
sl.add(5);
// sl.add(6);
System.out.println(sl.toString());
}
}
My code works if I only add 2 Integers to my list, but when I try to add the numbers 3,4,5 then I get 3,5,5...
What can be the problem? Thanks..
public class SortedList {
private Integer[] elements;
private int size=0;
private int capacity;
public SortedList(int cap) {
elements = new Integer[cap];
if (cap > 0)
{
capacity = cap;
}
else
capacity = 10;
}
public boolean isEmpty()
{
return size == 0;
}
public boolean isFull()
{
return size == capacity;
}
public int size()
{
return size;
}
public void doubleCapacity()
{
capacity = capacity * 2;
}
public void add(Integer el) throws Exception{
elements[size] = el;
size++;
if(size>capacity){
throw new Exception("Size Exceeded");
}
}
public String toString()
{
sort();
String s = "";
s = s + "<SortedList[";
for(int i = 0; i < this.size(); i++)
{
s = s + elements[i];
if(i < this.size()-1)
s = s + ",";
}
s = s + "]>";
return s;
}
public void sort(){
for (int i=0; i <size()-1; i++) {
if (elements[i] > elements[i+1]) {
// exchange elements
int temp = elements[i];
elements[i] = elements[i+1];
elements[i+1] = temp;
}
}
}
public static void main(String[] args)
{
try {
SortedList sl = new SortedList(5);
sl.add(3);
//sl.add(2);
sl.add(6);
sl.add(5);
// sl.add(6);
System.out.println(sl.toString());
} catch (Exception ex) {
Logger.getLogger(SortedList.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Your insertion code doesn't work.
elements[i+1] = elements[i];
elements[i] = el;
What happens to the old value of elements[i+1]?
I'd recommend the following changes to the previous solution. If you're only calling sort in toString(), your list is going to get out of order quickly in cases where you have multiple unsorted elements in a row (Now you could remove sort() from toString()). It's essentially a quick insertion sort that dies as soon as it can't make any more swaps down the list. Again, as dty suggested, a faster choice would be a binary search to find the insertion point.
public void doubleCapacity(){
capacity = capacity * 2;
Integer temp[] = new Integer[capacity];
for (int i = 0; i < size; i++){
temp[i] = elements[i];
}
elements = temp;
}
public void add(Integer el){
if(size+1>capacity){
doubleCapacity();
}
elements[size] = el;
size++;
sort();
}
public void sort(){
//Iterates down the list until it's sorted.
for (int i=size()-2; i >= 0 && (elements[i] < elements[i+1]); i--) {
// exchange elements
int temp = elements[i];
elements[i] = elements[i+1];
elements[i+1] = temp;
}
}