I have made a mergesort that is being juxtaposed with two already created selection and insertion sorts which both count the comparisons so that when executed the program illustrates which methods are faster.
I can't figure out how to get a count implemented into my mergeset
I really don't know if it's even working correctly or if I'm just displaying a previously already sorted array, that was sorted by selection or insertion above it. I think this because I wasn't able to call the method how the selection and insertion were. (You'll see below)
I'll post full code so far so you can see selection and insertion, how they were used.
Arraysort.java
public class ArraySort {
private long[] a; // ref to array a
private int nElems; // number of data items
public ArraySort(int max) // constructor
{
a = new long[max]; // create the array
nElems = 0; // no items yet
}
public void Clone(ArraySort c) // c is another array
{
c.nElems = this.nElems; // Copy nElems
System.arraycopy(this.a, 0, c.a, 0, this.nElems); // Copy elements
}
public void insert(long value) // put element into array
{
a[nElems++] = value; // insert value
}
public String toString() // displays array contents
{
String res="";
for(int j=0; j<nElems; j++) // for each element,
res = res + a[j] + " "; // append it to res
return res;
}
private int insertOrder(int n, long temp) { // insert temp into a[0..(n-1)]
// and keep a[0..n] sorted.
int count = 0;
while (n>0) {
count++; // count next comparison
if (a[n-1] > temp) { // until one is smaller,
a[n] = a[n-1]; // shift item to right
--n; // go left one position
} else break;
}
a[n] = temp; // insert marked item
return count;
}
public int insertionSort() {
int count = 0;
for (int n=1; n<nElems; n++)
count += insertOrder(n, a[n]); // insert a[n] into a[0..(n-1)]
return count;
} // end insertionSort()
private void swap(int one, int two) {
long temp = a[one];
a[one] = a[two];
a[two] = temp;
}
public int selectionSort() {
int out, in, max, count=0;
for(out=nElems-1; out > 0; out--) { // outer loop
max = out; // max is maximum item's index
for(in=0; in<out; in++) { // inner loop
if(a[in] > a[max] ) // if max is smaller,
max = in; // we have a new max
count++; // count one comparison
}
swap(out, max); // swap them
} // end for(out)
return count;
} // end selectionSort()
public void mergeSort() {
long[] ws = new long[nElems];
recMergeSort(ws, 0, nElems-1);
}
public void recMergeSort(long[] ws, int lower, int upper) {
if (lower == upper)
return;
else {
int mid = (lower + upper) / 2; //find midpoint
recMergeSort(ws, lower, mid); //sort lower
recMergeSort(ws, mid+1, upper); //sort upper
merge(ws, lower, mid+1, upper); //merge
}
}
public void merge(long[] ws, int lowPtr, int highPtr, int upper) {
int j = 0;
int lower = lowPtr;
int mid = highPtr-1;
int n = upper-lower+1; //# of items
while(lowPtr <= mid && highPtr <= upper)
if( a[lowPtr] < a[highPtr] )
ws[j++] = (int) a[lowPtr++];
else
ws[j++] = (int) a[highPtr++];
while(lowPtr <= mid)
ws[j++] = (int) a[lowPtr++];
while(highPtr <= upper)
ws[j++] = (int) a[highPtr++];
for(j=0; j<n; j++)
a[lower+j] = ws[j];
}
public void display() {
for(int j=0; j<nElems; j++) {
System.out.print(a[j] + " "); }
System.out.println("");
}
//end
}
SortComparison.java
import java.util.*;
public class SortComparison {
public static void main(String[] args) {
int count, maxSize = 100; // array size
ArraySort arr, carr; // reference to array
arr = new ArraySort(maxSize); // create the arrays
carr = new ArraySort(maxSize);
// insert some random numbers
Random generator = new Random();
for (int i = 0; i < 20; i++) {
arr.insert(Math.abs(generator.nextInt())%maxSize);
}
System.out.println("Before sort: " + arr); // display items
arr.Clone(carr);
count = carr.insertionSort(); // insertion-sort a clone of arr
System.out.println("\nInsert sort: \n" + carr + " ### Comparisons: " + count);
arr.Clone(carr);
count = carr.selectionSort(); // selection-sort a clone of arr
System.out.println("\nSelect sort: \n" + carr + " ### Comparisons: " + count);
carr.mergeSort();
System.out.println("\nMerge sort: ");
carr.display();
}
}
You can see how things should be called, with the count returning, by selection and insertion..
There are several ways you could return the count in addition to the sorted array. You could store either the count or the array as class variables. You could create an object which encapsulates both the count and the array. You could even tack the count onto the front of the array, if you promise to remember that the first element is the count, not a part of the sort (this is probably a bad idea).
You might want to check that your sort works correctly by copying the array again before you worry about counting the number of comparisons.
Related
I created a program that does a Selection Sort function of array using the elements our input that is given by the user. I am struggling in creating a loop or method to call or show each iteration that is completed to reach the final output of the sorting. I am all open for suggestions. Thanks!
Here's the code :
private static String arrayToString(int[] a)
{
String str="[";
if(a.length>0)
{
str+=a[0];
for(int i=1; i<a.length; i++)
str+="|"+a[i];
}
return str+"]";
}
public static void sort(int[] a)
// Sort the contents of array a in ascending numerical order
{
for(int i=0; i<a.length-1; i++)
{
int pos = smallestPosFrom(i,a);
swap(a,i,pos);
}
}
private static int smallestPosFrom(int from,int[] a)
// Return the index of the smallest element in the section of
// array 'a' from that indexed 'from' to the end of the array
{
int pos=from;
for(int i=from+1; i<a.length; i++)
if(a[i]<a[pos])
pos=i;
return pos;
}
private static void swap(int[] a,int pos1, int pos2)
// Swap the elements indexed pos1 and pos2 within array a
{
int temp;
temp = a[pos1];
a[pos1] = a[pos2];
a[pos2] = temp;
}
And this is how I call them in my main :
System.out.println("The array you entered is:");
System.out.println(arrayToString(Array));
sort(Array);
System.out.println("After sorting, the array is:");
System.out.println(arrayToString(Array));
break;
I'm not sure that I understood you well, but if you would like to see how an array was changed after each iteration of sorting you can just add some print to System.out in 'sort' method:
public static void sort(int[] a)
// Sort the contents of array a in ascending numerical order
{
String arrayAfterIteration;
for (int i = 0; i < a.length - 1; i++)
{
int pos = smallestPosFrom(i, a);
swap(a, i, pos);
arrayAfterIteration = arrayToString(a);
System.out.println("The array after step N" + i + " is:" + arrayAfterIteration);
}
}
I have the code for bubble sorting down below. I was wondering how I would be able to run more efficient and loop less amount of times
package bubbleSort;
public class BubbleSort {
public static void main(String[] args) {
// initialize array to sort
int size = 10;
int[] numbers = new int[size];
// fill array with random numbers
randomArray(numbers);
// output original array
System.out.println("The unsorted array: ");
printArray(numbers);
// call the bubble sort method
bubbleSort(numbers);
// output sorted array
System.out.println("The sorted array: ");
printArray(numbers);
}
public static void bubbleSort(int tempArray[]) {
//bubble sort code goes here (you code it)
// loop to control number of passes
for (int pass = 1; pass < tempArray.length; pass++) {
System.out.println(pass);
// loop to control number of comparisions for length of array - 1
for (int element = 0; element < tempArray.length - 1; element++) {
// compare side-by-side elements and swap tehm if
// first element is greater than second elemetn swap them
if (tempArray [element] > tempArray [element + 1]) {
swap (tempArray, element, element + 1);
}
}
}
}
public static void swap(int[] tempArray2,int first, int second) {
//swap code goes here (you code it)
int hold; // temporary holding area for swap
hold = tempArray2 [first];
tempArray2 [first] = tempArray2 [second];
tempArray2 [second] = hold;
}
public static void randomArray(int tempArray[]) {
int count = tempArray.length;
for (int i = 0; i < count; i++) {
tempArray[i] = (int) (Math.random() * 100) + 1;
}
}
public static void printArray(int tempArray[]) {
int count = tempArray.length;
for (int i = 0; i < count; i++) {
System.out.print(tempArray[i] + " ");
}
System.out.println("");
}
}
Any help would be greatly appreciated. I am new to coding and have been very stumped on how to improve efficiency and have it loop less times.
Bubble sort is an inefficiency sorting algorithm and there are much better sorting algorithm.
You can make a bubble sort more efficient, its called Optimized Bubble Sort (It is still quite inefficient)
Optimized bubble sort in short is, - you pass n times , but on the every iteration you 'bubble' the biggest (or smallest) element to the end of the array. Now that last item is sorted, so you don't have to compare it again.
I wrote this code last year, not to sure if it still works:
public static void bubbleSort_withFlag(Integer[] intArr) {
int lastComparison = intArr.length - 1;
for (int i = 1; i < intArr.length; i++) {
boolean isSorted = true;
int currentSwap = -1;
for (int j = 0; j < lastComparison; j++) {
if (intArr[j] < intArr[j + 1]) {
int tmp = intArr[j];
intArr[j] = intArr[j + 1];
intArr[j + 1] = tmp;
isSorted = false;
currentSwap = j;
}
}
if (isSorted) return;
lastComparison = currentSwap;
}
}
Here you can read on optimized bubble sort
Here you can find a list of different sorting algorithms that could be more efficient depending on your scenario.
This is the code from geeksforgeeks which generates and print bitstrings of n bits but I want to know instead of printing the array, how can I store the values of the array or return it so I can use the values in the main method.
import java.util.*;
class GFG
{
// Function to print the output
static void printTheArray(int arr[], int n)
{
for (int i = 0; i < n; i++)
{
System.out.print(arr[i]+" ");
}
System.out.println();
}
// Function to generate all binary strings
static void generateAllBinaryStrings(int n,
int arr[], int i)
{
if (i == n)
{
printTheArray(arr, n);
return;
}
// First assign "0" at ith position
// and try for all other permutations
// for remaining positions
arr[i] = 0;
generateAllBinaryStrings(n, arr, i + 1);
// And then assign "1" at ith position
// and try for all other permutations
// for remaining positions
arr[i] = 1;
generateAllBinaryStrings(n, arr, i + 1);
}
// Driver Code
public static void main(String args[])
{
int n = 4;
int[] arr = new int[n];
// Print all binary strings
generateAllBinaryStrings(n, arr, 0);
}
}
// This code is contributed by
// Surendra_Gangwar
Change the return type
Add a return statement
Like this:
// Function to generate all binary strings
static int[] generateAllBinaryStrings(int n,
// ^^^^^ change return type
int arr[], int i)
{
if (i == n)
{
printTheArray(arr, n);
return;
}
// First assign "0" at ith position
// and try for all other permutations
// for remaining positions
arr[i] = 0;
generateAllBinaryStrings(n, arr, i + 1);
// And then assign "1" at ith position
// and try for all other permutations
// for remaining positions
arr[i] = 1;
generateAllBinaryStrings(n, arr, i + 1);
return arr;
// ^^^^^^^^^^^ add return statement
}
I am currently learning Java. Below is a list of methods from a simple Java program I have written. Is there anything that stands out in these methods would cause the execution of the program to go very slow? It's taking four seconds to execute using an array containing just 6 integers:
EDITED: here's the entire program as requested. I wrote it in Textpad. I realise it is not the most efficient algorithm. It does what it is supposed to do, but takes too long to do it.
import java.util.*;
public class Supermarket
{
public static void main(String [] args)
{
int[] custTimes =
{
1, 6, 7, 4, 4, 3, 5, 1, 2, 1, 3, 6, 4
};
int checkOuts = 6;
int answer;
answer = Solution.solveSuperMarketQueue(custTimes, checkOuts);
System.out.println("Answer is " + answer);
}
}//~public class Supermarket...
class Solution
{
static int myTotal;
static int solveSuperMarketQueue(int[] customers, int n)
{
// ******************* INITIALIATION ***********************
myTotal = 0;
int len = customers.length; // length of customer queue
if (len < 1)
{
return 0;
}
int[] till = new int[n]; // array to store all tills and till queues
int tillMin; // Minimum time
int tillMax; // Maximum time
// Put the customers into an arraylist:
ArrayList<Integer> times = new ArrayList<Integer>();
for (int i = 0; i < len; i = i + 1)
{
times.add(i, customers[i]);
}
// create the array of tills and set all queue intial values to 0
for (int i = 0; i < n; n = n + 1)
{
till[i] = 0;
}
// Move the queue to tills to start off
ReturnPair result = copyQueue(till, times);
till = result.getArr();
times = result.getList();
int s = times.size();
tillMax = getMaxTime(till);
tillMin = getMinTime(till);
// ***************** END OF INITIALIATION ******************
// *****************MAIN LOOP ******************************
while (tillMax > 0)
{
// Find customer(s) with least time use that time to move all queues
// and update myTotal time.
// STEP 1: get minimum time in tills array (ignore zero)
tillMin = getMinTime(till);
// STEP 2: subtract minimum value from all the tills, but not if till has a zero
if (tillMin > 0)
{
till = subtractTime(till, tillMin);
}
// Move the queue to tills
if (s > 0)
{
result = copyQueue(till, times);
till = result.getArr();
times = result.getList();
}
tillMax = getMaxTime(till);
tillMin = getMinTime(till);
}
return myTotal;
// **************** END OF LOOP *****************************
}//~public static int solveS...
// ****************** METHODS **********************************
// Method to move queue foward
// For each till, a time is copied from the customer array.
// The values are copied in order.
// The value is coped only if array value is zero.
private static ReturnPair copyQueue(int[] arr, ArrayList<Integer> arrList)
{
int n = arr.length; // for each till...
for (int i = 0; i < n; i = i + 1)
{
if (arr[i] == 0 && arrList.size() > 0) // only copy if it current till value is 0 AND arrayList value exists
{
arr[i] = arrList.get(0);
arrList.remove(0);
}
}
// returns an instance of the object myResult which is a container for an array and an arraylist
return new ReturnPair(arr, arrList);
}
// Method to get minimum time from array (but not zero).
private static int getMinTime(int[] arr)
{
int minValue = 0;
// make sure arr[i] isn't zero.
for (int i = 0; i < arr.length; i = i + 1)
{
if (arr[i] != 0)
{
minValue = arr[i];
break;
}
}
// Find minimum value that isn't zero.
for (int i = 1; i < arr.length; i = i + 1)
{
if (arr[i] != 0 && arr[i] < minValue)
{
minValue = arr[i];
}
}
return minValue;
}//~static int getMinTime(in...
// Method to subtract minimum time from tills
private static int[] subtractTime(int[] arr, int min)
{
int n = arr.length;
for (int i = 0; i < n; i = i + 1)
{
if (arr[i] != 0)
{
arr[i] = arr[i] - min;
}
}
// update myTotal
myTotal = myTotal + min;
return arr;
}//~static void subtractTime...
private static int getMaxTime(int[] arr)
{
int maxValue = arr[0];
for (int i = 1; i < arr.length; i = i + 1)
{
if (arr[i] > maxValue)
{
maxValue = arr[i];
}
}
return maxValue;
}
}//~class Solution...
// Special class designed to return an array and an array list as an object
class ReturnPair
{
// set up fields
int[] newArr;
ArrayList<Integer> newArrList;
// define method
public ReturnPair(int[] first, ArrayList<Integer> second)
{
this.newArr = first;
this.newArrList = second;
}
public int[] getArr()
{
return newArr;
}
public ArrayList<Integer> getList()
{
return newArrList;
}
}
for (int i = 0; i < n; n = n + 1)
This line is incrementing n instead of i. it will loop until n overflows. It should be:
for (int i = 0; i < n; i++)
Because int arrays are initialized to 0 anyway, you can remove this loop completely.
I was wondering how to work with negative values and a negative target, right now my program gives index out of bounds errors whenever negative values are given to these variables. I need my hasSum function work with negative values for this project, I can't just assume positive.
import java.util.Stack;
import java.util.Scanner;
public class subsetSum {
static Scanner input = new Scanner(System.in);
static {
System.out.print("Enter the target (T)" + "\n");
}
/** Set a value for target sum */
static int TARGET_SUM = input.nextInt(); //this is the target
/** Store the sum of current elements stored in stack */
static int sumInStack = 0;
Stack<Integer> stack = new Stack<Integer>();
public static void main(String[] args) {
//the size is S
System.out.println("\n" + "Enter the size of the set (S)");
int values = input.nextInt(); //size = "values"
//value of each size entry
System.out.println("\n" + "Enter the value of each entry for S");
int [] numbers = new int[values];
for(int i = 0; i < values; i++) //for reading array
{
numbers[i] = input.nextInt();
}
if(hasSum(numbers, TARGET_SUM)){
System.out.println("\n" + "Can: ");
subsetSum get = new subsetSum(); // encapsulation
get.populateSubset(numbers, 0, numbers.length);
}else{
System.out.println("\n" + "Cannot");
}
}
//method based on dynamic programming O(sum*length)
public static boolean hasSum(int [] array, int sum)
{
int i;
int len = array.length;
boolean[][] table = new boolean[sum + 1][len + 1]; //this has to be changed for negative
//If sum is zero; empty subset always has a sum 0; hence true
for(i = 0; i <= len; i++){
table[0][i] = true;
}
//If set is empty; no way to find the subset with non zero sum; hence false
for(i = 1; i <= sum; i++){
table[i][0] = false;
}
//calculate the table entries in terms of previous values
for(i = 1; i <= sum; i++)
{
for(int j = 1; j <= len; j++)
{
table[i][j] = table[i][j - 1];
if(!table[i][j] && i >= array[j - 1]){
table[i][j] = table[i - array[j - 1]][j - 1];
}
}
}
return table[sum][len]; //this has to be changed for negative
}
public void populateSubset(int[] data, int fromIndex, int endIndex) {
/*
* Check if sum of elements stored in Stack is equal to the expected
* target sum.
*
* If so, call print method to print the candidate satisfied result.
*/
if (sumInStack >= TARGET_SUM) {
if (sumInStack == TARGET_SUM) {
print(stack);
}
// there is no need to continue when we have an answer
// because nothing we add from here on in will make it
// add to anything less than what we have...
return;
}
for (int currentIndex = fromIndex; currentIndex < endIndex; currentIndex++) {
if (sumInStack + data[currentIndex] <= TARGET_SUM) {
stack.push(data[currentIndex]);
sumInStack += data[currentIndex];
/*
* Make the currentIndex +1, and then use recursion to proceed
* further.
*/
populateSubset(data, currentIndex + 1, endIndex);
sumInStack -= (Integer) stack.pop();
}
}
}
/**
* Print satisfied result. i.e. 5 = 1, 4
*/
private void print(Stack<Integer> stack) {
StringBuilder sb = new StringBuilder();
for (Integer i : stack) {
sb.append(i).append(",");
}
// .deleteCharAt(sb.length() - 1)
System.out.println(sb.deleteCharAt(sb.length() - 1).toString());
}
}
Are you trying to find a sum of subset or a subarray?
If a subset, then a simple recursion could do the trick, e.g.:
public static boolean hasSum(int [] array, int sum)
{
return hasSum(array, 0, 0, sum);
}
private static boolean hasSum(int[] array, int index, int currentSum, int targetSum) {
if (currentSum == targetSum)
return true;
if (index == array.length)
return false;
return hasSum(array, index + 1, currentSum + array[index], targetSum) || // this recursion branch includes current element
hasSum(array, index + 1, currentSum, targetSum); // this doesn't
}
If you're trying to find a subarray, I'd use prefix sums, e.g.:
public static boolean hasSum(int [] array, int sum)
{
int[] prefixSums = new int[array.length];
for (int i = 0; i < prefixSums.length; i++) {
prefixSums[i] = (i == 0) ? array[i] : array[i] + prefixSums[i - 1];
}
for (int to = 0; to < prefixSums.length; to++) {
if (prefixSums[to] == sum)
return true; // interval [0 .. to]
for (int from = 0; from < to; from++) {
if (prefixSums[to] - prefixSums[from] == sum)
return true; // interval (from .. to]
}
}
return false;
}
BTW I think reading the input values from Scanner inside the static initializer is a bad idea, why don't you move them to main()?