I've been working on selection sort and bubble sort using recursion. I've finally come up with two methods, and they worked perfectly fine. But as I took a final look at those, they look like just one one method which is selectionSortRecursive. Could you tell me the difference (or are they the same)?
public static void selectionSortRecursive(Comparable[] list, int n)
{
Comparable temp;
if ( n > 1 ){
for ( int i = 0; i < n - 1; i++ )
{
if(list[i].compareTo(list[i + 1]) > 0){
temp = list[i];
list[i] = list[i + 1];
list[i + 1] = temp;
}
}
selectionSortRecursive(list, n - 1);
}
}
public static void bubbleSortRecursive( Comparable[] list, int n)
{
Comparable tmp;
if (n >1) {
for (int i = 0; i < n - 1; i++)
{
if(list[i+1].compareTo(list[i]) < 0)
{
tmp = list[i];
list[i] = list[i+1];
list[i+1] = tmp;
}
}
bubbleSortRecursive( list, n - 1);
}
}
The only line which is different is
if(list[i].compareTo(list[i + 1]) > 0){
and
if(list[i+1].compareTo(list[i]) < 0)
and provided compareTo is implemented correctly this will do the same thing.
BTW the if(n > 1) check is redundant. And I would move tmp to the most inner scope you can.
Both sorts are bubble sorts. A bubble sort "bubbles" values to the top/right position.
A selection sort selects the lowest/highest value repeatedly, swap in the selected with the position it needs to place it. i.e. the swap would be outside the loop to find the lowest/highest.
It's both bubble sort, one bubbles the element from the top to the bottom, the other one does it the way round. Selection sort is different: it searches the smallest elements of all remaining (unsorted) elements and places it in the next slot, it does not change any other elements. Bubble sort, instead, always compares tow elements and swaps them is the first one is bigger (or smaller) than the second one - which is what you are doing.
Related
I found this bubble sort (first sort I'm ever studying), I understand it almost fully but I'm stuck on one spot.
public static int[] bubbleSort(int[] tempArray) {
int i, j, temp, n = tempArray.length;
boolean swapped;
for (i = 0; i < n - 1; i++) {
swapped = false;
for (j = 0; j < n - i - 1; j++) {
if (tempArray[j] > tempArray[j + 1]) {
temp = tempArray[j];
tempArray[j] = tempArray[j + 1];
tempArray[j + 1] = temp;
swapped = true;
}
}
if (swapped == false)
break;
}
return tempArray;
}
what is the point of "n - 1" in outer loop besides helping to make inner loop (n - i - 1) shorter? I tried removing the "n -1" and having count++ to work in the inner loop and the result was the same, so what is the reason for it then? Thanks!
It is because the largest element is already sorted in the first iteration.
A picture is worth a thousand words
Image is from https://en.wikipedia.org/wiki/Bubble_sort
Additional there is no need for the last element because bubble sort is all about swapping adjacent element and the last element doesn't have adjacent element.
It is because bubble sorting works on swapping of adjacent element.
If outer loop goes till n then in the inner loop you cannot pick another element.
temp = tempArray[j];
tempArray[j] = tempArray[j + 1];
tempArray[j + 1] = temp;
This is because the size of array is till n and inner loop swap between j and j+1.
Feel free to ask further doubts.
I'm trying to implement quicksort in Java to learn basic algorithms. I understand how the algo works (and can do it on paper) but am finding it hard to write it in code. I've managed to do step where we put all elements smaller than the pivot to the left, and larger ones to the right (see my code below). However, I can't figure out how to implement the recursion part of the algo, so sort the left and right sides recursively. Any help please?
public void int(A, p, q){
if(A.length == 0){ return; }
int pivot = A[q];
j = 0; k = 0;
for(int i = 0; i < A.length; i++){
if(A[i] <= pivot){
A[j] = A[i]; j++;
}
else{
A[k] = A[i]; k++;
}
}
A[j] = pivot;
}
Big Disclaimer: I did not write this piece of code, so upvotes is not needed. But I link to a tutorial which explains quicksort in detail. Gave me a much needed refreshment on the algorithm as well! The example given has very good comments that might just help you to wrap your head around it.
I suggest you adapt it to your code and write som tests for it to verify it works
Quicksort is a fast, recursive, non-stable sort algorithm which works by the divide and conquer principle. Quicksort will in the best case divide the array into almost two identical parts. It the array contains n elements then the first run will need O(n). Sorting the remaining two sub-arrays takes 2 O(n/2). This ends up in a performance of O(n log n).
In the worst case quicksort selects only one element in each iteration. So it is O(n) + O(n-1) + (On-2).. O(1) which is equal to O(n^2).*
public class Quicksort {
private int[] numbers;
private int number;
public void sort(int[] values) {
// check for empty or null array
if (values ==null || values.length==0){
return;
}
this.numbers = values;
number = values.length;
quicksort(0, number - 1);
}
private void quicksort(int low, int high) {
int i = low, j = high;
// Get the pivot element from the middle of the list
int pivot = numbers[low + (high-low)/2];
// Divide into two lists
while (i <= j) {
// If the current value from the left list is smaller than the pivot
// element then get the next element from the left list
while (numbers[i] < pivot) {
i++;
}
// If the current value from the right list is larger than the pivot
// element then get the next element from the right list
while (numbers[j] > pivot) {
j--;
}
// If we have found a value in the left list which is larger than
// the pivot element and if we have found a value in the right list
// which is smaller than 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--;
}
}
// This is the recursion part you had trouble with i guess?
// Recursion
if (low < j)
quicksort(low, j);
if (i < high)
quicksort(i, high);
}
private void exchange(int i, int j) {
int temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
}
}
Link to tutorial
I have to make the following 2 modifications to a simple bubblesort program:
After the first pass, the largest number is guaranteed to be in the highest-numbered element of the array; after the second pass, the two highest numbers are “in place”; and so on. Instead of making nine comparisons on every pass, modify the bubble sort to make eight comparisons on the second pass, seven on the third, and so on.
The data in the array may already be in the proper order or near proper order, so why make nine passes if fewer will suffice? Modify the sort to check at the end of each pass if any swaps have been made. If none have been made, the data must already be in the proper order, so the program should terminate. If swaps have been made, at least one more pass is needed."
Any help as to how I should approach these would be greatly appreciated!
//sort elements of array with bubble sort
public static void bubbleSort (int array2[])
{
//loop to control number of passes
for (int pass = 1; pass < array2.length; pass++)
{
//loop to control number of comparisons
for (int element = 0; element < array2.length - 1; element++)
{
//compare side-by-side elements and swap them if
//first element is greater than second element
if (array2[element] > array2[element + 1]){
swap (array2, element, element + 1);
}
}
}
}
//swap two elements of an array
public static void swap (int array3[], int first, int second)
{
//temporary holding area for swap
int hold;
hold = array3[first];
array3[first] = array3[second];
array3[second] = hold;
}
I think this will do for you. A boolean is added to check and the run (j) is subtracted from the input.length for each run.
public static int[] bubbleSort(int input[])
{
int i, j, tmp;
bool changed;
for (j = 0; j < input.length; j++)
{
changed = false;
for (i = 1; i < input.length - j; i++)
{
if (tmp[i-1] > input[i])
{
tmp= input[i];
input[i] = input[i-1];
input[i-1] = tmp;
changed = true;
}
}
if (!changed) return input;
}
return input;
}
I have a small doubt while sorting arrays and yeah I am new to programming. Take a look at this code for example:
public void bubbleSort(int[] array) {
boolean swapped = true;
int j = 0;
int tmp;
while (swapped) {
swapped = false;
j++;
for (int i = 0; i < array.length - j; i++) {
if (array[i] > array[i + 1]) {
tmp = array[i];
array[i] = array[i + 1];
array[i + 1] = tmp;
swapped = true;
}
}
}
In the above code, why do we have to use j++ and i < (array.length-j) as the test expression? We could have rather used i < (array.length) as the test expression while omitting the variable j. Any answers?
"Why do we have to use j++ and i < (array.length-j) as the test expression?"
The reason behind is at any time elements array[ array.length -j ] to array[array.length - 1] are already sorted.
Example: Say you have array of length n.
So after the first iteration the biggest element will be placed at array[n - 1].
So because the largest element is already sorted on the next iteration we will only sort array of length n - 1.
After the second iteration the second biggest element will be placed at array[ n - 2].
So because the 1st largest and 2nd largest elements are already sorted on the next iteration we will only sort array of length n - 2, and so on...
The running time of the algorithm will be which is
As you said it we could have used i < (array.length - 1) but we will be just doing a lot of work for nothing. If we do this the running time will be (nn) which is O(nn). But though the running time is still O(n*n) but it is obvious that is smaller than , hence the first one is efficient.
here's my code that uses selection. i need to use a insertion and do not use temporary arrays or arraylist. i need help of how to do a insertion sort.
public static void sortStudents(ArrayList<Student> list)
{//selection sort
Student tempStudent;
int count1;
int count2;
int largest;
for (count1=0; count1<list.size()-1; count1++)
{
largest = 0;
for (count2=largest+1; count2<list.size()-count1; count2++)
{
if ((list.get(largest)).compareTo(list.get(count2)) < 0)
{
largest = count2;
}
}
tempStudent = list.get(list.size()-1-count1);
list.set(list.size()-1-count1, list.get(largest));
list.set(largest, tempStudent);
}
}
}
Both selection sort and insertion sort work quite similarly, by having a "not yet sorted" part of the list, and an "already sorted" part. In the beginning, the first one is the whole list, and the second part an empty list at the start or end. While sorting the "not yet sorted" part shrinks, while the "already sorted" part grows, by one element per iteration.
The difference between selection sort and insertion sort is this:
For selection sort, you search the minimum (or maximum) element of the "not yet sorted" part, remove it there and then add it to the end (or beginning) of the already sorted part.
For insertion sort, you take the next element of the "not yet sorted" part of the list, find it's insertion point in the "already sorted" part and insert it there.
This should be enough to change your selection sort to insertion sort.
You don't define variables outside the loop if it is only used in the loop. Restricting the lifetime of your variables makes it more easy to reason about the code.
public static void sortStudents (ArrayList<Student> list)
{
int largest;
for (int i=0; i < list.size () - 1; i++)
{
largest = 0;
for (int j=largest + 1; j < list.size () - i; j++)
{
if ((list.get (largest)).compareTo (list.get (j)) < 0)
{
largest = j;
}
}
Student tempStudent = list.get (list.size () - 1 - i);
list.set (list.size () - 1 - i, list.get (largest));
list.set (largest, tempStudent);
}
}
A bit more indentation makes your code more readable. Now what's your concrete error - doesn't it compile, throws it an exception or does it produce the wrong result?
Here is something suspicious in the inner loop:
largest = 0;
for (int j=largest + 1; j < list.size () - i; j++)
If you set largest to 0, then j will be initialized to 0 + 1 => 1. I guess you had another intention. Did you mean j = i + 1;?