I dont understand this step particularly in mergesort [duplicate] - c

This question already has answers here:
How does the Pseudocode for merge sort work?
(2 answers)
Closed 6 years ago.
In the above code i dont understand this. it calls merge sort again but when do merge come into play as the function repeatedly calls mergesort
but when do merge happens
The code i could not understand is recursive one that how after breaking into halves and repeated calling of mergesort and breaking inrtoa single elment merge comes into play.
REAL QUESTION WAS HOW REAL COMES INTO PLAY
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 50000
void merge (int arr[], int start, int mid, int end){
/* two sorted arrays arr[start ... mid]
and arr[mid+1 ... end] merge them */
int tempvals[MAX_SIZE];
int ptr1, ptr2, ptrnew=0, idx;
ptr1 = start;
ptr2 = mid+1;
/* compare both the sorted arrays element by element
move the element that is smaller to the new aray */
while ( (ptr1 <= mid) && (ptr2 <= end)){
/* compare elements at ptr1 and ptr2 */
if (arr[ptr1] < arr[ptr2]){
tempvals[ptrnew] = arr[ptr1];
ptr1 ++; ptrnew++;
} else {
tempvals[ptrnew] = arr[ptr2];
ptr2 ++; ptrnew++;
}
}
/* at this point --> one of the pointers has reached the end */
while (ptr1 <= mid){
tempvals[ptrnew] = arr[ptr1];
ptr1 ++; ptrnew++;
}
while (ptr2 <= end){
tempvals[ptrnew] = arr[ptr2];
ptr2 ++; ptrnew++;
}
/* transfer back to arr */
for (idx = start, ptrnew = 0; idx <= end; idx++, ptrnew++)
arr[idx] = tempvals[ptrnew];
}
void merge_sort (int arr[], int start, int end){
int mid = (start + end)/2;
/* termination condition */
if( start >= end) return;
/* recurse */
merge_sort(arr,start, mid); /* first half */
merge_sort (arr, mid+1, end); /* second half */
merge (arr, start, mid, end); /* do the merging */
}
void print_array (int arr[], int size){
int i;
for (i=0; i < size; i++)
printf ("%d ",arr[i]);
printf ("\n");
}
int main(){
int arr[MAX_SIZE];
int i;
/* initialize */
for (i=0; i < MAX_SIZE; i++)
arr[i] = rand();
/* sort and print */
merge_sort (arr,0, MAX_SIZE - 1);
}
Blockquote
In the above code i dont understand this
it calls merge sort again but when do merge come into play as the function repeatedly calls mergesort
/* recurse */
merge_sort(arr,start, mid); /* first half */
merge_sort (arr, mid+1, end); /* second half */
merge (arr, start, mid, end); /* do the merging */

It's under the comment recurse, and called out in the line-by-line comments. You recur on merge_sort to sort the left part of the array, the right part. Then you call merge to reunite them, now in order.
You do not call merge_sort forever: note the base case (a.k.a. termination condition) at the top of merge_sort:
if( start >= end) return;
When you get to a list of no more than one element, you simply return -- it's already in order. Then you crawl back up that large call chain, merging single elements, then larger lists, ... until you're done.

Related

Different order from the expected [duplicate]

I want to print all permutation of string in lexicographic order. I wrote this code:
void permute(char *a, int i, int n) {
if (i == (n-1)) printf("\"%s\"\n", a);
else {
for (int j = i; j < n; j++) {
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j));
}
}
}
Let's take for example string abc, I want to receive all permutation in lexicographic order as in the left column, but I have result as in the right column.
"abc" "abc"
"acb" "acb"
"bac" "bac"
"bca" "bca"
"cab" <
"cba" "cba"
> "cab"
Can someone help me with this? I saw some algorithms, but they look difficult. I think I can save all generated strings in an array and then sort this array, but I cannot write this (I'm a beginner in C).
In C
There's a pretty straightforward description of an algorithm (plus implementation) at geeksforgeeks:
Given a string, print all permutations of it in sorted order. For
example, if the input string is “ABC”, then output should be “ABC,
ACB, BAC, BCA, CAB, CBA”.
We have discussed a program to print all permutations in this post,
but here we must print the permutations in increasing order.
Following are the steps to print the permutations lexicographic-ally
Sort the given string in non-decreasing order and print it. The first permutation is always the string sorted in non-decreasing order.
Start generating next higher permutation. Do it until next higher permutation is not possible. If we reach a permutation where all
characters are sorted in non-increasing order, then that permutation
is the last permutation.
Steps to generate the next higher permutation:
1. Take the previously printed permutation and find the rightmost character in it, which is smaller than its next character. Let us call
this character as ‘first character’.
Now find the ceiling of the ‘first character’. Ceiling is the smallest character on right of ‘first character’, which is greater
than ‘first character’. Let us call the ceil character as ‘second
character’.
Swap the two characters found in above 2 steps.
Sort the substring (in non-decreasing order) after the original index of ‘first character’.
I've re-implemented it below:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void swap(char* left, char* right)
{
char temp = *left;
*left = *right;
*right = temp;
}
int compare (const void * a, const void * b)
{
return ( *(char*)a - *(char*)b );
}
void PrintSortedPermutations(char* inStr)
{
// Re-implementation of algorithm described here:
// http://www.geeksforgeeks.org/lexicographic-permutations-of-string/
int strSize = strlen(inStr);
// 0. Ensure input container is sorted
qsort(inStr, strSize, sizeof(char), compare);
int largerPermFound = 1;
do{
// 1. Print next permutation
printf("%s\n", inStr);
// 2. Find rightmost char that is smaller than char to its right
int i;
for (i = strSize - 2; i >= 0 && inStr[i] >= inStr[i+1]; --i){}
// if we couldn't find one, we're finished, else we can swap somewhere
if (i > -1)
{
// 3 find character at index j such that
// inStr[j] = min(inStr[k]) && inStr[k] > inStr[i] for all k > i
int j = i+1;
int k;
for(k=j;k<strSize && inStr[k];++k)
{
if (inStr[k] > inStr[i] && inStr[k] < inStr[j])
j = k;
}
// 3. Swap chars at i and j
swap(&inStr[i], &inStr[j]);
// 4. Sort string to the right of i
qsort(inStr+i+1, strSize-i-1, sizeof(char), compare);
}
else
{
largerPermFound = 0;
}
}while(largerPermFound);
}
int main(void) {
char str[] = "abc";
PrintSortedPermutations(str);
return 0;
}
Output
abc acb bac bca cab cba
Live Demo
In C++
std::next_permutation from the <algorithm> library will do this for you, just make sure you sort your container first:
Return value
true if the function could rearrange the object as a lexicographicaly
greater permutation. Otherwise, the function returns false to indicate
that the arrangement is not greater than the previous, but the lowest
possible (sorted in ascending order).
For example:
std::string myStr = "abc";
std::stable_sort(std::begin(myStr), std::end(myStr));
do {
for(auto&& element : myStr)
std::cout << element << " ";
std::cout << std::endl;
} while (std::next_permutation(std::begin(myStr), std::end(myStr)));
Output:
a b c a c b b a c b c a c a b c b a
Live Demo
I am presuming you want a recursive version.
Here are two solutions.
Solution 1)
Since you want lexicographic, all you need to do is pick the next smallest possible when you need to pick. That's it!
For example, here is a recursive version in python
def permute(done, remaining):
if not remaining:
print done
return
sorted_rem = sorted(remaining)
l = len(sorted_rem)
for i in xrange(0, l):
c = sorted_rem[i]
# Move to c to done portion.
done.append(c)
remaining.remove(c)
# Permute the remaining
permute(done, remaining)
# Put c back.
remaining.append(c)
# Remove from done.
del done[-1]
permute([], [1,2,3,4])
That's it.
Solution 2)
While Solution 1 works and is easy to understand, I suspect we might be wasting some time by sorting. This solution is closer to what you have.
Recursion is basically mathematical induction in disguise, and that way of thinking is really useful in understanding how to write recursive programs.
For example, assume your permute method always constructs the permutations in lexicographic order.
Here is a recursive version, with that assumption, please read the comments to understand what is going on.
// By induction assumption, permute(a, i, n)
// goes through all the permutations of a[i], ..., a[n-1]
// in lexicographic order, by modifying a itself.
void permute(char *a, int i, int n) {
if (i == (n-1)) {
printf("%s\n", a);
return;
}
int j;
// We pick the n-i posibilities for the position a+i, then recursively
// compute the permutations of a[i+1], ..., a[n-1]
// So first pick the smallest possible for a+i, recurse.
// Then the next possible for a+i, then recurse etc.
for (j = i; j < n; j++) {
permute(a, i+1, n);
// By our induction assumption, at this point,
// a[i+1], a[i+2], .., a[n-1]
// must be the lexicographically the largest possible!
// So now reverse that portion.
reverse(a+i+1, a+n-1);
// Now we need to pick the lexicographically next element for
// position a+i. This is nothing but the element which is just
// larger than the current a+i.
int k = i+1;
while(k < n && a[i] > a[k]) {
k++;
}
if (k >= n) {
continue;
}
// Choose the next value for a+i.
swap(a+i, a+k);
}
// Notice that the portion a[i+1], ..., a[n-1] is sorted increasing.
// when the loop exits. Also a[i] will be the largest element.
// We need to reverse so that a[i], .., a[n-1] is the lexicographically
// largest permutation to maintain the induction (recursion) assumption.
reverse(a+i+1, a+n-1);
}
Notice the similarity between this, and the iterative version (specified by the others and section below), where you reverse a chunk at the end, and swap two elements.
btw, the common iterative algorithm for generating permutations in lexicographic order is Narayana Pandita's algorithm, mentioned by other, but not by name.
See this link: http://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order
This is what std::next of C++ and a host of other libraries use.
This algorithm even works when there are repeated elements, and can in fact be used to generate combinations! (Initialize your array with zeroes and ones).
IMHO, it would be simpler to first sort the characters of the string because the number of permutations (n!) is always greater (or equal for n = 1 or 2) than the number of characters.
And you were not far from the solution but you must rotate instead of swap. Here is a slight variation that returns an array of dynamically allocated strings that are printed in the main :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int char_compare(const void *a, const void *b) {
return (*((char *) a)) - (*((char *) b));
}
int fact(int n) {
int f = 1;
while (n > 0) {
f *= n--;
if (f < 0) return 0;
}
return f;
}
void rotateback(char *a, int i, int j) {
int k;
char tmp;
tmp = a[i];
for(k=i; k<j; k++) {
a[k] = a[k+1];
}
a[j] = tmp;
}
void rotate(char *a, int i, int j) {
int k;
char tmp;
tmp = a[j];
for(k=j; k>i; k--) {
a[k] = a[k-1];
}
a[i] = tmp;
}
void permute(char *a, int i, int n, char ***permuts) {
int j;
if (i == (n-1)) {
**permuts = strdup(a); // store a copy of the string
*permuts += 1; // and point to next location
}
else {
for (j = i; j < n; j++) {
rotate(a, i, j);
permute(a, i+1, n, permuts);
rotateback(a, i, j);
}
}
}
char ** permutations(const char *str_orig) {
int i, j;
size_t n = strlen(str_orig);
size_t fact_n = fact(n);
char ** permuts, **work;
char * str = strdup(str_orig); // get a local copy
qsort(str, n, 1, char_compare); // and sort it
permuts = work = calloc(fact_n, sizeof(char *)); // allocate n! pointers
permute(str, 0, n, &work);
return permuts;
}
int main() {
char str[] = "cab";
int i;
char **permuts = permutations(str);
for (i=0; i<fact(strlen(str)); i++) {
printf("\"%s\"\n", permuts[i]);
free(permuts[i]);
}
free(permuts);
return 0;
}
Output is correctly :
"abc"
"acb"
"bac"
"bca"
"cab"
"cba"
Another twist on the lexical string permutations is to store the permutation in a dynamically allocated array of pointers-to-string and pass the array to qsort to provide output in lexical order. Since permutations grow exponentially, checks for memory exhaustion after each allocation are especially important. The string size below is limited to 16 characters, which may still result in memory exhaustion depending on the amount of memory available.
Updated passing the address of the array to hold the string permutations was required for reallocation to work in the recursive function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXS 128
#define MAXC 16
size_t maxs;
void swap (char *x, char *y);
int cmp_pa (const void * a, const void * b);
char **realloc_char (char **sp, size_t *n);
void permute_pa (char ***pa, size_t *idx, char *a, int i, int n);
int main (int argc, char **argv)
{
size_t i = 0;
size_t idx = 0;
size_t len = 0;
char a[MAXC] = {0};
char **pa = NULL;
maxs = MAXS; /* initialize realloc counter */
if (argc > 1) /* set string to permute */
strcpy (a, argv[1]);
else
strcpy (a, "abc");
len = strlen (a); /* lenght to permute or MAXC */
if (len > MAXC) len = MAXC;
if (!(pa = calloc (MAXS, sizeof *pa))) /* allocate MAXS pointers */
return 1;
permute_pa (&pa, &idx, a, 0, len - 1); /* call permute function */
printf ("\n no of permutations : %zu\n\n", idx);
printf (" unsorted permutations of %s\n\n", a);
for (i = 0; i < idx; i++)
printf (" %s\n", pa[i]);
qsort (pa, idx, sizeof *pa, cmp_pa); /* sort array of permutations */
printf ("\n sorted permutations of %s\n\n", a);
for (i = 0; i < idx; i++)
printf (" %s\n", pa[i]);
for (i = 0; i < idx; i++) /* free all allocated memory */
free (pa[i]);
free (pa);
return 0;
}
/* Function to swap values at two pointers */
void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* qsort compare function */
int cmp_pa (const void * a, const void * b)
{ return strcmp (*(char**)a, *(char**)b); }
/* realloc an array of pointers to strings setting memory to 0. */
char **realloc_char (char **sp, size_t *n)
{
char **tmp = realloc (sp, 2 * *n * sizeof *sp);
if (!tmp) {
fprintf (stderr, "Error: struct reallocation failure.\n");
// return NULL;
exit (EXIT_FAILURE);
}
sp = tmp;
memset (sp + *n, 0, *n * sizeof *sp); /* memset new ptrs 0 */
*n *= 2;
return sp;
}
/* Function to store permutations of string in array of pointers-to-string
This function takes five parameters:
1. allocated array of pointers-to-string
2. pointer to array index
3. string to permute
4. starting index of the string (zero based)
5. ending index of the string. (zero based)
*/
void permute_pa (char ***pa, size_t *idx, char *a, int i, int n)
{
int j;
if (i == n) {
(*pa)[*idx] = strdup (a);
if (!(*pa)[*idx]) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
(*idx)++;
if (*idx == maxs)
*pa = realloc_char (*pa, &maxs);
}
else {
for (j = i; j <= n; j++) {
swap ((a+i), (a+j));
permute_pa (pa, idx, a, i+1, n);
swap ((a+i), (a+j));
}
}
}
Output
$ ./bin/str_permute_lex
no of permutations : 6
unsorted permutations of abc
abc
acb
bac
bca
cba
cab
sorted permutations of abc
abc
acb
bac
bca
cab
cba
Memory Error Check
$ valgrind ./bin/str_permute_lex
==29709== Memcheck, a memory error detector
==29709== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==29709== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==29709== Command: ./bin/str_permute_lex
==29709==
no of permutations : 6
<snip>
==29709==
==29709== HEAP SUMMARY:
==29709== in use at exit: 0 bytes in 0 blocks
==29709== total heap usage: 7 allocs, 7 frees, 1,048 bytes allocated
==29709==
==29709== All heap blocks were freed -- no leaks are possible
==29709==
==29709== For counts of detected and suppressed errors, rerun with: -v
==29709== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
The basic idea is to start with our main string as "" and remaining string as "abc" (or any you want).
Now to the main string append character by character. Such a way that it don't repeat the used characters (for all possible characters).
Repeat the same until you get length n ( length of main string ).
Okay, the explanation isn't clear but watch out the code. It will make everything clear.
#include<iostream>
void perm(std::string sub, std::string rem, int n)
{
if(n==0)
//print if n is zero i.e length achieved
std::cout<<sub<<"\n";
for(int i=0; i<n; i++)
//append a character and pass remaining to rem string
perm(sub + rem[i] , rem.substr(0,i) + rem.substr(i+1,n-1), n-1);
}
int main()
{
perm("", "abc", 3);
}
Output
abc
acb
bac
bca
cab
cba
This is voluntarily an answer that does not answer this question.
This other question was marked as a duplicate to this one. This answer would be acceptable for the other question even if it is non sense here.
This could be a simple recursive C implementation to get all permutations in lexicographic order. It is not optimized but easy to understand and to implement:
get an array for the elements to permute
at any step, iterate through the elements that have not been used until here
add one of the iterated elements to the array of used elements
recurse
when the array of used element is full print it.
Concrete implementation:
#include <stdio.h>
#define SIZE 4
void disp(int *fullarr, int n, int * begin, int pos) {
int i, j;
int found;
if (pos == n) {
for(i=0; i< n; i++) {
printf("%2d", begin[i]);
}
printf("\n");
return;
}
for (i=0; i<n; i++) {
found = 0;
for (j=0; j<pos; j++) {
if (fullarr[i] == begin[j]) {
found = 1;
break;
}
}
if (! found) {
begin[pos] = fullarr[i];
disp(fullarr, n, begin, pos+1);
}
}
}
int main() {
int i;
int fullarr[SIZE], begin[SIZE];
for (i=0; i<SIZE; i++) {
fullarr[i] = i;
}
disp(fullarr, SIZE, begin, 0);
return 0;
}
OK, here is how to do it in any programming language. I will illustrate it with writing down all the permutations of S4 but one can see easily how in generalizes. One needs to know about special permutations called cycles. The cycle (132) is the permutation that sends 1 to 3, 3 to 2 and 2 back to 1. Think of a numbered circle and one rotates the circle. The cycles (321) and (213) represent the same cycle and permutation. A "two cycle" (13) is a transposition, simply interchanging 1 and 3 and leaving all the other members the same. A "one cycle" (2) sends 2 to 2 and leaves everything else the same, i.e., it does nothing to any element. However, I will write one cycles below to make it look "pretty".
With that intro, let us start with the set {[1,2,3,4]}. We act on this set by the following sets of cycles:
The set {(4)}. This does nothing leaving us with
{[1,2,3,4]}.
We act on this set with the pair of cycles, {(3),(43)}. This gives us
{ [1,2,3,4], [1,2,4,3] },
a set with two elements. We act on this second set with the cycles:
{(2),(32),(432)}. We have
(2) { [1,2,3,4], [1,2,4,3] } = { [1,2,3,4], [1,2,4,3] }
(32) { [1,2,3,4], [1,2,4,3] } = { [1,3,2,4], [1,3,4,2] }
(432) { [1,2,3,4], [1,2,4,3] } = { [1,4,2,3], [1,4,3,2] }
Writing these out, we have a set of 6 tuples:
{ [1,2,3,4], [1,2,4,3], [1,3,2,4], [1,3,4,2 [1,4,2,3], [1,4,3,2] }
Lastly we hit this set with the cycles {(1),(21),(321),(4321)}. This will give us 24 tuples which are the 4x6 = 24 permutations of S4 - all in lexicographic order!
void permute(string str,int index)
{
if(index == str.size())
{
cout<<str<<" ";
return;
}
else
{
for(int j=index;j<str.size();j++)
{
if(str[index] <= str[j]) // swap only in sorted order
swap(str[j],str[index]);
permute(str,index+1);
if(str[index] <= str[j]) // swap only in sorted order
swap(str[j],str[index]);
}
}
}
int main()
{
int t;
string str;
scanf("%d",&t);
while(t--){
// scanf("%d",&n);
cin>>str;
sort(str.begin(),str.end());
permute(str,0);
cout<<endl;
}
return 0;
}
from itertools import combinations
S,k = input().split()
for i in list(range(int(k)+1))[1:]:
for e in combinations(sorted(S),i ):
print(''.join(e))

Can not print properly a quicksort arranged matrix

I can not properly print the steps given by the quicksort algorithm. This function works when N=1, which means that the values in the matrix only repeat once, but for N>1 it does not print it properly.
This is for a program I am writing to represent the different sorting algorithms steps with the console.
void quicksort(int *target, int left, int right) {
char charac[MAX*N][MAX]; // this is the array I am going to print on screen
if(left >= right)
return;
int i = left, j = right;
int tmp, pivot = target[i];
for(;;) {
while(target[i] < pivot)
i++;
while(pivot < target[j])
j--;
if(i >= j)
break;
tmp = target[i];
target[i] = target[j];
target[j] = tmp;
i++; j--; //normal quicksort until here
for(int k=0;k<MAX*N;k++){ /*Here begin two loops that put the cursor on a certain point on the screen and then gives values to char[][]*/
GotoXY(k+30,5);
for(int l=0;l<MAX;l++){
If(l<target[k]) // if the value of the given vector is lower than l writes a space
charac[k][l]=32;
else
charac [k][l]=219; // else a block
printf("%c ",charac[k][l]); // print the block or space
GotoXY(k+35,5+l); // go to the next point of the column
}
printf("\n");
}
system("cls"); // clear the screen for the next graph
}
quicksort(target, left, i-1);
quicksort(target, j+1, right);
}
I expect to sort the values properly even if they are repeated but the result are not even close to that.
Here it is for N=1 at the beginning:
At the end:
With N=2 it is generated properly:
But this is the result:
It is not even close to something fine.
Thanks for your time.

Kth Ranked Element Among 2 Unsorted Arrays

Let us suppose we have two arrays A[] and B[]. Each array contains n distinct integers which are not sorted. We need to find kth ranked element in the union of the 2 arrays in the most efficient way possible.
(Please dont post answers about merging the arrays and then sorting them to return kth index in the merged array)
You can use the selection algorithm to find the Kth item, in O(N) time, where N is the sum of the sizes of the arrays. Obviously, you treat the two arrays as a single large array.
Union of arrays can be done in linear time. I am skipping that part.
You can use the partition() algorithm which is used in the quick sort. In quick sort, the function will have to recurse two branches. However here we will just conditionally invoke the recursive call and thus only 1-branched recursion.
Main concept: partition() will place the chosen PIVOT element at its appropriate sorted position. Hence we can use this property to select that half of the array in which we are interested and just recurse on that half. This will prevent us from sorting the entire array.
I have written the below code based on the above concept. Assumption rank = 0 implies the smallest element in the array.
void swap (int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int partition (int a[], int start, int end)
{
/* choose a fixed pivot for now */
int pivot = a[end];
int i = start, j;
for (j = start; j <= end-1; j++) {
if (a[j] < pivot) {
swap (&a[i], &a[j]);
i++;
}
}
/* Now swap the ith element with the pivot */
swap (&a[i], &a[end]);
return i;
}
int find_k_rank (int a[], int start, int end, int k)
{
int x = partition (a, start, end);
if (x == k) {
return a[x];
} else if (k < x) {
return find_k_rank (a, start, x-1, k);
} else {
return find_k_rank (a, x+1, end, k);
}
}
int main()
{
int a[] = {10,2,7,4,8,3,1,5,9,6};
int N = 10;
int rank = 3;
printf ("%d\n", find_k_rank (a, 0, N-1, rank));
}

Swaps and Comparisons in Quicksort

I think I have managed to figure the comparisons but I am trying to figure out how can I count the numbers of swaps. I have a problem with the value of swapcounter and the recursion. Any ideas?
int quicksort (int nums[],int n,int left,int right){//quicksort takes an array, the leftmost index and the rightmost index
int swapCounter=0;
int i=left,j=right,temp;
int comparisonCounter = 0;
int pivot = nums[(left + right) / 2];
/* partition */
while(i<=j){
comparisonCounter++;
while(nums[i]<=pivot)
i++;
while(nums[j]>pivot)
j--;
if(i<=j){
temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
i++;
j--;
swapCounter++;
}
}
/* recursion */
if (left < j)
comparisonCounter+=quicksort(nums,n, left, j);
if (i < right)
comparisonCounter+=quicksort(nums,n, i, right);
printf("\nSwaps=%d\n",swapCounter);
return comparisonCounter;
}
You can:
Make swapcounter global.
Make the function take a pointer to the variable.
Make the function call another function to do the counting, thus making maintaining the counter state Someone Else's problem.

Sequential Merge Sort in C

I am trying to re-write a recursive Merge Sort like
void MergeSort(int* data, int size){
int half=size/2;
if (size > 1) {
MergeSort(data, half);
MergeSort(data+half, half);
Merge(data, size);
}
}
in which
void Merge(int* data, int size){
int cnt;
int cntLow=0;
int half=size/2;
int cntHigh=half;
int* sorted;
sorted = (int*) malloc(size*sizeof(int));
for (cnt=0; cnt<size; cnt++){
if (cntLow == half)
sorted[cnt] = data[cntHigh++];
else if (cntHigh == size)
sorted[cnt] = data[cntLow++];
else if (data[cntLow] <= data[cntHigh])
sorted[cnt] = data[cntLow++];
else
sorted[cnt] = data[cntHigh++];
}
for (cnt=0; cnt<size; cnt++)
data[cnt] = sorted[cnt];
free(sorted);
}
to a non-recursive call. So I wrote the function
void MergeSort_NonRecursive(int* data, int size){
int i;
int j;
for (i=size; i>0; i=i/2){
for (j=0; j<i; j++){
Merge(data + j*size/i, size/i);
}
}
}
which apparently works for sequences of size $2^n$. However, when I run it in sequences of size different than $2^n$, it does not sort right, so in some point of MergeSort_NonRecursive, my code I must be mistaken.
So where did I do wrong (in MergeSort_NonRecursive)? (also, I need to use the Merge funcion).
Thanks in advance.
Since size is an int, size/2 truncates your quotient.
e.g. if size=4, size/2 = 2. if size=5, size/2 = 2. if size=6, size/2 = 3.
So for a size of 5, you want the first MergeSort recursive call to operator on size/2 elements (i.e. the first 3), and the second call to operate on the remaining 2 elements.
You can say e.g.
int half = size/2; //size = 5: half = 2
int rest = size - half; //rest = 3
so:
void MergeSort(int* data, int size){
int half=size/2;
int rest = size-half;
if (size > 1) {
MergeSort(data, half);
MergeSort(data+half, rest); //changed this line
Merge(data, size);
}
}
Edit:
Looks like you changed the question slightly, after I posted. The general idea still stands: When you divide an int by another int, the quotient is truncated.
In your MergeSort_NonRecursive, you're dividing ints in a number of places, e.g. i=i/2, j*size/i, size/i. Pay attention to the values that you would get.

Resources