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.)
Related
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.
I need to implement mergesort for arrays up to 100000 integers but the specifications are a bit troublesome: I need to use a pointer to an integer array, its length and an extra workspace array for merging,
The mergesort function should look something like this:
void merge_sort(int *a, int *w, int n)
where a is to be sorted and w is the workspace used for merging, cant use an array and two indexes between what I wanna sort
pseudocode:
merge_sort(int *a, int *w, int n) {
/* take care of stopping condition first */
if the array to be sorted has fewer than two elements then
return
merge_sort( first half of array a);
merge_sort( second half of array a);
merge the two halves of array a into array w
copy array w back into array a
}
merge(int *array, int *workspace, int len) {
initialise indices to point to the beginning of
the left and right halves of array
while there are elements in both halves of array {
compare the elements at the current left and right indices
put the smallest into workspace and increment both the index
it was taken from, and the index in workspace
}
add any remaining elements from left half of array to workspace
add any remaining elements from right half of array to workspace
}
Here is what I got so far:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ARRAY_MAX 100000
void merge_sort(int *a, int *w, int n) {
if (n == 1)
return;
else {
int *temp;
merge_sort(a, w, n / 2);
merge_sort(a + (n / 2), w, (n - (n / 2)));
/** Cannot figure what to pass to merge since it has to be the two halves
and how to copy contents of a to w **/
}
}
void merge(int *a, int *w, int n) {
/** Cannot figure this out **/
}
int main(void) {
int my_array[ARRAY_MAX];
int work_space[ARRAY_MAX];
int count = 0;
int i;
while (count < ARRAY_MAX && 1 == scanf("%d", &my_array[count])) {
count += 1;
}
start = clock();
merge_sort(my_array, workspace, count);
end = clock();
merge_sort(my_array, work_space, count);
for (i = 0; i < count; i++) {
printf("%d\n", my_array[i]);
}
fprintf(stderr, "%d %f \n", count, (end - start) / (double)CLOCKS_PER_SEC);
return EXIT_SUCCESS;
}
The merging phase in function merge_sort iterates on both halves in parallel, taking the smallest element from either side at a time:
void merge_sort(int *a, int *w, int n) {
if (n < 2) {
return;
} else {
int i, j, k;
int n1 = n / 2;
int *b = a + n1;
int n2 = n - n1;
/* sort the left half */
merge_sort(a, w, n1);
/* sort the right half */
merge_sort(b, w, n2);
/* merge the halves into w */
for (i = j = k = 0; i < n1 && j < n2;) {
if (a[i] <= b[j]) {
/* get smallest value from a */
w[k++] = a[i++];
} else {
/* get smallest value from b */
w[k++] = b[j++];
}
}
/* copy remaining elements from a */
while (i < n1) {
w[k++] = a[i++];
}
/* copy remaining elements from b */
while (j < n2) {
w[k++] = b[j++];
}
/* copy sorted elements back to a */
for (i = 0; i < n; i++) {
a[i] = w[i];
}
}
}
The rest of the code has a few issues too:
2 arrays of 100000 ints might exceed the space available for automatic variables.
you sort the array twice
start and end are not defined
Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ARRAY_MAX 100000
int main(void) {
int my_array[ARRAY_MAX];
int work_space[ARRAY_MAX];
int i, count;
clock_t start, end;
count = 0;
while (count < ARRAY_MAX && scanf("%d", &my_array[count]) == 1) {
count += 1;
}
start = clock();
merge_sort(my_array, workspace, count);
end = clock();
for (i = 0; i < count; i++) {
printf("%d\n", my_array[i]);
}
fprintf(stderr,"%d %f\n", count, (end - start) / (double)CLOCKS_PER_SEC);
return EXIT_SUCCESS;
}
Remember that in C, when you send an array as an argument to a function, what is really sent is a pointer to the first element. Then you can use that pointer inside the function in a way very similar to an array. So if you are confused about the ”pointers” in the description of (I assume) your homework, perhaps that is the reason?
The code does run. This is a little different version of quicksort I am working on. I am running into some major issues with it. First off It prints out the first element in the array as n: for example(if you set n = 3, even if you make the first element in the array 1 lets say, it will still print out 3 as the first element). Also when you print out the sorted version it doesn't actually change anything.
Example input with n = 3,
Set values = 8 , 7 , 6
Initial output will equal 3 , 7 , 6
Final output will equal 3 , 7 , 6
(The output SHOULD be 6 , 7 , 8)
I haven't been able to find any code online similar to my code, so this may be something new! Thanks.
//preprocessor directives and header files
#include <stdio.h>
#define MAX_ARRAY_SIZE 50
//function prototypes separated by data types
void print_array( int array[], int n ); // Print out the array values
void swap( int array[], int index1, int index2 ); // Swap two array elements.
void quicksort( int array[], int low, int high ); // Sorting algorithm
int populate_array( int array[] ); // Fill array with values from user.
int partition( int array[], int low, int high ); // Find the partition point (pivot)
//the main function
int main(void)
{
int array[MAX_ARRAY_SIZE];
//set n = to size of user created size of array
int n = populate_array(&array[MAX_ARRAY_SIZE]);
//print the original array to the screen
print_array(&array[MAX_ARRAY_SIZE], n );
//perform the algorithm
quicksort(array, 0, n-1);
printf("The array is now sorted:\n");
print_array(&array[MAX_ARRAY_SIZE], n);
return 0;
}
// *array and array[] are the same...
int populate_array(int array[])
{
int n = -1;
printf("Enter the value of n > ");
scanf("%d", &n);
if(n > MAX_ARRAY_SIZE)
{
printf("%d exceeds the maximum array size. Please try again.\n\n", n);
populate_array( &array[MAX_ARRAY_SIZE]);
}
else if(n < 0)
{
printf("%d is less than zero. Please try again.\n\n", n);
populate_array( &array[MAX_ARRAY_SIZE]);
}
else if(n == 0)
{
printf("%d Array of size 0? Please don't try this, and... Please try again.\n\n", n);
populate_array( &array[MAX_ARRAY_SIZE]);
}
else
{
for(int i = 0; i < n; i++)
scanf("%d", &array[i]);
}
printf("The initial array contains: \n");
return n;
}
void print_array(int array[], int n)
{
for(int i = 0; i < n; i++)
printf("%+5d\n", array[i]);
}
void quicksort(int array[], int low, int high)
{
if (low < high)
{
/* pivot is partitioning index, array[p] is now
at right place */
int pivot = partition(array, low, high);
// Separately sort elements before
// partition and after partition
quicksort(array, low, pivot - 1);
quicksort(array, pivot + 1, high);
}
}
int partition(int array[], int low, int high)
{
int pivot = array[high];
int i = low;
for (int j = low; j <= high- 1; j++)
{
// If current element is smaller than or
// equal to pivot
if (array[j] <= pivot)
{
swap(array, i, j);
i = i +1;
}
}
swap(array, i, high);
return i;
}
void swap(int array[], int index1, int index2)
{
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
Here is a heavily commented answer. I changed the code quite a bit.
This is now a fully functional quicksort array for user input.
The problem I was having before was with the &array[MAX_ARRAY_SIZE]. This needed to be changed to just "array" instead. The &array[MAX_ARRAY_SIZE] was trying to access a memory location past the actual size of the array.
Changing it to just "array" means that it is accessing the first element in the array.(Correct if wrong)
I also changed the populate array function to be a robust do-while loop. And instead of trying to re-call the function inside itself. The do-while loop will only allow you to change the value of 'n'.
/*
Author: Zachary Alberda
*/
//preprocessor directives and header files
#include <stdio.h>
#define MAX_ARRAY_SIZE 50
//function prototypes separated by data types
void print_array( int array[], int n ); // Print out the array values
void swap( int array[], int index1, int index2 ); // Swap two array elements.
void quicksort( int array[], int low, int high ); // Sorting algorithm
int populate_array( int array[] ); // Fill array with values from user.
int partition( int array[], int low, int high ); // Find the partition point (pivot)
//the main function
int main(void)
{
int array[MAX_ARRAY_SIZE]; //set n = to size of user created size of array
int n = populate_array(array); //print the original array to the screen
print_array(array, n ); //print array of size n
quicksort(array, 0, n-1); //perform the algorithm low is 0, high is size of array -1.
printf("The array is now sorted:\n");//Inform user that the array is sorted.
print_array(array, n);//print the sorted array
return 0; // exit without errors.
}
// *array and array[] are the same...
int populate_array(int array[])
{
int n = -1;//initialize variable n(local variable to function populate_array)
printf("Enter the value of n > ");//inform user of what to input
scanf("%d", &n);
/*
CHECK IF N IS VALID
This is a robust do while loop!
1) Performs the if-statements while 'n' is not valid in a do-while loop.
-The reason I do this is because it will cause errors
if the if-statements are individual without the do-while loop.
2)The program will not crash if you try different combinations
of inputs for 'n'. :)
3)Checks if user input is > MAX_ARRAY_SIZE
4)Checks if user input is < 0
5)Checks if user input is == 0
*/
do
{
if(n > MAX_ARRAY_SIZE)
{
printf("%d exceeds the maximum array size. Please try again.\n\n", n);
printf("Enter the value of n > ");
scanf("%d", &n);
}
else if(n < 0)
{
printf("%d is less than zero. Please try again.\n\n", n);
printf("Enter the value of n > ");
scanf("%d", &n);
}
else if(n == 0)
{
printf("%d Array of size 0? Please don't try this, and... Please try again.\n\n", n);
printf("Enter the value of n > ");
scanf("%d", &n);
}
}while(n <= 0 || n > MAX_ARRAY_SIZE);
//scan in array if user input is valid
for(int i = 0; i < n; i++)
scanf("%d", &array[i]);
printf("The initial array contains: \n");//Inform user of initial array
return n;
}
void print_array(int array[], int n)
{
//print array in pre/post order before and after the algorithm.
for(int i = 0; i < n; i++)
printf("%+5d\n", array[i]);
}
void quicksort(int array[], int low, int high)
{
if (low < high)
{
/* pivot is partitioning index, array[pivot] is now
at right place */
int pivot = partition(array, low, high);
// Separately sort elements before
// partition and after partition
quicksort(array, low, pivot - 1);
quicksort(array, pivot + 1, high);
}
}
int partition(int array[], int low, int high)
{
int pivot = array[high];
int i = low;
for (int j = low; j <= high- 1; j++)
{
// If current element is smaller than or
// equal to pivot
if (array[j] <= pivot)
{
swap(array, i, j);
i = i +1;
}
}
swap(array, i, high);
return i;
}
void swap(int array[], int index1, int index2)
{
//swap positions of array index 1 and 2
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
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");
}
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.