A permutation of integers from 1 to n is a sequence a1, a2, ..., an, such that each integer from 1 to n is appeared in the sequence exactly once.
Two integers in а permutation form an inversion, when the bigger one is before the smaller one.
As an example, in the permutation 4 2 7 1 5 6 3, there are 10 inversions in total. They are the following pairs: 4–2, 4–1, 4–3, 2–1, 7–1, 7–5, 7–6, 7–3, 5–3, 6–3.
Input n and array[n] 2<=n<=100,000
First I solved problem with bubble sorting but then i met time complexity problem.
Second I solved it mergesort but I didn't do well
Here is my cord
#include <stdio.h>
#include <malloc.h>
int n;
void sizein(){
scanf("%d",&n);
}
int count=0;
static void merge(int data[],int p,int q,int r){
int i,j,l;
int k=p;
int sorted[n];
for(i=p,j=q+1;i<=q&&j<=r;){
sorted[k++]=(data[i]<=data[j]) ? data[i++]:data[j++];
if(data[i>data[j]]){
count+=q-i;
}
}
if(i>q){
for(l=j;l<=r;l++,k++){
sorted[k]=data[l];
}
}
else{
for(l=i;l<=q;l++,k++){
sorted[k]=data[l];
}
}
for(l=p;l<=r;l++){
data[l]=sorted[l];
}
}
void merge_sort(int data[],int p,int r){
if(p<r){
int q=(p+r)/2;
merge_sort(data,p,q);
merge_sort(data,q+1,r);
merge(data,p,q,r);
}
}
int main(void){
int i;
int data[n];
for(i=0;i<n;i++){
scanf("%d",&data[i]);
}
merge_sort(data,0,n);
printf("%d",count);
return 0;
}
Where should i fix it
I cannot find some implementation bits in your code that divides the arrays into sub-arrays based on the index(as quick sort sorts based on value)
kindly have a look at the code provided below
int q = p + (r - l) / 2;//recommended to be used in the function mergesort
int q=(p+r)/2;//your implementation
try this code for your function part as my code runs well with over half a million values, I cannot clearly see any subarray to which values are copied in your implementation of the function merge I have added comments to make it easier for you to understand, the terminology of the variables are slightly different.
refer "ANANY LEVETIN-INTRODUCTION TO THE DESIGN AND ANALYSIS OF ALGORITHS" book for a vivid explanation on this algorithm
Have a look and try this
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
int L[n1], R[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];
/* Merge the temp arrays back into arr[l..r]*/
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
}
else {
arr[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there
are any */
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there
are any */
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r)
{
if (l < r) {
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l + (r - l) / 2;
// Sort first and second halves
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
}
/* Driver code */
int main()
{
int arr[] = { 12, 11, 13, 5, 6, 7 };
int arr_size = sizeof(arr) / sizeof(arr[0]);
printf("Given array is \n");
//printArray(arr, arr_size);
mergeSort(arr, 0, arr_size - 1);
printf("\nSorted array is \n");
//printArray(arr, arr_size);
return 0;
}
After reading the code for some time I still can not say I understand the idea of counting the inversions. However, I can point out three things in it which seem incorrect to me.
First, I can't see where you call the sizein() function to initialize the n variable.
The second problem is the condition here:
if(data[i>data[j]]){
count+=q-i;
}
You compare the index i to the value of a data item data[j] which looks strange. Even worse, if you were to sort an array of geometric figures or an array of songs it could be just impossible due to incompatibility of the types of data to be compared. What's even worse, even if comparison succeedes, as in the case of an int index and an int value in data[],the result of comparison is an int value 1 if comparison is satisfied or 0 otherwise. As a result this condition will resolve to
if(data[0]){
count+=q-i;
}
or to
if(data[1]){
count+=q-i;
}
which is obviously wrong.
The correct code looks like this:
if (data[i] > data[j]) {
count += q - i;
}
The error would be more apparent if you left appropriate spacing between operators and their operands.
Yet another error lurks in the call to merge_sort(). First, you fill the data[] array with this loop:
for (i = 0; i < n; i ++) {
scanf("%d", &data[i]);
}
Obviously, you fill an n-items array with data at indices from 0 through n-1.
Then you call the merge-sorting routine:
merge_sort( data, 0, n);
which suggests the parameter p is the index of the first item or the part to be sorted and q is one-past-the last item. However, this disagrees with recursive calls:
merge_sort( data, p, q);
merge_sort( data, q+1, r);
Setting q as the ending index in the first call and q+1 as the starting index in the second suggests the ending index is inclusive, that is, it is the position of the last item in the segment to be sorted. Otherwise the two calls would leave the item data[q] unsorted. This also follows from internal loops, which continue while i <= q or whle l <= r etc.
So the initial call shouldn't be
merge_sort( data, 0, n);
but rather
merge_sort( data, 0, n-1);
Related
This is my code for merge sort in C. I'm not able to understand what the issue is here. My knowledge of pointers is not that much. The merge function takes in 2 arrays and merges them. the sort function is a recursive function which is supposed to sort the array.
int * merge(int *fir, int n, int *sec, int m){
int res[m+n];
int x=0, y=0;
for(int i = 0; i < m+n; i++){
if(*(fir+x)<=*(sec+y)){
res[i] = *(fir+x);
x++;
}else{
res[i] = *(sec+y);
y++;
}
}
return res;
}
int * sort(int A[], int n){
if(n == 1){
return A;
}
int mid = n/2;
int AL[mid], AR[n-mid];
for(int i = 0; i < mid; i++){
AL[i] = A[i];
}
for(int i = 0; i < n-mid; i++){
AR[i] = A[i+mid];
}
int *BL, *BR;
BL = sort(AL, mid);
BR = sort(AR, n-mid);
return(merge(BL, mid, BR, n-mid));
}
int main(){
int n;
scanf("%d", &n);
int A[n];
for(int i = 0; i < n; i++){
scanf("%d", &A[i]);
}
int *sortedArray;
sortedArray = sort(A, n);
for(int i = 0; i < n; i++){
printf("%d ", *(sortedArray+i));
}
return 0;
}
And this is the output
q8.c:16:9: warning: address of stack memory associated with local variable 'res' returned [-Wreturn-stack-address]
return res;
^~~
1 warning generated.
7
23 12 56 67 11 99 97
97 32766 539779418 32767 -2002825496 32767 6 %```
There are two issues here: First, you merge your partial arrays into a temporary local array, which yoes out of bounds after you return from merge. The pointer you return points to invlid memory. That's what the warning about.
Second, you don't check whether you are reading beyond the limits of the partial arrays when you merge: The condition x < n must be true when you access fir, likewise for y < m and sec.
You are also causing confusion by returning a pointer to the first element of the sorted or merged arrays. That suggests that you create new sorted and merged arrays (and that's what you try to do in merge). This is okay for garbage-collected morern languages, but C doesn't work that way.
In C, if you need new memory, you must allocate it and later free it explicitly. In a recursive function like yours, this is tedious, because you are interested only in the final sorted array, not in the intermediate results. Therefore, C sorting algorithms usually work "in place": The same memory is used thoughout the sorting and elements are swapped. The original order of the elements is lost unless you make a copy before sorting.
For merge sort, you need auxiliary memory. In your case, you use the temporary arrays AL and AR, which are copies of the contents of the original array, A. Now when you merge, you can merge AL and AR back into A.
So istead of creating a ephemeral local array, pass in A so that it can be filled with the sorted elements:
void sort(int A[], int n)
{
if (n > 1) {
int mid = n / 2;
int AL[mid], AR[n - mid];
for (int i = 0; i < mid; i++) AL[i] = A[i];
for (int i = 0; i < n - mid; i++) AR[i] = A[i + mid];
sort(AL, mid);
sort(AR, n - mid);
merge(A, AL, mid, AR, n - mid);
}
}
Your merge function is now very similar to the one you has before, only that you have the result array as parameter and that you must catch the out-of-bound cases before accessing elements with [].
void merge(int *res, const int *fir, int n, const int *sec, int m)
{
int x = 0, y = 0;
for(int i = 0; i < m + n; i++) {
if (x == n) res[i] = sec[y++];
else if (y == m) res[i] = fir[x++];
else if (fir[x] <= sec[y]) res[i] = fir[x++];
else res[i] = sec[y++];
}
}
Wrong output!
I have tried each and every condition but failed to get the real result
I tried to accomplish this from the clrs book pseudo-code but I failed.
I am trying to write merge sort using iterators to implement myself pseudo-code in c language, but for some reason, this code is compiling but the outcome is not sorted. Can someone figure out what is wrong with it? it seems perfectly fine to my untrained eyes.
#include <stdio.h>
#include<math.h>
#include <stdlib.h>
int a[] = {5,3,65,6,7,3,7,8};
void print_array(int a[], int size)
{
int i;
for(i = 0;i < size;i++)
{
printf("%d ",a[i]);
}
}
void merge(int a[],int p,int q,int r)
{
int n1,n2,i,j,k;
n1 = q - p + 1;
n2 = r - q;
int l[n1];
int m[n2];
for(i = 0; i < n1; i++)
l[i] = a[i+p];
for(j = 0; j < n2; j++)
m[j] = a[q+1+j];
l[n1] = 9999999;
m[n2] = 9999999;
i = 0;
j = 0;
for(k = p;k < r; k++)
{
if(l[i] <= m[j])
{
a[k] = l[i];
i = i+1;
}
else
{
a[k] = m[j];
j = j+1;
}
}
}
void merge_sort(int a[],int p,int r)
{
if(p < r)
{
int q = floor((p + r) / 2);
merge_sort(a,p,q);
merge_sort(a,q+1,r);
merge(a,p,q,r);
}
}
int main()
{
int size = (sizeof(a) / sizeof(a[0]));
print_array(a,size);
printf("\n");
merge_sort(a,0,size);
print_array(a,size);
return 0;
}
//for this input out put is showing
//-1 -1 3 3 3 -1 6 7
Please pay attention to array bounds and sizes:
Your parameter r is not the size of the array, but the index of the rightmost element, so you should call merge_sort(a, 0, size - 1);.
When you want to use a large sentinel value, after the actual array, you must allocate space for it, so:
int l[n1];
int m[n2];
Because your value r is the index of the last element, you must consider it when merging and your loop condition should be for(k = p; k <= r; k++).
(Not really a problem, but you don't need to use floor like in JavaScript. When a and b are integers, a / b will perform a division that results in an integer.)
In C, arrays (and ranges in general) have inclusive lower bounds and exclusive upper bounds: lo is the first valid index and hi is the first invalid index after the valid range. For array indices, lo and hi are zero and the array size.
Embrace this convention. The C indices lead to the following style:
The length of a range is hi - lo;
Forward loops are for (i = lo; i < hi; i++);
Adjacent ranges share the hi and lo values.
For example, in your merge function the middle value p would be the first value in the right range, but also the exclusive upper bound of the left range.
If pseudocode or code in other languages uses one-based indices, I recommend translating it to the zero-based, exclusive upper-bound style of C. After a while, you'll get suspicious of spurious - 1's and <='s. :)
How can one iterate through order of execution?
I am developing a piece of software that have several steps to compute over some data, and i was thinking in may changing the order of those steps pragmatically so i can check what would be the best order for some data.
Let me exemplify: I have let's say 3 steps (it's actually more):
stepA(data);
stepB(data);
stepC(data);
And I want a contraption that allow me to walk thought every permutation of those steps and then check results. Something like that:
data = originalData; i=0;
while (someMagic(&data,[stepA,stepB,stepC],i++)){
checkResults(data);
data = originalData;
}
then someMagic execute A,B then C on i==0. A, C then B on i==1. B, A then C on i==2 and so on.
You can use function pointers, maybe something like the following:
typedef void (*func)(void *data);
int someMagic(void *data, func *func_list, int i) {
switch (i) {
case 0:
func_list[0](data);
func_list[1](data);
func_list[2](data);
break;
case 1:
func_list[0](data);
func_list[2](data);
func_list[1](data);
break;
case 2:
func_list[1](data);
func_list[0](data);
func_list[2](data);
break;
default: return 0;
}
return 1;
}
func steps[3] = {
stepA,
stepB,
stepC
}
while (someMagic(&data, steps, i++)) {
....
}
The key is to find a way to iterate over the set of permutations of the [0, n[ integer interval.
A permutation (in the mathematical meaning) can be seen as a bijection of [0, n[ into itself and can be represented by the image of this permutation, applied to [0, n[.
for example, consider the permutation of [0, 3[:
0 -> 1
1 -> 2
2 -> 0
it can be seen as the tuple (1, 2, 0), which in C, translate naturally to the array of integers permutation = (int []){1, 2, 0};.
Suppose you have an array of function pointers steps, then for each permutation, you'll then want to call steps[permutation[i]], for each value of i in [0, n[.
The following code implements this algorithm:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static void stepA(int data) { printf("%d: %s\n", data, __func__); }
static void stepB(int data) { printf("%d: %s\n", data, __func__); }
static void stepC(int data) { printf("%d: %s\n", data, __func__); }
static void (* const steps[])(int) = {stepA, stepB, stepC,};
static int fact(int n) { return n == 0 ? 1 : fact(n - 1) * n; }
static int compare_int(const void *pa, const void *pb)
{
return *(const int *)pa - *(const int *)pb;
}
static void get_next_permutation(int tab[], size_t n)
{
int tmp;
unsigned i;
unsigned j;
unsigned k;
/* to find the next permutation in the lexicographic order
* source: question 4 (in french, sorry ^^) of
* https://liris.cnrs.fr/~aparreau/Teaching/INF233/TP2-permutation.pdf
. */
/* 1. find the biggest index i for which tab[i] < tab[i+1] */
for (k = 0; k < n - 1; k++)
if (tab[k] < tab[k + 1])
i = k;
/* 2. Find the index j of the smallest element, bigger than tab[i],
* located after i */
j = i + 1;
for (k = i + 1; k < n; k++)
if (tab[k] > tab[i] && tab[k] < tab[j])
j = k;
/* 3. Swap the elements of index i and j */
tmp = tab[i];
tab[i] = tab[j];
tab[j] = tmp;
/* 4. Sort the array in ascending order, after index i */
qsort(tab + i + 1, n - (i + 1), sizeof(*tab), compare_int);
}
int main(void)
{
int n = sizeof(steps) / sizeof(*steps);
int j;
int i;
int permutation[n];
int f = fact(n);
/* first permutation is identity */
for (i = 0; i < n; i++)
permutation[i] = i;
for (j = 0; j < f; j++) {
for (i = 0; i < n; i++)
steps[permutation[i]](i);
if (j != f - 1)
get_next_permutation(permutation, n);
}
return EXIT_SUCCESS;
}
The outer loop in main, indexed by j, iterates over all the n! permutations, while the inner one, indexed by i, iterates overs the n steps.
The get_next_permutation modifies the permutation array in place, to obtain the next permutation in the lexicographical order.
Note that it doesn't work when the permutation in input is the last one (n - 1, ..., 1, 0), hence the if (j != f - 1) test.
One could enhance it to detect this case (i isn't set) and to put the first permutation (0, 1, ..., n - 1) into the permutation array.
The code can be compiled with:
gcc main.c -o main -Wall -Wextra -Werror -O0 -g3
And I strongly suggest using valgrind as a way to detect off-by-one errors.
EDIT: I just realized I didn't answer the OP's question precisely. The someMagic() function would allow a direct access to the i-th permutation, while my algorithm only allows to compute the successor in the lexicographic order. But if the aim is to iterate on all the permutations, it will work fine. Otherwise, maybe an answer like this one should match the requirement.
I've come to a solution that is simple enough:
void stepA(STRUCT_NAME *data);
void stepB(STRUCT_NAME *data);
void stepC(STRUCT_NAME *data);
typedef void (*check)(STRUCT_NAME *data);
void swap(check *x, check *y) {
check temp;
temp = *x;
*x = *y;
*y = temp;
}
void permute(check *a, int l, int r,STRUCT_NAME *data) {
int i, j = 0, score;
HAND_T *copy, *copy2, *best_order = NULL;
if (l == r) {
j = 0;
while (j <= r) a[j++](data);
} else {
for (i = l; i <= r; i++) {
swap((a + l), (a + i));
permute(a, l + 1, r, data);
swap((a + l), (a + i));
}
}
}
check checks[3] = {
stepA,
stepB,
stepC,
};
int main(void){
...
permute(checks,0,2,data)
}
#include <stdio.h>
#define ARRAY_SIZE 10
void lomuto (int A[], int l, int r, int smallerAtLeft)
{
if (smallerAtLeft == 1) //move elements smaller than pivot to the left and the greater ones to the right
{
int tmp, tmp2,pivot,i,j;
pivot = A[r];
i = l-1;
for (j =0; j<r-1; j++)
{
if (A[j] <= pivot)
{
i++;
tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
}
tmp2 = A[i+1];
A[i+1] = A[r];
A[r] = tmp2;
}
if (smallerAtLeft == 0) //move elements smaller than pivot to the right and the greater ones to the left
{
int tmp3, tmp4,pivot,i,j;
pivot = A[r];
i = l-1;
for (j=0; j<r-1; j++)
{
if (A[j]>= pivot)
{
i++;
tmp3 = A[i];
A[i] = A[j];
A[j] = tmp3;
}
}
tmp4 = A[i+1];
A[i+1] = A[r];
A[r] = tmp4;
}
}
void quicksort (int A[], int l, int r, int ascending)
{
lomuto (A,l,r,ascending);
}
int main()
{
int testarray;
int testArray[ARRAY_SIZE] = {4, 2, 5, 3, 6, 7, 8, 1, 0};
quicksort (testarray,0,8,1);
return testarray;
}
Good evening.
Usually I search almost every forum and deepest threads for dubiety in my codes.
But this time I did not found an answer that could help me. I would be so thankful if anyone could tell my why the code-exe stops working but during compiling there is no error showing onscreen.
We have to implement the quicksort algorithm with the lomuto-partitioning. If the variable "smallerAtLeft" ist equal to 1, the array should be ordered by an increasing property and if its equal to 0 decreasingly.
Furthermore we have to implement to void functions like you see in the code. The "lomuto-fct" and the "quicksort-fct" that contains the lomuto one.
Maybe this Reverse-Lomuto-Thread will help some other people too in the future..
I don't think you understand what the return value from main is and what it's used for. It is usually an indicator of success and failure, with the typical values 0 for success and a small positive value for failure. There are even macros defined for this purpose in the <stdlib.h> header file: EXIT_SUCCESS and EXIT_FAILURE.
If you want to see the sorted array you need to print it:
printf("Sorted array = {");
for (unsigned i = 0; i < ARRAY_SIZE; ++i)
{
printf(" %d", testArray[i]);
}
printf(" }\n");
That of course requires you to pass the actual array to your sorting function.
I am using a recursive function (from one of the posts here) to enumerate all combinations of selecting k items out of n. I have modified this function to save and return the enumerated combinations in a 2-dimensional array (which is passed to the function as arrPtr). I call this recursive function in a for loop (from main) for different values of k (k from 1 to n-1) to generate all the combinations for any value of n and k. Now, with 'count', being defined as static integer, the function generates all the combinations for k=1 and then goes to k=2, but then stops at one point. The reason is that I'm using the variable 'count' as an index for rows in arrPtr. Since it is a static variable, it does not reset to 0 when the function is called for the other rounds (k=2,3,4 etc.). So it results in access violation for arrPtr after a certain point. When I remove 'static' for 'count', it generates all the combinations for different values of k, but only the last combination in each round is saved in arrPtr (again due to removing 'static'). How can I save each generated combination in a row in arrPtr so I can get (and return) all of the combinations saved in one place pointed to by arrPtr at the end?
I tried to pass the index for rows in arrPtr to the function using pass by reference (passing the address of the variable) but that gets into trouble when the recursive function calls itself.
I searched a lot and found similar topics here (e.g., returning arrays from recursive functions), but they are mostly for other programming languages (I only use C; not even C++). I have spent many many hours on solving this and really need help now. Thank you in advance.
int** nCk(int n,int loopno,int ini,int *a,int **arrPtr, int k)
{
static int count=0;
int total; // equal to the total number of combinations of nCk
int i,j;
total = factorial(n)/(factorial(n-k)*factorial(k));
loopno--;
if(loopno<0)
{
a[k-1]=ini;
for(j=0;j<k;j++)
{
printf("%d,",a[j]);
arrPtr[count][j]=a[j];
}
printf("count =%d\n",count);
count++;
return 0;
}
for(i=ini;i<=n-loopno-1;i++)
{
a[k-1-loopno]=i+1;
nCk(n,loopno,i+1,a,arrPtr,k);
}
if(ini==0)
return arrPtr; // arrPtr is in fact an array of pointers, where each pointer points to an array of size k (one of the combinations of selecting k out of n elements
else
return 0;
}
what i understand is
you want to calculate the combination for any value of n and k in nCk,
define a factorial() function outside and
define a combi() function ... which calculates Combination value of n and k variables
both function before defining the main() function... that way you can avoid declaration and then defining (i mean avoid extra lines of code).
here is the code for combi() function
function combi(int n , int k){
int nFact, kFact, n_kFact, p;
int comb;
nFact=factorial(n);
kFact=factorial(k);
p=n-k;
n_kFact=factorial(p);
comb= nFact / ((n_kFact) * kFact);
return comb;
}
you can call this function in your main function .... use for loop to store the combination value for relative n and k .... thus you will get what you need .... also pass pointer or
&array[0][0]
i.e. starting address for the array... so that you can access that array anywhere in the program.
hope this may help you. thanks
GCC 4.7.3: gcc -Wall -Wextra -std=c99 enum-nck.c
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// Textbook recursive definition of, n-choose-k.
int nCk(int n, int k) {
assert(0 < k && k <= n);
if (k == n) { return 1; }
if (k == 1) { return n; }
return nCk(n - 1, k) + nCk(n - 1, k - 1);
}
// But you asked for a procedure to enumerate all the combinations.
void aux_enum_nCk(int n, int k, int* all, int* j, int a[], int i) {
a[i] = n;
if (i == k - 1) {
memcpy(&all[*j], &a[0], k * sizeof(int));
*j += k;
return;
}
for (int c = n - 1; c > 0; --c) {
aux_enum_nCk(c, k, all, j, a, i + 1);
}
}
void enum_nCk(int n, int k, int* arr) {
assert(0 < k && k <= n);
int j = 0;
int a[k];
for (int i = 0; i < k; ++i) { a[i] = 0; }
for (int c = n; c >= n - k - 1; --c) {
aux_enum_nCk(c, k, arr, &j, a, 0);
}
}
int main(int argc, char* argv[]) {
int n = 7;
int k = 3;
int x = nCk(n, k);
printf("%d choose %d = %d\n", n, k, x);
int arr[x][k];
enum_nCk(n, k, &arr[0][0]);
for (int i = 0; i < x; ++i) {
for (int j = 0; j < k; ++j) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}