counting number of swaps in insertion sort - c

In the problem given here, i have to count total no. of swaps required while sorting an array using insertion sort.
here is my approach
#include <stdio.h>
int main()
{
int t, N, swaps, temp, i, j;
scanf("%d", &t);
while(t--){
scanf("%d", &N);
int arr[N];
swaps = 0;
for(i=0; i<N; ++i){
scanf("%d", &temp);
j=i;
while(j>0 && arr[j-1] > temp){
arr[j] = arr[j-1];
++swaps;
--j;
}
arr[j] = temp;
}
printf("%d\n", swaps);
}
return 0;
}
but, this soln is giving time limit exceeded.
How can i make it more fast?
and, what are the other better solutions of this problem?

this is a standard problem named inversion count
This can be solved using mergesort in O(n*lg(n)). Here is my code for counting the inversions
int a[200001];
long long int count;
void Merge(int p,int q,int r)
{
int n1,n2,i,j,k,li,ri;
n1=q-p+1;
n2=r-q;
int l[n1+1],rt[n2+1];
for(i=0;i<n1;i++)
l[i]=a[p+i];
for(i=0;i<n2;i++)
rt[i]=a[q+1+i];
l[n1]=LONG_MAX;
rt[n2]=LONG_MAX;
li=0;ri=0;
for(i=p;i<=r;i++)
{
if(l[li]<=rt[ri])
a[i]=l[li++];
else
{
a[i]=rt[ri++];
count+=n1-li;
}
}
}
void mergesort(int p,int r)
{
if(p<r)
{
int q=(p+r)/2;
mergesort(p,q);
mergesort(q+1,r);
Merge(p,q,r);
}
}
int main()
{
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
count=0;
mergesort(0,n-1);
printf("%lld\n",count);
}
Basically the problem of inversion count is to find the no. of pairs i and j where j>i such that a[i]>a[j]
To know the idea behind this you should know the basic merge sort algorithm
http://en.wikipedia.org/wiki/Merge_sort
Idea:
Use divide and conquer
divide: size of sequence n to two lists of size n/2
conquer: count recursively two lists
combine: this is a trick part (to do it in linear time)
combine use merge-and-count. Suppose the two lists are A, B. They are already sorted. Produce an output list L from A, B while also counting the number of inversions, (a,b) where a is-in A, b is-in B and a>b.
The idea is similar to "merge" in merge-sort. Merge two sorted lists into one output list, but we also count the inversion.
Everytime a_i is appended to the output, no new inversions are encountered, since a_i is smaller than everything left in list B. If b_j is appended to the output, then it is smaller than all the remaining items in A, we increase the number of count of inversions by the number of elements remaining in A.

This reminds me of a similar problem you may want to look at: http://www.spoj.pl/problems/YODANESS/
In your problem, you can't afford the time to swap everything in case there are many swaps required. (imagine if the input was in reverse order 9,8,7,6.. then you would have to swap everything with everything basically.
I think in your case, each number must be swapped with all the numbers to the left of it that are smaller than it.
I suggest you use a range tree http://en.wikipedia.org/wiki/Range_tree
The great thing about a range tree is each node can know how many nodes are to its left and to its right. You could ask the tree "how many numbers are there greater than 10" very efficiently and that's how many swaps you would have for a 9 say.
The trick is to build the range tree as you move from i=0 to i=N-1. At each point you can query the tree against the ith number before inserting the ith number into the range tree.
good luck!

I did the same code in c++, and it is getting accepted,it is taking time about 4.2 seconds on spoj(http://www.spoj.com/submit/CODESPTB/).
here is the code snippet:
//http://www.spoj.com/problems/CODESPTB/
//mandeep singh #msdeep14
#include<iostream>
using namespace std;
int insertionsort(int arr[], int s)
{
int current,i,j,count=0;
for(i=1;i<s;i++)
{
current=arr[i];
for(j=i-1;j>=0;j--)
{
if(current<arr[j])
{
arr[j+1]=arr[j];
count++;
}
else
break;
}
arr[j+1]=current;
}
return count;
}
int main()
{
int t,n,i,res;
int arr[100000];
cin>>t;
while(t--)
{
cin>>n;
for(i=0;i<n;i++)
{
cin>>arr[i];
}
res=insertionsort(arr,n);
cout<<res<<endl;
}
return 0;
}

#include < stdio.h >
int main() {
int N, swaps, temp[100], i, j;
scanf("%d", & N);
int arr[N];
swaps = 0;
for (i = 0; i < N; i++) {
scanf("%d", & temp[i]);
j = i;
while (j > 0 && arr[j - 1] > temp[i]) {
arr[j] = arr[j - 1];
++swaps;
--j;
}
arr[j] = temp[i];
}
printf("%d", swaps);
return 0;
}

Related

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++)

Merge Sort doesn't work for a table of integers with more than 521096 elements

I am trying to sort a large table of integers using different types of sorting algorithms like quick sort, bubble sort and merge Sort, all of these algorithms works just fine. However, When trying to sort a table with more than than 521096 elements using Merge Sort, the program just exits without throwing any error(I'm guessing in C this is a runtime error)
Note that Merge Sort works perfectly with a table that contains less than 921096 elements.
Note also that for example Quick Sort works fine with tables of any length(I've tried up to 1 Million elements).
Here is the code I'm using:
void fillTable(int *t,int n){
srand(time(NULL));
int signe=1;
for(int *p=t;p<t+n;p++){
*(p)=signe*rand()%n;
signe*=-1;
}
}
void mergeTables(int *tab,int l,int m,int r){
int i,j,k;
int n1=m-l+1;
int n2=r-m;
int lTab[n1],rTab[n2];
for(i=0;i<n1;i++){
lTab[i]=tab[l+i];
}
for(i=0;i<n2;i++){
rTab[i]=tab[m+1+i];
}
i=0;j=0;k=l;
while(i<n1 && j<n2){
if(lTab[i]<=rTab[j]){
tab[k]=lTab[i];
i++;
}
else{
tab[k]=rTab[j];
j++;
}
k++;
}
while(i<n1){
tab[k]=lTab[i];
i++;
k++;
}
while(j<n2){
tab[k]=rTab[j];
j++;
k++;
}
}
void diviserTab(int *tab,int l,int r){
if(r>l){
int m=(r+l)/2;
diviserTab(tab,l,m);
diviserTab(tab,m+1,r);
mergeTables(tab,l,m,r);
}
}
void mergeSort(int* t,int n){
diviserTab(t,0,n-1);
}
double getTime(void(*f)(int*,int),int* t,int n){
clock_t start,end;
start=clock();
f(t,n);
end=clock();
return (double)(end-start)/CLOCKS_PER_SEC;
}
and here is my Main:
int main(){
int *tab;
int i;
int n=521096;
tab=(int*)malloc(n*sizeof(int));
fillTable(tab,n);
printf("First 10 elements before sorting");
for ( i = 0; i < 10; i++)
{
printf("%5d\t",tab[i]);
}
printf("%f\n",getTime(mergeSort,tab,n));
printf("\nFirst 10 elements before sorting\n");
for ( i = 0; i < 10; i++)
{
printf("%5d\t",tab[i]);
}
return 0;
}
Now to the results:
if n=521095 (number of elements in the array)
First 10 elements before sorting
18187 -12205 23363 -27523 30572 -31906 5475 -10341 5178 -27678
it took 0.179000 to sort the array
First 10 elements after sorting
-32767 -32767 -32767 -32767 -32767 -32767 -32767 -32766 -32766 -32766
if n=521096
First 10 elements before sorting
18243 -31088 32141 -10616 9312 -356 25619 -26113 23731 -21465
(and it just exits)
You are allocating some large arrays on the stack. From your mergeTables function:
int lTab[n1],rTab[n2];
With a large array to sort, n1 and n2, and therefore lTab and rTab, can become large (half the size of your initial array), and the stack is typically fairly small. If the arrays don't fit, all sorts of strange things can happen. When I tried your program with a large array (10 million integers), the program crashed.
Quicksort and bubble sort are usually performed in situ, so I assume you didn't need all this extra space for them.
I changed your two arrays to this:
int *lTab = malloc(n1 * sizeof(int));
int *rTab = malloc(n2 * sizeof(int));
And then at the end of the function:
free(lTab);
free(rTab);

QuickSort not sorting properly

I have a this program to receive a struct, store it and then sort it. I have tried to use Shell Sort, but then I went for the Quick Sort Algorithm. However, when I try to print the array after sorting, it still returns it unsorted. Bear in mind im trying to sort it by 'num_aluno'.
CODE
typedef struct ALUNO
{
char primeiro_nome[15];
char segundo_nome[15];
int num_aluno;
float nota;
}ALUNO;
void swap(ALUNO* a, ALUNO* b)
{
ALUNO t=*a;
*a=*b;
*b=t;
}
int partition(ALUNO *studentList, int low, int high)
{
int pivot= studentList[high].num_aluno;
int i=(low-1);
int j;
for(j=low;j<=high-1;j++)
{
if(studentList[j].num_aluno<=pivot);
{
i++;
swap(&studentList[i], &studentList[j]);
}
}
swap(&studentList[i+1], &studentList[high]);
return(i+1);
}
void quickSort(ALUNO *studentList, int low, int high)
{
if(low<high)
{
int pi=partition(studentList, low, high);
quickSort(studentList, low, pi-1);
quickSort(studentList, pi+1, high);
}
}
int main()
{
ALUNO *studentList=NULL;
int currentPos, studentListSize=1;
//float grade_sum=0;
studentList=(ALUNO*)calloc(studentList, studentListSize*sizeof(ALUNO));
printf("Insira o numero de alunos \n");
scanf("%d", &studentListSize);
studentList=(ALUNO*)realloc(studentList, studentListSize*sizeof(ALUNO));
for(currentPos=0;currentPos<studentListSize;currentPos++)
{
newStudent(studentList, currentPos);
}
quickSort(studentList, 0, studentListSize);
for(currentPos=0;currentPos<studentListSize;currentPos++)
{
printStudent(studentList,currentPos);
}
free(studentList);
return 0;
}
Any help would be appreciated
The reason it doesn't sort the list is, i and j are always the same value in the partition function.
You should start j from high -1, not from low.
Also, you are not considering the values of studentList[i]. You must guarantee that it is larger than pivot, otherwise there may be a value which is smaller than the pivot, yet at the left part of the array.
Here, corrected it.
int partition(ALUNO*studentList, int low, int high)
{
int pivot = studentList[high].num_aluno;
int i=low ;
int j;
for(j=high-1;j>=i;)
{
while(studentList[i].num_aluno < pivot)
i++;
while(studentList[j].num_aluno > pivot)
j--;
if(i<=j){
swap(&studentList[i], &studentList[j]);
i++;
j--;
}
}
swap(&studentList[i], &studentList[high]);
return(i+1);
}
An additional advice in case you have not heard of it, do not choose the first or last values as pivots. Instead, use the median of three strategy.
Median of three strategy: Pick the first, middle and last elements in the unsorted array. Change their locations according to their values in a sorted manner. Then take the middle value and use it as a pivot. This way you are avoiding the worst time complexity(O(n^2)) of QuickSort.

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;
}

How to find mode from an array

I have been trying to get this prototype for finding mode of an array to work but it is not returning the right thing, could someone please tell me what I am doing wrong.
int mode(int array[], int size)
{
int x;
int mode = 0;
int largest = 0;
for (x = 0; x < size; x++)
{
if (array[x] > largest)
{
largest = array[x];
mode = x;
}
}
return mode;
}
First of all if that's c++ Arrays are numbered from 0, so x should be 0 in the for. also x should be checked against < size. Other then that the code is good.
In the question you've mentioned that " prototype for finding mode of an array " ,but this program is intended to find the position of the largest number in an array, because
mode = x; // x is the value of i which in-turn is the position of element in the array
and the value of mode is returned. So the position of the largest element counting from the zero'th element's position is shown.
If you want a program to find the mode (element/number that occurs most often) in an array, here it is
#include <stdio.h>
int mode(int array[], int size);
int main()
{
int Num[100],size,ret_Val,i;
clrscr();
printf("Enter the size of the array\n");
scanf("%d",&size);
printf("%d ",size);
for(i=0;i<size;i++)
{
scanf("%d",&Num[i]);
}
ret_Val=mode(Num,size);
printf("Mode of the array is %d",ret_Val);
getch();
return 0;
}
int mode(int array[], int size)
{
int cntMde = 1;
int i;
int cnt = 1;
int num = array[0];
int mode = num;
for ( i=1; i<size; i++)
{
if (array[i] == num)
{
cnt++;
}
else
{
if (cnt > cntMde)
{
cntMde = cnt;
mode = num;
}
cnt = 1;
num = array[i];
}
}
return mode;
}
And the output is
Mode of the array is 44
I have analyzed four ways to calculate mode of the array:
If range of numbers in the array is small then use counting sort - O(N) time, (N) space but very efficient
Index elements in the array in hash table - O(N) time, O(N) space
Sort the array and then count successive equal elements - O(NlogN) time, O(1) space
Partially sort the array but skip partitions smaller than current candidate - O(NlogN) time, O(1) space but much more efficient than fully sorting the array because many partitions will be skipped
You can find source code for all four methods and performance comparison in this article: Finding Mode of an Array

Resources