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)
Related
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);
I'm trying to use these quick sort methods to figure out how many comparison are happening. We are given a global variable that does the counting but we aren't able to use the global variable when we hand it in. Instead we need to recursively count the comparisons. Now I am trying to figure out how to do that and I'm not looking for the answer, I'm trying to get on the right steps on how to solve this problem. I've been trying things for a couple hours now and no luck.
static int qSortCompares = 0; // GLOBAL var declaration
/**
* 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;
}
public static void quickSort(int array[]) {
qSortCompares = 0;
int qSCount = 0;
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 int doQuickSort(int array[], int start, int end) {
int pivotPoint;
int qSTotal = 0;
if (start < end) {
// Get the pivot point.
pivotPoint = partition(array, start, end);
// Note - only one +/=
// Sort the first sub list.
doQuickSort(array, start, pivotPoint - 1);
// Sort the second sub list.
doQuickSort(array, pivotPoint + 1, end);
}
return qSTotal;
}
/**
* The partition 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
int qSCount = 0;
// see http://www.cs.cmu.edu/~fp/courses/15122-s11/lectures/08-qsort.pdf
// for discussion of middle point - This improves the almost sorted cases
// of using quicksort
// 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++) {
qSortCompares++;
qSCount++;
if (array[scan] < pivotValue) {
endOfLeftList++;
// System.out.println("Pivot=" + pivotValue + "=" + endOfLeftList + ":" + scan);
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;
}
/**
* Print an array to the Console
*
* #param A
*/
public static void printArray(int[] A) {
for (int i = 0; i < A.length; i++) {
System.out.printf("%5d ", A[i]);
}
System.out.println();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
final int SIZE = 10;
int[] A = new int[SIZE];
// Create random array with elements in the range of 0 to SIZE - 1;
System.out.printf("Lab#2 Sorting Algorithm Performance Analysis\n\n");
for (int i = 0; i < SIZE; i++) {
A[i] = (int) (Math.random() * SIZE);
}
System.out.printf("Unsorted Data = %s\n", Arrays.toString(A));
int[] B;
// Measure comparisons and time each of the 4 sorts
B = Arrays.copyOf(A, A.length); // Need to do this before each sort
long startTime = System.nanoTime();
quickSort(B);
long timeRequired = (System.nanoTime() - startTime) / 1000;
System.out.printf("Sorted Data = %s\n", Arrays.toString(B));
System.out.printf("Number of compares for quicksort = %8d time = %8d us Ratio = %6.1f compares/us\n", qSortCompares, timeRequired, qSortCompares / (double) timeRequired);
// Add code for the other sorts here ...
}
The instructions give some hints but I am still lost:
The quicksort method currently counts the # of comparisons by using a global variable. This is not a good programming technique. Modify the quicksort method to count comparisons by passing a parameter. This is a little trickier as the comparisons are done in the partition method. You should be able to see that the number of comparisons can be determined before the call to the partition method. You will need to return this value from the Quicksort method and modify the quickSort header to pass this value into each recursive call. You will need to add the counts recursively.
As an alternative to the recursive counting, you can leave the code as is and complete the lab without the modification.
The way I have been looking at this assignment I made a variable in the partition method called qSCount which when it is called will count how many comparisons were made. However I can't use that variable because I am not returning it. And I'm not sure how I would use recursion in that state. My idea was after each time qSCount had a value I could somehow store it in doQuickSort method under qSTotal. But then again the hint is saying I need to make a parameter in quicksort so I am all sorts of confused.
In order to count something with a recursive method (without a global variable) we need to return it. You have:
private static int doQuickSort(int array[], int start, int end)
This is the right idea. But since the comparisons actually happen within
private static int partition(int array[], int start, int end)
you need to have partition return how many comparisons were made.
This leaves us with two options:
We can either create or use an existing Pair class to have this method return a pair of integers instead of just one (the pivot).
We can create a counter class and pass a counter object around and have the counting done there. This eliminates the need to return another value since the parameter could be used to increase the count.
I'm implementing a mergeSort function. I understand the logic of divide and conquer, but the actual merging part is confusing me. This is a past homework problem, but I'm trying to understand it.
/**
* Implement merge sort.
*
* It should be:
* stable
* Have a worst case running time of:
* O(n log n)
*
* And a best case running time of:
* O(n log n)
*
* You can create more arrays to run mergesort, but at the end,
* everything should be merged back into the original T[]
* which was passed in.
*
* ********************* IMPORTANT ************************
* FAILURE TO DO SO MAY CAUSE ClassCastException AND CAUSE
* YOUR METHOD TO FAIL ALL THE TESTS FOR MERGE SORT
* ********************************************************
*
* Any duplicates in the array should be in the same relative position
* after sorting as they were before sorting.
*
* #throws IllegalArgumentException if the array or comparator is null
* #param <T> data type to sort
* #param arr the array to be sorted
* #param comparator the Comparator used to compare the data in arr
*/
For this method, the parameters, public, static, and generics can't be changed. I don't know how to do the recursive merge function.
public static <T> void mergesort(T[] arr, Comparator<T> comparator) {
if (arr == null || comparator == null) {
throw new IllegalArgumentException("Null arguments were passed.");
}
if (arr.length >= 2) {
//Midpoint from which we will split the array.
int middle = arr.length / 2;
//Each half of the split array
T[] left = (T[]) new Object[middle];
T[] right = (T[]) new Object[arr.length - middle];
//Copy items from original into each half
for (int i = 0; i < middle; i++) {
left[i] = arr[i];
}
for (int i = middle; i < length; i++) {
right[i] = arr[i];
}
//Keep splitting until length is 1
mergesort(left, comparator);
mergesort(right, comparator);
//merge each array back into original which would now be sorted.
merge(left, right, middle, arr, comparator);
merge(right, middle, arr, comparator);
}
}
private static <T> T[] merge(T[] left, T[] right, int middle, T[] arr,
Comparator<T>
comparator) {
int i = 1, j = middle + 1, k = 1;
while (i <= middle && j <= arr.length) {
arr[k++] = (comparator.compare(arr[k], partioned[i]) < 0)
? arr[j++] : partioned[i++];
}
while (i <= middle) {
arr[k++] = partioned[k++];
}
}
Here's one possible solution. I don't remember if there's a better way to do this, since I generally just use Collections.sort().
Note that there's no need to return a value, since the contents of the original array are going to be modified.
There's also no need to pass in the middle index.
private static <T> void merge(T[] left, T[] right, T[] dest) {
if (left.length + right.length != dest.length)
throw new IllegalArgumentException(
"left length + right length must equal destination length");
int leftIndex = 0;
int rightIndex = 0;
int destIndex = 0;
while (destIndex < dest.length) {
if (leftIndex >= left.length) //no more entries in left array, use right
dest[destIndex++] = right[rightIndex++];
else if (rightIndex >= right.length) // no more entries in right array, use left
dest[destIndex++] = left[leftIndex++];
else if (left[leftIndex] < right[rightIndex]) //otherwise pick the lower value
dest[destIndex++] = left[leftIndex++];
else
dest[destIndex++] = right[rightIndex++];
}
}
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());
}
}