Okay so this is one of my last assignments and of course this is creating the most stress for me but the only thing keeping me from turning this assignment in is being able to apply heapsort on the Heap that the user inputs their own integer values into an array list which is displayed and here is the code for that:
The heap propgram works fine but the Heapsort doesn't work or i can't use it or make a call for it in the HeapApp class
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.Scanner;
/**
*/
public class Heap<T extends Comparable<T>> {
private ArrayList<T> items;
public Heap() {
items = new ArrayList<T>();
}
private void siftUp() {
int k = items.size() - 1;
while (k > 0) {
int p = (k-1)/2;
T item = items.get(k);
T parent = items.get(p);
if (item.compareTo(parent) > 0) {
// swap
items.set(k, parent);
items.set(p, item);
// move up one level
k = p;
} else {
break;
}
}
}
public void insert(T item) {
items.add(item);
siftUp();
}
private void siftDown() {
int k = 0;
int l = 2*k+1;
while (l < items.size()) {
int max=l, r=l+1;
if (r < items.size()) { // there is a right child
if (items.get(r).compareTo(items.get(l)) > 0) {
max++;
}
}
if (items.get(k).compareTo(items.get(max)) < 0) {
// switch
T temp = items.get(k);
items.set(k, items.get(max));
items.set(max, temp);
k = max;
l = 2*k+1;
} else {
break;
}
}
}
public T delete()
throws NoSuchElementException {
if (items.size() == 0) {
throw new NoSuchElementException();
}
if (items.size() == 1) {
return items.remove(0);
}
T hold = items.get(0);
items.set(0, items.remove(items.size()-1));
siftDown();
return hold;
}
public int size() {
return items.size();
}
public boolean isEmpty() {
return items.isEmpty();
}
public String toString() {
return items.toString();
}
//----------------------------------------------------------------------------------------------------------------------------------------
public class Heapsort<T extends Comparable<T>> {
/**
* Sort the array a[0..n-1] by the heapsort algorithm.
*
* #param a the array to be sorted
* #param n the number of elements of a that have valid values
*/
public void sort(T[] a, int n) {
heapsort(a, n - 1);
}
/**
* Sort the ArrayList list by the heapsort algorithm.
* Works by converting the ArrayList to an array, sorting the
* array, and converting the result back to the ArrayList.
*
* #param list the ArrayList to be sorted
*/
public void sort(ArrayList<T> items) {
// Convert list to an array.
#SuppressWarnings("unchecked")
T[] a = (T[]) items.toArray((T[]) Array.newInstance(items.get(0).getClass(), items.size()));
sort(a, items.size()); // sort the array
// Copy the sorted array elements back into the list.
for (int i = 0; i < a.length; i++)
items.set(i, a[i]);
}
/**
* Sort the array a[0..lastLeaf] by the heapsort algorithm.
*
* #param items the array holding the heap
* #param lastLeaf the position of the last leaf in the array
*/
private void heapsort(T[] items, int lastLeaf) {
// First, turn the array a[0..lastLeaf] into a max-heap.
buildMaxHeap(items, lastLeaf);
// Once the array is a max-heap, repeatedly swap the root
// with the last leaf, putting the largest remaining element
// in the last leaf's position, declare this last leaf to no
// longer be in the heap, and then fix up the heap.
while (lastLeaf > 0) {
swap(items, 0, lastLeaf); // swap the root with the last leaf
lastLeaf--; // the last leaf is no longer in the heap
maxHeapify(items, 0, lastLeaf); // fix up what's left
}
}
/**
* Restore the max-heap property. When this method is called, the max-heap
* property holds everywhere, except possibly at node i and its children. When
* this method returns, the max-heap property holds everywhere.
*
* #param items the array holding the heap
* #param i index of the node that might violate the max-heap property
* #param lastLeaf the position of the last leaf in the array
*/
private void maxHeapify(T[] items, int i, int lastLeaf) {
int left = leftChild(i); // index of node i's left child
int right = rightChild(i); // index of node i's right child
int largest; // will hold the index of the node with the largest element
// among node i, left, and right
// Is there a left child and, if so, does the left child have an
// element larger than node i?
if (left <= lastLeaf && items[left].compareTo(items[i]) > 0)
largest = left; // yes, so the left child is the largest so far
else
largest = i; // no, so node i is the largest so far
// Is there a left child and, if so, does the right child have an
// element larger than the larger of node i and the left child?
if (right <= lastLeaf && items[right].compareTo(items[largest]) > 0)
largest = right; // yes, so the right child is the largest
// If node i holds an element larger than both the left and right
// children, then the max-heap property already held, and we need do
// nothing more. Otherwise, we need to swap node i with the larger
// of the two children, and then recurse down the heap from the larger
// child.
if (largest != i) {
swap(items, i, largest);
maxHeapify(items, largest, lastLeaf);
}
}
/**
* Form array a[0..lastLeaf] into a max-heap.
*
* #param items array to be heapified
* #param lastLeaf position of last valid data in a
*/
private void buildMaxHeap(T[] items, int lastLeaf) {
int lastNonLeaf = (lastLeaf - 1) / 2; // nodes lastNonLeaf+1 to lastLeaf are leaves
for (int j = lastNonLeaf; j >= 0; j--)
maxHeapify(items, j, lastLeaf);
}
/**
* Swap two locations i and j in array a.
*
* #param items the array
* #param i first position
* #param j second position
*/
private void swap(T[] items, int i, int j) {
T t = items[i];
items[i] = items[j];
items[j] = t;
}
/**
* Return the index of the left child of node i.
*
* #param i index of the parent node
* #return index of the left child of node i
*/
private int leftChild(int i) {
return 2 * i + 1;
}
/**
* Return the index of the right child of node i.
*
* #param i index of the parent node
* #return the index of the right child of node i
*/
private int rightChild(int i) {
return 2 * i + 2;
}
/**
* For debugging and testing, print out an array.
*
* #param a the array to print
* #param n number of elements of a to print
*/
public void printArray(T[] items, int n) {
for (int i = 0; i < n; i++)
System.out.println(items[i]);
}
}
}
import java.util.Scanner;
public class HeapApp{
/**
* #param args
*/
public static void main(String[] args) {
Heap<Integer> hp = new Heap<Integer>();
Scanner sc = new Scanner(System.in);
System.out.print("Enter next int, 'done' to stop: ");
String line = sc.next();
while (!line.equals("done")) {
hp.insert(Integer.parseInt(line));
System.out.println(hp);
System.out.print("Enter next int, 'done' to stop: ");
line = sc.next();
}
while (hp.isEmpty()) {
//int max = hp.delete();
System.out.println( " " + hp);
}
System.out.println(hp);
System.out.println("After sorting " + hp);
}
}
Now i'm not asking anyone to do it for me but i just need help figuring out how to get the Heapsort to work with the heap PLEASE HELP! The most i have tried is setting the parameters within the Heap sort method.
My question and code is not a duplicate for one this is based on a Heap and heapsort from the user input:
public static void main(String[] args) {
Heap<Integer> hp = new Heap<Integer>();
Scanner sc = new Scanner(System.in);
System.out.print("Enter next int, 'done' to stop: ");
String line = sc.next();
while (!line.equals("done")) {
hp.insert(Integer.parseInt(line));
System.out.println(hp);
System.out.print("Enter next int, 'done' to stop: ");
line = sc.next();
}
Also the entire Heap is implemented using an ArrayList:
public class Heap<T extends Comparable<T>> {
private ArrayList<T> items;
public Heap() {
items = new ArrayList<T>();
}
Add a sort method to your Heap class like this:
public void sort()
{
new Heapsort<T>().sort(items);
}
Then in your HeapApp class call the sort method before printing it out:
hp.sort();
System.out.println("After sorting " + hp);
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 am an Undergraduate Computer Science Student and we're actually starting to learn the Java Language.
I am trying to solve one of my Labs but I have a problem.
My Problem is how to call a method from an other class, which is located in another package, and the package is already imported in my class.
I tried to write the nameOftheClass.nameOfthemethod(parameters); but that didn't work for me.
To be more Specefic, I was trying to call the method getElementAt(index) which is located in the frame package and in the SortArray Class .. But I don't have a clue why is this not working for me!
this is my QuicksortB Class :
package lab;
import frame.SortArray;
public class QuickSortB extends QuickSort {
/**
* Quicksort algorithm implementation to sort a SorrtArray by choosing the
* pivot as the median of the elements at positions (left,middle,right)
*
* #param records
* - list of elements to be sorted as a SortArray
* #param left
* - the index of the left bound for the algorithm
* #param right
* - the index of the right bound for the algorithm
* #return Returns the sorted list as SortArray
*/
#Override
public void Quicksort(SortArray records, int left, int right) {
// TODO
// implement the Quicksort B algorithm to sort the records
// (choose the pivot as the median value of the elements at position
// (left (first),middle,right(last)))
int i = left, j = right;
//Get The Element from the Middle of The List
int pivot = SortArray.getElementAt(left + (right-left)/2);
//Divide into two Lists
while (i <= j) {
// If the current value from the left list is smaller then the pivot
// element then get the next element from the left list
while (SortArray.getElementAt(i) < pivot) {
i++;
}
// If the current value from the right list is larger then the pivot
// element then get the next element from the right list
while (SortArray.getElementAt(j) > pivot) {
j--;
}
// If we have found a values in the left list which is larger then
// the pivot element and if we have found a value in the right list
// which is smaller then the pivot element then we exchange the
// values.
// As we are done we can increase i and j
if (i <= j) {
exchange(i,j)
i++;
j--;
}
}
public void exchange(int i, int j) {
int temp = SortArray.getElementAt(i);
SortArray.getElementAt(i) = SortArray.getElementAt(j);
SortArraz.getElementAt(j) = temp;
}
}
}
And this is My SortArray Class :
package frame;
import java.util.ArrayList;
import lab.SortingItem;
/**
* Do NOT change anything in this class!
*
* The SortArray class provides simple basic functions, to store a list of
* sortingItems to track the number of operations.
*
* This class contains two members (readingOperations and writingOperations)
* that act as counters for the number of accesses to the arrays to be sorted.
* These are used by the JUnit tests to construct the output. The methods
* provided in this class should be sufficient for you to sort the records of
* the input files.
*
* #author Stefan Kropp
*/
public class SortArray {
private int numberOfItems;
private ArrayList<SortingItem> listOfItems;
private int readingOperations;
private int writingOperations;
/**
* #param numberOfItems
* number of items to hold
*/
public SortArray(ArrayList<String[]> items) {
numberOfItems = items.size();
readingOperations = 0;
writingOperations = 0;
listOfItems = new ArrayList<>();
for (String[] element : items) {
SortingItem s = new SortingItem();
s.BookSerialNumber = element[0];
s.ReaderID = element[1];
s.Status = element[2];
listOfItems.add(s);
}
}
/**
* sets the elements at index. if index is >= numberOfItems or less then
* zero an IndexOutOfBoundException will occur.
*
* #param index
* the index of the Elements to set
* #param record
* a 3-dimensional record which holds: BookSerialNumber,
* ReaderID, Status
*/
public void setElementAt(int index, SortingItem record) {
this.listOfItems.set(index, record);
writingOperations++;
}
/**
* Retrieves the information stored at position Index. if index is >=
* numberOfItems or less then zero an IndexOutOfBoundException will occur.
*
* #param index
* Index defines which elements to retrieve from the SortArray
* #return Returns a 3-dimensional String array with following format:
* BookSerialNumber, ReaderID, Status.
*
*/
public SortingItem getElementAt(int index) {
SortingItem result = new SortingItem(this.listOfItems.get(index));
readingOperations++;
return result;
}
/**
* #return Returns the number of reading operations.
*/
public int getReadingOperations() {
return readingOperations;
}
/**
* #return Returns the number of writing operations.
*/
public int getWritingOperations() {
return writingOperations;
}
/**
* #return Returns the numberOfItems.
*/
public int getNumberOfItems() {
return numberOfItems;
}
}
You attempted to call the method getElementAt as a static function. You have to create an instance of SortArray and then call the method on that object, e.g.
ArrayList<String[]> myList = ...; // some initialization
SortArray sortObject = new SortArray(myList);
SortingItem result = sortObject.getElementAt(0);
If you want your function to be accessible as you tried, you have to use the static modifier, which in turn means, you don't have access to members of the class (i.e. non-static fields).
public void doSomething() {
this.numberOfItems++; // this is allowed
}
In contrast to:
public static void doSomethingStatic() {
this.numberOfItems++; // this is not allowed
}
to call a method, you have to know if the method is static method (class method) or object method.
If it is static method, (like the famous main(String[] args)) you can just call it by ClassName.method(), if it is not static method, you have to first get the instance of the class, by calling the constructor for example, then call the method via oneInstance.method()
I suggest you reading the related chapters in your lecture text book, then do some test on your own.
I just don't give codes since this is an assignment.
The way you are trying to access the function is as if it were static, since you try to call it through the actual class, not from an object.
You should generate an object which references the desired class, in this case SortArray.
In QuickSortB
public SortArray sortArray;
#Override
public void Quicksort(SortArray records, int left, int right) {
// TODO
// implement the Quicksort B algorithm to sort the records
// (choose the pivot as the median value of the elements at position
// (left (first),middle,right(last)))
sortArray = new SortArray ();
int i = left, j = right;
//Get The Element from the Middle of The List
int pivot = sortArray.getElementAt(left + (right-left)/2);
//Divide into two Lists
while (i <= j) {
// If the current value from the left list is smaller then the pivot
// element then get the next element from the left list
while (sortArray.getElementAt(i) < pivot) {
i++;
}
// If the current value from the right list is larger then the pivot
// element then get the next element from the right list
while (sortArray.getElementAt(j) > pivot) {
j--;
}
// If we have found a values in the left list which is larger then
// the pivot element and if we have found a value in the right list
// which is smaller then the pivot element then we exchange the
// values.
// As we are done we can increase i and j
if (i <= j) {
exchange(i,j)
i++;
j--;
}
}
public void exchange(int i, int j) {
int temp = SortArray.getElementAt(i);
sortArray.getElementAt(i) = SortArray.getElementAt(j);
sortArray.getElementAt(j) = temp;
}
}
}
Hope it helps^^
Create an instance of SortArray object and call using that reference check the below code for clarity
public class QuickSortB extends QuickSort {
//create instance of sortArray
SortArray sortArray=new SortArray();
//call the method like this
sortArray.getElementAt(i)
}
public class SortArray {
// code skipped for clarity
public SortingItem getElementAt(int index) {
SortingItem result = new SortingItem(this.listOfItems.get(index));
readingOperations++;
return result;
}
// code skipped for clarity
}
Like a Max-heap and Min-heap, I want to implement a Median-heap to keep track of the median of a given set of integers. The API should have the following three functions:
insert(int) // should take O(logN)
int median() // will be the topmost element of the heap. O(1)
int delmedian() // should take O(logN)
I want to use an array (a) implementation to implement the heap where the children of array index k are stored in array indices 2*k and 2*k + 1. For convenience, the array starts populating elements from index 1.
This is what I have so far:
The Median-heap will have two integers to keep track of number of integers inserted so far that are > current median (gcm) and < current median (lcm).
if abs(gcm-lcm) >= 2 and gcm > lcm we need to swap a[1] with one of its children.
The child chosen should be greater than a[1]. If both are greater,
choose the smaller of two.
Similarly for the other case. I can't come up with an algorithm for how to sink and swim elements. I think it should take into consideration how close the number is to the median, so something like:
private void swim(int k) {
while (k > 1 && absless(k, k/2)) {
exch(k, k/2);
k = k/2;
}
}
I can't come up with the entire solution though.
You need two heaps: one min-heap and one max-heap. Each heap contains about one half of the data. Every element in the min-heap is greater or equal to the median, and every element in the max-heap is less or equal to the median.
When the min-heap contains one more element than the max-heap, the median is in the top of the min-heap. And when the max-heap contains one more element than the min-heap, the median is in the top of the max-heap.
When both heaps contain the same number of elements, the total number of elements is even.
In this case you have to choose according your definition of median: a) the mean of the two middle elements; b) the greater of the two; c) the lesser; d) choose at random any of the two...
Every time you insert, compare the new element with those at the top of the heaps in order to decide where to insert it. If the new element is greater than the current median, it goes to the min-heap. If it is less than the current median, it goes to the max heap. Then you might need to rebalance. If the sizes of the heaps differ by more than one element, extract the min/max from the heap with more elements and insert it into the other heap.
In order to construct the median heap for a list of elements, we should first use a linear time algorithm and find the median. Once the median is known, we can simply add elements to the Min-heap and Max-heap based on the median value. Balancing the heaps isn't required because the median will split the input list of elements into equal halves.
If you extract an element you might need to compensate the size change by moving one element from one heap to another. This way you ensure that, at all times, both heaps have the same size or differ by just one element.
Here is a java implementaion of a MedianHeap, developed with the help of above comocomocomocomo 's explanation .
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;
/**
*
* #author BatmanLost
*/
public class MedianHeap {
//stores all the numbers less than the current median in a maxheap, i.e median is the maximum, at the root
private PriorityQueue<Integer> maxheap;
//stores all the numbers greater than the current median in a minheap, i.e median is the minimum, at the root
private PriorityQueue<Integer> minheap;
//comparators for PriorityQueue
private static final maxHeapComparator myMaxHeapComparator = new maxHeapComparator();
private static final minHeapComparator myMinHeapComparator = new minHeapComparator();
/**
* Comparator for the minHeap, smallest number has the highest priority, natural ordering
*/
private static class minHeapComparator implements Comparator<Integer>{
#Override
public int compare(Integer i, Integer j) {
return i>j ? 1 : i==j ? 0 : -1 ;
}
}
/**
* Comparator for the maxHeap, largest number has the highest priority
*/
private static class maxHeapComparator implements Comparator<Integer>{
// opposite to minHeapComparator, invert the return values
#Override
public int compare(Integer i, Integer j) {
return i>j ? -1 : i==j ? 0 : 1 ;
}
}
/**
* Constructor for a MedianHeap, to dynamically generate median.
*/
public MedianHeap(){
// initialize maxheap and minheap with appropriate comparators
maxheap = new PriorityQueue<Integer>(11,myMaxHeapComparator);
minheap = new PriorityQueue<Integer>(11,myMinHeapComparator);
}
/**
* Returns empty if no median i.e, no input
* #return
*/
private boolean isEmpty(){
return maxheap.size() == 0 && minheap.size() == 0 ;
}
/**
* Inserts into MedianHeap to update the median accordingly
* #param n
*/
public void insert(int n){
// initialize if empty
if(isEmpty()){ minheap.add(n);}
else{
//add to the appropriate heap
// if n is less than or equal to current median, add to maxheap
if(Double.compare(n, median()) <= 0){maxheap.add(n);}
// if n is greater than current median, add to min heap
else{minheap.add(n);}
}
// fix the chaos, if any imbalance occurs in the heap sizes
//i.e, absolute difference of sizes is greater than one.
fixChaos();
}
/**
* Re-balances the heap sizes
*/
private void fixChaos(){
//if sizes of heaps differ by 2, then it's a chaos, since median must be the middle element
if( Math.abs( maxheap.size() - minheap.size()) > 1){
//check which one is the culprit and take action by kicking out the root from culprit into victim
if(maxheap.size() > minheap.size()){
minheap.add(maxheap.poll());
}
else{ maxheap.add(minheap.poll());}
}
}
/**
* returns the median of the numbers encountered so far
* #return
*/
public double median(){
//if total size(no. of elements entered) is even, then median iss the average of the 2 middle elements
//i.e, average of the root's of the heaps.
if( maxheap.size() == minheap.size()) {
return ((double)maxheap.peek() + (double)minheap.peek())/2 ;
}
//else median is middle element, i.e, root of the heap with one element more
else if (maxheap.size() > minheap.size()){ return (double)maxheap.peek();}
else{ return (double)minheap.peek();}
}
/**
* String representation of the numbers and median
* #return
*/
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("\n Median for the numbers : " );
for(int i: maxheap){sb.append(" "+i); }
for(int i: minheap){sb.append(" "+i); }
sb.append(" is " + median()+"\n");
return sb.toString();
}
/**
* Adds all the array elements and returns the median.
* #param array
* #return
*/
public double addArray(int[] array){
for(int i=0; i<array.length ;i++){
insert(array[i]);
}
return median();
}
/**
* Just a test
* #param N
*/
public void test(int N){
int[] array = InputGenerator.randomArray(N);
System.out.println("Input array: \n"+Arrays.toString(array));
addArray(array);
System.out.println("Computed Median is :" + median());
Arrays.sort(array);
System.out.println("Sorted array: \n"+Arrays.toString(array));
if(N%2==0){ System.out.println("Calculated Median is :" + (array[N/2] + array[(N/2)-1])/2.0);}
else{System.out.println("Calculated Median is :" + array[N/2] +"\n");}
}
/**
* Another testing utility
*/
public void printInternal(){
System.out.println("Less than median, max heap:" + maxheap);
System.out.println("Greater than median, min heap:" + minheap);
}
//Inner class to generate input for basic testing
private static class InputGenerator {
public static int[] orderedArray(int N){
int[] array = new int[N];
for(int i=0; i<N; i++){
array[i] = i;
}
return array;
}
public static int[] randomArray(int N){
int[] array = new int[N];
for(int i=0; i<N; i++){
array[i] = (int)(Math.random()*N*N);
}
return array;
}
public static int readInt(String s){
System.out.println(s);
Scanner sc = new Scanner(System.in);
return sc.nextInt();
}
}
public static void main(String[] args){
System.out.println("You got to stop the program MANUALLY!!");
while(true){
MedianHeap testObj = new MedianHeap();
testObj.test(InputGenerator.readInt("Enter size of the array:"));
System.out.println(testObj);
}
}
}
Here my code based on the answer provided by comocomocomocomo :
import java.util.PriorityQueue;
public class Median {
private PriorityQueue<Integer> minHeap =
new PriorityQueue<Integer>();
private PriorityQueue<Integer> maxHeap =
new PriorityQueue<Integer>((o1,o2)-> o2-o1);
public float median() {
int minSize = minHeap.size();
int maxSize = maxHeap.size();
if (minSize == 0 && maxSize == 0) {
return 0;
}
if (minSize > maxSize) {
return minHeap.peek();
}if (minSize < maxSize) {
return maxHeap.peek();
}
return (minHeap.peek()+maxHeap.peek())/2F;
}
public void insert(int element) {
float median = median();
if (element > median) {
minHeap.offer(element);
} else {
maxHeap.offer(element);
}
balanceHeap();
}
private void balanceHeap() {
int minSize = minHeap.size();
int maxSize = maxHeap.size();
int tmp = 0;
if (minSize > maxSize + 1) {
tmp = minHeap.poll();
maxHeap.offer(tmp);
}
if (maxSize > minSize + 1) {
tmp = maxHeap.poll();
minHeap.offer(tmp);
}
}
}
Isn't a perfectly balanced binary search tree (BST) a median heap? It is true that even red-black BSTs aren't always perfectly balanced, but it might be close enough for your purposes. And log(n) performance is guaranteed!
AVL trees are more tighly balanced than red-black BSTs so they come even closer to being a true median heap.
Here is a Scala implementation, following the comocomocomocomo's idea above.
class MedianHeap(val capacity:Int) {
private val minHeap = new PriorityQueue[Int](capacity / 2)
private val maxHeap = new PriorityQueue[Int](capacity / 2, new Comparator[Int] {
override def compare(o1: Int, o2: Int): Int = Integer.compare(o2, o1)
})
def add(x: Int): Unit = {
if (x > median) {
minHeap.add(x)
} else {
maxHeap.add(x)
}
// Re-balance the heaps.
if (minHeap.size - maxHeap.size > 1) {
maxHeap.add(minHeap.poll())
}
if (maxHeap.size - minHeap.size > 1) {
minHeap.add(maxHeap.poll)
}
}
def median: Double = {
if (minHeap.isEmpty && maxHeap.isEmpty)
return Int.MinValue
if (minHeap.size == maxHeap.size) {
return (minHeap.peek+ maxHeap.peek) / 2.0
}
if (minHeap.size > maxHeap.size) {
return minHeap.peek()
}
maxHeap.peek
}
}
Another way to do it without using a max-heap and a min-heap would be to use a median-heap right away.
In a max-heap, the parent is greater than the children.
We can have a new type of heap where the parent is in the 'middle' of the children - the left child is smaller than the parent and the right child is greater than the parent. All even entries are left children and all odd entries are right children.
The same swim and sink operations which can be performed in a max-heap, can also be performed in this median-heap - with slight modifications. In a typical swim operation in a max-heap, the inserted entry swims up till it is smaller than a parent entry, here in a median-heap, it will swim up till it is lesser than a parent (if it is an odd entry) or greater than a parent (if it is an even entry).
Here's my implementation for this median-heap. I have used an array of Integers for simplicity.
package priorityQueues;
import edu.princeton.cs.algs4.StdOut;
public class MedianInsertDelete {
private Integer[] a;
private int N;
public MedianInsertDelete(int capacity){
// accounts for '0' not being used
this.a = new Integer[capacity+1];
this.N = 0;
}
public void insert(int k){
a[++N] = k;
swim(N);
}
public int delMedian(){
int median = findMedian();
exch(1, N--);
sink(1);
a[N+1] = null;
return median;
}
public int findMedian(){
return a[1];
}
// entry swims up so that its left child is smaller and right is greater
private void swim(int k){
while(even(k) && k>1 && less(k/2,k)){
exch(k, k/2);
if ((N > k) && less (k+1, k/2)) exch(k+1, k/2);
k = k/2;
}
while(!even(k) && (k>1 && !less(k/2,k))){
exch(k, k/2);
if (!less (k-1, k/2)) exch(k-1, k/2);
k = k/2;
}
}
// if the left child is larger or if the right child is smaller, the entry sinks down
private void sink (int k){
while(2*k <= N){
int j = 2*k;
if (j < N && less (j, k)) j++;
if (less(k,j)) break;
exch(k, j);
k = j;
}
}
private boolean even(int i){
if ((i%2) == 0) return true;
else return false;
}
private void exch(int i, int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
private boolean less(int i, int j){
if (a[i] <= a[j]) return true;
else return false;
}
public static void main(String[] args) {
MedianInsertDelete medianInsertDelete = new MedianInsertDelete(10);
for(int i = 1; i <=10; i++){
medianInsertDelete.insert(i);
}
StdOut.println("The median is: " + medianInsertDelete.findMedian());
medianInsertDelete.delMedian();
StdOut.println("Original median deleted. The new median is " + medianInsertDelete.findMedian());
}
}
I'm trying to make a string binary search program. Trouble is I don't remember a straight forward way to convert a string array into a Integer array.
I've written a long and complicated way to convert them. However Netsbeans is saying my string array identifier is expected.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication3;
/**
*
* #author Ivan Beazer
*/
import java.io.*;
/**
This program demonstrates the search method in
the IntBinarySearcher class.
*/
public class BinarySearchTest
{
private static String aString;
// Convert string array to string
public static String arrayToString2(String[] words, String aString)
{
StringBuilder result = new StringBuilder();
if (words.length > 0)
{
result.append(words[0]);
for (int i=1; i<words.length; i++)
{
result.append(aString);
result.append(words[i]);
}
}
return result.toString();
}
public static void main(String [] args) throws IOException
{
int result, searchValue;
String input;
// A String array of words to search.
// This is the error. netbeans says identifier is expected.
String[] words = {"Jake", "Jerry". "Bill", "Lousie", "Goku", "Ivan", "John", "sarah", "kim"};
// convert string to int array
int[] numbers = new int[aString.length()];
for(int i=0; i<aString.length(); i++)
numbers[i] = Character.getNumericValue(aString.charAt(i));
// Create the console input objects.
InputStreamReader reader =
new InputStreamReader(System.in);
BufferedReader keyboard =
new BufferedReader(reader);
// First we must sort the array in ascending order.
IntQuickSorter.quickSort(numbers);
do
{
// Get a value to search for.
System.out.print("Enter a value to search for: ");
input = keyboard.readLine();
searchValue = Integer.parseInt(input);
// Search for the value
result = IntBinarySearcher.search(numbers, searchValue);
// Display the results.
if (result == -1)
System.out.println(searchValue + " was not found.");
else
{
System.out.println(searchValue + " was found at " +
"element " + result);
}
// Does the user want to search again?
System.out.print("Do you want to search again? (Y or N): ");
input = keyboard.readLine();
} while (input.charAt(0) == 'y' || input.charAt(0) == 'Y');
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication3;
/**
*
* #author Devon B
*/
/**
The IntBinarySearcher class provides a public static
method for performing a binary search on an int array.
*/
public class IntBinarySearcher
{
/**
The search method performs a binary search on an int
array. The array is searched for the number passed to
value. If the number is found, its array subscript is
returned. Otherwise, -1 is returned indicating the
value was not found in the array.
#param array The array to search.
#param value The value to search for.
*/
public static int search(int[] array, int value)
{
int first; // First array element
int last; // Last array element
int middle; // Mid point of search
int position; // Position of search value
boolean found; // Flag
// Set the inital values.
first = 0;
last = array.length - 1;
position = -1;
found = false;
// Search for the value.
while (!found && first <= last)
{
// Calculate mid point
middle = (first + last) / 2;
// If value is found at midpoint...
if (array[middle] == value)
{
found = true;
position = middle;
}
// else if value is in lower half...
else if (array[middle] > value)
last = middle - 1;
// else if value is in upper half....
else
first = middle + 1;
}
// Return the position of the item, or -1
// if it was not found.
return position;
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication3;
/**
*
* #author Devon B
*/
/**
The IntQuickSorter class provides a public static
method for performing a QuickSort on an int array.
*/
public class IntQuickSorter
{
/**
The quickSort method calls the doQuickSort method
to sort an int array.
#param array The array to sort.
*/
public static void quickSort(int array[])
{
doQuickSort(array, 0, array.length - 1);
}
/**
The doQuickSort method uses the QuickSort algorithm
to sort an int array.
#param array The array to sort.
#param start The starting subscript of the list to sort
#param end The ending subscript of the list to sort
*/
private static void doQuickSort(int array[], int start, int end)
{
int pivotPoint;
if (start < end)
{
// Get the pivot point.
pivotPoint = partition(array, start, end);
// Sort the first sub list.
doQuickSort(array, start, pivotPoint - 1);
// Sort the second sub list.
doQuickSort(array, pivotPoint + 1, end);
}
}
/**
The partiton method selects a pivot value in an array
and arranges the array into two sub lists. All the
values less than the pivot will be stored in the left
sub list and all the values greater than or equal to
the pivot will be stored in the right sub list.
#param array The array to partition.
#param start The starting subscript of the area to partition.
#param end The ending subscript of the area to partition.
#return The subscript of the pivot value.
*/
private static int partition(int array[], int start, int end)
{
int pivotValue; // To hold the pivot value
int endOfLeftList; // Last element in the left sub list.
int mid; // To hold the mid-point subscript
// Find the subscript of the middle element.
// This will be our pivot value.
mid = (start + end) / 2;
// Swap the middle element with the first element.
// This moves the pivot value to the start of
// the list.
swap(array, start, mid);
// Save the pivot value for comparisons.
pivotValue = array[start];
// For now, the end of the left sub list is
// the first element.
endOfLeftList = start;
// Scan the entire list and move any values that
// are less than the pivot value to the left
// sub list.
for (int scan = start + 1; scan <= end; scan++)
{
if (array[scan] < pivotValue)
{
endOfLeftList++;
swap(array, endOfLeftList, scan);
}
}
// Move the pivot value to end of the
// left sub list.
swap(array, start, endOfLeftList);
// Return the subscript of the pivot value.
return endOfLeftList;
}
/**
The swap method swaps the contents of two elements
in an int array.
#param The array containing the two elements.
#param a The subscript of the first element.
#param b The subscript of the second element.
*/
private static void swap(int[] array, int a, int b)
{
int temp;
temp = array[a];
array[a] = array[b];
array[b] = temp;
}
}
Look after the string "Jerry":
String[] words = {"Jake", "Jerry". "Bill", "Lousie", "Goku", "Ivan", "John", "sarah", "kim"};
You have a dot ( . ) instead of a comma ( , )
I'm a first year computer science student having a problem with part of an assignment. The goal of the assignment was to store the coefficients for a polynomial and find its roots using both an array and a linked list. I was able to successfully complete the array version; however the linked list is giving me a headache.
I am able to successfully store the initial round of variables provided in polynomial.java; however, things go a bit crazy once the root calculations begin and the program ends up terminating without giving any roots. I have a feeling this might be being cause by the way the Polynomial.java calculates the roots causing problems with the linked list; however, I am not allowed to change polynomial.java, only LinkedIntList.java. I have been banging my head against the computer for the past 7 hours trying to find the bug and am about ready to just give up on the assignment as I can't reach the professor for help.
I'd greatly appreciate anyone who can spot the bug or are willing to look over the code to provide tips on what I may be doing wrong or how I can work around my problem.
File 1: Node.Java
package lists;
public class Node
{
int element;
Node next = null;
/**
* Constructor which creates a new node containing the value specified by item
*
*/
public Node (int item)
{
element = item;
}
/**
* Returns the current value of the data item contained inside this node
*/
public int getElement ()
{
return element;
}
/**
* Sets the current value of the data item contained inside this node to
* the value specified by newVal
*/
public void setElement (int newVal)
{
element = newVal;
}
/**
* Links this node to the node passed in as an argument
*/
public void setNext (Node n)
{
next = n;
}
/**
* Returns a reference to the node that follows this node in the
* linked list, or null if there is no such node
*/
public Node getNext ()
{
return next;
}
/**
* Returns a string based representation of the data item contained
* in this node.
*/
public String toString()
{
return Integer.toString(element);
}
}
File 2: LinkedIntList.Java
package lists;
public class LinkedIntList implements IntList
{
Node head = null;
int count = 0;
/**
* Standard Java toString method that returns a string
* equivalent of the IntList
*
* #return a string indicating the values contained in
* this IntList (ex: "[5 3 2 9 ]")
*/
public String toString()
{
String retVal = "";
String intermediary = "";
Node n;
for (n = head; n.getNext() != null; n = n.getNext())
{
intermediary = Integer.toString(n.getElement());
retVal = intermediary + " " + retVal;
}
retVal = n.getElement() + " " + retVal;
return retVal;
}
/**
* Adds the given value to the <b>end</b> of the list.
*
* #param value the value to add to the list
*/
public void add (int value)
{
Node newNode = new Node (value);
if (head == null)
head = newNode;
else
{
Node n = head;
while (n.getNext() != null)
{
n = n.getNext();
}
n.setNext(newNode);
}
count++;
}
/**
* Returns the number of elements currently in the list.
*
* #return the number of items currently in the list
*/
public int size()
{
return count;
}
/**
* Returns the element at the specified position in this list.
*
* #param index index of the element to return (zero-based)
* #return the element at the specified position in this list.
* #throws IndexOutOfBoundsException if the index is out of range
* (index < 0 || index >= size()).
*/
public int get(int index) throws IndexOutOfBoundsException
{
Node reference = head;
if (index < 0 || index >= count)
{
throw new IndexOutOfBoundsException("Index out of bounds.");
}
for (int i = 0; i != index; i++)
{
reference.getNext();
}
return reference.getElement();
}
/**
* Replaces the element at the specified position in this list with
* the specified element.
*
* #param index index of the element to return (zero-based)
* #param value element to be stored at the specified position.
* #throws IndexOutOfBoundsException if the index is out of range
* (index < 0 || index >= size()).
*/
public void set (int index, int value) throws IndexOutOfBoundsException
{
if (index < 0 || index >= count)
{
throw new IndexOutOfBoundsException("Index out of bounds.");
}
Node newNode = new Node (value);
Node trailingReference = head;
Node leadingReference = head.getNext();
for(int i = 1; i != index; i++)
{
trailingReference = leadingReference;
leadingReference = leadingReference.getNext();
}
trailingReference.setNext(newNode);
newNode.setNext(leadingReference);
count++;
}
}
File 3: IntList.Java
package lists;
public interface IntList
{
/**
* Standard Java toString method that returns a string
* equivalent of the IntList
*
* #return a string indicating the values contained in
* this IntList (ex: "[5 3 2 9 ]")
*/
public String toString();
/**
* Adds the given value to the <b>end</b> of the list.
*
* #param value the value to add to the list
*/
public void add (int value);
/**
* Returns the number of elements currently in the list.
*
* #return the number of items currently in the list
*/
public int size();
/**
* Returns the element at the specified position in this list.
*
* #param index index of the element to return (zero-based)
* #return the element at the specified position in this list.
* #throws IndexOutOfBoundsException if the index is out of range
* (index < 0 || index >= size()).
*/
public int get(int index);
/**
* Replaces the element at the specified position in this list with
* the specified element.
*
* #param index index of the element to return (zero-based)
* #param value element to be stored at the specified position.
* #throws IndexOutOfBoundsException if the index is out of range
* (index < 0 || index >= size()).
*/
public void set (int index, int value);
}
File 4: Polynomial.java
/**
* A program which finds the integer (whole number) roots of a
* polynomial with integer coeffecients. The method used is based
* upon the ideas presented at:
*
*/
import lists.*;
public class Polynomial
{
public static void main (String [] args)
{
// trick to get out of static context
new Polynomial().runMe();
}
public void runMe()
{
IntList poly = new LinkedIntList();
// Create the polynomial:
// 3x^10 + 12x^9 - 496x^8 - 211x^7 + 18343x^6 -43760x^5 +
// 11766x^4 + 26841x^3 - 126816x^2 + 37278x - 84240
poly.add (-84240);
poly.add (37278);
poly.add (-126816);
poly.add (26841);
poly.add (11766);
poly.add (-43760);
poly.add (18343);
poly.add (-211);
poly.add (-496);
poly.add (12);
poly.add (3);
System.out.print ("Finding the integer roots of the polynomial: ");
System.out.println (poly);
IntList roots = findRoots (poly);
for (int x = 0; x < roots.size(); x++)
System.out.println ("Root found: " + roots.get(x));
}
/**
* Find all *integer* roots of the polynomial represented by the IntList.
*
* #param poly a polynomial encoded as a list of coefficients
* #return a list of all roots of the given polynomial. Note that
* the returned list may have duplicate entries.
*/
public IntList findRoots (IntList poly)
{
IntList l = new LinkedIntList();
int q = poly.get(poly.size() - 1);
int p = poly.get(0);
IntList pVals = divTerms(Math.abs(p));
IntList qVals = divTerms(Math.abs(q));
IntList possibleZeros = findPotentialZeros(pVals, qVals);
//for (Integer i : possibleZeros)
for (int x = 0; x < possibleZeros.size(); x++)
if (eval (poly, possibleZeros.get(x)) == 0)
l.add (possibleZeros.get(x));
return l;
}
/**
* Evaluates the polynomial represented by the IntList with the given
* value.
*
* #param poly a
* #param val the value to evaluate the polynomial with.
* #return f(val), where f is the polynomial encoded as poly
*/
private int eval (IntList poly, int val)
{
int result = 0;
for (int x = poly.size() - 1; x >= 0; x--)
result += poly.get(x) * (int) Math.pow (val, x);
return result;
}
private IntList findPotentialZeros (IntList plist, IntList qlist)
{
IntList result = new LinkedIntList();
for (int p = 0; p < plist.size(); p++)
{
for (int q = 0; q < qlist.size(); q++)
{
// add it only if q evenly divides p (we're looking
// for integer roots only
if (plist.get(p) % qlist.get(q) == 0)
{
int x = plist.get(p) / qlist.get(q);
result.add (x);
result.add (-x);
}
}
}
return result;
}
/**
* Find all integers that evenly divide i.
*
* #param i the integer to find all divisors of
* #return a list of all integers that evenly divide i
*/
private IntList divTerms (int i)
{
IntList v = new LinkedIntList();
// 1 divides all numbers
v.add(1);
// find all divisors < i and >= 2
for (int x = 2; x < i; x++)
if (i % x == 0)
v.add(x);
// all numbers are evenly divisible by themselves
if (i > 1)
v.add(i);
return v;
}
}
I think, the mistake (or one of them) is in your LinkedList imlementation, exactly in get method:
public int get(int index) throws IndexOutOfBoundsException
{
Node reference = head;
if (index < 0 || index >= count)
{
throw new IndexOutOfBoundsException("Index out of bounds.");
}
for (int i = 0; i != index; i++)
{
reference.getNext(); // <--- the mistake is here
}
return reference.getElement();
}
Your reference always refers on the head of the list.
If you're allowed to use any java packages - use java.util.LinkedList. Otherwise, use java.util.LinkedList until all other parts of your programm would be finished and tested and work as you wish. After that carefully replace it with your LinkedList implementation.
The set method in the LinkedIntList isn't adhering to the contract specified in the Javadoc. It says replace the element at the given index but I see code that adds a new Node.
Have a look at what methods the Node class provides to help you make the set method a lot easier and correct.
Take a good look at your get implementation. It does not do what you think.