I'm trying to write a bubblesort method that needs to be able to sort on demand in both descending and ascending order while using a minimum amount of duplicate code.
So far this has been my temporal solution:
public void burbuja() {
String TipoOrdenamiento = "Max";
int i, j, aux;
for (i = 1; i < A.length; i++) {
for (j = A.length - 1; j >= i; j--) {
if (TipoOrdenamiento == "Min") {
if (A[j - 1] > A[j]) {
aux = A[j - 1];
A[j - 1] = A[j];
A[j] = aux;
}
}
if (TipoOrdenamiento == "Max") {
if (A[j - 1] < A[j]) {
aux = A[j - 1];
A[j - 1] = A[j];
A[j] = aux;
}
}
}
}
}
As you guys may notice, there's very little actual difference between ascending and descending sorting so I'm very curious to know if there are any neat tricks that allow me to compact my method further.
Thanks in advance for your answers.
Use a boolean to denote if the comparison between j and j-1 should be true or false.
public static void bubbleSort(int[] A, String TipoOrdenamiento) {
boolean increasingOrder = TipoOrdenamiento == "Min";
for (int i = 1; i < A.length; i++) {
for (int j = A.length - 1; j >= i; j--) {
if (A[j - 1] < A[j] != increasingOrder && A[j - 1] != A[j]) {
int aux = A[j - 1];
A[j - 1] = A[j];
A[j] = aux;
}
}
}
}
Since you are using Java, Comparator is nice way to achieve generality:
class MinComp implements Comparator<Integer>
{
public int compare(Integer a, Integer b)
{
if (a < b)
return -1;
if (a == b)
return 0;
if (a > b)
return -1;
}
}
public class Bubble
{
public static void main(String[] args)
{
MinComp minComp = new MinComp();
burbuja(minComp);
}
static public void burbuja(Comparator comp)
{
int i, j, aux;
for (i = 1; i < A.length; i++)
{
for (j = A.length - 1; j >= i; j--)
{
if (comp.compare(A[j - 1], A[j]) > 0)
{
aux = A[j - 1];
A[j - 1] = A[j];
A[j] = aux;
}
}
}
}
}
By defining different type of comparators, you can choose various orderings.
Related
I have an assignment to draw a graph and analyze the Hoare's partitioning algorithm and compare theoretical and practical worst-case scenario values. It says that I need a count variable to keep track of critical steps (i.e comparison and swapping). I wrote this code for Hoare's partitioning.
public static int partition(Comparable[] a, int left, int right) {
Comparable pivot = a[(left + right) / 2];
int i = left - 1, j = right + 1;
while (true) {
do {
i++;
} while (a[i].compareTo(pivot) < 0);
do {
j--;
} while (a[j].compareTo(pivot) > 0);
if (i < j) {
Comparable temp = a[i];
a[i] = a[j];
a[j] = temp;
} else {
return j;
}
}
}
Now I am confused about where to add the count variable. I know that count variable will be incremented in if (i < j) line. But do I also need to increment count in both do-while loops to keep track of comparisons?
So, the updated code will be like this?
public static int partition(Comparable[] a, int left, int right) {
int count = 0;
Comparable pivot = a[(left + right) / 2];
int i = left - 1, j = right + 1;
while (true) {
do {
count++;
i++;
} while (a[i].compareTo(pivot) < 0);
do {
count++;
j--;
} while (a[j].compareTo(pivot) > 0);
if (i < j) {
count++;
Comparable temp = a[i];
a[i] = a[j];
a[j] = temp;
} else {
return j;
}
}
}
Or like this?
public static int partition(Comparable[] a, int left, int right) {
int count = 0;
Comparable pivot = a[(left + right) / 2];
int i = left - 1, j = right + 1;
while (true) {
do {
i++;
} while (a[i].compareTo(pivot) < 0);
do {
j--;
} while (a[j].compareTo(pivot) > 0);
if (i < j) {
count++;
Comparable temp = a[i];
a[i] = a[j];
a[j] = temp;
} else {
return j;
}
}
}
My array is {8,3,5,9,2} and I get {3,5,9,2}
public static void insertionsort(int[] a) {
for (int i = 1; i < a.length; i++) {
int value = a[i];
// int c=0;
for (int j = i - 1; value < a[j + 1] && j >= 0; j--) {
int temp = a[j - 1];
a[j - 1] = a[j];
a[j] = temp;
// c++;
}
}
}
Could some one help me figure out the problem in my code
.
You never enter the second for loop.
At start i=1 j=i-1 value=3 a[j+1]=3
value < a[j + 1] is like 3<3 so it is always false.
Try this:
int n = a.length;
for (int i=1; i<n; ++i)
{
int temp = a[i];
int j = i-1;
while (j >= 0 && a[j] > temp)
{
a[j+1] = a[j];
j = j-1;
}
a[j+1] = temp;
}
I'm using the pseudocode called Lomuto partition scheme on https://en.wikipedia.org/wiki/Quicksort. But I just don't understand what it is that I am doing wrong here. The array never gets organized (regardless of the input size). This is preparation for my final exam. My professor wants us to use this algorithm, but I can't just learn it unless I have an understanding of how it works by testing it.
private static void quickSort(Integer A[], int l, int r) {
if (l < r) {
int k = partition(A, l, r);
quickSort(A, l, k - 1);
quickSort(A, k + 1, r);
}
}
private static int partition(Integer A[], int l, int r) {
int pivot = A[r];
int i = l;
for (int j = l; j <= r - 1; j++) {
if (A[j] <= pivot) {
i++;
int temp = A[j];
A[j] = pivot;
pivot = temp;
}
}
int temp = A[i + 1];
A[i + 1] = A[r];
A[r] = temp;
return i + 1;
}
I don't know what else to say other than that you just didn't transcribe the pseudocode correctly. At the beginning of partition, i should equal l - 1, but you set it to l.
Also, you're not swapping A[i] with A[j] within the nested loop. Here's the correct implementation:
private static int partition(Integer A[], int l, int r) {
int pivot = A[r];
int i = l - 1;
for (int j = l; j <= r - 1; j++) {
if (A[j] < pivot) {
i++;
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
}
int temp = A[i + 1];
A[i + 1] = A[r];
A[r] = temp;
return i + 1;
}
I've written this to sort two arrays and then compare the values to see if they're the same, but it always returns false, and I can't figure out why.
It is supposed to find if two arrays are permutations of each other.
public class Permutations {
public static void main(String[] args) {
int[] a = {1,4,6,7,8,34};
int[] b = {34,6,8,1,4,7};
System.out.println(arePermutations(a, b));
}
public static boolean arePermutations(int[] a, int[] b)
{
int count = 0;
int temp = 0;
if(a.length == b.length)
{
for(int i=0; i<a.length-1; i++)
for(int j=0; j<a.length-1; j++)
if(a[i] > a[j+1] && i>j+1)
{
temp = a[i];
a[i] = a[j+1];
a[j+1] = temp;
}
{
for(int i=0; i<b.length-1; i++)
for(int j=0; j<b.length-1; j++)
if(b[i] > b[j+1] && i>j+1)
{
temp = b[i];
b[i] = b[j+1];
b[j+1] = temp;
}
}
for(int i=0; i<a.length; i++)
if(a[i] == b[i])
{
count++;
}
if (count == a.length)
{
return true;
}
else return false;
}
else return false;
}
}
The problem is in the implementation of the bubble sort. Change your sorting loops to the following:
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length - 1; j++) {
if (a[j] > a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
for (int i = 0; i < b.length; i++) {
for (int j = 0; j < b.length - 1; j++) {
if (b[j] > b[j + 1]) {
temp = b[j];
b[j] = b[j + 1];
b[j + 1] = temp;
}
}
}
This code works because a bubble sort just swaps adjacent elements if they need swapping, but needs to run through the entire array multiple times (up to the number of items in the array) to get all the items into the correct position.
I need to count the number of loops and comparisons which occur over four different sorting methods. I am using the Selection, Bubble, Insertion, and Quick sort methods. Ideally, I would just place a int such as loopCounter and ++ it every time it loops/compares. Although, being quite new to all of this, I am having trouble distinguishing when I need to include such counters. As you will be able to see in the following code, I attempted to create multiple counters. Although, I think only the selection counters are correct so far.
Additionally, I am required to count the number of times that a value is shifted. In other words, how many times integers are swapped.
Any help with this would be extremely appreciated!
Thanks
ArrayList<Integer> list = new ArrayList<Integer>();
//Counters for Selection Sort
int loopCounter = 0;
int compCounter = 0;
//Counters for Bubble Sort
int loopCounter2 = 0;
int compCounter2 = 0;
//Counters for Insertion Sort
int loopCounter3 = 0;
int compCounter3 = 0;
//Counters for Quick Sort
int loopCounter4 = 0;
int compCounter4 = 0;
public void selectionSort(Integer[] a) {
for(int i = 0; i < a.length; i++) {
int smallestValue = a[i];
int smallestIndex = i;
if(ascButton.isSelected()){
for(int j = i+1; j < a.length; j++) {
if (smallestValue > a[j]) {
smallestValue = a[j];
smallestIndex = j;
loopCounter++;
compCounter++;
}
}
a[smallestIndex] = a[i];
a[i] = smallestValue;
} else if(desButton.isSelected()){
for(int j = i+1; j < a.length; j++) {
if (smallestValue < a[j]) {
smallestValue = a[j];
smallestIndex = j;
loopCounter++;
compCounter++;
}
}
a[smallestIndex] = a[i];
a[i] = smallestValue;
}
}
}
public void bubbleSort(Integer[] a) {
int temp;
for (int i = a.length - 1; i > 0; i--) {
if(ascButton.isSelected()) {
for(int j = 0; j < i; j++) {
loopCounter2++;
compCounter2++;
if(a[j] > a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
} else if(desButton.isSelected()) {
for(int j = 0; j < i; j++) {
loopCounter2++;
compCounter2++;
if(a[j] < a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}
}
public void insertionSort(Integer[] a) {
for(int i = 1; i < a.length; i++) {
loopCounter3++;
compCounter3++;
int temp = a[i];
int j = i - 1;
if(ascButton.isSelected()) {
while(j >= 0 && a[j] > temp) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = temp;
} else if(desButton.isSelected()) {
while(j >= 0 && a[j] < temp) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = temp;
}
}
}
public void quickSort(Integer[] a, int left, int right) {
int i = left;
int j = right;
int temp;
int pivot = a[(left + right)/2];
while(i <= j) {
if(ascButton.isSelected()) {
while(a[i] < pivot)
i++;
while(a[j] > pivot)
j--;
} else if(desButton.isSelected()) {
while(a[i] > pivot)
i++;
while(a[j] < pivot)
j--;
}
if(i <= j) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
i++;
j--;
}
}
if(left < j) {
quickSort(a,left,j);
}
if(i < right) {
quickSort(a, i, right);
}
}
With counters, you simply want to "count" when you want to program to count something. So if you don't understand your own code, then it will be difficult to know when you want to "count" something. I suggest you figure out when a swap is happening, when that is happening in your code, that is when you want to do some sort of:
swapCount++;//Each time a swap happens increment by 1
iterationCount++//A full pass has happened increment by 1
Note: above just because a full pass has happened in many sort, which you probably know, does not mean it is sorted, it is just saying it has done 1 pass.
I'm not sure if this theory will help you any. Give me some feedback on what your still having trouble with and I'll see if I can change my answer to better reflect what your looking for.
As #Andreas suggested, your loop and comparison counters are in place correctly.
As far as the swap counter is concerned, think of it this way - you cannot swap without a temp variable. As a result, whenever a temp variable is involved you want to increase your swap counter.
As an example, for your quicksort, it would look like this:
public void quickSort(Integer[] a, int left, int right) {
int i = left;
int j = right;
int temp;
int pivot = a[(left + right)/2];
while(i <= j) {
if(ascButton.isSelected()) {
while(a[i] < pivot)
i++;
while(a[j] > pivot)
j--;
} else if(desButton.isSelected()) {
while(a[i] > pivot)
i++;
while(a[j] < pivot)
j--;
}
if(i <= j) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
i++;
j--;
swapCounterForQuickSort++;
}
}
if(left < j) {
quickSort(a,left,j);
}
if(i < right) {
quickSort(a, i, right);
}
}
Follow the same logic for your other sorts.
Also, some general suggestions:
Always name variables so that they tell you what they are used for. Rather than loopCounter1 try using loopCounterForSelectionSort and so on. Don't be afraid of long variable names. Information is power!
Make your functions as short and reusable as possible. For example, you swap integers a lot in your code. Maybe you can just copy the swap code and paste it into a swapIntegers() function. Then everytime you just call this function when you want to swap! Also, notice how this makes your swap counter question easier to answer since you can put a counter in the swap method to do the counting for you. (Although be aware since multiple methods will call the swap counter so you may want to pass it as an argument etc.)