Counting Sort issue in array - c

I am making an algorithm for counting sort. In first step i have initialized the second array with 0. Secondly i counted the frequency of elements in second for loop. In third loop i am trying to sort the array. The third loop does not run in code blocks. Also it's not giving me right sorted result.Any issue with third loop. As it changes array to 1-1-2-0-2-2-0-1-1 rather it should be 0-0-0-1-1-1-1-2-2-2
printf("Hello world!\n");
unsigned m=3;
unsigned n=10;
unsigned x;
unsigned k;
unsigned data[10] = {0, 2, 1, 1, 0, 2, 2, 0, 1, 1};
unsigned *count;
count =(unsigned *)malloc(sizeof(unsigned)*m);
int y=sizeof(data);
for(int i=0;i<m;i++)
{
count[i]=0;
}
for(int j=0;j<n;j++)
{
x=data[j];
count[x]++;
}
for(k=n-1;k>=0;k--)
{
data[count[data[k]]-1]=data[k];
count[data[k]]=count[data[k]]-1;
}
for(int i=0;i<n;i++)
{
printf("%d \n",data[i]);
}
return 0;
}

In this line
for(k=n-1;k>=0;k--)
k is unsigned so k >= 0 is always true. When an unsigned integer would go below zero, its value "wraps".
Also, your sorting loop does not sort anything. It can't because there are no comparisons. You may like to review your algorithm.

The problem (in addition to the loop condition error mentioned in another answer) is that this appears to be a combination of two incompatible counting sort approaches.
The "traverse the input array backwards, inserting each element into the appropriate place in the output array" approach requires a separate output array. Consider the simple case of sorting {2, 1}: if we copy the 1 into the appropriate slot in the same array, it becomes {1, 1}, which will end up being our final output. Instead, that 1 needs to be placed into the appropriate slot of a separate array so that we don't overwrite the 2.
Additionally, this approach requires us to make a second pass over the count array to change its semantic meaning from "count of elements with value n" to "index of first element with value > n". This is accomplished by adding the total so far to each element of count (so in your case, count would go from {3, 4, 3} to {3, 7, 10}). After this step, count[n] - 1 is the index in the output array at which the next n should be placed.
Given that you're sorting integers, a second (easier) approach is also possible: once you've finished your initial traversal of the input array, count holds all the information you need, so you can freely overwrite the input array. Just start at the beginning and insert count[0] 0s, count[1] 1s, etc. This approach doesn't require any postprocessing of count or any separate output array.

Related

Element with left side smaller and right side greater in C

I'm very confused about the function implemented for the following code. What does the returning of 'i' mean? What is the exact logic behind it? If I do the dry run and return 'i', where is this 'i' getting returned to?
Given an array, find an element before which all elements are smaller than it, and after which all are greater than it. Return the index of the element if there is such an element, otherwise, return -1.
Input: arr[] = {5, 1, 4, 3, 6, 8, 10, 7, 9};
Output: 4
int SlideToTheLeft(int a[],int n){
int left[n], i;
left[0]=0;
for(i=1;i<n;i++){
left[i]=Max(left[i-1],a[i-1]);
}
int right=100;
for(i=n-1;i>=0;i--){
if(left[i]<a[i] && right>a[i]){
return i;
}
right=Min(right,a[i]);
}
return -1;
}
The first loop populates the "left" array. This array stores the largest value to the left of a given index. So for example, if left[3] is 7, we know that a[0], a[1], and a[2] are less than or equal to 7.
The second loop traverses the array from right to left, keeping track of the largest value to the right of the current index. We start with a value of right=100. This assumes that all values of a[] will be less than 100. We then traverse the array and update "right" if we encounter lower values of a[] than our current lowest. This is done in "right=Min(right,a[i]);".
Every time we go through the loop, we check for the condition where left[i]<a[i] (all indexes to the left are smaller than a[i], and right>a[i] (all indexes to the right are greater than a[i]. If we meet this condition, we return i (since this is the index which meets this condition).

Replace the array element with the multiples of all other elements throughout the array with O(n)

I have an array arr = [3,4,2,5,6,8,2]. Every element in the array has to be replaced with the multiples of all other elements in the array.
e.g index=0, value 3 must be replaced with 4*2*5*6*8*2 and index=3, value 5 must be replaced with 3*4*2*6*8*2.
And this must be done in O(n).
I have solutions with dequeue and stack but i end up doing n*n-1 iterations resulting in O(n^2). Any help?
First, calculate the total Product of this array.
Then, for each element in the array divide by that value and assign the result to its position.
So the total product is done in O(n), the assignment is also done in O(n).
=> ALG: O(2*n) = O(n)
Form two arrays: one cumulative product from the left, and one cumulative product from the right. They can each be constructed in O(2*n).
Take the left-cumulative product for the element to the left and multiply by the right-cumulative product to the right. That takes O(n).
Something like:
leftCumulative[1]=1;
for(j=2;j<=n;++j) leftCumulative[j]=leftCumulative[j-1]*arr[j];
rightCumulative[n]=1;
for(j=n-1;j>=1;--j) rightCumulative[j]=arr[j]*rightCumulative[j+1];
arr[1]=rightCumulative[2];
arr[n]=leftCumulative[n-1];
for(j=2;j<=n-1;++j) arr[j]=leftCumulative[j-1]*rightCumulative[j+1];
It is possible to use less extra memory, and make the loop cleaner, but this solves the stated problem. It even works if multiplication is non-commutative!
Using java,
int[] arr = {3, 4, 2, 5, 6, 8, 2};
int wholeProduct = arr[0]; // wholeProduct = arr[0] * arr[1] * ... * arr[n-1]
for(int i=1; i<arr.length; i++)
wholeProduct *= arr[i];
for(int i=0; i<arr.length; i++)
arr[i] = wholeProduct/arr[i];
Same technique described by #Lecagy.
Please Note, when the contains many elements, the wholeProduct may not contains the result, you need to change the type to long or BigInteger.

Why is this code for implementing mergesort not producing correct result?

Here in I'm trying to implement mergesort on array of 10 elements. On providing the input a[10]={9,8,7,6,5,4,3,2,1,0} , I obtain the output as {0,0,1,1,0, 4,4,4,3,2} while the expected output is {0,1,2,3,4,5,6,7,8,9}. I am calling the mergesort in main with l=0,h=9.
void mergesort(int a[],int l,int h)
{
int c[10];
int m=(l+h)/2;
if(l<h)
{
mergesort(a,l,m); // Recursive call to sort first half
mergesort(a,m+1,h); // Recursive call to sort second half
}
int i,k=l,j=l;
while(k<=h) // Merging the first and second half of the array
{
if(a[j]<a[m+1])
{
c[k]=a[j];
k++;
j++;
}
else
{
c[k]=a[m+1];
k++;
m++;
}
}
for(i=l;i<=h;i++)
a[i]=c[i];
}
One of the few problems: Your value of l is no longer a valid left limit after the while loop since you are incrementing it. So when you are copying from array c to a later in the for loop, you are copying invalid data.
The problem is that in your while loop you are sometimes looking outside the bounds you should be.
Assuming you put in a check at the beginning of your function saying if l==h then return (since sorting a one element array is unnecessary) then the first time it will do anything is when it recurses to mergesort(a, 0,1). Here we are basically merging two single element arrays.
When going through your loop the first time we have i,j,k,m=0. We will go into the else part of the if because element 0 is greater than 1. We thus write out a[1] into the output array and we now have i,j=0 and k,m=1. What we now should do is note that our second array is exhausted and fill from the remaining elements in the first array.
Instead what we do is compare elements j and m+1 (ie 0 and 2). This is clearly wrong because element 2 shouldn't appear in the array. We of course find element 2 is smaller and thus put that into the output array at position two. Once we copy this over a we get {8, 7, 7, 6, 5, 4, 3, 2, 1, 0} and this is where it all goes wrong.

What does ++ do after the array in this function?

void doSomething()
{
int hist[5] = { 0 };
int num_bins = 5;
int indices[10] = { 0, 0, 2, 3, 3, 3, 3, 4, 4, 4 };
int num_indices = 10;
int i;
for (i = 0; i < num_indices; i++)
{
hist[indices[i]]++;
}
for (i = 0; i < num_bins; i++)
{
printf("%d ", hist[i]);
}
printf("\n");
}
Assume I have correct libraries this is a conceptual question from class. I am wondering how the answer comes out to 2 0 1 4 3 for the array.
The line
hist[indices[i]]++
Says "go to the element of the hist array at index indices[i], then increment it." If you think of the array as a list of counters, this says to increment the counter at position indices[i].
This code builds a histogram of the frequencies of various numbers in an array. The idea behind the above code is to iterate over the array and increment the frequencies of each element.
Hope this helps!
The elements in indices range from 0 to 4, which are all valid index of the 5 elements array hist. (That's why the array is named indices, as it's for indexing)
So for instance, i is 2, then indices[i] is 2.
hist[indices[i]]++;
is equivalent to
hist[2]++;
For small questions like this you should try to write down the state of every element of each array on a piece of paper and execute your code step by step. You could also write the code to print useful information in runtime.
If after that you still can't figure it out then it's worth asking here. Otherwise you won't be learning much.
This program increments the 0's in
hist
as it indexes appear in
indices[10]
eg.
when you have the first for interation
hist[indices[0]]++ // hist[0]++ --> 0++;
It looks like "2 0 1 4 3" is a count of how many items exists in the array. 2 0's, 0 1's, 1 2, 4 3's and 3 4's. So the query is counting how many instances of each number are in the array and then printing out that result.
So the statement:
hist[indices[i]]++
find the value of indices[], then increments the int in the hist[] array by 1 giving you a count of how many of those elements are in the array.
1.As you have partially initialized your array, compiler sets other values to 0
2.hist[indices[i]]++; this statement increments the value of hist[i], for the current value of i
3.the value of i is denoted by your array indices[]
4.try having values grater than 5 in your array named indices[].

Interleave array in constant space

Suppose we have an array
a1, a2,... , an, b1, b2, ..., bn.
The goal is to change this array to
a1, b1, a2, b2, ..., an, bn in O(n) time and in O(1) space.
In other words, we need a linear-time algorithm to modify the array in place, with no more than a constant amount of extra storage.
How can this be done?
This is the sequence and notes I worked out with pen and paper. I think it, or a variation, will hold for any larger n.
Each line represents a different step and () signifies what is being moved this step and [] is what has been moved from last step. The array itself is used as storage and two pointers (one for L and one for N) are required to determine what to move next. L means "letter line" and N is "number line" (what is moved).
A B C D 1 2 3 4
L A B C (D) 1 2 3 4 First is L, no need to move last N
N A B C (3) 1 2 [D] 4
L A B (C) 2 1 [3] D 4
N A B 1 (2) [C] 3 D 4
L A (B) 1 [2] C 3 D 4
N A (1) [B] 2 C 3 D 4
A [1] B 2 C 3 D 4 Done, no need to move A
Note the varying "pointer jumps" - the L pointer always decrements by 1 (as it can not be eaten into faster than that), but the N pointer jumps according to if it "replaced itself" (in spot, jump down two) or if it swapped something in (no jump, so the next something can get its go!).
This problem isn't as easy as it seems, but after some thought, the algorithm to accomplish this isn't too bad. You'll notice the first and last element are already in place, so we don't need to worry about them. We will keep a left index variable which represents the first item in the first half of the array that needs changed. After that we set a right index variable to the first item in the 2nd half of the array that needs changed. Now all we do is swap the item at the right index down one-by-one until it reaches the left index item. Increment the left index by 2 and the right index by 1, and repeat until the indexes overlap or the left goes past the right index (the right index will always end on the last index of the array). We increment the left index by two every time because the item at left + 1 has already naturally fallen into place.
Pseudocode
Set left index to 1
Set right index to the middle (array length / 2)
Swap the item at the right index with the item directly preceding it until it replaces the item at the left index
Increment the left index by 2
Increment the right index by 1
Repeat 3 through 5 until the left index becomes greater than or equal to the right index
Interleaving algorithm in C(#)
protected void Interleave(int[] arr)
{
int left = 1;
int right = arr.Length / 2;
int temp;
while (left < right)
{
for (int i = right; i > left; i--)
{
temp = arr[i];
arr[i] = arr[i - 1];
arr[i - 1] = temp;
}
left += 2;
right += 1;
}
}
This algorithm uses O(1) storage (with the temp variable, which could be eliminated using the addition/subtraction swap technique) I'm not very good at runtime analysis, but I believe this is still O(n) even though we're performing many swaps. Perhaps someone can further explore its runtime analysis.
First, the theory: Rearrange the elements in 'permutation cycles'. Take an element and place it at its new position, displacing the element that is currently there. Then you take that displaced element and put it in its new position. This displaces yet another element, so rinse and repeat. If the element displaced belongs to the position of the element you first started with, you have completed one cycle.
Actually, yours is a special case of the question I asked here, which was: How do you rearrange an array to any given order in O(N) time and O(1) space? In my question, the rearranged positions are described by an array of numbers, where the number at the nth position specifies the index of the element in the original array.
However, you don't have this additional array in your problem, and allocating it would take O(N) space. Fortunately, we can calculate the value of any element in this array on the fly, like this:
int rearrange_pos(int x) {
if (x % 2 == 0) return x / 2;
else return (x - 1) / 2 + n; // where n is half the size of the total array
}
I won't duplicate the rearranging algorithm itself here; it can be found in the accepted answer for my question.
Edit: As Jason has pointed out, the answer I linked to still needs to allocate an array of bools, making it O(N) space. This is because a permutation can be made up of multiple cycles. I've been trying to eliminate the need for this array for your special case, but without success.. There doesn't seem to be any usable pattern. Maybe someone else can help you here.
It's called in-place in-shuffle problem. Here is its implementation in C++ based on here.
void in_place_in_shuffle(int arr[], int length)
{
assert(arr && length>0 && !(length&1));
// shuffle to {5, 0, 6, 1, 7, 2, 8, 3, 9, 4}
int i,startPos=0;
while(startPos<length)
{
i=_LookUp(length-startPos);
_ShiftN(&arr[startPos+(i-1)/2],(length-startPos)/2,(i-1)/2);
_PerfectShuffle(&arr[startPos],i-1);
startPos+=(i-1);
}
// local swap to {0, 5, 1, 6, 2, 7, 3, 8, 4, 9}
for (int i=0; i<length; i+=2)
swap(arr[i], arr[i+1]);
}
// cycle
void _Cycle(int Data[],int Lenth,int Start)
{
int Cur_index,Temp1,Temp2;
Cur_index=(Start*2)%(Lenth+1);
Temp1=Data[Cur_index-1];
Data[Cur_index-1]=Data[Start-1];
while(Cur_index!=Start)
{
Temp2=Data[(Cur_index*2)%(Lenth+1)-1];
Data[(Cur_index*2)%(Lenth+1)-1]=Temp1;
Temp1=Temp2;
Cur_index=(Cur_index*2)%(Lenth+1);
}
}
// loop-move array
void _Reverse(int Data[],int Len)
{
int i,Temp;
for(i=0;i<Len/2;i++)
{
Temp=Data[i];
Data[i]=Data[Len-i-1];
Data[Len-i-1]=Temp;
}
}
void _ShiftN(int Data[],int Len,int N)
{
_Reverse(Data,Len-N);
_Reverse(&Data[Len-N],N);
_Reverse(Data,Len);
}
// perfect shuffle of satisfying [Lenth=3^k-1]
void _PerfectShuffle(int Data[],int Lenth)
{
int i=1;
if(Lenth==2)
{
i=Data[Lenth-1];
Data[Lenth-1]=Data[Lenth-2];
Data[Lenth-2]=i;
return;
}
while(i<Lenth)
{
_Cycle(Data,Lenth,i);
i=i*3;
}
}
// look for 3^k that nearnest to N
int _LookUp(int N)
{
int i=3;
while(i<=N+1) i*=3;
if(i>3) i=i/3;
return i;
}
Test:
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int length = sizeof(arr)/sizeof(int);
in_place_in_shuffle(arr, length);
After this, arr[] will be {0, 5, 1, 6, 2, 7, 3, 8, 4, 9}.
If you can transform the array into a linked-list first, the problem becomes trivial.

Resources