I previously tested the same variable called "swaps" for bubble sort algorithm and it worked perfectly. Now, with selection sorting, variable loses its value even after incrementing it.
Any help will be very much appreciated.
int list[] = {10, 5, 6, 3, 4, 11, 9, 7, 2};
int min = list[0], pos = 0, temp_max = 0;
// Loop until no swap is needed
for (int j = 0, n = sizeof(list) / sizeof(int); j < n; j++)
{
int swaps = 0,
// Iterate through array to find min value
for (int i = j, y = sizeof(list) / sizeof(int); i < y; i++)
{
if (list[i] < min)
{
min = list[i];
pos = i;
}
}
// Insert min value in left most position and add 1 to swaps, meaning array is not yet sorted
if (pos > j)
{
temp_max = list[j];
list[j] = min;
list[pos] = temp_max;
swaps++;
}
// The error might occur here: "swaps" keeping value 0 after previous if statement ends
printf ("swaps = %d\n", swaps);
// If no swaps ocurred, array is sorted
if (swaps == 0)
{
// Print sorted array and return
}
}
Move the declaration int swaps = 0 outside the for loop.
In other words, change this:
for (int j = 0, n = sizeof(list) / sizeof(int); j < n; j++)
{
int swaps = 0;
...
}
To this:
int swaps = 0;
for (int j = 0, n = sizeof(list) / sizeof(int); j < n; j++)
{
...
}
I want to thank you all very much. I have solved the problem with your help. Turns out the error had to do with the variable scope (where it was declared). Follow below the working code.
int main (void)
{
//Declare list to be sorted and other variables
int list[] = {9, 5, 7, 8, 4, 3, 2, 1, 6};
int minValPos = 0, maxTempVal = list[0];
for (int j = 0, siz = sizeof (list) / sizeof (int); j < siz; j++)
{
int swaps = 0, minVal = list[j];
// Look for min value after each j iteration
for (int i = j; i < siz; i++)
{
// Find minimum value (minVal) and store its position (minValPos)
if (list[i] < minVal)
{
minVal = list[i];
minValPos = i;
}
}
// Once with MinVal pinpointed, proceed to swap with jth item
if (minValPos > j)
{
maxTempVal = list[j];
list[j] = minVal;
list[minValPos] = maxTempVal;
swaps++;
}
// When array did not need any swaps, it means it is sorted
if (swaps == 0)
{
for (int r = 0; r < siz; r++)
{
printf ("Position [%d] = %d\n", r, list[r]);
}
}
}
}
That means your if statement is not becoming true in the meantime.
min should be set in each loop of j.
min=list[j] in for(j=...){min=list[j]; ... }
And also pos=j
Adding to the other answers, which will fix the problem specifically with your code, you can also approach the selection sort algorithm like this.
Steps to writing this algorithm for an array:
1. Write a helper function to find the index of the biggest element in the array:
size_t index_of_largest(int list[], size_t n) {
size_t i, biggest;
biggest = 0;
for (i = 0; i < n; i++) {
if (list[i] > list[biggest]) {
biggest = i;
}
}
return biggest;
}
2. Iterate over i=n to i=1, and find the biggest value between list[0] and list[i-1]. After this element is found, swap it into the last position. The function could look like this:
void sort_list(int list[], size_t n) {
size_t i, biggest;
for (i = n; i > 0; i--) {
biggest = index_of_largest(list, i);
int_swap(&list[biggest], &list[i-1]); /* swapping function */
}
}
3. Considering these ideas, you can write a simple version of the algorithm like this:
#include <stdio.h>
void sort_list(int list[], size_t n);
size_t index_of_largest(int list[], size_t n);
void print_array(int list[], size_t n);
void int_swap(int *x, int *y);
int main(void) {
int list[] = {10, 5, 6, 3, 4, 11, 9, 7, 2};
size_t n = sizeof list / sizeof *list;
printf("Before: ");
print_array(list, n);
sort_list(list, n);
printf("After: ");
print_array(list, n);
return 0;
}
void sort_list(int list[], size_t n) {
size_t i, biggest;
for (i = n; i > 0; i--) {
biggest = index_of_largest(list, i);
int_swap(&list[biggest], &list[i-1]);
}
}
size_t index_of_largest(int list[], size_t n) {
size_t i, biggest;
biggest = 0;
for (i = 0; i < n; i++) {
if (list[i] > list[biggest]) {
biggest = i;
}
}
return biggest;
}
void print_array(int list[], size_t n) {
size_t i;
for (i = 0; i < n; i++) {
printf("%d ", list[i]);
}
printf("\n");
}
void int_swap(int *x, int *y) {
int temp;
temp = *x;
*x = *y;
*y = temp;
}
Output:
Before: 10 5 6 3 4 11 9 7 2
After: 2 3 4 5 6 7 9 10 11
Compiled with:
gcc -Wall -Wextra -o progname progname.c
Related
Given two sets of natural number A and B of size n such that each member of A has to be paired to at at most one member of B. There is also cost associated with each pairing i.e if the absolute difference b\l sum of all n-length possible pair permutations of elements of A with B.
The following (crude and far from being optimized and safe -- I used a global variable: horror!) code does the job:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define SWAP(x, y, T) do { T SWAP = x; x = y; y = SWAP; } while (0)
int factorial(int N) {
int product = 1;
for (int j = 1; j <= N; j++)
product *= j;
return product;
}
// Prints the array
void printArr(int a[], int n)
{
for (int i = 0; i < n; i++) {
printf("%d ", a[i]);
}
printf("\n");
}
// Stores the array
void storeArr(int a[], int n, int counter, int** out)
{
for (int i = 0; i < n; i++) {
out[counter][i] = a[i];
}
}
int get_cost(int a, int b) {
int diff = abs(a - b);
if (diff >= 5 && diff < 10) {
return 0;
}
else if (diff < 5) {
return 1;
}
else {
return 2;
}
}
int cost_perm(int* a, int* b, int n) {
int cost = 0;
for (int i = 0; i < n; ++i) {
cost += get_cost( a[i], b[i] );
}
return cost;
}
// Globals are bad but...
int counter;
// Generating permutation using Heap Algorithm
void heapPermutation(int a[], int size, int n, int** out)
{
// if size becomes 1 then stores the obtained
// permutation
if (size == 1) {
storeArr(a, n, counter++, out);
return;
}
for (int i = 0; i < size; i++) {
heapPermutation(a, size - 1, n, out);
// if size is odd, swap 0th i.e (first) and
// (size-1)th i.e (last) element
if (size % 2 == 1)
SWAP(a[0], a[size - 1], int);
// If size is even, swap ith and
// (size-1)th i.e (last) element
else
SWAP(a[i], a[size - 1], int);
}
}
// Driver code
int main()
{
int a[] = { 169, 165, 161, 131, 145 };
int b[] = { 214, 174, 218, 188, 168 };
int n = sizeof a / sizeof a[0];
int numperm = factorial(n);
int** perm_of_a = calloc(numperm, sizeof(int*));
int** perm_of_b = calloc(numperm, sizeof(int*));
for (int i = 0; i < numperm; ++i) {
perm_of_a[i] = calloc(n, sizeof(int));
perm_of_b[i] = calloc(n, sizeof(int));
}
counter = 0;
heapPermutation(a, n, n, perm_of_a);
counter = 0;
heapPermutation(b, n, n, perm_of_b);
int min_cost = 1000;
int cost;
int mina = 0;
int minb = 0;
for (int i = 0; i < numperm; ++i) {
for (int j = 0; j < numperm; ++j) {
cost = cost_perm(perm_of_a[i], perm_of_b[j], n);
if (cost < min_cost) {
min_cost = cost;
mina = i;
minb = j;
}
}
}
printArr( perm_of_a[mina], n );
printArr( perm_of_b[minb], n );
printf( "%d\n", min_cost );
return 0;
}
You are trying to find one individual pair at each iteration, but you want to minimize the cost over all permutations.
You need to figure out how to generate all permutations of a vector and use code like this:
for permuted_A in all_permutations_of_A
for permuted_B in all_permutations_of_B
cost = cost(permuted_A, permuted_B)
if cost < min_cost
min_cost = cost
min_permuted_A = permuted_A
min_permuted_B = permuted_B
Once you figure out how to enumerate the permutations, the rest will be trivial.
I am trying to implement the Selection Sort Algorithm and here is my attempt:
int select(int arr[], int i)
{
int j, minIndex;
minIndex = i;
for (j = i + 1; arr[j]; j++)
{
if (arr[j] < arr[minIndex])
minIndex = j;
}
return minIndex;
}
void selectionSort(int arr[], int n)
{
int i, iMin;
for (i = 0; i < n - 1; i++)
{
iMin = select(arr, i);
if (iMin != i)
{
int temp = arr[i];
arr[i] = arr[iMin];
arr[iMin] = temp;
}
}
}
Even though my code works fine, if there is an element in the array with value zero it fails. Here is an example case:
4 1 3 9 0
Output:
1 3 4 9 0
I know that my logic is correct, because it works with other cases, but why is it failing if there is a 0 in the array element?
Your loop condition is wrong:
for (j = i + 1; arr[j]; j++)
instead of arr[j] you need j < n.
Renamed select() to selectMin() to avoid conflict with existing function with that name. If you specify the length n before the array arr your can document how the two are related with current compilers.
Extracted the swap() function.
Minimized scope of variables.
size_t instead of int for indices as they are non-negative. The type difference also helps you distinguish between the indices of the array (size_t) the values of the array (int) which was the root cause of your troubles.
Hard-coded your test case and implemented a print() functions to verify correct result.
#include <stdio.h>
#include <stdlib.h>
void print(size_t n, int a[n]) {
for(size_t i = 0; i < n; i++)
printf("%d%s", a[i], i + 1 < n ? ", " : "\n");
}
size_t selectMin(size_t n, int arr[n], int i) {
size_t minIndex = i;
for (size_t j = i + 1; j < n; j++)
if (arr[j] < arr[minIndex])
minIndex = j;
return minIndex;
}
void selectionSort(size_t n, int arr[n]) {
for (size_t i = 0; i < n - 1; i++) {
size_t iMin = selectMin(n, arr, i);
if (iMin != i)
swap(arr + i, arr + iMin);
}
}
void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
int main(void) {
int a[] = {4, 1, 3, 9, 0};
selectionSort(sizeof a / sizeof *a, a);
print(sizeof a / sizeof *a, a);
}
and the output is:
0, 1, 3, 4, 9
The loop
for (j = i + 1; arr[j]; j++)
is problematic because of the loop condition arr[j]. As a condition it's equivalent to arr[j] != 0. C doesn't have any concept of "null values" like e.g. C# or Java.
You need to pass the array length to the select function, you can't rely on the array data itself to know when and where the array ends.
Using the array data itself will either lead to premature loop end if the data contains zeros. Or will go out of bounds if the array data doesn't contain any zeros.
I'm trying to write a basic selection-sort program in C. From debugging, I can see that under the first for loop (// Swap the values), selection(nums, size, i).index returns the same value as i. However, if I call the selection function with the exact same code outside of the for loop, it will correctly return the index (of the number in the array with the smallest value and to the right of the given index).
How can I make selection return the correct value inside the for loop?
#include <stdio.h>
typedef struct {
int value;
int index;
} sorted;
sorted selection(int integers[], int size, int idx);
int main(void) {
int nums[] = {7, 2, 3, 0, 1, 4, 6, 5};
int size = sizeof(nums)/sizeof(int);
int temp;
// Swap the values
for (int i = 0; i < size; i++) {
temp = nums[i];
nums[i] = selection(nums, size, i).value;
nums[selection(nums, size, i).index] = temp;
}
// Print the array
printf("[");
for (int j = 0; j < size; j++) {
if (!(j == size - 1)) {
printf("%i ", nums[j]);
}
else {
printf("%i", nums[j]);
}
}
printf("]\n");
}
sorted selection(int arr[], int size, int start) {
sorted smallest;
for (int i = start; i < size; i++) {
// If first element
if (i == start) {
smallest.value = arr[i];
smallest.index = i;
}
// If smaller
else if (arr[i] < smallest.value) {
smallest.value = arr[i];
smallest.index = i;
}
}
return smallest;
}
The reason why your version is failing is that you are calling selection a second time after starting to modify the array, when the index just needed to be retained after the first call.
The use of sorted and selection are, as #WhozCraig pointed out, completely unnecessary. You are also passing sorted by value which is not the convention in C.
I've renamed the function to indicate its purpose. This could be simplified to take only the elements right of the current index, but that would require some additional adjustments when handling the return value, so its a trade off.
#include <stdio.h>
int indexOfSmallest(int integers[], int size, int idx);
int main(void) {
int nums[] = {7, 2, 3, 0, 1, 4, 6, 5};
int size = sizeof(nums)/sizeof(int);
int temp;
// Swap the values
for (int i = 0; i < size; i++) {
temp = nums[i];
int smallest = indexOfSmallest(nums, size, i);
nums[i] = nums[smallest];
nums[smallest] = temp;
}
// Print the array
printf("[");
for (int j = 0; j < size; j++) {
if (!(j == size - 1)) {
printf("%i ", nums[j]);
}
else {
printf("%i", nums[j]);
}
}
printf("]\n");
}
int indexOfSmallest(int arr[], int size, int start) {
int smallest = start;
for (int i = start; i < size; i++) {
if (arr[i] < arr[smallest]) {
smallest = i;
}
}
return smallest;
}
You need change loop "// Swap the values"
// Swap the values
for (int i = 0; i < size; i++)
{
sorted select = selection(nums, size, i);
temp = nums[i];
nums[i] = select.value;
nums[select.index] = temp;
}
I was requested to write an effecient function with running time n which sort array by the remainder of 3 the program puts the elements which the remainder from dividing in 3 is 0 afterwards the elements that the remainder is 1 and afterwards 2
for example the array {7, 16, 3, 28, 12, 31, 14, 12}
will be sortes that way {12, 3, 12, 28, 16, 31, 7, 14}
so I tries to write an efficient function but it have not cover all cases and does not works for all arrays
int arr[] = { 7,16,3,28,12,31,14,12 };
int rem0 = 0, rem1 = 1, rem2 = 2;
for (int i = 0; i < 8; i++) {
if (arr[i] % 3 == 0)
rem0++;
if (arr[i] % 3 == 1)
rem1++;
if (arr[i] % 3 == 2)
rem2++;
}
int k = rem0, p = 0, m = 0 = 0;
for (int i = 0; i < 8; i++) {
while (rem0-k){
swap(&arr[i], &arr[rem0 - k]);
k--;
}
if (arr[i] % 3 == 1 && rem0+m<7) {
swap(&arr[i], &arr[rem0 + m]);
m++;
}
if (arr[i] % 3 == 1 && rem0 + rem1 + p<7) {
swap(&arr[i], &arr[rem0+rem1 + p]);
p++;
}
}
for (int l = 0;l <8;l++) {
printf("%d\n", arr[l]);
}
}
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
swap switch elements,
Can anyone tells me how can I fix that?
thanks:)
Since you want your function to run in O(n) time, you cannot sort the array completely. All you need to do is put all the elements in 3 buckets.
The following algorithm runs in 2 phases.
//First we count the number of elements in each bucket
int count[3] ={0, 0, 0};
for (int i = 0; i < NUM_ELEMENTS; i++) {
count[arr[i]%3]++;
}
Now that we have the number of elements, we can calculate the offsets of each bucket and create and output array
int output[NUM_ELEMENTS]; // In place bucketing can also be done using swaps
count[2] = count[0] + count[1];
count[1] = count[0];
count[0] = 0;
for (int i = 0; i < NUM_ELEMENTS; i++) {
output[count[arr[i]%3]] = arr[i];
count[arr[i]%3]++;
}
// Finally print the array
for (int i = 0; i < NUM_ELEMENTS; i++) {
printf("%d", output[i]);
}
Demo on Ideone
Here is the solution which you are looking for which uses the same array:
#include <stdio.h>
#define REMINDER 3
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,0};
int arr_size = sizeof(arr)/sizeof(arr[0]);
int idx=0;
for (int r=0; r<REMINDER; r++) {
for (int i=0; i<arr_size; i++) {
if (arr[i]%REMINDER==r) {
swap(&arr[idx++], &arr[i]);
}
}
}
for (int i=0; i<arr_size; i++) {
printf("%d ", arr[i]);
}
return 0;
}
Here is a another solution which is just simpler by using other place to store the result:
#include <stdio.h>
#define REMINDER 3
#define ARR_SIZE 10
int main()
{
int arr[ARR_SIZE] = {1,2,3,4,5,6,7,8,9,0};
int arr_sorted[ARR_SIZE];
int idx=0;
for (int r=0; r<REMINDER; r++) {
for (int i=0; i<ARR_SIZE; i++) {
if (arr[i]%REMINDER==r) {
arr_sorted[idx++]=arr[i];
}
}
}
for (int i=0; i<ARR_SIZE; i++) {
printf("%d ", arr_sorted[i]);
}
return 0;
}
Here's a 1-pass in-place Dutch national flag algorithm implementation (thanks to #Virgile who pointed out the algorithm)
void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
// Dutch National Flag (see xlinux.nist.gov/dads/HTML/DutchNationalFlag.html)
void sort3dnf(int *a, size_t n) {
int *bot = a;
int *mid = a;
int *top = a + n - 1;
while (mid <= top) {
switch (*mid % 3) {
default: swap(bot++, mid++); break;
case 1: mid++; break;
case 2: swap(mid, top--); break;
}
}
}
See ideone.com/6QXXCN
hey thanks for the advice
sadly we had requested to write the code
without any added array
I will be very glad if you could help me to
solve the issue
thanks :)
hey thanks for the advice sadly we had requested to write the code without any added array I will be very glad if you could help me to solve the issue thanks :)
Here is the answer without adding any extra array:
#include <stdio.h>
#define REMINDER 3
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,0};
int arr_size = sizeof(arr)/sizeof(arr[0]);
int idx=0;
for (int r=0; r<REMINDER; r++) {
for (int i=0; i<arr_size; i++) {
if (arr[i]%REMINDER==r) {
swap(&arr[idx++], &arr[i]);
}
}
}
for (int i=0; i<arr_size; i++) {
printf("%d ", arr[i]);
}
return 0;
}
I want to reverse numbers of array,
but I can't understand why it didn't run.
Thanks for explaining what does Debug Error_ Run-Time Check Failure #2 -S mean..
Thanks,
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5 };
int size, i, j;
int temp = 0;
size = sizeof(arr) / sizeof(arr[0]); //use this for changing size
printf("first_array :");
for (i = 0; i < size; i++)
{
printf("%d", arr[i]);
}
printf("\n");
for (i = 0; i <= (size / 2); i++)
{
j = size - i;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
printf("Riv_array :");
for (i = 0; i < size; i++)
{
printf("%d", arr[i]);
}
return 0;
}
Array index starts from 0 in C and your array has 5 elements so arr[4] is the last element but your code:
j = size - i;
arr[j];
when i=0 access to arr[5], this is your code error: Array index out of bound.
you should use j = size - i-1; to point to the last element of array, not j = size - i;
see this working sample (your sample code with some edit):
#include <stdio.h>
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
int size, i, j;
int temp = 0;
size = sizeof(arr) / sizeof(arr[0]); //use this for changing size
printf("first_array :");
for (i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
for (i = 0; i <= (size / 2); i++)
{
j = size - i - 1;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
printf("Riv_array :");
for (i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
another way to reverse array using pointers:
#include <stdio.h>
void reverse(int* p, int count){
int temp;
int* q = p + count - 1; // point to the end
count /= 2;
while (count--) {
temp = *p;
*p++ = *q;
*q-- = temp;
}
}
void print_array(int *p, int count){
while (count--) printf("%d ", *p++);
printf("\n");
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
int count = ((&arr)[1] - arr);
print_array(arr, count);
reverse(arr, count);
print_array(arr, count);
return 0;
}
output:
1 2 3 4 5
5 4 3 2 1