Java: Selection Sort My implementation vs. another - java

The following is my implementation of Selection Sort:
package algorithm.selectionsort;
public class SelectionSort {
public static void main(String[] args) {
int[] myArray = selectionSort(new int[] { 9, 9, 9, 8, 7, 73, 32, 109, 1100, 432, 321, 0 });
for (int element : myArray) {
System.out.print("" + element + " ");
}
}
public static int[] selectionSort(int[] a) {
int min;
for (int i = 0; i < a.length - 1; i++) {
min = i;
for (int j = i + 1; j < a.length; j++) {
if (a[j] < a[min]) {
min = j;
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
}
return a;
}
}
I noticed that my instructor codes it slightly differently:
public static int[] selectionSort(int[] a) {
int min;
for (int i = 0; i < a.length - 1; i++) {
min = i;
for (int j = i + 1; j < a.length; j++) {
if (a[j] < a[min]) {
min = j;
}
}
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
return a;
}
Both implementations work. I'm curious as to what the difference here is. Is it efficiency?

The difference between your instructor's and yours is that he iterate through the array and for each element, search for the minimum, then perform a swap with the element after the wall index.
For yours, you iterate through the array and for each element, while searching for the minimum, if current value is < then the current tentative min, perform a swap with the element after the wall index.
So instead of swapping n times, you could possible swap n*n times for worst case:
Your swap for just one pass (worst case):
100, 90, 88, 70, 55, 43, 32, 28, 19, 10
90, 100, 88, 70, 55, 43, 32, 28, 19, 10
88, 100, 90, 70, 55, 43, 32, 28, 19, 10
70, 100, 90, 88, 55, 43, 32, 28, 19, 10
55, 100, 90, 88, 70, 43, 32, 28, 19, 10
43, 100, 90, 88, 70, 55, 32, 28, 19, 10
32, 100, 90, 88, 70, 55, 43, 28, 19, 10
28, 100, 90, 88, 70, 55, 43, 32, 19, 10
19, 100, 90, 88, 70, 55, 43, 32, 28, 10
10, 100, 90, 88, 70, 55, 43, 32, 28, 19
Your instructor's swap for just one pass (worst case):
100, 90, 88, 70, 55, 43, 32, 28, 19, 10
10, 90, 88, 70, 55, 43, 32, 28, 19, 100
In essence, you swap the values while in the midst of searching for the min. The "min" you swapped may not be the lowest value in the array.

ofcouse your instructor's code is more efficiency and more elegant.
What is Selection Sort?
The algorithm divides the input list into two parts: the sublist of items already sorted, which is built up from left to right at the front (left) of the list, and the sublist of items remaining to be sorted that occupy the rest of the list. Initially, the sorted sublist is empty and the unsorted sublist is the entire input list. The algorithm proceeds by finding the smallest (or largest, depending on sorting order) element in the unsorted sublist, exchanging (swapping) it with the leftmost unsorted element (putting it in sorted order), and moving the sublist boundaries one element to the right.
If the length of the list to be sorted is n, then just n times of exchange should be done, but in your code, it's n*(n-1)*(n-2)....

Related

looking for a sorting algorithm that can sort 1-100 using the least amount of statements

As the title says, I am looking for a sorting algorithm that can sort the numbers between 1 and 100 using the least amount of statements in only one method which is the main.
Here's an example to give you an idea on how I can check it(using a counter)
class Solution{
public static void main(String[] args) {
//declaration
int count = 0,inner, outer, temp, h = 1; count++;
int [] array = {100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,}; count++;
System.out.println("Before: " + Arrays.toString(array)); count++;
//start of the sort
while (h <= array.length / 3) //start of while loop 1
{
h = h * 3 + 1; count++;
}count++; //end of while loop 1
while (h > 0) //start of while loop 2
{
for (outer = h; outer < array.length; outer++) //start of for loop
{
temp = array[outer]; count++;
inner = outer;count++;
while (inner > h - 1 && array[inner - h] >= temp) //start of while loop 3
{
array[inner] = array[inner - h]; count++;
inner -= h; count++;
}count++; //end of for loop 3
array[inner] = temp; count++;
}count++; //end of for loop
//equation to count for
count = count + array.length-h+1 + array.length - h +1 -1;
h = (h - 1) / 3; count++;
}count++; //end of while loop 2
System.out.println("After: " + Arrays.toString(array) + "\n" + "Counter = " + count);
}
}
The fastest algorithm with example would be quicksort, also as you are asking i believe this would also take the least amount of statments. Below you can find a link and also description of how it works.
https://www.geeksforgeeks.org/quick-sort/

Quicksort implementation program array out of bounds error and not sorting generated numbers

I am new to programming and cannot seem to figure out my errors when trying to write a Quicksort program. I have most of the implementation done with the exception of a few errors that I cannot seem to figure out. Here is my current code:
public class Quicksort {
public static void main(String[] args) {
Integer[] numbers = new Integer[20];
for (int i = 0; i < numbers.length; i++) {
numbers[i] = (int) (Math.random() * 100);
}
printArray(numbers);
quicksort(numbers);
printArray(numbers);
}
public static <T> void printArray(T[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + (i < array.length - 1 ? ", " : "\n"));
}
}
public static <T> void printArrayPartition(T[] array, int low, int high, int pivot) {
for (int i = 0; i < array.length; i++) {
String element = "" + array[i];
if (i == pivot)
element = "*" + element + "*";
if (i == low)
element = "[" + element;
if (i == high)
element += "]";
System.out.print(element + (i < array.length - 1 ? ", " : "\n"));
}
}
public static <T extends Comparable<T>> void quicksort(T[] array) {
quicksort(array, 0, array.length - 1);
}
private static <T extends Comparable<T>> void quicksort(T[] array, int low, int high) {
if (low < high) {
int pivotIndex = partition(array, low, high);
int pivot = pivotIndex;
printArrayPartition(array, low, high, pivot);
quicksort(array, low - 1, pivotIndex - 1);
quicksort(array, pivotIndex + 1, high + 1);
}
}
private static <T extends Comparable<T>> int partition(T[] array, int low, int high) {
T pivotValue = array[high];
int left = low;
for (int i = 0; i < array.length; i++) {
if (array[i].compareTo(pivotValue) > 0) {
left++;
}
}
swap(array, high, left);
return left;
}
private static <T> void swap(T[] array, int a, int b) {
T temp = array[a];
array[a] = array[b];
array[b] = temp;
}
}
When running this program I am getting ArrayIndexOutOfBounds error and I'm not sure why. I have traced few my code a few times and still cannot seem to figure it out.
Stack trace:
54, 91, 26, 43, 98, 65, 88, 78, 88, 60, 58, 75, 74, 46, 79, 81, 64, 49, 67, 31
[54, 91, 26, 43, 98, 65, 88, 78, 88, 60, 58, 75, 74, 46, 79, 81, 64, 49, *31*, 67]
54, 91, 26, 43, 98, 65, 88, 78, 88, 60, 58, 75, 74, 46, *49*, 81, 64, 79], 31, 67
54, 91, 26, 43, 98, 65, 88, 78, 88, 60, 58, 75, 74, 49], *46*, 81, 64, 79, 31, 67
54, 91, 26, 43, 98, 65, 88, 78, 88, 60, 58, 75, *49*, 74], 46, 81, 64, 79, 31, 67
54, 91, 26, *75*, 98, 65, 88, 78, 88, 60, 58, 43], 49, 74, 46, 81, 64, 79, 31, 67
54, 91, 46], 75, 98, 65, 88, 78, 88, 60, 58, 43, 49, 74, *26*, 81, 64, 79, 31, 67
54, 91, *74*, 75, 98, 65, 88, 78, 88, 60, 58, 43, 49, 46], 26, 81, 64, 79, 31, 67
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -6
at Quicksort.swap(Quicksort.java:79)
at Quicksort.partition(Quicksort.java:72)
at Quicksort.quicksort(Quicksort.java:47)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:52)
at Quicksort.quicksort(Quicksort.java:41)
at Quicksort.main(Quicksort.java:13)
In your recursive calls:
quicksort(array, low - 1, pivotIndex - 1);
quicksort(array, pivotIndex + 1, high + 1);
You subtract one from low and pivotIndex and then later pass those values to
swap(array, high, left); //via int left = low;
Which in turn calls the index of high and low. When you start the method low is set to zero. And then you subtract one to get a negative number. If the condition: if (array[i].compareTo(pivotValue) > 0) is never met then left will never be increased and you will be passing a negative number to swap(…). And in the swap() method:
T temp = array[a]; //a is left here
array[a] = array[b];
array[b] = temp;
You directly try to call the index of left which might be a negative number, thus the indexoutofboundsexception with a negative index
And in the same fashion the quicksort(array, pivotIndex + 1, high + 1); can add one to high and thus cause it to go out of bounds

Using Insertion Sort to sort an array

I'm supposed to take an array of the numbers: {51, 63, 48, 98, 75, 63, 92, 30, 32, 32, 36, 89, 4, 76, 73, 90, 64, 99, 36, 96} and sort them from lowest to highest, and then highest to lowest.
When I try to print the highest to lowest it makes the first output the same. Does anyone see any errors in my code?
package l7c14sort;
import java.util.Arrays;
public class L7C14Sort {
public static void main(String a[]){
int[] arr1 = {51, 63, 48, 98, 75, 63, 92, 30, 32, 32, 36, 89, 4, 76, 73, 90, 64, 99, 36, 96};
int[] arr2 = doInsertionSort(arr1);
int[] arr3 = doInsertionSortAgain(arr1);
System.out.println("Original input: "+Arrays.toString(arr1)+"\n");
System.out.println("Lowest to highest:\n");
for(int i:arr2)
{
System.out.print(i);
System.out.print(", ");
}
System.out.println("\n\n");
System.out.println("Highest to lowest:\n");
for(int k:arr3)
{
System.out.print(k);
System.out.print(", ");
}
System.out.println("\n");
}
public static int[] doInsertionSort(int[] input){
int temp;
for (int i = 1; i < input.length; i++) {
for(int j = i ; j > 0 ; j--){
if(input[j] < input[j-1]){
temp = input[j];
input[j] = input[j-1];
input[j-1] = temp;
}
}
}
return input;
}
public static int[] doInsertionSortAgain(int[] input2){
int temp2;
for (int k = 1; k < input2.length; k++) {
for(int j = k ; j > 0 ; j--){
if(input2[j] > input2[j-1]){
temp2 = input2[j];
input2[j] = input2[j-1];
input2[j-1] = temp2;
}
}
}
return input2;
}
}
Output:
Original input: [99, 98, 96, 92, 90, 89, 76, 75, 73, 64, 63, 63, 51,
48, 36, 36, 32, 32, 30, 4]
Highest to lowest:
99, 98, 96, 92, 90, 89, 76, 75, 73, 64, 63, 63, 51, 48, 36, 36, 32, 32, 30, 4,
Lowest to highest:
4,30,32,32,36,36,48,51,63,63,64,73,75,76,89,90,92,96,98,99
Good news: Your algorithm works fine.
In Java, arrays are passed by reference, not by value. What this means is that when you set int[] arr2 = doInsertionSort(arr1);, the array arr2 is being set to the result of your doInsertionSort method, which returns its input parameter after sorting it. Basically, arr1, arr2, arr3, input and input2 are all pointing to the very same array.
You have two easy options to fix the fact that you're printing:
Restructure main() so that you use one array: print its contents, sort it lowest to highest, print its contents again, sort it highest to lowest, then print its contents again. (This is probably what your instructor intends for you to do, if this is coursework.)
Make a copy of the input parameter to operate on. You can do this with System.arraycopy() like so:
int[] myArray;
System.arraycopy(input, 0, myArray, 0, input.length );
Then, for option 2, you would need to edit your method to use myArray instead of input for every other time you use input.
As a note, you don't need to call your variables input2, temp2, etc. Just like i, j and k go out of scope and are forgotten after the end of a for loop, your variables input and temp mean nothing outside of the block you declared them in.
Hope this helps!
You are ended up with same results, because arrays are mutable. Because of the following code, input array is mutated and its final value is printed.(Highest to lowest).
int[] arr2 = doInsertionSort(arr1);
int[] arr3 = doInsertionSortAgain(arr1);
If you organize your code like:
public static void main(String a[]) {
int[] arr1 = {51, 63, 48, 98, 75, 63, 92, 30, 32, 32, 36, 89, 4, 76, 73, 90, 64, 99, 36, 96};
System.out.println("Original input: " + Arrays.toString(arr1) + "\n");
System.out.println("Lowest to highest:\n");
int[] arr2 = doInsertionSort(arr1);
for (int i : arr2) {
System.out.print(i);
System.out.print(", ");
}
System.out.println("\n\n");
System.out.println("Highest to lowest:\n");
int[] arr3 = doInsertionSortAgain(arr1);
for (int k : arr3) {
System.out.print(k);
System.out.print(", ");
}
System.out.println("\n");
}
You are going to get:
Original input: [51, 63, 48, 98, 75, 63, 92, 30, 32, 32, 36, 89, 4, 76, 73, 90, 64, 99, 36, 96]
Lowest to highest:
4, 30, 32, 32, 36, 36, 48, 51, 63, 63, 64, 73, 75, 76, 89, 90, 92, 96, 98, 99,
Highest to lowest:
99, 98, 96, 92, 90, 89, 76, 75, 73, 64, 63, 63, 51, 48, 36, 36, 32, 32, 30, 4,

Random Tour Generation Issues

I am trying to generate a random tour from the graph. I am using the adjacency-list method.
There is a problem with the vertices. When I add a vertex to a particular list, the vertex gets added to all the lists in the graph. I do not understand why! Here's the code:
public static void main(String[] args) {
defaultData(6);
}
public static void defaultData(int n) {
Integer costs[] = { 26, 95, 38, 74, 80, 73, 73, 92, 22, 97, 13, 81, 41,
17, 4, 2, 47, 54, 21, 68, 78, 4, 77, 3, 66, 55, 99, 42, 62, 39, 8, 36,
53, 74, 26, 8, 42, 66, 30, 58, 69, 14, 49, 39, 85, 98, 72, 3, 18, 99,
96, 66, 64, 36, 17, 44, 70, 0, 8, 14, 62, 41, 84, 59, 94, 27, 5, 27,
96, 10, 15, 52, 43, 20, 2, 86, 45, 43, 32, 17, 49, 92, 9, 15, 6, 49,
72, 7, 51, 21, 2, 26, 63, 82, 98, 48, 21, 96, 16 };
ArrayList<ArrayList<Integer>> costGraph = new ArrayList<>();
ArrayList<ArrayList<Integer>> completeGraph = new ArrayList<>();
Random rand = new Random(System.currentTimeMillis());
int costIndex = 0;
for (int i = 0; i <= n; i++) {
ArrayList<Integer> cost = new ArrayList<>();
ArrayList<Integer> edge = new ArrayList<>();
for (int j = 0; j <= n; j++) {
if (i == j) {
continue;
}
edge.add(j);
cost.add(costs[costIndex]);
costIndex++;
}
completeGraph.add(edge);
costGraph.add(cost);
}
System.out.println(completeGraph);
ArrayList<ArrayList<Integer>> dummyGraph =
(ArrayList<ArrayList<Integer>>)completeGraph.clone();
ArrayList<ArrayList<Integer>> randomTour = new ArrayList<>();
ArrayList<Integer> dummyList = new ArrayList<>();
for (int i = 0; i <= n; i++) {
randomTour.add(dummyList);
}
System.out.println(dummyGraph);
int edgeCount = 0;
Integer row = rand.nextInt(n);
Integer start = row;
while(edgeCount <= n-1){
//dummyList = dummyGraph.get(row);
// To keep the bounds of the random equal
// to the new reduced size of the lists in the graph
Integer col = dummyGraph.get(row).get(rand.nextInt(n-edgeCount));
randomTour.get(row).add(col);
System.out.println(row);
System.out.println(randomTour);
edgeCount++;
for(int k = 0; k < n; k++)
dummyGraph.get(k).remove(row);
row = col;
}
randomTour.get(row).add(start);
System.out.println(randomTour);
}
I would be very grateful for a timely response. Thanks in advance!
You don't want to do this:
for (int i = 0; i <= n; i++) {
randomTour.add(dummyList);
}
It keeps adding the same reference lots of times, so all the ArrayLists in the ArrayList are actually the same object.
Instead you want to do this:
for (int i = 0; i <= n; i++) {
randomTour.add(new ArrayList<Integer>());
}
That way the ArrayList instances in the ArrayList are all different.
I hope this answer was timely enough!

Insertion sort algorithm flaw in Java code

So I am going through some of the common sorting algorithms and have written this:
Code:
public void insertionSort() {
int key;
int i;
for ( int j = 1; j < this.a.length; j++ ) {
key = a[j];
i = j;
while ( i > 0 && a[i-1] > key ) {
a[i] = a[i-1];
i = i - 1;
}
a[i] = key;
}
}
Result:
jan#janspc:~/Dropbox/programming/java/algorithms$ javac sort.java
jan#janspc:~/Dropbox/programming/java/algorithms$ java Test
49, 68, 60, 14, 70, 8, 83, 96, 29, 7, 92, 35, 17, 84, 31, 62, 48, 95, 16, 22, 31, 97, 72, 55, 88, 63, 1, 63, 96, 32, 74, 15, 92, 77, 50, 13, 12, 36, 90, 93, 20, 15, 67, 88, 23, 31, 95, 90, 86, 65, 35, 27, 60, 4, 90, 11, 22, 97, 65, 88, 23, 1, 25, 21, 9, 81, 87, 56, 2, 4, 63, 52, 55, 86, 62, 30, 55, 64, 19, 10, 45, 92, 87, 43, 39, 95, 20, 43, 3, 30, 74, 64, 4, 90, 91, 93, 94, 44, 87, 21,
49, 1, 1, 2, 3, 4, 4, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 16, 17, 19, 20, 20, 21, 21, 22, 22, 23, 23, 25, 27, 29, 30, 30, 31, 31, 31, 32, 35, 35, 36, 39, 43, 43, 44, 45, 48, 50, 52, 55, 55, 55, 56, 60, 60, 62, 62, 63, 63, 63, 64, 64, 65, 65, 67, 68, 70, 72, 74, 74, 77, 81, 83, 84, 86, 86, 87, 87, 87, 88, 88, 88, 90, 90, 90, 90, 91, 92, 92, 92, 93, 93, 94, 95, 95, 95, 96, 96, 97, 97,
Execution took: 110628 nano sek?
As you can see from testing, the first value is not affected by sort. What's wrong with my algorithm?
In the first iteration, the while loop doesn't execute, because i < 0. In the next iteration, the while loop doesn't run because i == 0.
You should probably use while (i >= 0 && a[i] > key) (not tested though)
You need >= here:
while ( i >= 0 && a[i] > key ){
Without this change it never compares the following elements against the first one.
while ( i > 0 && a[i] > key ){ should be while ( i >= 0 && a[i] > key ){
Best luck...
In Insertion Sort we need to check each and every element from array and compare with other element getting more accurate result. The problem in your code in while loop
we need line
while ( i >= 0 && a[i] > key )
Here is another implementation of insertion sort in java
public class InsertionSort {
static int intArray[] = { 1000, 1, 100, 101, 15 };
public static void doSort() {
for (int outer = 1; outer < intArray.length; outer++) {
for(int inner=outer;inner>0; inner--){
if(intArray[inner]<intArray[inner-1]){
int temp=intArray[inner];
intArray[inner]=intArray[inner-1];
intArray[inner-1]=temp;
continue;
}
}
}
}
public static void printArray() {
for (int i = 0; i < intArray.length; i++) {
System.out.print(" " + intArray[i]);
}
}
public static void main(String args[]) {
System.out.print("Array Before Sorting->");
printArray();
doSort();
System.out.print("\nArray After Sorting ->");
printArray();
}
}
Detailed explanation of the code and/or the algortithm can be seen at -
http://www.javabrahman.com/algorithms-in-java/insertion-sort-in-java/
here is a very easy implementation of insertion sort
package insertion_sort;
public class insertion_sort {
public static void main(String ar[]) {
int[] a = {24, 13, 9, 64, 7, 23, 34, 47, 87, 9, 37, 1992};
insertion(a,12);
}
public static void insertion(int[] a, int n) {
for (int i = 1; i <= n - 1; i++) {
int value = a[i];
int hole = i;
while (hole > 0 && a[hole - 1] > value) {
a[hole] = a[hole - 1];
hole = hole - 1;
}
a[hole] = value;
}
print(a);
}
public static void print(int[] A) {
for (int i = 0; i < A.length; i++) {
System.out.print(A[i] + " ");
}
System.out.println();
}
}
Below is the pseudo code of Insertion sort(taken from CLR "Introduction to algorithms" book).
Insertion-Sort(A)
for (j=2 to A.length)
key = A[j]>
i = j-1
while i>0 && A[i]>key
A[i+1] = A[i]
i = i-1
A[i+1] = key
Your code is almost similar to above pseudo code. All you need is to change initialization of int j=0 to int j=1 in for loop:
for ( int j = 1; j < this.a.length; j++ ) {
key = a[j];
i = j - 1;
while ( i > 0 && a[i] > key ) {
a[i + 1] = a[i];
i = i - 1;
}
a[i+1] = key;
}
Corrected code:
public void insertionSort() {
int key;
int i;
for ( int j = 1; j < this.a.length; j++ ) {
key = a[j];
i = j;
while ( i > 0 && a[i-1] > key ) {
a[i] = a[i-1];
i = i - 1;
}
a[i] = key;
}
}
public static int[] insrtSort(int array[]){
for(int i=0 ; i<array.length-1;i++){
int value=array[i+1],k=i;
while(value<array[k] ){
array[k+1]=array[k];
if(k!=0)
k--;
else
array[0]=value;
}
if(k!=0)
array[k+1]=value;
}
return array;
}
This is the same code but as a method that can be passed an array of ints to sort.
public static int[] insertionSort(int[] array) {
int key;
int i;
for ( int j = 1; j < array.length; j++ ) {
key = array[j];
i = j;
while ( i > 0 && array[i-1] < key ) {
array[i] = array[i-1];
i = i - 1;
}
array[i] = key;
}
return array;
}

Categories