public static void sort(int[] a){
if (a.length>1){
int pivot=a[a.length-1];
int left=0;
int right=a.length-1;
while(left<=right){
while(a[left]<pivot)
left++;
while(a[right]>pivot)
right--;
if(left<=right){
int tmp=a[right];
a[right]=a[left];
a[left]=tmp;
left++;
right--;
}
}
int[] tmp1=new int[right];
for(int i=0;i<tmp1.length;i++)
tmp1[i]=a[i];
int[] tmp2=new int[a.length-right-1];
for(int i=left;i<a.length;i++)
tmp2[i-left]=a[i];
sort(tmp1);
sort(tmp2);
}
}
Im trying to write a quicksort algorithm with one function and it doesn't work. Any help is aprrecitated. Thanks
EDIT: I solved it thanks everyone for your input.
I think the problem is that at the end you are not using the tmp1 and tmp2 to conform the new array a... Here is a way to do it without creating others arrays:
public static void sort(int[] a, int left, int right){
if (left < right){
int pivot = a[right];
int pos = left - 1;
for (int i = left; i < right; i++)
if (a[i] <= pivot)
Swap(a, ++pos, i);
Swap(a, pos + 1, right);
sort(a, left, pos);
sort(a, pos + 1, right);
}
}
public static void Swap(int[] a, int i, int j){
int temp = a[j];
a[j] = a[i];
a[i] = temp;
}
The first call of sort must be sort(a, 0, a.length - 1)
I hope this helps you
Your sort method seems extremely compared to most int sort methods. Here is a quick and easy one.
public static void sort(int[] intArray){
int n = intArray.length;
int temp = 0;
for(int i=0; i < n; i++){
for(int j=1; j < (n-i); j++){
if(intArray[j-1] > intArray[j]){
temp = intArray[j-1];
intArray[j-1] = intArray[j];
intArray[j] = temp;
}
}
}
}
This is just a bubble sort. I don't see the point of the recursion. There a bunch of other types of sorts but for a short array length this is the easiest (IMO). Look up some other ones, its kinda cool what they do (Sorting algorithm).
To get to your question....
Like #RobinCurbelo said, you didn't use temp1 and temp2 correctly. Your idea is there but I think you were thinking too much into what you needed to do.
Related
I'm using this simple implementation. I just want to count the comparisons. Below the code actually works.
The list is [3, 9, 8, 4, 6, 10, 2, 5, 7, 1].
The answer for comparison count is 25 but I'm getting 30. I can't figure out why. What causes this code to do "more work" than it is supposed to? Thanks in advance!
public void sort(int[] values){
int length = values.length;
if(values == null || length == 0){
return;
}
quicksort(values, 0, length-1);
}
private int partition(int arr[], int left, int right){
int i = left+1;
int pivot = arr[left];
for(int j=(left+1); j<=right; j++){
comparisonCount++;
if(arr[j] < pivot){
swap(arr,i,j);
i++;
}
}
swap(arr,left, i-1);
return i;
}
private void quicksort(int arr[], int left, int right) {
int index = partition(arr, left, right);
if (left < index - 1){
quicksort(arr, left, index-1);
}
if (index < right){
quicksort(arr, index, right);
}
}
private void swap(int[] arr, int i, int j){
int tmp;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
Well, I appear to have found where the discrepancy is coming from:
quicksort(values, 0, length - 1); // initial call in sort()
for (int j = (left + 1); j <= right; j++) { // loop in partition()
Versus
quicksort(values, 0, length); // initial call in sort()
for (int j = (left + 1); j < right; j++) { // loop in partition()
First one gives 30 comparisons, second gives 25.
Why this is the case? I suspect it has something to do with how the loop invariant is set up. My guess is that you're comparing some pivot multiple times due to the way the bounds were set up. I'm too brain-dead to figure out the exact bounds, so I'll try to remember to come back once I get that figured out.
I'm writing a program that tests if a sort function sorts a program properly. I have to have it test the quick sort and merge sort methods. Also it must ask the user which method they would like to test and make an array of random objects. Why won't my program run properly? It just spits out the same array for the quick sort and it randomly re arranges them for the merge sort. Is the problem my sorting methods or my tester method? Someone please help.
import java.util.Random;
import java.util.Scanner;
public class sortArrays {
public static void main (String[] args)
{
Random gen = new Random();
int[] a = new int[20];
Scanner reader = new Scanner(System.in);
String choice;
int left = a[0];
int right = a[19];
int[] buffer = new int [a.length];
for (int i = 0; i < a.length; i++)
a[i] = gen.nextInt(100);
printArray(a);
System.out.println("Type quick to test the quick sort method.");
System.out.println("Type merge to test the merge sort method.");
choice = reader.nextLine();
if (choice.equals("quick"))
quickSort(a, left, right);
else if (choice.equals("merge"))
mergeSort(a, buffer, 0, 9, 19);
printArray(a);
}
private static void printArray(int[] a)
{
for(int i : a)
System.out.print(i + " ");
System.out.println("");
}
private static void quickSort (int[] a, int left, int right)
{
if (left >= right) return;
int i = left;
int j = right;
int pivotValue = a[(left + right) / 2];
while (i < j)
{
while (a[i] < pivotValue) i++;
while (pivotValue < a[j]) j--;
if (i <= j)
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
i++;
j--;
}
}
quickSort(a, left, j);
quickSort(a, i, right);
}
private static void mergeSort(int[] a, int[] copyBuffer, int low, int middle, int high)
{
int i1 = low, i2 = middle + 1;
for(int i = low; i <= high; i++)
{
if(i1 > middle)
copyBuffer [i] = a[i2++];
else if(i2 > high)
copyBuffer[i] = a[i1++];
else if(a[i1] < a[i2])
copyBuffer[i] = a[i1++];
else
copyBuffer[i] = a[i2++];
}
for(int i = low; i <= high; i++)
a[i] = copyBuffer[i];
}
}
Well, your printArray() looks OK, but one thing stands out right away:
The initial parameters you are passing to quickSort() are incorrect. You have:
int[] a = new int[20];
...
int left = a[0];
int right = a[19];
...
quickSort(a, left, right);
You are initializing left and right to 0, and thus you end up calling quickSort(a, 0, 0) (not what you want). You probably mean to do this instead, as left and right hold the index:
int left = 0;
int right = 19;
Or simply:
quickSort(a, 0, 19);
As for your mergeSort(), the implementation is simply incomplete. It appears you have implemented the "merge" operation (an essential piece of the algorithm), but not the "merge sort" overall algorithm. You may want to check out Mergesort in Java (for examples) or Merge Sort (for general overview).
By the way, you may wish to specify a.length - 1 instead of 19, that way you can change the size of a without having to modify other code (same would go for the 9 you pass to mergeSort(), but that is moot as you will see it is unnecessary once you implement the algorithm fully).
I need help figuring out what exactly is wrong with this partitioning code. I have been struggling with it for a few days now, cant seem to wrap my head around it.
The pIdx is the pivot index, left and right are the bounds integer options for the array, and the array a is just an array or stored long values.
protected static int partition(long[] a, int left, int right, int pIdx) {
//long numbers[] = {4,3,8,9,7,2,1,5};
long pivot = a[pIdx];
swap(a, pIdx, right);
int storeIndex = left;
for(int i=left; i<right; i++) {
if(a[i] <= pivot)
swap(a, i, storeIndex);
}//for
swap(a, right, storeIndex);
return storeIndex;
}//partitio
I tried fixing your code. See if this works for you.
protected static int partition(long[] a, int left, int right, int pIdx) {
//long numbers[] = {4,3,8,9,7,2,1,5};
long pivot = a[pIdx];
swap(a, pIdx, right);
int storeIndex = left;
for(int i=left; i<right; i++) {
if(a[i] < pivot) {
swap(a, i, storeIndex);
storeIndex = storeIndex + 1;
}
}
swap(a, storeIndex, right);
return storeIndex;
}
I'm trying to understand recursion and how to turn my currently iterative insertion sort into a recursive one.
What would I need to do to my code to make it recursive?
I think I need a base case so it doesn't become an infinite loop.
I'm not sure I entirely understand recursion. Maybe you can make it clearer for me?
I've done a lot of reading but I still don't know where to start.
Here is my code:
public class InsertionSort
{
public static void main(String a[])
{
int i;
int array[] =
{ 8, 33, 12, 99, 0, 17 };
System.out.println("Values of Array before the sort: ");
for (i = 0; i < array.length; i++)
{
System.out.print(array[i] + " ");
}
insertion_srt(array, array.length);
System.out.println("");
System.out.println("Values of Array after the sort: ");
for (i = 0; i < array.length; i++)
{
System.out.print(array[i] + " ");
}
}
public static void insertion_srt(int array[], int n)
{
for (int i = 1; i < n; i++)
{
int j = i;
int B = array[i];
while ((j > 0) && (array[j - 1] > B))
{
array[j] = array[j - 1];
j--;
}
array[j] = B;
}
}
}
This is great approach I personally likes. It does use three methods but they're very simple to understand. Think of the insertionOut as the outer for loop and the insertionIn as the inner nested for loop
public static void insertionRecursive(int[] a){
if(a.length > 0){ // base case
insertionOut(a, 1, a.length);
}
}
private static void insertionOut(int[] a, int i, int length){ //outer loop
if(i < length){ // iterates from 1 to the length
int temp = a[i]; // temp value
int k = i;
insertionIn(a, k, temp);
insertionOut(a, i + 1, length); // iterates through the loop
}
}
private static void insertionIn(int[] a, int k, int temp){ // inner loop
if(k > 0 && a[k - 1] > temp){
//this does a basic swap
a[k] = temp;
a[k] = a[k - 1];
a[k - 1] = temp;
insertionIn(a, k - 1, temp); // iterates through the loop
}
}
Transforming the outer for loop is kind of trivial. To overcome the while loop you need a little recursive helper function. You have to call the function in your main as insertion_srt(array, 0, array.length):
public static void insertion_srt(int array[], int beg_index, int n) {
if(beg_index >= n-1)
return;
int i = beg_index + 1;
int j = i;
int B = array[i];
j=helper(array, j, B);
array[j] = B;
insertion_srt(array, beg_index + 1, n);
}
private static int helper(int[] array, int j, int B) {
if(j <= 0 || array[j-1] <= B)
return j;
array[j] = array[j - 1];
return helper(array, j-1, B);
}
A good way to understand how recursion works is to understand the concept of Divide and conquer algorithm. This technique is a basis of efficient algorithms for all kinds of problems.
The idea behind it is to divide a problem into smaller subproblems that can all be solved in the same way:
Divide into 2 (or more) subproblems.
Solve each subproblem recursively.
Combine the results.
Insertion sort is not the best example of a divide and conquer algorithm, but it can still be approached this way. You can divide the problem into 2 subproblems:
last element
everything else
This way you will obtain so called tail recursion. All loops are relatively easy to transform into tail recursions.
public static void insertion_srt(int array[], int n, int j) {
if (j < n) {
int i;
int temp = array[j];
for (i=j; i > 0 && array[i-1] > temp; i--) array[i] = array[i-1];
array[i] = temp;
insertion_srt(array,n, j+1);
}
}
Try this simple recursive approach:
public static void insertionSort(int[] array, int index) {
if(array.length == index + 1) return;
insertionSort(array, index + 1);
// insert array[index] into the array
}
I am implementing a quicksort algorithm and have succesfully partitioned the input array around a pivot. The problem is, I am confused in how to recursively sort the 1st part and 2nd part of the array (i.e specifying the range) using the same input array.
Below is my implementation
class QuickSort {
int i;
int l = 0;
public void quicksort(int A[], int n) {
if (n == 1) {
return;
} else {
partition(A, 0, n);
//----Confused as from this point
quicksort(A, A[i]);
//Recursively sort both parts of the array
}
}
public int partition(int A[], int l, int r) {
int p = A[l];//Choose pivot
i = l + 1;
//Partition around A through P
for (int j = i; j < r; j++) {
if (A[j] < p) {
swap(A, i, j);
++i;
}
}
swap(A, l, i - 1 );
return i;
}
public void swap(int A[], int i, int j) {
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
public void display(int A[]){
for (int i = 0; i < A.length; i ++){
System.out.print(A[i] + " ");
}
}
}
class QuickSortApp{
public static void main(String args[]){
QuickSort quick = new QuickSort();
int A[] = {6,2,7,8,4,3,5};
quick.quicksort(A, A.length);
quick.display(A);
}
}
Please, I would also appreciate being corrected on any other inefficencies in my algorithm. Thanks
Change your quicksort() signature to quicksort(int[] A, int begin, int end)
Since, you actually did the sorting inside partition(). What I would do is this:
if (end-begin <= 1) {
return;
} else {
int pivot = partition(A, begin, end);
quicksort(A, begin, pivot);
quicksort(A, pivot, end);
}
Create a wrapper for the quicksort call with the signature you have which calls another one like quicksort(A, i, j) and your call from the wrapper will be quicksort(A, 0, n).