Radix Sort showing wrong values in the output - c

I am learning dsa and I tried to implement radix sort in c. I used this tutorial from programiz.
I implemented it but the array of numbers they are using get sorted correctly but when I used a different array it shows some garbage value.
When I insert this
int array[] = {121, 432, 564, 23, 1, 45, 788};
The output is "1 23 45 121 432 564 788" output
But When I insert this
int array[] = {3,4,1,5,2};
The output is "1 2 3 4 2496"
output
I implemented the code as it is from the tutorial. Can any one point out the issue
#include <stdio.h>
void radix_sort(int array[], int size);
void counting_sort(int array[], int size, int place);
int main(void)
{
int array[] = {3,4,1,5,2};
int size = sizeof(array) / sizeof(int);
radix_sort(array, size);
for (int i = 0; i < size; i++)
printf("%i ", array[i]);
printf("\n");
}
void radix_sort(int array[], int size)
{
int max = array[0];
for (int i = 1; i < size; i++)
{
if (array[i] > max)
max = array[i];
}
for (int place = 1; max / place > 0; place *= 10)
counting_sort(array, size, place);
}
void counting_sort(int array[], int size, int place)
{
int output[size + 1];
int max = (array[0] / place) % 10;
for (int i = 1; i < size; i++)
{
if (((array[i] / place) % 10) > max)
max = array[i];
}
int count[max+1];
for (int i = 0; i < max; ++i)
count[i] = 0;
for (int i = 0; i < size; i++)
count[(array[i] / place) % 10]++;
for (int i = 1; i < 10; i++)
count[i] += count[i - 1];
for (int i = size-1; i >= 0; i--)
{
output[count[(array[i] / place) % 10] - 1] = array[i];
count[(array[i] / place) % 10]--;
}
for (int i = 0; i < size; i++)
array[i] = output[i];
}

for (int i = 1; i < 10; i++) { will access the array out of bounds since count[max+1] => count[5+1] so your program has undefined behavior. It could crash or output garbage or do just about anything.
You should use i <= max in that loop:
for (int i = 1; i <= max; i++) // use `i <= max` here
count[i] += count[i - 1];
You also need to zero out the memory of the variable length array count because it will contain indeterminate values after it's been created. You tried doing that with for (int i = 0; i < max; ++i) count[i] = 0; but that misses the last element in the array. You need i <= max there too:
int count[max + 1];
for (int i = 0; i <= max; ++i) count[i] = 0;

Related

Function argument function cannot operate with array

I was trying to make a functional bucket sort array in c with a variable funtion parameter in order to sort each bucket, so I tried to pass the bubblesort algorithm but it doesn't seems to do anything with each bucket, my question is: What am I doing wrong?, at my first glance it seems that there aren't mistakes in my code: (sorry for the mess)
void bubblesort (int arr[], unsigned char size) {
size /= sizeof(int);
for (unsigned char i = 0; i < size - 1; i++)
for (unsigned char j = 0; j < size - i - 1; j++)
if (arr[j] > arr[j+1])
arr[j] = arr[j] + arr[j+1],
arr[j+1] = arr[j] - arr[j+1],
arr[j] = arr[j] - arr[j+1];
}
/* More sorting algorithms */
void bucketsort (int arr[], unsigned char size, unsigned char n, void sort(int[],unsigned char)) {
// to be fixed
size /= sizeof(int); int *bucket[n]; unsigned char s[n];
for (unsigned char i = 0; i < n; i++) s[i] = 0, bucket[i] = NULL;
int min = arr[0], max = arr[0];
for (unsigned char i = 1; i < size; i++) {
if (arr[i] < min) min = arr[i];
if (arr[i] > max) max = arr[i];
} for (unsigned char i = 0; i < size; i++)
s[n*(arr[i]-min)/(max-min+1)]++,
bucket[n*(arr[i]-min)/(max-min+1)] = (int*)realloc(bucket[n*(arr[i]-min)/(max-min+1)],s[n*(arr[i]-min)/(max-min+1)]*sizeof(int)),
bucket[n*(arr[i]-min)/(max-min+1)][s[n*(arr[i]-min)/(max-min+1)]-1] = arr[i];
for (int i = 0; i < n; i++) {for (int j = 0; j < s[i]; j++) printf("%d ",bucket[i][j]); printf("\n");}
for (unsigned char i = 0; i < n; i++) sort(bucket[i],s[i]), fflush(NULL);
for (int i = 0, index = 0; i < n; i++) for (int j = 0; j < s[i]; j++) arr[index++] = bucket[i][j];
}
int main (void) {
int a[] = {3,6,4,9,1,7,5,8,2,0};
bucketsort(a,sizeof(a),4,bubblesort);
for (signed char i = 0; i < (signed char)(sizeof(a)/sizeof(int)); i++) printf("%d, ",a[i]);
}
In my function parameter I´ve tried replacing the [] with * but it doesn't make any difference.
You have to remove the line "size /= sizeof(int)" - and the size is correct
void bubblesort (int arr[], unsigned char size) {
// size /= sizeof(int);
for (unsigned char i = 0; i < size - 1; i++)
for (unsigned char j = 0; j < size - i - 1; j++)
if (arr[j] > arr[j+1])
arr[j] = arr[j] + arr[j+1],
arr[j+1] = arr[j] - arr[j+1],
arr[j] = arr[j] - arr[j+1];
}
Test:
1 2 0
3 4
6 7 5
9 8
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ~"[Thread 26424.0x564c exited with code 0]

Reverse Bubble Sort Algorithm in C using only while loop

I am trying to create a reverse bubble sort algorithm. It works but the first output is a big crazy number that i dont understand. The remaining outputs seem to be sorted in descending order. Where is my code wrong?
#include <stdio.h>
void ft_rev_int_tab(int *tab, int size)
{
int i;
int j;
int k;
i = 0;
while (i < size)
{
j = 0;
while (j < size -i)
{
if (tab[j] < tab[j+1])
{
k = tab[j];
tab[j] = tab[j+1];
tab[j + 1] = k;
}
j++;
}
i++;
}
}
int main(void)
{
int tab[] = {9, 320, 0, 113, 15};
int size = sizeof(tab) / sizeof(*tab);
ft_rev_int_tab(tab, size);
for (int i = 0; i < size; i++)
{
printf ("%d\n", tab[i]);
}
}
i = 0; before while (i < size) is wrong. The condition j < size -i is equivalent to j < size when i is zero. In this case j will be at most size-1 and now tab[j+1] is out-of-range.
It should be changed to i = 1;.
void ft_rev_int_tab(int *tab, int size) {
int i;
int j;
int k;
i = 0;
while (i < size) {
j = 0;
while (j < size - i - 1) {
if (tab[j] < tab[j + 1]) {
k = tab[j];
tab[j] = tab[j + 1];
tab[j + 1] = k;
}
j++;
}
i++;
}
}
Your condition in the nested while loop should be (j < size - i - 1)
because you only need to check the value from tab[0] to tab[i-1]. Your if and swap checks tab[j] and tab[j+1], so when i is equal to the size of the array, you will compare it with a value outside of the array. In your example is the tab[5]'s value.

What is this sorting algorithm? And is there a more efficient way?

I wrote this algorithm while learning about O(N) algorithms, and after the last question I posted moments ago, I was wondering if theres a similar algorithm that already exists as well.
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
/*algorithm designed by hoholee12*/
typedef struct{
int val;
int dup;
} duplicates;
int ScoopSort(int* arr, int size, int buf){
//subarr buffer size
buf += size;
int* bigarr = malloc(size * sizeof(int));
duplicates* subarr = malloc(buf * sizeof(duplicates));
//subarr init: O(N)
for (int i = 0; i < buf; i++) {
subarr[i].val = INT_MIN;
subarr[i].dup = 0;
}
//will always have biggest number of section
int lastsize = INT_MIN;
//big loop(until all elements are scooped: O(count of 'diff bigger than size'))
int j = 0;
int loopcount = 0;
while (1){
//min check per iteration: O(N)
int min = INT_MAX;
for (int i = 0; i < size; i++){
if (min > arr[i] && arr[i] > lastsize) min = arr[i];
}
//initval per iteration
int initval = min - 1;
//follow index: incr dup
for (int i = 0; i < size; i++){
int val = arr[i] - min;
if (val < buf && val >= 0){
subarr[val].val = arr[i];
subarr[val].dup++;
}
}
//scoop subarr to bigarr: O(N)
for (int i = 0; i < buf; i++){
if (subarr[i].val > initval){
for (int x = 0; x < subarr[i].dup; x++) bigarr[j++] = subarr[i].val;
subarr[i].dup = 0;
if (lastsize < subarr[i].val) lastsize = subarr[i].val;
}
}
loopcount++;
//break on all scooped
if (j >= size) break;
}
//copy back: O(N)
for (int i = 0; i < size; i++) arr[i] = bigarr[i];
free(subarr);
free(bigarr);
return loopcount;
}
int test2(){
#define ARRSIZE 1000000
int* arr = malloc(ARRSIZE * sizeof(int));
srand(time(NULL));
for (int i = 0; i < ARRSIZE; i++){
arr[i] = rand() *(RAND_MAX + 1) + rand();
}
//printf("before: ");
//for (int i = 0; i < ARRSIZE; i++) printf("%d ", arr[i]);
//printf("\n");
time_t start = time(NULL);
int result = ScoopSort(arr, ARRSIZE, 0);
time_t end = time(NULL);
//printf("after: ");
for (int i = 0; i < ARRSIZE; i++) printf("%d ", arr[i]);
printf("\nlooped %d time(s).\ntook %d second(s).", result, end - start);
free(arr);
return 0;
}
int test1(){
//3 0 3 2 6 3 1 4 1 7
int arr[10] = { 8, 3, 4, 9, 4, 3, 9, 5, 4, 0 };
srand(time(NULL));
printf("before: ");
for (int i = 0; i < 10; i++) printf("%d ", arr[i]);
printf("\n");
time_t start = time(NULL);
int result = ScoopSort(arr, 10, 0);
time_t end = time(NULL);
printf("after: ");
for (int i = 0; i < 10; i++) printf("%d ", arr[i]);
printf("\nlooped %d time(s).\ntook %d second(s).", result, end - start);
return 0;
}
int main(){
test2();
return 0;
}
in short, it is somewhat of a count sort mixed with bucket sort for limited memory. so still O(N^2) but probably faster than the last one..
I went from the last question -> count sort + insertion sort -> to this. I am also wondering if theres still a more efficient way (except for hashing).
test results:
size = 10000000, rand() short int range:
quicksort: took 12 seconds
above: 1 loop, took 0 seconds
size = 10000000, rand() int range:
quicksort: took 8 seconds
above: 108 loops, took 21 seconds
its good enough for small values since its basically a counting sort, but for big values not so much.

Counting Sort displays a weird behavior

I have implemented a Counting Sort in an assignment given to us by a teacher but sometimes it doesn't work for large arrays.
Here is the code:
void countingSort(int *t, int n) {
int min = findMin(t, n);
int max = findMax(t, n);
int range = max - min + 1;
int *count, *output;
int i;
count = (int *)malloc(range * sizeof(int));
output = (int *)malloc(n * sizeof(int));
for (i = 0; i < range; i++) {
count[i] = 0;
}
for (i = 0; i < n; i++) {
count[t[i] - min]++;
}
for (i = 1; i < range; i++) {
count[i] += count[i - 1];
}
for (i = n - 1; i >= 0; i--) {
output[count[t[i] - min] - 1] = t[i];
count[t[i] - min]--;
}
for (i = 0; i < n; i++) {
t[i] = output[i];
}
}
What's wrong with my code?
Your code seems to work for small values of range, but might fail if min and max are too far apart, causing the computation of range to overflow the range of int and malloc() to fail.
You should check for overflow in range and check memory allocation success. Note too that calloc() is more appropriate than malloc() for the count array. Finally, you must free the allocated arrays.
Here is a modified version:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int findMax(const int *t, int n) {
int max = INT_MIN;
while (n-- > 0) {
if (max < *t) max = *t;
t++;
}
return max;
}
int findMin(const int *t, int n) {
int min = INT_MAX;
while (n-- > 0) {
if (min > *t) min = *t;
t++;
}
return min;
}
int countingSort(int *t, int n) {
int min, max, range, i;
int *count, *output;
if (n <= 0)
return 0;
min = findMin(t, n);
max = findMax(t, n);
if (min < 0 && max >= 0 && (unsigned)max + (unsigned)(-min) >= INT_MAX) {
fprintf(stderr, "countingSort: value range too large: %d..%d\n", min, max);
return -1;
}
range = max - min + 1;
if ((count = (int *)calloc(range, sizeof(int))) == NULL) {
fprintf(stderr, "countingSort: cannot allocate %d element count array\n", range);
return -1;
}
if ((output = (int *)malloc(n * sizeof(int))) == NULL) {
fprintf(stderr, "countingSort: cannot allocate %d element output array\n", n);
free(count);
return -1;
}
for (i = 0; i < n; i++) {
count[t[i] - min]++;
}
for (i = 1; i < range; i++) {
count[i] += count[i - 1];
}
for (i = n; i-- > 0;) {
output[count[t[i] - min] - 1] = t[i];
count[t[i] - min]--;
}
for (i = 0; i < n; i++) {
t[i] = output[i];
}
free(count);
free(output);
return 0;
}
You can avoid the cumbersome and potentially inefficient downward loop by replacing the second and third for loops with this:
/* compute the first index for each value */
int index = 0;
for (i = 0; i < range; i++) {
incr = count[i];
count[i] = index;
index += incr;
}
/* copy each value at the corresponding index and update it */
for (i = 0; i < n; i++) {
output[count[t[i] - min]++] = t[i];
}

Radix sort for 10^6 array in C [duplicate]

This question already has answers here:
Understanding memory allocation, test program crashing
(4 answers)
Closed 7 years ago.
i have this code and it crash in the middle of processing. System gives message "filename.exe stopped working. What is wrong here?
I declare array as global to be able to have so big number of elements, but still it doesn't work.
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000000
#define SHOWPASS
void print(int *a, int n) {
int i;
for (i = 0; i < n; i++)
printf("%d\t", a[i]);
}
void radix_sort(int *a, int n) {
int i, b[MAX], m = 0, exp = 1;
for (i = 0; i < n; i++) {
if (a[i] > m)
m = a[i];
}
while (m / exp > 0) {
int box[10] = { 0 };
for (i = 0; i < n; i++)
box[a[i] / exp % 10]++;
for (i = 1; i < 10; i++)
box[i] += box[i - 1];
for (i = n - 1; i >= 0; i--)
b[--box[a[i] / exp % 10]] = a[i];
for (i = 0; i < n; i++)
a[i] = b[i];
exp *= 10;
#ifdef SHOWPASS
printf("\n\nPASS : ");
print(a, n);
#endif
}
}
int arr[MAX];
int main() {
//int arr[MAX];
int i, num;
printf("\nEnter total elements (num < %d) : ", MAX);
scanf("%d", &num);
printf("\ncreate array : ");
for (i = 0; i < num; i++)
arr[i]=rand()%10;
printf("\nARRAY : ");
print(&arr[0], num);
radix_sort(&arr[0], num);
printf("\n\nSORTED : ");
print(&arr[0], num);
return 0;
}
Here is another code i tried, this time i used malloc. But still it crashes before starting sort. everything is fine if number of elements is <100000.
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000000
#define SHOWPASS
void print(int *a, int n) {
int i;
for (i = 0; i < n; i++)
printf("%d\t", a[i]);
}
void radix_sort(int *a, int n) {
int i, b[MAX], m = 0, exp = 1;
for (i = 0; i < n; i++) {
if (a[i] > m)
m = a[i];
}
while (m / exp > 0) {
int box[10] = { 0 };
for (i = 0; i < n; i++)
box[a[i] / exp % 10]++;
for (i = 1; i < 10; i++)
box[i] += box[i - 1];
for (i = n - 1; i >= 0; i--)
b[--box[a[i] / exp % 10]] = a[i];
for (i = 0; i < n; i++)
a[i] = b[i];
exp *= 10;
#ifdef SHOWPASS
printf("\n\nPASS : ");
print(a, n);
#endif
}
}
int i, num;
int main() {
int* arr = (int*)malloc(MAX * sizeof(int));
int i;
printf("\ncreate array : ");
for (i = 0; i < MAX; i++)
arr[i]=rand()%10;
printf("\nARRAY : ");
print(&arr[0], MAX);
radix_sort(&arr[0], MAX);
printf("\n\nSORTED : ");
print(&arr[0], MAX);
free(arr);
return 0;
}
The bug is here:
int i, b[MAX], m = 0, exp = 1;
Allocating a huge (1 million int) array on the stack is not possible on some if not most systems.
You should malloc the temporary array and allocate only the size needed for the sort, namely n * sizeof(int).
Another problem is this: your radix_sort cannot handle negative numbers.
Less important but worth mentioning: your implementation is not stable. Not a problem for simple int arrays, but potentially incorrect for larger structures.
Furthermore, your code is inefficient: you use division and modulo 10. It would be much faster to use shifting and masking.
Here is a more efficient implementation for large arrays:
#include <limits.h>
#include <string.h>
#include <stdlib.h>
static void radix_sort(int *a, size_t size) {
size_t counts[sizeof(*a)][256] = {{ 0 }}, *cp;
size_t n, i, sum;
unsigned int *tmp, *src, *dst, *aa;
dst = tmp = malloc(size * sizeof(*a));
src = (unsigned int *)a;
for (i = 0; i < size; i++) {
unsigned int v = src[i] + (unsigned int)INT_MIN;
for (n = 0; n < sizeof(*a) * 8; n += 8)
counts[n >> 3][(v >> n) & 255]++;
}
for (n = 0; n < sizeof(*a) * 8; n += 8) {
cp = &counts[n >> 3][0];
if (cp[0] == size) continue;
for (i = sum = 0; i < 256; i++)
cp[i] = (sum += cp[i]) - cp[i];
for (i = 0; i < size; i++)
dst[cp[((src[i] + (unsigned int)INT_MIN) >> n) & 255]++] = src[i];
aa = src;
src = dst;
dst = aa;
}
if (src == tmp) {
memcpy(a, src, size * sizeof(*a));
}
free(tmp);
}

Resources