I am trying to re-size a hash table. I find that my logic is correct, but the code is all wrong. I know that when adding elements into a hash table you must consider the load factor, if the load factor is exceeded, the capacity doubles.
Example. Size = 3, Capacity = 5.
Load Factor = 5 * 0.75 = 3.75
If we add an element Size = 4, which exceeds the load factor, thus Capacity = 10.
However, I am return the original Capacity.
/**
* size if load >.75 or < .5
*/
private void resize(int newCap)
{
//
double capacity = buckets.length * 0.75;
//System.out.println(capacity);
if (currentSize > capacity) {
int C = buckets.length * 2;
newCap = C
//System.out.println(C);
}
}
/**
* Gets the length of the array backing this HashSet
* #return the length of the array backing this HashSet
*/
public int getCap()
{
//
int capac = buckets.cap
resize(capac);
return capac;
}
newCap = C in method resize will not change the value of capac
You should be returning the newCap from resize method
/**
* size if load >.75 or < .5
*/
private int resize(int newCap)
{
//
double capacity = buckets.length * 0.75;
//System.out.println(capacity);
if (currentSize > capacity) {
int C = buckets.length * 2;
return C;
//System.out.println(C);
}
return newCap;
}
/**
* Gets the length of the array backing this HashSet
* #return the length of the array backing this HashSet
*/
public int getCap()
{
//
int capac = buckets.cap;
capac = resize(capac);
return capac;
}
In java, there is always pass-by-value. See a relevant discussion here
Edit: Changed the return type as rightly pointed out.
Related
I am very confused with passing. I have created a Quick sort algorithm in eclipse. The class is an abstract class. Here is the Interface class.
public interface ArraySort<T extends Comparable<T>>
{
/**
* Sort the array
*/
public void sort(T[] array);
}
This is the class in which the Quick sort has been created.
public class QuickSort <T extends Comparable<T>> extends ArraySortTool<T>{
public <T> void quickSort(T[] array, Comparator<T>com, int a, int b) {
if(a >= b) return;
int left = a;
int right = b-1;
T pivot = array[b];
T temp;
while (left <= right){
//Look for element larger or equal to the pivot
while(left <= right&&com.compare(array[left], pivot)<0)left++;
//Look for element smaller or equal to pivot
while(left <= right&&com.compare(array[right], pivot)>0)right--;
if(left <= right){
temp = array[left]; array[right]=array[right]=temp;
left++; right--;
}
}
//place pivot into its final location marked by left index
temp = array[left]; array[left] = array[b]; array[b] = temp;
quickSort(array, com, a, left - 1);
quickSort(array, com, left + 1,b);
}
#Override
public void sort(T[] array) {
quickSort(array, int, 0, 0);
}
}
In order to pass the references I have also tried this method but had no luck.
#Override
public void sort(T[] array, Comparator<T>com, int a, int b) {
int left = a;
int right = b-1;
T pivot = array[b];
T temp;
I was getting an error here
public class QuickSort <T extends Comparable<T>> extends ArraySortTool<T>{
I am trying to do this without interfering with the interface class.
Here is the code for the ArraySortTool
public abstract class ArraySortTool<T extends Comparable<T>> implements ArraySort<T>
{
/**
* #param inArray an array to be sorted
* #return the time, in milliseconds, taken to sort the array
*/
private double timeTakenMillis(T[] array) {
double startTime = System.nanoTime();
sort(array);
return ((System.nanoTime()-startTime)/1000000.0);
}
/**
* Run a sequence of tests on sets of arrays of increasing size, reporting the average time taken for each
* size of array. For each size of array, <tt>noPerSize</tt> tests will be run, and the average time taken.
* Timings will be generated for array sizes 1,2,...,9,10,20,...,90,100,200,...,900,1000,2000,...until the
* maximum time is exceeded. Times are reported in milliseconds.
* #param generator an array generator for generating the random arrays
* #param noPerSize the number of timings per array size set
* #param maxTimeSeconds the cut-off time in seconds - once a timing takes longer than this the timing sequence will be terminated
*/
public void timeInMillis(RandomArray<T> generator,int noPerSize,int maxTimeSeconds)
{
int size = 1; // initial size of array to test
int step = 1; // initial size increase
int stepFactor = 10; // when size reaches 10*current size increase step size by 10
double averageTimeTaken;
do {
double totalTimeTaken = 0;
for (int count = 0; count < noPerSize; count++) {
T[] array = generator.randomArray(size);
totalTimeTaken += timeTakenMillis(array);
}
averageTimeTaken = totalTimeTaken/noPerSize;
System.out.format("Average time to sort %d elements was %.3f milliseconds.\n",size,averageTimeTaken);
size += step;
if (size >= stepFactor*step) step *= stepFactor;
} while (averageTimeTaken < maxTimeSeconds*1000);
System.out.println("Tests ended.");
}
/**
* Check whether a given array is sorted.
* #param array the array to be checked
* #return true iff the array is sorted - either ascending or descending
* The first non-equal neighbouring elements will determine the expected
* order of sorting.
*/
public boolean isSorted(T[] array) {
int detectedDirection = 0; // have not yet detected increasing or decreasing
T previous = array[0];
for (int index = 1; index < array.length; index++) {
int currentDirection = previous.compareTo(array[index]); // compare previous and current entry
if (currentDirection != 0) { // if current pair increasing or decreasing
if (detectedDirection == 0) { // if previously no direction detected
detectedDirection = currentDirection; // remember current direction
} else if (detectedDirection * currentDirection < 0) { // otherwise compare current and previous direction
return false; // if they differ array is not sorted
}
}
previous = array[index];
}
// reached end of array without detecting pairs out of order
return true;
}
}
I am trying to pass the quicksort method into the sort method as it is in the interface class. Please let me know how to do this as I am new to passing by reference. An example using my code will be great. Kind regards.
try this:
public class QuickSort <T extends Comparable<T>> implements ArraySort<T>{...}
(edited to match revised code in the question)
I have to distribute i. no. of items into n no. of boxes where each box has different capacity level c1, c2 ... cn. I want to distribute the items in ratio of their capacity. So the box with highest capacity will contain highest no. of items and vice versa. The capacities may not be in ascending order. The capacities can also be 0. Also, if the no. of items exceed the total capacity, then fill all the boxes upto their maximum capacity.
Is there already a solution for this problem?
Because I've written following algo. But it's not efficient. Also its looping infinitely at following input. Since the -2 difference is never settled. So there must also be other use cases where it breaks.
int[] arrCap = {1,1,0,1,1};
new Distributor(arrCap, 2).distribute();
import java.util.Arrays;
public class Distributor {
/** Capacity of each box */
private final int[] boxCapacity;
/** Total no. of boxes */
private final int NO_OF_BOXES;
/** Total no. of items that are to be distributed into each box */
private final int NO_OF_ITEMS;
/** Total capacity available. */
private long totalCapacity;
/** Fractionally ratio distributed items according to capacity */
private float[] fractionalRatios;
/** Ratio distributed items according to capacity */
private int[] ratioDistributedCapacity;
/** Sorted Rank of distributed items in ascending / descending order */
private int[] rankIndex;
/** The difference between the totalCapacity and total of ratioDistributedCapacity */
private int difference;
/**
* Validates the total capacity and no. of items to be distributed.
* Initializes the distributor with box capacity array, no of items.
* Implicitly calculates no. of boxes as length of box capacity array.
* #param boxCapacity Array of capacity of each box.
* #param noOfItems No. of Items to be distributed.
*/
public Distributor(int[] boxCapacity, int noOfItems) {
calculateBoxes(boxCapacity);
this.boxCapacity = boxCapacity;
this.NO_OF_ITEMS = noOfItems;
NO_OF_BOXES = boxCapacity.length;
ratioDistributedCapacity = new int[NO_OF_BOXES];
rankIndex = new int[NO_OF_BOXES];
}
/**
* Calculates the ratio into which the items are to be distributed.
* Actually assigns the items into each box according to the ratio.
* #return Array of int[] containing ratio distributed items according to its capacity.
*/
public int[] distribute() {
// If NO_OF_ITEMS to be distributed is more than totalCapacity then distribute all the items upto full capacity
if (NO_OF_ITEMS >= totalCapacity) {
ratioDistributedCapacity = boxCapacity;
} else {
calculateRatioAndDistribute();
}
return ratioDistributedCapacity;
}
/**
* Calculates the ratio & distributes the items according to the capacity.
*/
private void calculateRatioAndDistribute() {
fractionalRatios = new float[NO_OF_BOXES];
for (int i=0; i<NO_OF_BOXES; i++) {
fractionalRatios[i] = ((float) boxCapacity[i] * (float) NO_OF_ITEMS) / (float) totalCapacity;
ratioDistributedCapacity[i] = Math.round(fractionalRatios[i]);
}
print(fractionalRatios);
print(ratioDistributedCapacity);
// keep redistributing the difference until its not 0
while ((difference = rectifyAndGetDistributionResult()) != 0) {
redistribute();
}
print(ratioDistributedCapacity);
}
/**
* Redistributes the difference between the already allotted ratioDistributedCapacity array.
* Also if the difference is 0 that means everything is already settled.
* No more further need to do anything.
* #param difference the difference that needs to be settled to equal the no. of items with total distributed items.
*/
private void redistribute() {
if (difference > 0) {
// calculate distribution ranks in ascending order
calculateDistributionRanks(true); // orderDescending = true
// eliminate the invalid ranks from rankIndex
eliminateInvalidRanks();
// In case all the ranks have become invalid. In this case the rankIndex will be empty.
// So we need to re calculate the distribution ranks in opposite order.
if (rankIndex.length == 0) {
calculateDistributionRanks(false); // orderDescending = false
}
} else if (difference < 0) {
// calculate distribution ranks in descending order
calculateDistributionRanks(false); // orderDescending = false
// eliminate the invalid ranks from rankIndex
eliminateInvalidRanks();
// In case all the ranks have become invalid. In this case the rankIndex will be empty.
// So we need to re calculate the distribution ranks in opposite order.
if (rankIndex.length == 0) {
calculateDistributionRanks(true); // orderDescending = true
}
}
// add / substract 1 from the ratioDistributedCapacity of the element in order of the rankIndex
// according to negative / positive difference until the difference becomes 0.
final int len = rankIndex.length;
for (int i=0; i<len; i++) {
if (difference == 0) {
break;
} else if (difference > 0) {
ratioDistributedCapacity[ rankIndex[i] ]++;
difference--;
} else if (difference < 0) {
ratioDistributedCapacity[ rankIndex[i] ]--;
difference++;
}
}
}
/**
* If the value of any ratioDistributedCapacity element exceeds its capacity or is less than 0,
* revert it with its initial capacity value.
*/
private void rectify() {
for (int i=0; i<NO_OF_BOXES; i++) {
ratioDistributedCapacity[i] = ((ratioDistributedCapacity[i] > boxCapacity[i]) || (ratioDistributedCapacity[i] < 0)) ? boxCapacity[i] : ratioDistributedCapacity[i];
}
}
/**
* Calculates the distribution ranks i.e. indexes of fractionalRatios array.
* Sorts them into ascending or descending order.
* #param orderDesc Sort order. true for descending and false for ascending.
*/
private void calculateDistributionRanks(boolean orderDesc) {
// Copy fractionalRatios array to another tmp array. Note:- Use fractionalRatios so ranking can be more accurate.
float[] tmp = Arrays.copyOf(fractionalRatios, NO_OF_BOXES);
// Sort the array in ascending order
Arrays.sort(tmp);
// re-initialize the rankIndex array
rankIndex = new int[NO_OF_BOXES];
for (int i=0; i<NO_OF_BOXES; i++) {
innerLoop: for (int j=0; j<NO_OF_BOXES; j++) {
if (tmp[i] == fractionalRatios[j]) {
// Store the array index of unsorted array if its value matches value of sorted array.
rankIndex[i] = j;
break innerLoop;
}
}
}
// reverse the rank array if orderDesc flag is true
if (orderDesc) reverse();
print(rankIndex);
}
/**
* Remove the indexes from rank which are already full or equal to 0
* or are not eligible for increment / decrement operation.
*/
private void eliminateInvalidRanks() {
final int len = rankIndex.length;
int invalidRankCount = 0;
final int markInvalidRank = -1;
for (int i = 0; i < len; i++) {
if (boxCapacity[rankIndex[i]] <= 0) {
// mark this rank number as invalid, for removal
rankIndex[i] = markInvalidRank;
invalidRankCount++;
continue;
}
if (difference > 0) {
if ((ratioDistributedCapacity[rankIndex[i]] >= boxCapacity[rankIndex[i]])) {
// mark this rank number as invalid, for removal
rankIndex[i] = markInvalidRank;
invalidRankCount++;
continue;
}
} else if (difference < 0) {
if (ratioDistributedCapacity[rankIndex[i]] <= 0) {
// mark this rank number as invalid, for removal
rankIndex[i] = markInvalidRank;
invalidRankCount++;
continue;
}
}
}
int[] tmp = new int[(len - invalidRankCount)];
int j = 0;
for (int i = 0; i < len; i++) {
if (rankIndex[i] != markInvalidRank) {
tmp[j++] = rankIndex[i];
}
}
rankIndex = tmp;
print(rankIndex);
}
/**
* Rectifies the elements value inside ratioDistributedCapacity.
* Calculates the total of already distributed items.
* #return Difference between total distributed items and initial no. of items that were to be distributed.
*/
private int rectifyAndGetDistributionResult() {
rectify();
int remaining = NO_OF_ITEMS;
for (int tmp: ratioDistributedCapacity) {
remaining -= tmp;
}
return remaining;
}
/**
* Validates the capacity array and no. of items to be distributed.
* #param arrCapacity Array of capacity of each box.
*/
private void calculateBoxes(int[] arrCapacity) {
for (int i: arrCapacity) {
totalCapacity += i;
}
}
/**
* Prints the array elements and the total of the elements within it.
* #param x
*/
private void print(int[] x) {
final int len = x.length;
final StringBuilder sb = new StringBuilder("");
for (int i=0; i<len; i++) {
sb.append(x[i]).append(", ");
}
System.out.println(sb.toString());
}
/**
* Prints the array elements and the total of the elements within it.
* #param x
*/
private void print(float[] x) {
final int len = x.length;
final StringBuilder sb = new StringBuilder("");
for (int i=0; i<len; i++) {
sb.append(x[i]).append(", ");
}
System.out.println(sb.toString());
}
private void reverse() {
final int len = rankIndex.length;
for (int i=0; i < (len/2); i++) {
rankIndex[i] += rankIndex[len - 1 - i]; // a = a+b
rankIndex[len - 1 - i] = rankIndex[i] - rankIndex[len - 1 - i]; // b = a-b
rankIndex[i] -= rankIndex[len - 1 - i]; // a = a-b
}
}
}
I wonder if you do simple math to find out ratio would solve the problem easily.
So Ni is number of items you have to distribute, B sum of all boxes capacity(ie c1+c2+...+cn)
So R = Ni/B would be your ration.
R*cn would be number of items you would want to put into box n
Example:
you have total of 8 items. and 2 boxes capacity 4, 12(N1 = 16).
R = 8/(4+12) = 1/2
for box would have R*4 = 2
second box would have R*12 = 6
Of course you would have to handle rounding issues, there will be +/-1 items in the boxes.
PS
For fixing rounding issue you will do following.
you create a variable sumSoFar = 0 //initial value
box1 contains R*c1
then you add sumSoFar+=Math.round(R*c1)
box2 contains Math.round(R*c2)
then you add sumSoFar+=Math.round(R*c2)
for last box you put N1-sumSoFar So you distribute all values.
here is the code:
static int[] distribute(int[] boxes, int items) {
int[] result = new int[boxes.length];
int sumSoFar = 0;
int totalCapacity = 0;
for (int box : boxes) {
totalCapacity += box;
}
float R = (float) items / totalCapacity;
for (int i = 0; i < boxes.length - 1; i++) {
int box = boxes[i];
result[i] = Math.round(R * box);
sumSoFar += result[i];
}
result[boxes.length - 1] = items - sumSoFar;
return result;
}
Calling:
System.out.println(Arrays.toString(distribute(new int[]{1, 2}, 10)));
System.out.println(Arrays.toString(distribute(new int[]{4, 12}, 8)));
Results:
[3, 7]
[2, 6]
Two approaches come to mind
Optimal Rounding
Treat the problem like an optimal rounding problem. Since you want the items distributed in the boxes "in ratio of their capacity", then for each box compute their share which is "capacity / sum of all capacities". Then multiply that share by the number of items. That'll usually give you a fractional number of items for each box. I assume your items are indivisible. Now you just have to determine how to "optimally round" these values. Here is one SO question that discusses how to do that. You can also search for "optimal rounding under integer constraints" to find several papers on the subject.
Fair Division
Treat the problem using fair division. The link covers numerous approaches (most are approximations). However, the key part will be how will each of your boxes ascribe a value to each item, so that the algorithms will know how to parcels the items. You can use a metric that is proportional to their capacity.
So as the title, I've got different results running my Magic Square program from Eclipse and cmd command. The eclipse one does not make sense.
(The position of sentence "Wrong number..." should be wrong in the eclipse one)
Anyone know how to fix it? Thanks a lot!
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class MagicSquare{
// the two-dimensional array to restore my own magic square.
private int[][] myMagicSquare;
private int n;
public MagicSquare(){
}
/**
* Function: this constructor takes and positive, odd integer parameter to generate a new
* magic square.</br>
* #param n the length of magic square</br>
* #throws IllegalArgumentException for negative or even parameter.
* Preston Jul 5, 20151:15:40 AM</br>
*/
public MagicSquare(int n){
//throws runtime error.
if(!rangeCheck(n)){
throw new IllegalArgumentException("Illegal number");
}else{
// create my magic square array with length of given integer.
this.n = n;
myMagicSquare = new int[n][n];
// generate the magic square.
createMagicSquare();
}
}
/**
*
* Function: this constructor takes a 2D array as a parameter. If the 2D array can generate
* a magic square, then put the values into <i>my magic square</i></br>, if not then throws
* the exception.
* #param newMagicSquare the tested 2D array</br>
* #throws IllegalArgumentException
* Preston Jul 5, 20151:23:10 AM</br>
*/
public MagicSquare(int[][] newMagicSquare){
this.n = newMagicSquare.length;
// determine whether or not the 2D array can generate a magic square.
if(isMagic(newMagicSquare))
myMagicSquare = newMagicSquare;
else
throw new IllegalArgumentException("This is not a magic square");
}
/**
*
* Function:Range check for the input of magic square length</br>
* #param n the length of magic square
* #return true if the length is a positive, odd number</br>
* Preston Jul 5, 20152:53:29 PM</br>
*/
private static boolean rangeCheck(int n){
return !((n>0&&n%2==0)||n<=0);
}
/**
*
* Function: return the magic number of the magic square.</br>
* #return the value magic number.</br>
* Preston Jul 5, 20151:29:02 AM</br>
*/
private int getMagicNumber(){
return (n*(n*n+1))/2;
}
/**
*
* Function: For challenging level: check if all numbers for 1 to n*n only appeared once
* in the given 2D array.</br>
* #param temp the temporary 2D array as parameter.
* #return true if all numbers from 1 to n*n only appeared once</br>
* Preston Jul 5, 20151:30:03 AM</br>
*/
private static boolean noRepeatedNum(int[][] temp){
int n = temp.length;
// Set up the standard Set for comparison.
Set<Integer> standardSet = new HashSet<>();
for(int i=1;i<=n*n;i++){
standardSet.add(i);
}
// the Set made of all numbers from temp. All repeated numbers show only once in Set.
Set<Integer> arraySet = new HashSet<>();
for(int[] x : temp){
for(int a : x){
arraySet.add(a);
}
}
// return if two Sets are equal.
return arraySet.equals(standardSet);
}
/**
*
* Function: Check if the given 2D array can consist a magic square</br>
* #param temp a parameter 2D array.
* #return true if numbers in the parameter array could consist a magic square</br>
* Preston Jul 5, 20151:36:44 AM</br>
*/
private static boolean isMagic(int[][] temp){
//store the return value
boolean isMagic = true;
int tempN = temp.length;
int magicNumber = (tempN*(tempN*tempN+1))/2;
// accumulator for two diagonals
int diagonalOneSum = 0;
int diagonalTwoSum = 0;
// check rows and columns
for(int i=0; i<tempN;i++){
int rowSum = 0;
int columnSum = 0;
for(int j=0;j<tempN;j++){
// single-row sum
rowSum += temp[i][j];
// single-column sum
columnSum += temp[j][i];
}
if(rowSum!=magicNumber||columnSum!=magicNumber){
isMagic = false;
// return false immediately if there's inequality. Save calculations and performance.
return isMagic;
}
}
// counter for the second diagonal
int diagonalTwoCounter = tempN-1;
// sum of two diagonals
for(int i=0;i<temp.length;i++){
diagonalOneSum += temp[i][i];
diagonalTwoSum += temp[diagonalTwoCounter][diagonalTwoCounter];
diagonalTwoCounter--;
}
if(diagonalOneSum!=magicNumber||diagonalTwoSum!=magicNumber){
isMagic = false;
return isMagic;
}
// check if there are repeated numbers in the pretty magic square already.
return noRepeatedNum(temp);
}
/**
*
* Function: check if the position of the number in the magic square is at boundary</br>
* #param boundary the row OR column number of the position
* #return true if the value of<code>boundary</code> is zero</br>
* Preston Jul 5, 20151:53:24 PM</br>
*/
private boolean Boundary(int boundary){
return boundary==0;
}
/**
*
* Function: Put numbers from 1 to n*n into my own 2D array using Siamese Method.</br>
* Preston Jul 5, 20153:20:56 PM</br>
*/
private void createMagicSquare(){
// starting Row number -> middle
int startRow = this.n/2;
// starting Column number -> the first column
int startColumn = 0;
// start to put number from 2
int startNum = 2;
// put 1 in the starting position
myMagicSquare[startRow][startColumn] = 1;
while(startNum<=n*n){
// the positions on upper boundary
if(Boundary(startRow)&&!Boundary(startColumn)){
myMagicSquare[n-1][startColumn-1] = startNum;
startRow = n-1;
startColumn -= 1;
}
// the positions on left boundary
else if(Boundary(startColumn)&&!Boundary(startRow)){
myMagicSquare[startRow-1][n-1] = startNum;
startRow -= 1;
startColumn = n-1;
}
// upper left corner.
else if(Boundary(startRow)&&Boundary(startColumn)){
myMagicSquare[startRow][startColumn+1] = startNum;
startColumn += 1;
}
else{
// if the coming position is filled with number.
if(myMagicSquare[startRow-1][startColumn-1]!=0){
myMagicSquare[startRow][startColumn+1] = startNum;
startColumn += 1;
}
// general movement
else{
myMagicSquare[startRow-1][startColumn-1] = startNum;
startRow -= 1;
startColumn -= 1;
}
}
startNum++;
}
}
public String toString() {
// align my 2D array.
return toString(myMagicSquare);
}
/**
*
* Function:align the numbers in the parameter 2D array pretty</br>
* #param temp the parameter 2D array.
* #return the beautifully aligned String</br>
* Preston Jul 5, 20153:26:15 PM</br>
*/
public static String toString(int[][] temp){
int largestNum = 0;
// get the largest number in temp.
for(int[] x : temp){
for(int a : x){
if(a>=largestNum)
largestNum = a;
}
}
// how many digits does the biggest number have?
int longestDigit = String.valueOf(largestNum*largestNum).length();
// store the final String
StringBuilder printOut = new StringBuilder();
printOut.append('\n');
for(int[] x : temp){
for(int a : x){
// space between each number
printOut.append('\t');
// add spaces for alignment.
for(int i=0;i<longestDigit-String.valueOf(a).length();i++){
printOut.append(" ");
}
printOut.append(String.valueOf(a));
}
printOut.append('\n').append('\n');
}
// return the big String
return printOut.toString();
}
/**
*
* Function: the main function scans user input as the length of 2D array to make my
* own magic square. If the <code>userInput</code> is out of range, print out the error
* message and ask for the number again. Enter the code 0 to exit.</br>
* #param args</br>
* Preston Jul 5, 20153:28:57 PM</br>
*/
public static void main(String[] args) {
int userInput;
do{
// title
System.out.println("Enter a positive, odd number");
System.out.print("Exit code is 0, enter 0 to quit: ");
// user input
userInput = new Scanner(System.in).nextInt();
// if the userInput is out of range, show error message.
if(rangeCheck(userInput)){
MagicSquare m = new MagicSquare(userInput);
System.out.println(m.toString());
}else
if(userInput==0)
System.out.println("The magic square is not generated. QUIT");
else
System.err.println("Wrong number: Please enter a positive, odd number");
// restart
System.out.println("-------------------");
}while(userInput != 0); // enter 0 to exit.
}
}
The reason for above issue is that bug in handling of stdout and stderr in eclipse.Follow this link. (Not sure whether this is fixed or not.)
I also tried to reproduce this issue, but it is occurring in some cases and in some cases output and error output is showing at correct places.
Just for check :-
You may get this issue at very first run on eclipse, so don't exit the code, try again with wrong number (i.e. 2/4/6 ...) ;you may see error and output gets correctly printed.
1.) I'm having difficulty testing me heap class. When I try to print my heap, it's giving me code instead of the array. I tried using toString() and DeeptoString() and neither worked.
2.) In my updateValue method. I realize that it doesn't know what to do once it's reached a node that has no children. It shoots me an index out of bounds. I think an easy way to check for that is to see if the left and right child index is greater or equal to the size. If it is...I guess I want it to do nothing.
Code below:
import java.util.NoSuchElementException;
public class MaxHeap {
public int[] heap;
private int size;
public static void main(String args[]){
MaxHeap testHeap = new MaxHeap(5);
testHeap.add(5);
testHeap.add(4);
testHeap.add(3);
testHeap.add(2);
testHeap.add(1);
System.out.println((testHeap));
testHeap.maxHeapify(0);
System.out.println(testHeap);
testHeap.extractMax();
System.out.println(testHeap);
testHeap.updateValue(1, 6);
System.out.println(testHeap);
}
/**
* _Part 0: Implement this constructor._
*
* Creates a new Heap instance initially capable of storing the specified
* number of elements.
*
* #param initialsize the initial size of the heap array
*/
public MaxHeap(int initialsize) {
// TODO: implement this
heap = new int [initialsize];
}
/**
* Provides read-only access to the heap's size. Size here is the number
* of *valid* items in the heap
*
* #return the number of items in the heap
*/
public int size() {
return size;
}
/**
* _Part 1: Implement this method._
*
* Adds an item to the heap maintaining the heap condition.
*
* An item is added to the next available slot in the array, and then
* bubbled up to its parent until the heap condition is restored.
*
* #param item
* the new int to add to the heap
*/
public void add(int item) {
// TODO: implement this
int parentIndex = (size-1)/2;
int childIndex = size;
heap[size] = item; //put it at the end
while (heap[parentIndex] < heap[childIndex] && parentIndex >= 0){ //check to make sure it's a proper heap
int temp = heap[parentIndex]; //start percolating up
heap[parentIndex] = heap[childIndex];
heap[childIndex] = temp;
childIndex = parentIndex;
parentIndex = (parentIndex-1)/2;
}
size+=1;
}
/**
* _Part 2: Implement this method._
*
* Restore the heap condition to a tree rooted at the specified index when
* the left and right subtrees obey the heap condition, but the root may
* not. This is also known as "Bubble Down".
*
* That is, given the specified index, and the fact that the left and
* right subtrees are heaps (if they exist), ensure that the largest of
* these three nodes get's swapped with the root, and then recursively
* restore the heap condition for the subtree with the element that was
* moved from the root.
*
* In essence, this method bubbles a value down from the root until the
* heap condition is restored.
*
* #param index
* the root tree to restore
*/
public void maxHeapify(int index) {
// TODO: implement this
int left, right, large, tmp; // declare variables left child, right child, largest node, temp for swap
int i = index;
left = 2 * i + 1; // left child
right = 2 * i + 2; // right child
if(left <= heap.length-1 && heap[left] > heap[i]) // find smallest child
large = left; // save index of smaller child
else
large = i;
if(right <= heap.length-1 && heap[right] > heap[large])
large = right; // save index of smaller child
if(large != i) // swap and percolate, if necessary
{
tmp = heap[i]; // exchange values at two indices
heap[i] = heap[large];
heap[large] = tmp;
maxHeapify(large);}
}
/**
* _Part 3: Implement this method._
*
* Removes the maximum valued item from the heap and restores the heap
* condition. If the heap is empty, this method should throw
* a NoSuchElementException
*
* This function is performed by:
*
* 1. removing the root of the heap
* 2. placing element from the end of the heap at the root
* 3. calling maxHeapify to restore the heap condition
* 4. making sure the size is updated
*
* #return the highest valued item from the heap
* #throws NoSuchElementException if called on an empty heap
*/
public int extractMax() {
// TODO: implement this
if (size < 1){
//throw no such element
throw new NoSuchElementException();
}
int max = heap[0];
heap[0] = heap[size-1];
size = size-1;
maxHeapify(0);
return max;
}
/**
* _Part 4: Implement this method._
*
* Checks to make sure that the *max* heap condition is upheld on a
* given array of integers.
*
* HINT: Full credit will be given on this one if you implement this
* method as a *recursive* function. It will probably make sense to
* create a private method that takes another argument (e.g., the index
* of the heap's root) to indicate where the checking should begin.
*
* My private method has the following signature:
* private static boolean check(int [] arry, int rootindx, int sz)
*
*
* #param array
* the array of data to check
* #param size
* the number of elements 'in' the heap (starting at index 0)
* #return true if the *max* heap condition is upheld
*/
public static boolean checkHeapCondition(int[] array, int size) {
// TODO: implement this
if (array != null)
return helpCheck(array,0, size);
return false;
}
//Helper method
private static boolean helpCheck(int[] arr, int i, int size) {
//Base case
if (i == size-1)
return true;
//2nd base case
if (2*i+1 >= size){
return true;
}
// check if a parent's value is larger or equal to both of
// its left child and right child
else if (arr[i] >= arr[2*i + 1] && arr[i] >= arr[2*i + 2])
return (helpCheck(arr, 2*i + 1, size) && helpCheck(arr, 2*i + 2, size));
else
return false;
}
/**
* _Part 5: Implement this method._
*
* Changes the value of an element in the heap. And bubbles the value
*
* #param index
* the index of the item to be modified
* #param newValue
* the new value of the specified item
* #return the old value of that item
* #throws IndexOutOfBoundsException if the specified index is invalid
*/
public int updateValue(int index, int newValue) {
// TODO: implement this
int parent = (index-1)/2;
int leftChild = (2*index +1);
int rightChild = (2*index+2);
if (heap == null || index >= size ){
throw new IndexOutOfBoundsException();}
int oldValue = heap[index];
heap[index] = newValue;
while (heap[parent] < heap[index] && parent >= 0 ){
int temp = heap[parent];
heap[parent] = heap[index];
heap[index] = heap[temp];
index = parent;
parent = (parent-1)/2;
}
//We need to check to see if the children don't exist
if (heap[leftChild] > heap[index] || heap[rightChild] > heap[index]){
maxHeapify(index);
return oldValue;
}
else return oldValue;
}
}
The method System.out.print(Object o) uses the parameter Object's toString() method. If you have not overridden this method to provide custom behavior, it will use the parent method (in this case, the default Object.toString()).
To print the value of MaxHeap, override it's toString method, returning a String that you want to represent an instance of this class. For instance:
#Override
public String toString(){
return java.util.Arrays.toString(heap);
}
I have found what's wrong with my updateValue. I created another if statement to check if the index value of the left and right child were within bounds. Thanks for all your help.
What i am trying to do is
...
int sum[];
...
for(int z.....){
...
sum[z] = some_random_value;
...
}
But it gives an error at line sum[z]=ran; that variable sum might not have been initialized.
I tried int sum[] = 0; instead of int sum[]; but even that gave an error.
(I am basically a C programmer)
An array of dynamic size isn't possible in Java - you have to either know the size before you declare it, or do resizing operations on the array (which can be painful).
Instead, use an ArrayList<Integer>, and if you need it as an array, you can convert it back.
List<Integer> sum = new ArrayList<>();
for(int i = 0; i < upperBound; i++) {
sum.add(i);
}
// necessary to convert back to Integer[]
Integer[] sumArray = sum.toArray(new Integer[0]);
This is for getting rid of compile-time error:
int sum[] = null;
However, to prevent runtime-errors I strongly suggest you to initialize your array like this:
int[] sum = new int[10];
The number in brackets denotes the array size.
And if your size is dynamic, then use a List implementation, such as ArrayList.
int sum[]= new int[length];
You haven't initialized. As of now , you just declared.
And do not for get that the length of the array should decide at the time of initialization.
Even if you do int sum[] = null; you'll end up with an NullPointerException while you do sum[z]=ran;
Can't i just keep it dynamic? the length is variable
No. Arrays lenght should be fixed while initializing it. Look into Collection's in java. More specifically A List interface with ArrayList implementation, which is
Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null.
By writing int[] anArray = new int[10]; you are telling that
Allocate an array with enough memory for 10 integer elements and assigns the array to the anArray variable.
Seems you are new to array's and even for java. The tutorial may help you better to understand.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
If you're talking about dynamic arrays, the class can be represented as -
public class DynArray {
private int size; // The current size of the array (number of elements in the array)
private int maxSize; // Size of memory allocated for the array
private Object[] array; // size of array == maxSize
/**
* An array constructor
* Argument specifies how much memory is needed to allocate for elements
*
* #param sz
* #throws IndexOutOfBoundsException
*/
public DynArray(int sz) throws IndexOutOfBoundsException {
// Here called another more general constructor
this(sz, sz, null);
}
/**
* Call the constructor, in which indicated how much memory is allocated
* for the elements and how much memory is allocated total.
*
* #param sz
* #param maxSz
* #throws IndexOutOfBoundsException
*/
public DynArray(int sz, int maxSz) throws IndexOutOfBoundsException {
// Here called another more general constructor
this(sz, maxSz, null);
}
/**
* Additional argument contains an array of elements for initialization
*
* #param sz
* #param maxSz
* #param iniArray
* #throws IndexOutOfBoundsException
*/
public DynArray(int sz, int maxSz, Object[] iniArray) throws IndexOutOfBoundsException {
if((size = sz) < 0) {
throw new IndexOutOfBoundsException("Negative size: " + sz);
}
maxSize = (maxSz < sz ? sz : maxSz);
array = new Object[maxSize]; // memory allocation
if(iniArray != null) { // copying items
for(int i = 0; i < size && i < iniArray.length; i++) {
array[i] = iniArray[i];
// Here it was possible to use the standard method System.arraycopy
}
}
}
/**
* Indexing
*
* #param i
* #return
* #throws IndexOutOfBoundsException
*/
public Object elementAt(int i) throws IndexOutOfBoundsException {
if (i < 0 || i >= size) {
throw new IndexOutOfBoundsException("Index" + i +
" out of range [0," + (size - 1) + "]");
}
return array[i];
}
/**
* Changing the current size of the array. argument delta specifies
* direction of change (positive - increase the size;
* negative - decrease the size)
*
* #param delta
*/
public void resize(int delta) {
if (delta > 0) enlarge(delta); // increasing the size of the array
else if (delta < 0) shrink(-delta); // decreasing the size of the array
}
/**
* Increasing the size of the array
*
* #param delta
*/
public void enlarge(int delta) {
if((size += delta) > maxSize) {
maxSize = size;
Object[] newArray = new Object[maxSize];
// copying elements
for(int i =0; i < size - delta; i++)
newArray[i] = array[i];
array = newArray;
}
}
/**
* Decreasing the size of the array
*
* #param delta
*/
public void shrink(int delta) {
size = (delta > size ? 0 : size - delta);
}
/**
* Adding a new element
* (with a possible increasing the size of the array)
*
* #param e
*/
public void add(Object e) {
resize(1);
array[size-1] = e;
}
/**
* Removing the given value - shifting elements and subsequent
* reduction the size of the array
*
* #param e
*/
public void remove(Object e) {
int j;
for(j = 0; j < size; j++) {
if(e.equals(array[j])) {
break;
}
}
if(j == size) {
return false;
} else {
for(int k = j; k < size; k++)
array[k] = array[k + 1];
resize(-1);
return true;
}
}
}
You still need to initialize your array after it's declared: int sum[]= new int[length];.
Now you can assign values in the array up to the size specified when you initialized it.
If you want to have a dynamically sized array, use ArrayList and call toArray at the end to convert it back to a regular array.