bucket sort Implementation without using vector,pointer and counting sort - c

We want to use Bucket sort to sort numbers between 1 to 2001. the count of numbers can be 10E6.
I know the bucket sort algorithm. But the issue is that in this question, we are not permitted to use variable-length array, vector and pointer. (The only pointer related thing allowed is "pass by reference" of the array) The only solution I found is using using counting sort for each bucket, like the code below, so the code is more like counting sort than the bucket sort: (C language)
#include <stdio.h>
int buckets[201][10]={}; int numbers[1000001]={};
void bucket_sort (int a[],int n) {
for (int i =0;i<=n-1;i++)
{
int index = a[i]/10, index2 = a[i]%10;
buckets[index][index2]++;
}
int counter =0;
for (int i =0;i<=200;i++)
{
for (int j =0; j<=9;j++)
{
while (buckets[i][j])
{
a[counter] = i*10+j;
counter++;
buckets[i][j]--;
}
}
} }
int main() {
int n;
scanf("%d",&n);
if (n==0)
{
return 0;
}
for (int i =0;i<=n-1;i++)
{
scanf("%d",&numbers[i]);
numbers[i];
}
bucket_sort(numbers,n);
for (int i =0;i<=n-1 ;i++)
{
printf("%d\n", numbers[i]);
}
return 0; }
I want to know can bucket sort be implemented without variable-length array, vector and pointer and also without counting sort. Probably using Insertion or Bubble sort. Note that it must be a reasonable bucket-sort algorithm. So defining very big buckets like int bucket [201][1000000]; is also an unacceptable approach.

Given that you can't use variable length arrays or pointers, one of which is required for a bucket sort, your best bet is to go with a counting sort. You only have 2000 possible values, so create an array of size 2000 and for each value you find increments the corresponding array element.
void counting_sort(int a[], int n)
{
int count[2002] = { 0 };
int i, j;
for (i=0; i<n; i++) {
count[a[i]]++;
}
for (i=0, j=0; i<n; i++) {
while (!count[j]) {
j++;
}
a[i] = j;
count[j]--;
}
}

Related

Left Shift/ Right Shift an array using two pointers in C

I am trying to implement a Left shift/ Right Shift on arrays.
I was able to accomplish this using double loops.
Can I get some help to improve the efficiency?
This is the working code for LeftShift/RightShift which is using 2 loops.
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
struct Array
{
int A[10];
int size;
int length;
};
void Display(struct Array arr)
{
printf("\nElements are : \n");
for(int i = 0;i<arr.length;i++)
printf("%d ", arr.A[i]);
}
// Left Shift-------------------------------------------------------------------------------------------------------
void LeftShift1(struct Array *arr, int n) //n is the number of shifts
{
int temp = arr->A[0];
for(int i=0; i<n; i++)
{
for(int j=0; j<arr->length-1; j++)
{
arr->A[j] = arr->A[j+1];
}
arr->A[arr->length-1] = 0;
}
}
//Right Shift-------------------------------------------------------------------------------------------------------
void RightShift(struct Array *arr, int n) //n is the number of shifts
{
for(int i = 0; i<n; i++)
{
for(int j=arr->length-1; j>0; j--)
{
arr->A[j] = arr->A[j-1];
}
arr->A[0] = 0;
}
}
int main()
{
struct Array arr={{1,2,3,4,5},10,5};
LeftShift1(&arr, 2);
//RightShift(&arr, 1);
Display(arr);
return 0;
}
I'm trying something like this which uses 2 iterators to solve this problem!
This is also working!
void LeftShift2(struct Array *arr, int n)
{
for(int k=0; k<n; k++)
{
int i,j;
for(i=0, j=0; j<arr->length-1; i++, j++)
{
arr->A[j] = arr->A[j+1];
}
arr->A[arr->length-1] = 0;
}
}
But can this be solved without loops? OR with a single loop?
Can this be made more efficient?
some help to improve the efficiency?
Shift: Shift once. Go from O(n*length) to O(length).
Rotate: Shift once into a temporary. Go from O(n*length) to O(length).
Qualify n first.
void LeftShift_alt(struct Array *arr, int n) {
if (n > arr->length) {
n = arr->length;
}
memmove(&arr->A[0], &arr->A[n], (arr->length - n)*sizeof arr->A[0]);
memset(&arr->A[arr->length - n], 0, n * sizeof arr->A[0]);
}
void LeftRotate_alt(struct Array *arr, int n) {
if (arr->length > 0) {
n %= arr->length;
if (n > 0) {
int temp[n];
memcpy(temp, arr->A, sizeof temp);
memmove(arr->A, arr->A + n, sizeof arr->A[0] * (arr->length - n));
memcpy(arr->A + n, temp, sizeof temp);
}
}
}
Replace mem...() with pointer code if desired.
Rather than actually moving the contents of the array around, you could provide all the common accessor operators (<<, >>, [], etc.) in the struct. (Assuming you're using a compiler that supports this. Otherwise, you'll need to create these functions C-style.) If someone did this:
my_array <<= 5;
my_array >>= 2;
...you'd simply keep track of how much the array has been shifted. In this case, they've shifted a total of 3 positions to the left. When someone indexes into the array, you add the accumulated offset to their index (modulo the size of the array) to get the actual location of the entry they're looking for. This makes shifts O(1) instead of O(n). If you're looking for an efficient solution, this is about as good as it gets.
After CODE REVIEW:
In C, efficiency can be improved by using a single loop. Instead of shifting elements one position at a time we can move them n positions!
Something like this:
void LeftShift1(struct Array* arr, unsigned int n) {
if (n > arr->length) {
n = arr->length;
}
for (unsigned int i = 0; i < arr->length; i++) {
if (i + n < arr->length)
arr->A[i] = arr->A[i + n];
else
arr->A[i] = 0;
}
}
In practical usage, we would want to consider doing this array shifting with element types other than a plain int. In fact, it may be a complex type like a string and we should not do raw memcpy on string.
In my code, I was setting the shifted-out elements to 0 which was OK for an integer and related types, but it won't work similarly in string.
As of C++20, there is a standard std::shift_left and std::shift_right ready to use.
There also exists std::rotate which can be used to rotate the elements.
int arr[] = {1,2,3,4,5};
using std::ranges::begin;
using std::ranges::end;
std::shift_left (begin(arr),end(arr),2);
Display(arr);
Also in C++, we should use flexible container like vector in place of struct!
Also If we are doing a lot of adding and removing elements from both ends then there is a container specifically designed for that called deque ("doubly ended queue").

Bubble Function sorting in C on an array of integers

I have coded out a Bubble Function that is supposed to Bubble sort an array of user input integers, but for some reason, my array is only working with arrays with size 6... otherwise the array outputs a zero for the largest number. Please run this code and help me identify the problem.
#include <stdio.h>
//prototype
void bubble(int array[], int size);
int main(void)
{
int n,i,j,size,temp,counter = 0;
//FOR SOME REASON, ONLY INPUT SIZE 6 WORKS PERFECTLY.
int k;
printf("How many numbers to sort?\n");
scanf("%d",&size);
int array[size];
for(i=0;i<size;i++)
{
printf("Enter number %d\n",i+1);
scanf("%d",&k);
array[i] = k;
}
printf("Array before sorting:\n");
for(i=0;i<size;i++)
{
printf("%d ",array[i]);
}
bubble(array,size);
return 0;
}
// use this if you want to test print an array
// for(i=0;i<size;i++)
// {
// printf("%d",array[i]);
// }
void bubble(int array[], int size)
{
int i, j, temp;
for(j=0;j<size;j++)
{
printf("\nIteration# %d\n",j+1);
for(i=0;i<size;i++)
{
if(array[i] > array[i+1])
{
temp = array[i];
array[i] = array[i+1];
array[i+1] = temp;
}
printf("%4d",array[i]);
}
}
}
// void select(int array[], int size)
// {
// int i, j, temp;
// min = array[0];
// for(j=0;j<size;j++)
// {
// if(array[j] < min)
// {
// array[j] = temp;
// min = array[j];
// }
// }
// }
Your inner-loop top-end conditional break is size, but within the loop you reference array[i+1], which means you're referring to array[size]. Since C arrays are zero-base indexed, the only allowable indexing is from 0...(size-1). Your code breaches that by one item repeatedly.
Changing the top-end of the inner loop to size-1 will work in your case. but there is arguably a better alternative that alleviates you from remembering the minus-1 in the first place. It involves modifying size as you sort to control the top-end of your inner loop directly. It also eliminates one local variable that you no longer need).
void bubble(int array[], int size)
{
while (size-- > 0)
{
for(int i=0; i<size; ++i)
{
if(array[i] > array[i+1])
{
int temp = array[i];
array[i] = array[i+1];
array[i+1] = temp;
}
}
}
}
Often called a "goes-down-to" expression (because it looks like a long arrow pointing at a limiting value), the outer loop has been changed to become while (size-- > 0). This takes the current value of size to a temporary, decrements size, and compares the temporary against > 0 (more or less). The result is size now reflects the top limit of your inner loop that you want. Each enumeration of the outer loop will shrink the next inner loop pass by one. The point of bubble sort is that, once an element has been "bubbled up" to its proper position, you need not visit that element ever again, something your code is not taking advantage of.
Bonus Optimization
Finally, you can optimize this further and give your bubblesort the one and only redeeming quality the algorithm can offer: O(n) in best case where the sequence is already sorted. You do this by doing "swap-detection". If you ever pass over the inner loop without making a single swap, it makes no sense to perform anymore sorting. The sequence is sorted and you're done. It's a near-freebie addition to the original algorithm above, and looks like this:
void bubble(int array[], int size)
{
int swapped = 1;
while (swapped && size-- > 0)
{
swapped = 0;
for(int i=0; i<size; ++i)
{
if(array[i] > array[i+1])
{
int temp = array[i];
array[i] = array[i+1];
array[i+1] = temp;
swapped = 1;
}
}
}
}
Given an already sorted sequence of a ten, a hundred, or a hundred-thousand elements, this will finish after only one pass. Worth noting: even one element out of position on one extreme end will make this optimization irrelevant. I.e. if any element that belongs near the beginning is originally near the end, it will take up to size iterations to bring it home, and with that the optimization becomes moot. In short, this sequence
1 3 4 5... 9998 9999 2
will completely foil the optimization above. There are techniques to combat this as well including a two pass inner loop enumeration, where you ascend to bubble up larger values, then reverse direction to descend, bubbling down smaller values. but at this point you're better off using a finer algorithm like quicksort or heapsort. The discussion of that, and indeed the latter half of this post, is beyond the scope of your question.
i<size in combination with i+1 will go past the bounds of the array.
You should replace this:
for(i=0;i<size;i++)
with this:
for(i=0;i<size-1;i++)

sorting algorithm implementation in c

in order to sort an array in ascending order, i thought of the following:
#define SIZE 10 //as an example
void swapValues(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
void sort(int *array)
{
int i, j;
for(i = 0; i < SIZE-1; i++) {
for(j = i + 1; j < SIZE; j++) {
if(array[i] > array[j]) {
swapValues( (array+i) , (array+j) );
}
}
}
}
the function works, but after taking a look on
this, i'm a bit curious, this looks like a bubble sort algorithm, but it isn't, so:
is this function an implementation of an already known sorting algorithm?
how would this function fare in comparison to other simple sorting algorithms like bubble sort or selection sort?
Your implementation is using selection sort. It's not bubble sort. Since in bubble sort we compare two consecutive elements at once, therefore this isn't it. This is selection sort where in you compare one element with the rest of elements at a time in an array, and swap accordingly.

Radix sort gives wrong answer by changing just one loop of count subroutine

It seems a very trivial problem but after a lot of thinking I still can't figure it out. I worte these two codes for Radix sort.
Code 1
#include <stdio.h>
#include <malloc.h>
#define BUCKET_SIZE 10
void prin(int* arr,int n)
{
int i;
for(i=0;i<n;i++)
printf("%d ",*(arr+i));
printf("\n");
}
int maxi(int* arr,int n)
{
int i,max=0;
for(i=0;i<n;i++)
{
if(arr[i]>max)
max=arr[i];
}
return max;
}
int* count(int *arr,int n,int k)
{
int* count,i,index;
int* output;
count=(int*)calloc(BUCKET_SIZE-1,sizeof(int));
output=(int*)malloc(n*sizeof(int));
for(i=0;i<n;i++)
{
index=(arr[i]/k)%10;
count[index]++;
}
for(i=0;i<BUCKET_SIZE;i++)
count[i]+=count[i-1];
for(i=n-1;i>=0;i--)
{
index=(arr[i]/k)%10;
output[count[index]-1]=arr[i];
count[index]--;
}
return output;
}
int* radixsort(int* arr,int n)
{
int i,max,k=1;
max=maxi(arr,n);
while(max>0)
{
max/=10;
arr=count(arr,n,k);
k=k*10;
}
return arr;
}
void main()
{
int n,i;
scanf("%d",&n);
int* arr;
arr=(int*)malloc(n*sizeof(int));
for(i=0;i<n;i++)
scanf("%d",(arr+i));
arr=radixsort(arr,n);
prin(arr,n);
}
Now if I change the sort subroutine like below, this code will not sort the given array and I can't figure why this happened, I am still traversing the whole array so and I am still calculating the right index so my elements should be filled in the right place and I should have a sorted array.
Code 2
Only count function last loop changed.
int* count(int *arr,int n,int k)
{
int* count,i,index;
int* output;
count=(int*)calloc(BUCKET_SIZE-1,sizeof(int));
output=(int*)malloc(n*sizeof(int));
for(i=0;i<n;i++)
{
index=(arr[i]/k)%10;
count[index]++;
}
for(i=0;i<BUCKET_SIZE;i++)
count[i]+=count[i-1];
for(i=0;i<n;i++)
{
index=(arr[i]/k)%10;
output[count[index]-1]=arr[i];
count[index]--;
}
return output;
}
When I am doing just counting sort both functions work well. Can someone point me out where I am going wrong with radix sort, or what is the thing I am missing, and how both well in counting sort.
Thanks.
In your final loop in your count function,
when these lines copy the contents of each "bucket",
they write the last element of the output "bucket" first,
followed by the next-to-last, ending with the first element:
output[count[index]-1]=arr[i];
count[index]--;
In the first version of your program, since you visit the elements of the input array starting at the end of the array and working your way back toward the beginning,
you encounter the last element of each bucket first (and therefore put it in the last position in the output bucket), then the next-to-last element
(which you put in the next-to-last position in the output),
and so forth. The first element of each bucket is the last copied
and is copied to the first position in the bucket.
In the second version of your program, you continue to fill in the spaces in each output bucket from back to front, but you read the input from front to back. This has the result of putting the first element of each bucket in the last position within that bucket, and the last element of the bucket in the first position.
That is, each time you run the count function it reverses the order of elements within each bucket.
If you want to copy the input array reading it from front to back,
you need to fill in each output bucket from front to back
by using ++count[index] instead of --count[index].
You also have to start each entry of count[index] at a lower number so that you write to the correct locations.
Aside: your program does a lot more allocation than it needs to, and doesn't free any memory, so you have a potentially massive memory leak.
You might consider passing already-allocated arrays into count instead of always allocating new ones.
Here is a front to back example, that also replaces the original array with a sorted array, freeing the original array. An alternative would be to do a one time allocation of a second working array, radix sort back and forth between original and working arrays, then keep the sorted array, and free the "other" array.
#include <stdio.h>
#include <stdlib.h>
#define BUCKET_SIZE 10
void prin(int* arr, int n)
{
int i;
for(i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
}
int maxi(int* arr, int n)
{
int i,max = 0;
for(i = 0; i < n; i++)
{
if(arr[i] > max)
max = arr[i];
}
return max;
}
/* replaces array with sorted array, frees original array */
void count(int** parr, int n, int k)
{
int* count, i, index;
int* arr = *parr;
int* output;
int sum, cur;
count=calloc(BUCKET_SIZE, sizeof(int));
output=malloc(n*sizeof(int));
for(i = 0; i < n; i++){
index = (arr[i]/k)%10;
count[index]++;
}
sum = 0;
for(i = 0; i < BUCKET_SIZE; i++){
cur = count[i];
count[i] = sum;
sum += cur;
}
for(i = 0; i < n; i++){
index = (arr[i]/k)%10;
output[count[index]++] = arr[i];
}
free(arr);
free(count);
*parr = output;
}
void radixsort(int** parr,int n)
{
int max,k=1;
max=maxi(*parr,n);
while(max>0)
{
max/=10;
count(parr,n,k);
k=k*10;
}
}
int main()
{
int n,i;
int* arr;
scanf("%d",&n);
arr = malloc(n*sizeof(int));
for(i = 0; i < n; i++)
scanf("%d",&arr[i]);
radixsort(&arr,n);
prin(arr,n);
free(arr);
return 0;
}

LCP array for Suffix Array

How to compute the LCP array for a suffix array? It doesn't have to be the most efficient. O(n log n) or O(n) will do. Something relatively easy to code if possible.
Here is a simple C++ implementation.
Longest common prefix(LCP) will be saved in lcp[MAX] array :)
char str[MAX];
int n,gap,sa[MAX],pos[MAX],tmp[MAX],lcp[MAX];
// sa stores the sorted index of the suffixes
// pos stores the serial number of a index in the sorted sequence
bool sufCmp(int i, int j)
{
if(pos[i]!=pos[j])
return pos[i]<pos[j];
i+=gap;
j+=gap;
return (i<n&&j<n)?pos[i]<pos[j]:i>j;
}
void buildSA()
{
n=strlen(str);
for(int i=0;i<n;i++)
sa[i]=i,pos[i]=str[i];
for(gap=1;;gap*=2)
{
sort(sa,sa+n,sufCmp);
for(int i=0;i<n-1;i++)
tmp[i+1]=tmp[i]+sufCmp(sa[i],sa[i+1]);
for(int i=0;i<n;i++)
pos[sa[i]]=tmp[i];
if(tmp[n-1]==n-1)
break;
}
}
void buildLCP()
{
for(int i=0,k=0;i<n;++i)
{
if(pos[i]==n-1)
lcp[pos[i]]=0;
else
{
for(int j=sa[pos[i]+1];str[i+k]==str[j+k];)
k++;
lcp[pos[i]]=k;
if(k)
k--;
}
}
}

Resources