Sort elements in array C [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am trying to create a program that will sort elements in 4 steps (read elements - print elements - sort them - print the sorted version).
I need help with the sorting (third) part.
Here is my code:
/*
* A simple program to sort numbers in correct order
*/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
#define SENTINEL -99
int main()
{
int tableFill(int a[], int max);
void tableInsert(int a[], int num, int val);
void tableSort(int a, int n);
void tablePrint(int a, int n);
int num;
int table[MAXSIZE];
int max;
num=tableFill(table,MAXSIZE);
return EXIT_SUCCESS;
}
int tableFill(int a[], int max)
{
int r; // input from scanf
int next; // score from user
int cnt = 0;
printf("Enter the numbers! \n");
while ((r=scanf("%i", &next))!= EOF && cnt<max)
{
if (r == 0) //invalid input data
{
printf("Nonnumeric data entered. Please enter a number. \n");
while (getchar()!= '\n'); // flush invalid data
}
else
a[cnt++]=next;
}
if(r==1) //another value was read but the array is full
printf("Error - too many values. Array size %i.\n", max);
}
void tableInsert (int a[], int num, int val)
{
int pos;
for(pos = num; pos>0 && val<a [pos-1]; pos--)
a [pos] = a [pos -1];
a[pos] = val;
}
void tableSort(int a, int n)
{
}
void tablePrint(int a, int n)
{
int i;
for(i = n -1; i>=0; i++)
{
printf("%i\n",a[i]);
}
}
SOLUTION
I used David C. Rankin's solution and fixed my code. This is my final version:
/*
* A simple program to sort numbers in the correct order
*/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10 //max elements in array
int main () {
int tableFill (int a[], int max);
void tableSort (int a[], int n);
void tablePrint (const a[], int n);
int arr[MAXSIZE]; //creating an array
int n = tableFill (arr, MAXSIZE); //declaring variable to work with array
tablePrint (arr, n); //prints unsorted values
printf ("Here is your sorted array:\n");
tableSort (arr, n); // sorts values in order
tablePrint (arr, n); // prints sorted values
return 0;
}
// read values from stdin into array up to 'max' values
int tableFill(int a[], int max) {
int r; // input from scanf
int next; // score from user
int cnt = 0; // loop variable
printf("Enter the numbers! \n");
while ((r=scanf("%i", &next))!= EOF && cnt<max)
{
if (r == 0) //invalid input data
{
printf("Nonnumeric data entered. Please enter a number. \n");
while (getchar()!= '\n'); // flush invalid data
}
else
a[cnt++]=next;
}
if(r==1) //another value was read but the array is full
printf("Error - too many values. Array size %i.\n", max);
return cnt;
}
// swap values at array indexes 'i' and 'j'.
void tableSwap (int a[], int i, int min_index)
{
int tmp = a[i];
a[i] = a[min_index];
a[min_index] = tmp;
}
//sort array
void tableSort (int a[], int n)
{
void tableSwap (int a[], int i, int min_index);
int i, j; //loop counters
int min, min_index; //adjusting variables for loops
for (i = 0; i <= n - 2; i++) {
min = a[i];
min_index = i;
for (j = i + 1; j <= n - 1; j++) {
if (a[j] < min){
min = a[j];
min_index = j;
}
}
tableSwap (a, i, min_index);
}
}
//print all elements in array.
void tablePrint (const a[], int n)
{
int i; //variable for print
for (i = 0; i < n; i++)
printf ("%d ", a[i]);
printf ("\n");
}

As pointed out in the comments, qsort is the defacto standard sort routine contained in the C standard library. It is incredibly flexible and incredibly fast due to using a combination of sorting methods optimized for the range of data being sorted. Beginning C users generally have difficulty writing the compare functions because it involves the use of pointers. Just take the time needed to write a few compare functions are get comfortable with it -- it will save you a lot of grief in the long run.
That said, before looking at both alternative sorts, C-style generally uses lower-case for variable and function names. Leave camelCase names for C++. See e.g. NASA - C Style Guide, 1994
Sorting with the old-slow bubblesort. For sorting anything with greater than 100 elements, the efficiency of the bubblesort craters. It is hundreds of times slower than qsort for any large number of element. That being said, putting a bubblesort together that incorporates your tableswap requirement is straightforward:
/** sort array using slow old bubblesort */
void tablebubblesort (int *a, int n)
{
int i, j;
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - i - 1; j++) {
if (a[j] > a[j + 1]) /* For decreasing order use < */
tableswap (a, n, j, j+1);
}
}
}
Your tableswap function will look similar to:
/** swap values at array indexes 'i' and 'j'. */
void tableswap (int *a, int n, int i, int j)
{
if (i >= n || j >= n) return;
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
Simply call the function in your code with tablebubblesort (arr, n);
qsort is even simpler. The full function (you really don't need a separate function) is:
/** qsort the array */
void tablesort (int *a, int n, size_t sz)
{
qsort (a, n, sz, compare);
}
It requires a compare function which is simply:
/** qsort compare function */
int compare (const void *a, const void *b)
{
return (*(int *)a - *(int *)b);
}
Don't let you eyes roll over in your head simply because you see const void *a, etc.. it is really straight forward. Your a and b pointers represent a pointer to individual integers in the array (e.g if say a[1] = 5, the pointer is just &a[1] the address of the element). So taking the compare function apart, knowing you are just passing the address of an element (e.g. integer pointers) to compare, you would write it long-hand as follows:
int compare (const void *a, const void *b)
{
int *value1 = (int *)a; /* cast each to int pointer */
int *value2 = (int *)b;
if (*value1 > *value2) /* compare dereferenced values */
return 1;
if (*value1 < *value2)
return -1;
return 0;
}
Or, if it makes you happier, you can cast and dereference all at once and then just operate on integer values:
int compare (const void *a, const void *b)
{
int value1 = *(int *)a;
int value2 = *(int *)b;
if (value1 > value2)
return 1;
if (value1 < value2)
return -1;
return 0;
}
Either way it is the same. (arguably, the first is the most proper because it avoid the "appearance" of type punning pointers and derefencing void values, but that is for another day) There is no magic, just do it enough times for integers, strings, structs, etc.. until it sinks in. It's more than worth the time.
Putting the rest of the pieces together, you could meet your requirements with something similar to the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXI 128
int tablefill (int *a, int max);
void tableinsert (int *a, int *n, int max, int num, int val);
void tableswap (int *a, int n, int i, int j);
void tablesort (int *a, int n, size_t sz);
void tablebubblesort (int *a, int n);
void tableprint (int *a, int n);
int compare (const void *a, const void *b);
int main (void) {
int arr[MAXI] = {0};
int n = 0;
printf ("enter array values ([ctrl+d] to end)\n");
n = tablefill (arr, MAXI);
tableprint (arr, n);
printf ("\ninsert '5' as the '2nd' element of array\n");
tableinsert (arr, &n, MAXI, 2, 5);
tableprint (arr, n);
printf ("\nswap indexes '1' and '3'\n");
tableswap (arr, n, 1, 3);
tableprint (arr, n);
printf ("\nsorted array\n");
#ifdef WQSORT
tablesort (arr, n, sizeof *arr); /* gcc -DWQSORT to use tablesort */
#else
tablebubblesort (arr, n);
#endif
tableprint (arr, n);
return 0;
}
/** read values from stdin into array up to 'max' values. */
int tablefill (int *a, int max)
{
int idx = 0, tmp;
while (idx + 1 < max && scanf ("%d", &tmp) == 1)
a[idx++] = tmp;
return idx;
}
/** insert 'val' as the 'num' element in 'a' ('num - 1' index),
* update 'n' to current number of elements.
*/
void tableinsert (int *a, int *n, int max, int num, int val)
{
if (num >= max || *n + 1 == max) return;
if (num >= *n) { a[num] = val; (*n)++; return; }
int i;
for (i = *n; i >= num; i--)
a[i] = a[i-1];
a[i] = val;
(*n)++;
}
/** swap values at array indexes 'i' and 'j'. */
void tableswap (int *a, int n, int i, int j)
{
if (i >= n || j >= n) return;
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
/** qsort the array */
void tablesort (int *a, int n, size_t sz)
{
qsort (a, n, sz, compare);
}
/** sort array using slow old bubblesort */
void tablebubblesort (int *a, int n)
{
int i, j;
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - i - 1; j++) {
if (a[j] > a[j + 1]) /* For decreasing order use < */
tableswap (a, n, j, j+1);
}
}
}
/** print all elements in array. */
void tableprint (int *a, int n)
{
if (!a) return;
int i;
for (i = 0; i < n; i++)
printf (" a[%2d] : %d\n", i, a[i]);
}
/** qsort compare function */
int compare (const void *a, const void *b)
{
return (*(int *)a - *(int *)b);
}
The code contains both the bubblesort and qsort version of the sort. You simply pass the define -DWQSORT to compile with the qsort code or compile without it for the bubblesort. e.g.
Compile Both Versions
$ gcc -Wall -Wextra -Ofast -o bin/array_fill array_fill.c
$ gcc -Wall -Wextra -Ofast -DWQSORT -o bin/array_fill_qsort array_fill.c
Example Use/Output
$ echo "1 4 2 3" | ./bin/array_fill
enter array values ([ctrl+d] to end)
a[ 0] : 1
a[ 1] : 4
a[ 2] : 2
a[ 3] : 3
insert '5' as the '2nd' element of array
a[ 0] : 1
a[ 1] : 5
a[ 2] : 4
a[ 3] : 2
a[ 4] : 3
swap indexes '1' and '3'
a[ 0] : 1
a[ 1] : 2
a[ 2] : 4
a[ 3] : 5
a[ 4] : 3
sorted array
a[ 0] : 1
a[ 1] : 2
a[ 2] : 3
a[ 3] : 4
a[ 4] : 5
$ echo "1 4 2 3" | ./bin/array_fill_qsort
<same outoput>
Look over all the code and let me know if you have questions. This is basic meat and potatoes C and you need to make sure you understand each line, and each character in each line. Take it slow.

Regarding
int tableFill(int a[], int max);
void tableInsert(int a[], int num, int val);
void tableSort(int a, int n);
void tablePrint(int a, int n);
You're declaring the prototypes inside main which is not usually done. They are usually declared in global scope so that they stay put till the end.
Regarding
int tableFill(int a[], int max)
You're not returning anything. Since you're dealing with the pointers you could change int to void.
Regarding
void tableInsert (int a[], int num, int val)
Ask yourself from where you are calling this function.
Regarding
void tableSort(int a, int n)
{
}
See this guide which explains sorts.
Regarding :
void tablePrint(int a, int n)
{
int i;
for(i = n -1; i>=0; i++)
{
printf("%i\n",a[i]);
}
}
Since you're printing an array,so one parameter to this function should be an array.

Related

static keyword not working in C (Visual Studio)

Question -
N numbers are entered by the user (N is also given by the user). Store the numbers in
an array. Write a C function which deletes all the second largest elements and
rearranges the array. The program should appropriately print the new array and the
value of N. For e.g if N=7 and the elements are 7 11 13 11 8 7 4 the output should be
N=5 and the array is 7 13 8 7 4
My Code -
#include<stdio.h>
int secondLargest(int arr[], int n);
int indexOfSecondLargest(int arr[], int n, int max2);
void deleteElement(int arr[], int n, int index);
void deleteSecondLargest(int arr[], int n);
void printArray(int arr[], int n);
int main()
{
static int n;
printf("Enter value of n \n");
scanf("%d", &n);
int arr[100];
printf("Enter n numbers \n");
for (int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
deleteSecondLargest(arr, n);
printf("New value of n = %d and the array is \n", n);
printArray(arr, n);
return 0;
}
int secondLargest(int arr[], int n)
{
int max1 = arr[0], max2 = arr[0];
for (int i = 0; i < n; i++)
{
if (arr[i] > max1)
{
max2 = max1;
max1 = arr[i];
}
if (arr[i] > max2 && arr[i] < max1)
{
max2 = arr[i];
}
}
return max2;
}
int indexOfSecondLargest(int arr[], int n, int max2)
{
for (int i = 0; i < n; i++)
{
if (arr[i] == max2)
{
return i;
}
}
return -1;
}
void deleteElement(int arr[], int n, int index)
{
for (int i = index; i < n - 1; i++)
{
arr[i] = arr[i+1];
}
n = n - 1;
}
void deleteSecondLargest(int arr[], int n)
{
int max2 = secondLargest(arr, n);
int index = indexOfSecondLargest(arr, n, max2);
while (index != -1)
{
deleteElement(arr, n, index);
index = indexOfSecondLargest(arr, n, max2);
}
}
void printArray(int arr[], int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
}
My Output -
Enter value of n
7
Enter n numbers
7 11 13 11 8 7 4
New value of n = 7 and the array is
7 13 8 7 4 4 4
Even though I am using static keyword before int n, the value of n is not getting updated to 5 in main() function. I even tried putting int n as a global variable but still it doesn't work.
Can someone help me ??
Adding static to int n; says “This n persists through all of program execution.” it does not say “This n is the only n in the whole program.” Where a parameter n is declared, as in void deleteElement(int arr[], int n, int index), that creates an n different from the n in main.
However, even if no parameter is declared with the name n, an n declared inside main is not visible in any other function. To use the same n throughout the program, you need to declare int n; or static int n; outside of any function, anywhere before the first function that uses n, and you need to not declare any other n.
That would likely solve this problem for you. However, it is bad practice to use external identifiers for objects. Instead, you should use int n; in main and modify deleteElement so that it provides main with the updated value. It could do this by returning an int instead of void, or you could modify deleteElement to take a pointer to an int instead of taking an int, by making the parameter int *n. Then you would have to use it inside the function as *n instead of n.

C malloc, realloc. How to remove single element from array.

I've got a homework to create 2 functions add which adds element to dynamic array (what i've done) and remove which removes indicated element from that array. I have a problem with that 2nd function. I have no clue how to code it.
PS. I can't use memmove().
#include <stdlib.h>
#include <stdio.h>
void print_array(int *tab, int n);
void add(int x, int y, int *tab, int idx);
void remove_element(int *tab, int idx, int array_length);
int main() {
int *tab = malloc(24*sizeof(*tab));
int idx = 0;
tab[idx++] = 44;
tab[idx++] = 82;
tab[idx++] = 57;
tab[idx++] = 77;
printf("Before insert\n");
print_array(tab, idx);
idx++;
add(7, 0, tab, idx);
printf("After insert\n");
print_array(tab, idx);
free(tab);
idx--;
printf("After delete\n");
remove_element(tab, 3, idx);
print_array(tab, idx);
free(tab);
return(0);
}
void print_array(int *tab, int n) {
int i;
for (i = 0; i < n; i++) {
printf("t[%d] = %d\n", i, tab[i]);
}
}
void add(int x, int y, int *tab, int idx) {
int i;
for (i = idx; i > y; i--) {
tab[i] = tab[i-1];
}
tab[y] = x;
}
void remove_element(int *tab, int idx, int array_length) {
void *tmp = realloc(tab, (array_length - 1) * sizeof(int) );
array_length = array_length - 1;
tab = tmp;
}
About your array you can keep information about its size (eg iSize) and the number of elements in use (eg iUse). iUse<=isize, of course.
When you need to add an element but the array is too small (iUse==iSize), you increase its size, add the element and increment iUse.
When you remove an element, you just decrement iUse and, if you can't use memmov, make a loop to move al higher elements down.

Function to sum all permutations

some time ago I wrote a program that prints all possible permutations of of a given array, even printing all partial arrays:
#define MAXARRAY 32
#include <stdio.h>
void combinations(int array[], int temp[], int start, int end, int index, int r);
void print_combinations(int array[], int n, int r){
int temp[r];
combinations(array, temp, 0, n-1, 0, r);
}
void combinations(int array[], int temp[], int start, int end, int index, int r){
if (index == r){
for (int j=0; j<r; j++)
printf("%d ", temp[j]);
printf("\n");
return;
}
for (int i=start; i<=end && end-i+1 >= r-index; i++){
temp[index] = array[i];
combinations(array, temp, i+1, end, index+1, r);
}
}
int main(){
int array[MAXARRAY];
int r;
int n = sizeof(array)/sizeof(array[0]);
int i=MAXarray, j;
for(j=0;j<MAXARRAY;j++){
array[j]=j+1;
}
for(r=0;r<=i;r++)
print_combinations(array, n, r);
}
Now I'm trying to convert this program to do the following:
Instead of printing the permutations, I want to sum up ALL permutations and compare the sum with a fixed value, and if the sum of numbers in the permutation truly is equal to that fixed value, it increases the counter so in the end I could check how many sums of permutation equals that value. This is what I came up with for now:
#define MAXARRAY 32
#include <stdio.h>
int combinations (int array[], int temp[], int start, int end, int index, int r);
void print_combinations (int array[], int n, int r){
int temp[r];
combinations(array, temp, 0, n-1, 0, r);
}
int combinations (int array[], int temp[], int start, int end, int index, int r){
int sum=0, counter=0;
if (index == r) {
for (int j=0; j<r; j++){
sum=sum+temp[j];
}
if(sum==264){
counter++;
}
}
for (int i=start; i<=end && end-i+1 >= r-index; i++){
temp[index] = array[i];
combinations(array, temp, i+1, end, index+1, r);
}
return counter;
}
int main()
{
int array[MAXARRAY];
int r;
int n = sizeof(array)/sizeof(array[0]);
int i=MAXARRAY, j;
for(j=0;j<MAXARRAY;j++){
array[j]=j+1;
}
for(r=0;r<=i;r++)
print_combinations(array, n, r);
I don't know how to alter this correctly to get what I want, precisely I am a bit lost with how to switch up the void function to print a counter that does not appear in the function, and I am unsure if I can just easily "alter" this code to get what I want, or I just need to write completely new functions.
You want to know in how many ways you can pick numbers from a given set so that they sum up to a given target value. You seem to approach this the wrong way, because you have mixed up permutations and combinations.
Permutations are different arrangements of a set of items with a fixed size n and number of possible arrangements is n! if all of the items are different. That's of no use here, because summation is commutative; the order of operands doesn't matter.
Combinations tell you which items of a set are included and which are not. This is what you want here. Luckily for you, there are only 2ⁿ possilbe ways to pick items from a set of n, including all items or none.
You can also solve this recursively. Each level of recursion treats one item and you can either chose to include it or not. For thee items, you get the following decision tree:
0
/ \
0 1
/ \ / \
0 2 0 2
/ \ / \ / \ / \
0 3 0 3 0 3 0 3
sum 0 3 2 5 1 4 3 6
Take the left branch to omit an item and take the right branch to include it. This will give you the sum of 3 twice and all other sums from 0 to 6 inclusively once. There are 8 possible paths.
The program below does that:
#include <stdlib.h>
#include <stdio.h>
#define N 32
#define TARGET 264
/*
* Print the summands
*/
void print(const int a[], int n)
{
int i;
for (i = 0; i < n; i++) {
if (i) printf(" + ");
printf("%d", a[i]);
}
puts("");
}
/*
* Actual recursive combination function
*/
size_t combine_r(const int pool[], // summand pool
int res[], // currently included items
int max, // length of pool
int n, // length of res
int i, // current item's index in pool
int sum, // running sum
int target) // desired target
{
int count = 0;
if (i == max) {
if (sum == target) {
//print(res, n);
count++;
}
} else {
count += combine_r(pool, res, max, n, i + 1, sum, target);
res[n++] = pool[i];
count += combine_r(pool, res, max, n, i + 1,
sum + pool[i], target);
}
return count;
}
/*
* Interface function for the recursive function.
*/
size_t combine(const int pool[], int n, int target)
{
int res[n];
return combine_r(pool, res, n, 0, 0, 0, target);
}
int main()
{
int pool[N];
size_t n;
int i;
for (i = 0; i < N; i++) pool[i] = i + 1;
n = combine(pool, N, TARGET);
printf("%zu combinations.\n", n);
return 0;
}
The function goes down each path and records a hit if the sum equals the target. The number of hits in each subtree is returned as you return from the recursion and go up the tree, so that the root level you've got the total number of hits.
The function combine is just a front-end to the actual recursive function, so that you don't have to pass so many zeros from main. The arguments for the recursive function could probably be reduced and organised more elegantly. (Tow of them exist only because in C you have to pass i the length of an array. If you just want to count the possibilities, you can get rid of res and n, which just serve to print the array.)

Parallelization of Combination

I have got a piece of code that prints the combination of M number From N (nCm);
As it is a recursion, it works very slow when N is large.
#include <stdio.h>
#include <stdlib.h>
#define N 80
#define M 4
int result[M]= {0}; // THE ARRAY THAT SAVE THE RESULT OF ONE COMBINATION
int queue[N] = {0};
int top = 0;
void comb(int* input,int s, int n, int m)
{
if (s > n)
return ;
if (top == m)
{
for (int i = 0; i < m; i++)
{
result[i] = queue[i];
printf("%d\n", queue[i]);
}
}
queue[top++] = input[s];
comb(input,s+1, n, M);
top--;
comb(input,s+1, n, M);
}
int main()
{
int array[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,
73,74,75,76,77,78,79,80};
printf("\ncombination():\n");
comb(array,0, N, M);
printf("\n");
}
I would like to know if there is any space for improvement in the algorithm above?
if possible, can I use openMP ?
Thanks
To me your code was even giving the desired output. see
I have changed
printing format each combination was not good enough.
repeated combinations. (note: else part of if statement added).
reduced 2 recursive call with a loop and a recursive call. (Less space.)
The required code is:
#include <stdio.h>
#include <stdlib.h>
#define N 20
#define M 6
int result[M]= {0}; // THE ARRAY THAT SAVE THE RESULT OF ONE COMBINATION
int queue[N] = {0};
int top = 0;
void comb(int* input,int s, int n, int m)
{
if (s > n)
return ;
if (top == m)
{
printf("\n");
for (int i = 0; i < m; i++)
{
result[i] = queue[i];
printf("%d ", queue[i]);
}
}else{
for(int ss=s;ss<n;ss++){
queue[top++] = input[ss];
comb(input,ss+1, n, m);
top--;
}
//comb(input,s+1, n, m);
}
}
int main()
{
int array[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,
73,74,75,76,77,78,79,80};
printf("\ncombinations():\n");
comb(array,0, N, M);
printf("\n");
}

unable to pass array properly in quicksort

Here is my program it is compiling and running without syntax errors.How ever it does not sort the array.The problem lies in where I am passing the array in function
#include<stdio.h>
#include<string.h>
int partition (int *,int,int);
void quicksort (int *,int,int);
static int call=0;
int main()
{
int i,j,choice;
int length;
int a[]={81, 12, 90, 3, 49, 108, 47};
i=0;
length=sizeof(a)/sizeof(a[0]);
quicksort(a,0,length-1);
printf("the sorted array is\n");
for(i=0;i<length;i++)
printf (" %d ",a[i]);
}
int partition(int *num,int p,int r)
{
int x,j,i,temp,bak;
x=num[r];
i=p-1;
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
{
printf(" %d",num[bak]);
}
}
}
num[i+1]=num[r];
return i+1;
}
void quicksort (int *num,int p,int r)
{
int q;
if (p<r)
{
call++;
q=partition(num,p,r);
quicksort(num,p,q-1);
quicksort(num,q+1,r);
}
}
The above way of passing array in functions is that right that is what I want to know because that is giving problem in function partition.
Inside the function partition when swapping happens then I tried printing the array there itself (it is not sorted array but just to see upto what point things reached) then I saw that only 2 or 3 elements of array which I had passed are being printed and rest of the array is lost some where.So my doubt is array is not being passed properly.
To be able to see as what is the problem with array passing in a function I wrote a smaller program ka1.c
#include<stdio.h>
void pass(int *);
int main ()
{
int a[]={3,5,61,32,12};
pass(a);
}
void pass (int *num)
{
int i,j;
j=sizeof(num)/sizeof(num[0]);
for (i=0;i<j;i++)
printf(" %d",num[i]);
}
Now when I run the above code I get output just
3 5
I was expecting the complete array to be printed in output of ka1.c.
Where as if you notice rest of the array is not getting printed.Where did that go?
I have used the same logic in quicksort also hence I feel the error is same in both cases.
UPDATE1
After the comment below I checked the length of array recieved in quicsort.c paritition function via
sizeof(num)/sizeof(num[0]);
and found of original array
int a[]={81, 12, 90, 3, 49, 108, 47};
which is having length 7 here when I passed it in the function partition
the length is only 2.
The same is case with program ka1.c So why only length is 2 in both cases?
UPDATE2
As the suggestions given below now I have passed on the length also
#include<stdio.h>
#include<string.h>
int partition (int *,int,int,int);
void quicksort (int *,int,int,int);
static int call=0;
int main()
{
int i,j,choice;
int length;
int a[]={81, 12, 90, 3, 49, 108, 47};
i=0;
printf("the sorted array is\n");
length=sizeof(a)/sizeof(a[0]);
printf("length of array %d\n",length);
printf("quick sort called in main\n");
quicksort(a,0,length-1,length);
for(i=0;i<length;i++)
printf (" %d ",a[i]);
}
int partition(int *num,int p,int r,int june)
{
int x,j,i,temp,bak,length;
x=num[r];
i=p-1;
bak=0;
printf("inside the partition\n");
printf("length of june recieved =%d \n",june);
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
printf("printing array after swap\n");
for(;bak<7;bak++)
{
printf(" %d ",num[bak]);
}
}
}
num[i+1]=num[r];
return i+1;
}
void quicksort (int *num,int p,int r,int june)
{
int q,bbc,ccd;
if (p<r)
{
call++;
printf("partition called %d times p=%d r=%d\n",call,p,r);
printf("before sending to function length of june=%d \n",june);
q=partition(num,p,r,june);
bbc=q-1-p+1;
quicksort(num,p,q-1,bbc);
ccd=r-q-1+1;
quicksort(num,q+1,r,ccd);
}
}
But the program is still failing to print the sorted array.
You can compile and run the above code.
SOLVED
Finally with help of replies below I have been able to solve the above problem.
The mistake lied in function partition in statement
for (j = 0; j <= r - 1; j++)
instead it should have been
for (j = p; j <= r - 1; j++)
note j=p and j=0
here
j=0
is wrong since when recursively second partition is tried to be sorted it started disturbing the first partition and hence the result was also wrong.
In this program I faced a problem in using gdb to debug a recursive function.
Please check this thread also
Debugging recurssion was quite tricky.
SO the correct code is
#include<stdio.h>
#include<string.h>
int partition (int *, int, int, int);
void quicksort (int *, int, int, int);
static int call = 0;
int
main ()
{
int i, j, choice;
int length;
int a[] = { 81, 12, 90, 3, 49, 108, 47 };
i = 0;
printf ("the sorted array is\n");
length = sizeof (a) / sizeof (a[0]);
printf ("length of array %d\n", length);
printf ("quick sort called in main\n");
quicksort (a, 0, length - 1, length);
for (i = 0; i < length; i++)
printf (" %d ", a[i]);
}
int
partition (int *num, int p, int r, int june)
{
int x, j, i, temp, bak, length;
x = num[r];
i = p - 1;
bak = 0;
for (j = p; j <= r - 1; j++)
{
if (num[j] <= x)
{
i = i + 1;
temp = num[i];
num[i] = num[j];
num[j] = temp;
}
}
temp=num[i+1];
num[i + 1] = num[r];
num[r]=temp;
return i + 1;
}
void
quicksort (int *num, int p, int r, int june)
{
int q, bbc, ccd;
if (p < r)
{
call++;
q = partition (num, p, r, june);
bbc = q - 1 - p + 1;
quicksort (num, p, q - 1, bbc);
ccd=r-q+1;
quicksort (num, q + 1, r, ccd);
}
}
The problem is in the way you are calculating the length of teh array.......try simply giving the number of elements in the array as the parameter for the quicksort method....i guess u will have the right answer...
and also i agree to the point made....try and passing the length of the array with the array.....try both and tell me which works...:)
NEW CODE:
#include<stdio.h>
#include<string.h>
//int partition (int *,int,int);
void q_sort(int*,int,int);
void quicksort (int *,int);
static int call=0;
int main()
{
int i,j,choice;
int length;
int a[]={81, 12, 90, 3, 49, 108, 47};
i=0;
printf("the sorted array is\n");
length=sizeof(a)/sizeof(a[0]);
printf("length of array %d\n",length);
printf("quick sort called in main\n");
quicksort(a,length);
for(i=0;i<length;i++)
printf (" %d ",a[i]);
}
/*int partition(int *num,int p,int r)
{
int x,j,i,temp,bak,length;
x=num[r];
i=-1;
bak=0;
printf("inside the partition\n");
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
printf("printing array after swap\n");
for(;bak<7;bak++)
{
printf(" %d ",num[bak]);
}
}
}
num[i+1]=num[r];
return i+1;
}
*/
/*void quicksort (int *num,int p,int r)
{
int q,bbc,ccd;
if (p<r)
{
call++;
printf("partition called %d times p=%d r=%d\n",call,p,r);
q=partition(num,p,r);
bbc=q-1-p+1;
quicksort(num,p,q-1);
ccd=r-q-1+1;
quicksort(num,q+1,r);
}
}*/
void quicksort(int numbers[], int array_size)
{
q_sort(numbers, 0, array_size - 1);
}
void q_sort(int numbers[], int left, int right)
{
int pivot, l_hold, r_hold;
l_hold = left;
r_hold = right;
pivot = numbers[left];
while (left < right)
{
while ((numbers[right] >= pivot) && (left < right))
right--;
if (left != right)
{
numbers[left] = numbers[right];
left++;
}
while ((numbers[left] <= pivot) && (left < right))
left++;
if (left != right)
{
numbers[right] = numbers[left];
right--;
}
}
numbers[left] = pivot;
pivot = left;
left = l_hold;
right = r_hold;
if (left < pivot)
q_sort(numbers, left, pivot-1);
if (right > pivot)
q_sort(numbers, pivot+1, right);
}
You need to put a ; at the end of the function declaration before main:
void pass(int *) ;
^
You have to pass the size of the array along with the array itself. The function receiving the array cannot determine its size. The receiving function only sees num as a pointer, so when you use sizeof(num) it returns the size of the pointer num, not the size of the memory allocated for the array in the main function. So, you have to do something like this:
#include<stdio.h>
void pass(int *, int);
int main ()
{
int a[]={3,5,61,32,12};
int length;
length = sizeof(a)/sizeof(a[0]);
pass(a, length);
}
void pass (int *num, int size)
{
int i;
for (i=0;i<size;i++)
printf(" %d",num[i]);
}
This post explains a similar issue in more detail:
Passing an array as an argument in C++

Resources