Pointer array sorting in C has unexpected output - c

#include <stdio.h>
void sort(int *ptr, int n) {
int i,j,tmp;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (ptr[i] < ptr[j])
{
tmp=ptr[i];
ptr[i]=ptr[j];
ptr[j]=tmp;
}
}
int main() {
int i,n;
int *ptr;
printf("Nr. of elements : 5 \n");
n=5;
ptr=(int*)malloc( n * sizeof(int));
for (i=0;i<n;i++) {
scanf("%d",&ptr[i]);
}
printf("Initial array is : ");
for (i=0;i<n;i++) {
printf("%d ",ptr[i]);
}
sort(ptr,n);
printf("Sorted array is : ");
for (i=0;i<n;i++) {
printf("%d ",ptr[i]);
}
return 0;
}
This is my code. I'm trying to sort a pointer array using a function.
Whatever the (int) input, it sorts out fine.
My confusion is that i'm using
ptr[i] < ptr[j]
instead of
ptr[i] > ptr[j]
as it should normally be to sort it ascending.
Why is that?

No, your confusion is misplaced. Look at the for loops, and the relation between i and j. There are times when i < j and times when i > j, so what constitutes being "out of order" and requiring a swap?
The inner loop should start at i+1 not at '0'; that will make the relation between i and j invariant.

Given your loops go from i = 0 .. n and j = 0 .. n, there is no guarantee in your code that i < j.
There's two ways to fix this:
void sort(int *ptr, int n) {
int i,j,tmp;
for (i=0; i<n; i++) {
for (j=0; j<n; j++) {
if (i < j && ptr[i] < ptr[j]) { // Note the changed conditional
tmp=ptr[i];
ptr[i]=ptr[j];
ptr[j]=tmp;
}
}
}
}
or
void sort(int *ptr, int n) {
int i,j,tmp;
for (i=0; i<n; i++) {
for (j=i+1; j<n; j++) { // Note the changed start value
if (ptr[i] < ptr[j]) {
tmp=ptr[i];
ptr[i]=ptr[j];
ptr[j]=tmp;
}
}
}
}

As we can see, you are using bubble sort.
In bubble sort, our main intention is either transfer the heavier element to the end or lighter element to the top.
(ptr[i] < ptr[j])
what you are doing is moving the heavy elements to the end of the array, this is why whenever you are finding ptr[j](j is an inner loop variable) which is bigger than the ptr[i] (outer loop variable), you are doing a swap.

Related

Facing Runtime error while Solving finding and counting duplicates in c

Can someone please help me i am facing runtime error while solving this problem.
I have first defined the integers and then used scanf to take the input.
Then i check whether the 2 consecutive elements of array are equal are not.
if they are equal i equate j variable to i+1 and so that it can traverse and find if same duplicate elements are side by side (eg- 15 15 15).
I increment the j element till a[j] is equal to a[i].
Then using i try to print the number with the number of occurences of it which is j-i and then assign i with vakue of j-1.
#include <stdio.h>
int main()
{
int n,j=0,i;
scanf("%d",&n);
int a[n];
for (i = 0; i < n; ++i) {
scanf("%d",&a[i]);
}
for (i = 0; i < n - 1; ++i)
{
if(a[i]==a[i+1])
{
j=i+1;
while(j<n && a[i]==a[j])
{
j++;
}
printf("%d is appearing %d times\n",a[i],j-i);
}
i=j-1;
}
return 0;
}
The input array needs to be sorted first to count duplicated, the loop logic needs to be fixed to reassign the index i.
A fixed code might like this:
#include <stdio.h>
#include <stdlib.h>
static int cmp_intp(const void *p1, const void *p2) {
return *(const int *)p1 > *(const int *)p2;
}
int main() {
int n, j = 0, i;
scanf("%d", &n);
int a[n];
for (i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
qsort(a, n, sizeof(a[0]), cmp_intp);
for (i = 0; i < n;) {
if (i < n - 1 && a[i] == a[i + 1]) {
j = i + 1;
while (j < n && a[i] == a[j]) {
j++;
}
printf("%d is appearing %d times\n", a[i], j - i);
i = j;
} else {
++i;
}
}
return 0;
}
The problem is created by the line,
i=j-1;
in the case when two consecutive elements are not equal.
move it within the if condition.

bubble sorting of Array in c

I Made a selection and bubble sort for the array , the selection sort is ok ,but the bubble sort start sorting from the element no (5) of the array and from {0 to 4} no sorting
#include <stdio.h>
#include <stdlib.h>
//// Makeing a swaping Function/////
void swap(int* x,int* y)
{
int temp= *y;
*y= *x;
*x= temp;
}
//// Makeing a sorting Function selection_ sort/////
void selection_sort_elements(int array[],int len)
{
int i,j;
int flag =1;
for (i=0;i<len;i++)
{
printf("Number of Iteration: %d \n",i);
for(j=i+1;j<len;j++)
{
if(array[i]>array[j])
{
swap(&array[i],&array[j]);
}
}
}
}
//// Makeing a sorting Function Bubble sort/////
void bubble_sort_elements(int array[],int len)
{
int i=0,j=0;
//int flag =1;
for (i = 0; i < len ;i++)
{
printf("Number of Iteration: %d \n",i);
//if(flag == 0){
// return;
//}
//flag=0;
for(j = i+1 ; j < len ;j++)
{
if(array[j] < array[j-1])
{
// flag=1;
swap(&array[j],&array[j-1]);
}
}
}
}
int main()
{
int arr[10];
int i=0;
printf("Please Enter A Five Element Of The Array\n");
for (i=0;i<10;i++)
{
scanf("%d",&arr[i]);
}
printf(" You Entered The Array:");
for (i=0;i<10;i++)
{
printf(" %d ", arr[i]);
}
bubble_sort_elements(arr,sizeof(arr)/sizeof(arr[0])); // Calling Sorting Function
printf("\n Now We Sorted Your Array :");
for (i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
printf(" %d ", arr[i]);
}
//Getting The max Number in the array and its position
printf("\n The MAX Number In The Array IS %d And it location is %d ", arr[(sizeof(arr)/sizeof(arr[0]))-1], sizeof(arr)/sizeof(arr[0])-1);
//Getting The Min Number in the array and its position
printf("\n The Min Number In The Array IS %d And it location is %d ", arr[0], sizeof(arr)/sizeof(arr[0])-sizeof(arr)/sizeof(arr[0]));
return 0;
}
I Made a selection and bubble sort for the array , the selection sort is ok ,but the bubble sort start sorting from the element no (5) of the array and from {0 to 4} no sorting
I uploaded image for the response
Your bubble-sort algorithm is wrong. You either need an ascending sweep with a continuously reduced ceiling, or a descending sweep with a continuously advanced floor. You have an ascending sweep with a continuously advancing floor. Your inner loop should be for (j = 1; j<(len-i); ++j) if you want to keep the ascending sweep, but fix the algorithm to use a continuously reduced ceiling.
void bubble_sort_elements(int array[], size_t len)
{
size_t i = 0, j = 0;
for (i = 0; i < len; i++)
{
printf("Number of Iteration: %zu \n", i);
for (j = 1; j<(len-i); ++j)
{
if (array[j] < array[j - 1])
{
// flag=1;
swap(&array[j], &array[j - 1]);
}
}
}
}
Alternatively, you can forego the i and just continuously reduce len on the outer loop:
void bubble_sort_elements(int array[], size_t len)
{
while (len-- > 0)
{
for (size_t j = 0; j<len; ++j)
{
if (array[j+1] < array[j])
swap(array+j, array+j+1);
}
}
}
Finally, if you want swap detection to short-circuit an already-sorted sequence once it falls into place, the latter algorithm is immediately adaptable to that:
void bubble_sort_elements(int array[], size_t len)
{
int swapped = 1;
while (len-- > 0 && swapped)
{
swapped = 0;
for (size_t j = 0; j<len; ++j)
{
if (array[j+1] < array[j])
{
swap(array+j, array+j+1);
swapped = 1;
}
}
}
}

Can't print a modified array in C

User is asked to give a number of rows and columns to fill an array of 10x10 array with random numbers.(A part of the table will be filled e.g 2x2). Then a function called printArray will print its values.Then,function change_array will find in every row the biggest value and replace the elements left of it with the value.
For instance:
Initial Array
<p>41 67 34 0 </p>
<p>69 24 78 58</p>
<p>62 64 5 45</p>
changed Array
<p>67 67 34 0 </p>
<p>78 78 78 58 </p>
<p>64 64 5 45 </p>
However,the program gives this:
Initial Array
<p>41 67</p> <p>34 0</p>
Changed Array
<p>67 67</p>
<p>24576000 508</p>
Why is this happening?
simpio.h gets an input of integer value
This can't be done with pointers(We are not there yet in class)
The modified array must be printed in main()
#include <stdio.h>
#include <stdlib.h>
#include "simpio.h"
void populate_data(int R, int C, int A[R] [C]);
void printArray(int R, int C, int A[R] [C]);
void change_array(int R, int C, int A[R] [C]);
int main(void)
{
int A[10] [10],R,C,i,j;
while (TRUE)
{
printf("Give the number of rows: ");
R = GetInteger();
if (R>=0 && R<=10)
break;
else
{
printf("Wrong Answer\n");
}
}
while (TRUE)
{
printf("Enter the number of columns: ");
C = GetInteger();
if (C>=0 && C<=10)
break;
else
{
printf("Wrong Answer\n");
}
}
populate_data(R,C,A);
printf("Initial Array\n");
printArray(R,C,A);
change_array(R,C,A);
printf("Changed Array\n");
for (i=0; i<R; i++)
{
for (j=0; j<C; j++)
{
printf("%d ",A[i] [j]);
}
printf("\n");
}
return 0;
}
void populate_data(int R, int C, int A[R] [C])
{
int i,j;
for (i=0; i<R; i++)
{
for (j=0; j<C; j++)
{
A[i] [j] = rand() % 100;
}
}
}
void printArray(int R, int C, int A[R] [C])
{
int i,j;
for (i=0; i<R; i++)
{
for (j=0; j<C; j++)
{
printf("%-3d ",A[i] [j]);
}
printf("\n");
}
}
void change_array(int R, int C, int A[R] [C])
{
int i, j, max[R], m[R];
for (i=0; i<R; i++)
{
max[i] = A[i] [0];
for (j=0; j<C; j++)
{
if (max[i]< A[i] [j])
{
max[i] =A[i] [j];
m[i] = j;
}
}
}
for (i=0; i<R; i++)
{
for (j=0; j<C; j++)
{
if (j<m[i])
A[i] [j] = max [i];
}
}
}
This happens if the max value in a row is on first position, so you will never enter this block
if (max[i]< A[i] [j])
{
max[i] =A[i] [j];
m[i] = j;
}
and m[i] will stay uninitialized. Just add a
m[i] = 0;
before that loop.
Edit:
You must change your function definitions from A[R][C] to A[10][10], because R and C are unknown to the function at that point.
Also, there is no reason to declare the array with size 10x10. You can do that after you got the dimension from input with the correct number of rows and columns.

I want to print the number of times an element is repeated in an array of random numbers in C

Hi wanted to display repeated elements of a Random array whose size can be specified by the user. The problem I am getting in the output is , the function is printing a repeated number as many times as it has been repeated but I want to print it only once.
Here is my code and output following the former:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int array_size = 0;
int *my_array;
int i = 0;
printf("Enter the size of the array:\n");
scanf("%d",&array_size);
my_array = malloc(array_size * sizeof my_array[0]);
if(NULL == my_array) {
fprintf(stderr,"MEMORY ALLOLCATION FAILED \n");
return EXIT_FAILURE;
}
for(i=0;i<array_size;i++){
my_array[i] = rand()%array_size;
}
printf("What's in the array:\n");
for(i = 0;i<array_size;i++){
printf("%d ",my_array[i]);
}
printf("\n");
display_repeats(my_array, array_size);
free(my_array);
return EXIT_SUCCESS;
}
void display_repeats(int *a,int n){
int *repeats;
repeats = malloc(n * sizeof repeats[0]);
int i=0;
int j=0;
int count = 0;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i] == a[j]){
count++;
}
}
if(count>1){
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
count = 0;
}
free(repeats);
}
Here is the output I am getting
Enter the size of the array:
5
What's in the array:
3 1 2 0 3
3 occurs 2 times
3 occurs 2 times
I want "3 occurs 2 times" to print once.
Please help!
What's happening is that your code realizes 3 is repeated twice, in this block:
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i] == a[j]){
count++;
}
}
if(count>1){
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
}
When i is equal to 0, it will look at the array and realize that 3 is repeated, so count>1 will be true. Then, when i is equal to 4, count>1 will be true again, and you get the double print.
In order to fix this, I would create an array that stores the numbers that have already been verified as repeated and check against that.
Since in your case, value of elements < size_array, so can take this approach.
memset(repeats, 0, n*sizeof(repeats[0]));
for(i=0;i<n;i++){
for(j=0;j<n;j++){
count = repeats[a[i]];
if(count>0)
break;
if(a[i] == a[j]){
count++;
}
}
repeats[a[i]] = count;
The idea is to store the count for each value and check before starting search for each new value to check if it has already been counted.
Try it:
for(i=0;i<n-1;i++)
{
for(j=1;j<n;j++)
{
So, don't compare the same one element with itself.
Thanks guys I got it working with the above ideas!
here is what I got..
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int array_size = 0;
int *my_array;
int i = 0;
printf("Enter the size of the array:\n");
scanf("%d",&array_size);
my_array = malloc(array_size * sizeof my_array[0]);
if(NULL == my_array) {
fprintf(stderr,"MEMORY ALLOLCATION FAILED \n");
return EXIT_FAILURE;
}
for(i=0;i<array_size;i++){
my_array[i] = rand()%array_size;
}
printf("What's in the array:\n");
for(i = 0;i<array_size;i++){
printf("%d ",my_array[i]);
}
printf("\n");
display_repeats(my_array, array_size);
free(my_array);
return EXIT_SUCCESS;
}
void display_repeats(int *a,int n){
int *freq;
freq = malloc(n * sizeof freq[0]);
int i=0;
int j=0;
int count = 0;
for(i=0;i<n;i++){
freq[i] = -1;
}
for(i=0;i<n;i++){
count = 1;
for(j=i+1;j<n;j++){
if(a[i]==a[j]){
count++;
freq[j] = 0;
}
}
if(freq[i]!=0){
freq[i] = count;
}
}
for(i=0;i<n;i++){
if(freq[i]!=1 && freq[i]!=0){
printf("%d occurs %d times\n",a[i],freq[i]);
}
}
free(freq);
}
In display_repeats(), you may simply update 2 lines and add 3 lines to make your program have the correct behaviour. And we will see it later: we can optimize the final code using C99 syntax and the comma C operator, to write far less lines than your original code (9 lines instead of 20 lines!).
So, in this answer, you will find how to get the final code that has the correct behaviour and is very short, shorter than your initial code:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for (int j = i + 1; j < n; j++)
if (a[i] == a[j]) count++, a[j] = -1;
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
The idea is to set to -1 each array value that has matched a previous one, just after the count increment. Because you do not want to count this value again.
So simply do the following:
In the two lines where you write count = 0, replace 0 by 1, because you are sure that each number in the list must be counted at least one time.
This way, you can avoid checking the case where i equals j in the inner loop: it is already taken into account in count. So add if (i == j) continue; at the beginning of the inner loop.
With the previous updates, you are now sure that when you increment count, in the inner loop, j is not equal to i. Therefore, you can change the value of a[j] without changing a[i], in the array.
So, add a[j] = -1; just after having increased count. This way, when i will be incremented to check for a new count of a new value, it is impossible that the new counted value has already been counted.
Finally, you do not want to count how many times -1 is in the array. But you have replaced some values with -1. So simply add if (a[i] == -1) continue; at the beginning of the outer loop to avoid counting how -1 there are in the array.
This intermediate code is:
void display_repeats(int *a,int n) {
int *repeats;
repeats = malloc(n * sizeof repeats[0]);
int i=0;
int j=0;
int count = 1;
for(i=0; i<n; i++) {
if (a[i] == -1) continue;
for(j=0; j<n; j++) {
if (i == j) continue;
if(a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if(count > 1) {
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
count = 1;
}
free(repeats);
}
Now, we can optimize this code.
First, we can avoid testing a[i] == a[j] when j <= i: if such a case happens, we know that we have previously displayed the count for a[j] (the number of times a[j] appears in the array). Therefore we can replace for (j=0; j < n; j++) { by for (j=i+1; j<n; j++) {.
With this last update, we know that the first line of the inner loop will never match: i can not be equal to j. So we can remove this line (if (i == j) continue;).
Note that the values stored in the repeats array are only used to get the value of count in the printf() call. So we can remove every reference to the repeats array and simply use count in the printf() call.
Now, you can see that we set count to 1, two times. We can do it only one time, if we do not set it to 1 at the end of the main loop, to prepare a new loop, but at the beginning.
Now, note that i, j and count have the same type, so only one line may be used to define them: int i = 0, j = 0, count = 1;. More over, i and j are defined later in the for loops, so no need to define their initial value here. So we can simply write int i, j, count = 1;. But count is now defined at the beginning of the outer loop, so we do not need to define it previously. So we only need to define i, j and count without an initial value: int i, j, count;.
The new intermediate code is:
void display_repeats(int *a, int n) {
int i, j, count;
for (i = 0; i < n; i++) {
if (a[i] == -1) continue;
count = 1;
for(j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
Using C99 syntax
But we can do more, using the C99 specification: we can define a variable with the for instruction: we can write for (int i = ...). No more need to define it previously. So we can avoid having to write int i, j, count;, we will define them at first use:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for(int j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
Using the comma C operator
Again, we can do much better! We can use the comma operator (,): it is a binary operator that evaluates its first operand, discards the result, evaluates the second operand and returns its value. Using the comma operator, we can transform count++; a[j] = -1; to a single instruction: a[j] = (count++, -1). But we can avoid the parenthesis writing count++, a[i] = -1. Now, we do not need a block for the if statement, since there is only one instruction. Therefore, we can remove a lot of parenthesis.
The final code is:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for (int j = i + 1; j < n; j++)
if (a[i] == a[j]) count++, a[j] = -1;
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}

C: Sort vector elements in descending order

I am trying to create a function that will rearrange an array so it is in descending order. The array is made up from positive integers, with no two equal elements. This is what I have:
int check (int *v, int n){
int i;
for (i=0; i<n; i++){
if (v[i] != -1){
return -1;
break;
}
else return 1;
}
}
void sortVector (int *v, int n){
int i, k, j=0, vp[n];
while (check(v,n) == -1){
for (i=0; i<n; i++){
for (k=i+1; k<n; k++){
if (v[k] > v[i]) break;
else if (k == n-1){
vp[j] = v[i];
v[i] = -1;
j++;
}
}
}
}
for (i=0; i<n; i++)
v[i] = vp[i];
}
Which is not working correctly. I've been thinking about this for the past week so some pointers would be great. Thanks.
I tried to follow the idea that you have stated in your comment by starting from your code above and made few changes and here is the two final functions
#include <stdio.h>
int check (int *v, int n)
{
int i;
for (i=0; i<n; i++)
{
if (v[i] != -1)
{
return -1; // break is useless because return has the same effect
}
}
return 1; // you need to add a return here to handle all the cases
// the case if the loop is not entered you need to return a value
}
void sortVector (int *v, int n)
{
int i, k, j=0, vp[n];
int maxIndex=0;//you need to add this variable in order to keep track of the maximum value in each iteration
while (check(v,n) == -1)
{
for (i=0; i<n; i++)
{
maxIndex=i; //you suppose that the maximum is the first element in each loop
for (k=i+1; k<n; k++)
{
if (v[k] > v[maxIndex])
maxIndex=k; // if there is another element greater you preserve its index in the variable
}
//after finishing the loop above you have the greatest variable in the array which has the index stored in maxIndex
vp[i] = v[maxIndex]; // put it in vp array
v[maxIndex]=v[i];//put it in treated elements zone
v[i]=-1;// make it -1
j++;
}
}
for (i=0; i<n; i++)
v[i] = vp[i];
}
This is the test
int main()
{
int tab[]= {1,152,24,11,9};
sortVector (tab, 5);
int i=0;
for(i=0; i<5; i++)
{
printf("%d ",tab[i]);
}
return 0;
}
which gives the desired output
152 24 11 9 1
Note: You can improve your code by making swaps on the same array instead of allocating another array !
There are really lots of algorithms for sorting. A simple algorithm is to find the minimum element in your array and put it in the first position by swapping it with whatever item was in the first position and then recursively sorting the array but this time starting at the next position.
void sort(int a[], int l, int r)
{ if(l == r) return; /* 1-elemnt array is already sorted */
int min = l;
for(int i = l+1; i <= r; i++)
{ if(a[i] < a[min])
{ min = i;
}
}
swap(a[l], a[min]);
sort(a, l+1, r);
}
You can also do it iteratively.
Perhaps, the intention like following
int check (int *v, int n){
int i;
for (i=0; i<n; i++){
if (v[i] != -1){
return -1;
//break; //This code that does not reach
}
//else return 1; //move to after for-loop
}
return 1;
}
void ordenaVetor (int *v, int n){
int i, k, j=0, vp[n];
while (check(v,n) == -1){
for (i=0; i<n; i++){
if(v[i]<0) continue;//Element of -1 excluded. v[k] too.
for (k=i+1; k<n; k++){
if (v[k]>=0 && v[i] < v[k]) break;
}
if (k == n){
vp[j] = v[i];
v[i] = -1;
j++;
break;//start over
}
}
}
for (i=0; i<n; i++){
v[i] = vp[i];
}
}
You could use an existing sort implementation instead of reinventing the wheel:
#include <stdlib.h>
int desc(void const *a, void const *b)
{
if ( *(int *)a < *(int *)b ) return 1;
return -1;
}
void sortVector (int *v, int n)
{
qsort(v, n, sizeof *v, desc);
}

Resources