Sorting array only with while and if - c

I get a message when I try to run the program. Why?
Segmentation fault
my code:
#include <stdio.h>
void sort_array(int *arr, int s);
int main() {
int arrx[] = { 6, 3, 6, 8, 4, 2, 5, 7 };
sort_array(arrx, 8);
for (int r = 0; r < 8; r++) {
printf("index[%d] = %d\n", r, arrx[r]);
}
return(0);
}
sort_array(int *arr, int s) {
int i, x, temp_x, temp;
x = 0;
i = s-1;
while (x < s) {
temp_x = x;
while (i >= 0) {
if (arr[x] > arr[i]) {
temp = arr[x];
arr[x] = arr[i];
arr[i] = temp;
x++;
}
i++;
}
x = temp_x + 1;
i = x;
}
}
I think that the problem is in the if statement.
What do you think? Why does it happen? I think that I use in positive way with the pointer to the array.
Thank you!

This loop in your program
while (i >= 0) {
//...
i++;
}
does not make sense because i is increased unconditionly.
The program can look the following way
#include <stdio.h>
void bubble_sort( int a[], size_t n )
{
while ( !( n < 2 ) )
{
size_t i = 0, last = 1;
while ( ++i < n )
{
if ( a[i] < a[i-1] )
{
int tmp = a[i];
a[i] = a[i-1];
a[i-1] = tmp;
last = i;
}
}
n = last;
}
}
int main( void )
{
int a[] = { 6, 3, 6, 8, 4, 2, 5, 7 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
bubble_sort( a, N );
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
return 0;
}
The program output is
6 3 6 8 4 2 5 7
2 3 4 5 6 6 7 8
If you want that the sorting function had only one while loop then you can implement it the following way
void bubble_sort( int a[], size_t n )
{
size_t i = 0;
while ( ++i < n )
{
if ( a[i] < a[i-1] )
{
int tmp = a[i];
a[i] = a[i-1];
a[i-1] = tmp;
i = 0;
}
}
}

In your inner loop, you increment i beyond the size of the array. Your algorithm should require you to decrement i instead, but I am not sure this would be enough to fix the sorting algorithm.
You should first try to implement Bubble sort with a single while loop where you compare adjacent items and step back whenever you swap them.

Related

How to sort an array that going down and then going up, to array that going down all the way?

I have an assignment to make a function that sort array that going down and then going up (for example: 9, 8, 7, 6, 5, 7, 11, 13) to array that going down all the way (for example: 13, 11, 9, 8, 7, 7, 6, 5).
I wrote this in online compiler (programiz), but it just doesn't work for me.
#include <stdio.h>
#include <stdlib.h>
#define N 10
void sort_dec_inc(int a[], int n) {
int pivot, i, q = 0;
int c[n];
for (i=0; i<n; i++) {
c[i] = 0;
}
for (i=0; i<n-1; i++) {
if (a[i]<a[i+1]) {
pivot=i+1;
break;
}
}
if (pivot == n-1) {
return;
}
for (i=0; i<pivot && n>=pivot; q++) {
if (a[i]>=a[n]) {
c[q] = a[i];
i++;
}
else {
c[q] = a[n];
n--;
}
}
if (n==pivot) {
while(i<pivot) {
c[q] = a[i];
q++;
i++;
}
}
else {
while (n>=pivot) {
c[q] = a[n];
q++;
n--;
}
}
for(i=0; i<n; i++) {
a[i] = c[i];
}
}
int main()
{
int num_arr[N] = {9, 7, 5, 3, 1, 2, 4, 6, 8, 10};
sort_dec_inc(num_arr, N);
int i;
for(i = 0; i < N; i++) {
printf("%d ", num_arr[i]);
}
return 0;
}
output (most of the times) : 9 7 5 3 1 2 4 6 8 10
Sometimes the output is different, for example: (410878976 10 9 8 1 2 4 6 8 10 )
If someone can answer in simple code its the best, I don't understand yet all the options in C.
(I'm sorry if its a clumsy code, I'm new for this.)
thanks a lot!
Solution based on the comments below:
#include <stdio.h>
#include <stdlib.h>
#define N 10
void sort_dec_inc(int a[], int n) {
int left, i = 0;
int right = n-1;
int c[n];
while (i<n) {
if (a[left] >= a[right]) {
c[i] = a[left];
left++;
}
else {
c[i] = a[right];
right--;
}
i++;
}
for(i=0; i<n; i++) {
a[i] = c[i];
}
}
int main()
{
int num_arr[N] = {9, 7, 5, 3, 1, 2, 4, 6, 8, 10};
sort_dec_inc(num_arr, N);
int i;
for(i = 0; i < N; i++) {
printf("%d ", num_arr[i]);
}
return 0;
}
output: 10 9 8 7 5 5 4 3 2 1
For starters it is a bad idea to define an auxiliary variable length array. Such an approach is unsafe because the program can report that there is no enough memory to allocate the array.
At least this code snippet
for (i=0; i<n-1; i++) {
if (a[i]<a[i+1]) {
pivot=i+1;
break;
}
}
if (pivot == n-1) {
return;
}
contains a logical error.
Consider an array that contains only two elements { 1, 2 }. In this case a[0] is less than a[i+1] that is than a[1]. So the condition of the if statement
if (pivot == n-1) {
return;
}
evaluates to logical true and the function returns the control though the array was not sorted in the descending order. It stays unchanged.
Or consider this code snippet
if (a[i]>=a[n]) {
c[q] = a[i];
i++;
}
The expression a[n] accesses memory beyond the array that results in undefined behavior.
A straightforward approach is to use the method insertion sort.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
void insertion_sort( int a[], size_t n )
{
size_t i = 1;
while ( i < n && !( a[i-1] < a[i] ) ) i++;
for ( ; i < n; i++ )
{
size_t j = i;
while ( j != 0 && a[j-1] < a[i] ) --j;
if ( i != j )
{
int tmp = a[i];
memmove( a + j + 1, a + j, ( i - j ) * sizeof( int ) );
a[j] = tmp;
}
}
}
int main( void )
{
int a[] = { 9, 7, 5, 3, 1, 2, 4, 6, 8, 10 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
insertion_sort( a, N );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
}
The program output is
9 7 5 3 1 2 4 6 8 10
10 9 8 7 6 5 4 3 2 1
I would recommend a bubble sort.
It is an easy way to sort numbers in numerical order:
for (int i = 0; i < quant; i++)
{
for (int j = 0; j < quant-1; j++)
{
if (Array[j] < Array[j + 1])
{
int temp = Array[j];
Array[j] = Array[j + 1];
Array[j + 1] = temp;
}
}
}
quant is the quantity of numbers you want to sort. Don't forget to define an integer array with length quant for the sorting process.
To access the array, just use a for loop to return all the results.

find a pair of elements with the same value with the largest distance between the elements

I have an array of 'N' double values but I am trying to find a pair of the same elements that have the furthest distance between them.
So as an example;
{1, 3, 5, 3, 7, 9, 10, 5, 6, 7, 1}
Output: (1,1) has the largest distance between them
Does anyone have any ideas on how I approach this because I am completely stumped?
Thanks in advance!
Here are my five cents.:)
#include <stdio.h>
int main(void)
{
int a[] = { 1, 3, 5, 3, 7, 9, 10, 5, 6, 7, 1 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t first = 0, last = 0;
for ( size_t i = 0; i < N - ( last - first ); i++ )
{
size_t j = N;
while ( --j != i && a[j] != a[i] );
if ( j != i )
{
if ( last - first < j - i )
{
first = i;
last = j;
}
}
}
if ( first != last )
{
printf( "%d: ( %zu, %zu )\n", a[first], first, last );
}
return 0;
}
The program output is
1: ( 0, 10 )
The loops can be more optimized if to include the following condition
if ( i == 0 || a[i] != a[last] )
to skip values that were already considered.
Here is the program with this if statement.
#include <stdio.h>
int main(void)
{
int a[] = { 1, 3, 5, 3, 7, 9, 10, 5, 6, 7, 1 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t first = 0, last = 0;
for ( size_t i = 0; i < N - ( last - first ); i++ )
{
if ( i == 0 || a[i] != a[last] )
{
size_t j = N;
while ( --j != i && a[j] != a[i] );
if ( j != i )
{
if ( last - first < j - i )
{
first = i;
last = j;
}
}
}
}
if ( first != last )
{
printf( "%d: ( %zu, %zu )\n", a[first], first, last );
}
return 0;
}
Here is the same program in which a test output is inserted to show how often the inner loop is executed.
#include <stdio.h>
int main(void)
{
int a[] = { 1, 1, 1, 1, 2, 2, 2, 2, 2, 3 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t first = 0, last = 0;
for ( size_t i = 0; i < N - ( last - first ); i++ )
{
if ( i == 0 || a[i] != a[last] )
{
printf( "Inner loop for %d\n", a[i] );
size_t j = N;
while ( --j != i && a[j] != a[i] );
if ( j != i )
{
if ( last - first < j - i )
{
first = i;
last = j;
}
}
}
}
if ( first != last )
{
printf( "%d: ( %zu, %zu )\n", a[first], first, last );
}
return 0;
}
The program output is
Inner loop for 1
Inner loop for 2
2: ( 4, 8 )
So the inner loop is executed only two times.
Code could try every pair.
Yet a key is to avoid testing pairs that are less than the current known max distance.
size_t max_common_element_distance(size_t n, const double *x) {
size_t max_distance = 0;
for (size_t i = 0; i < n; i++) {
for (size_t j = i+1; j + max_distance < n; j++) {
// test beyond the max distance for a better one.
if (x[i] == x[j + max_distance]) {
max_distance = j + max_distance - i;
// Perhaps record other info here, like the index of the 2 elements
// to use as part of the "Output: ..." report
}
}
}
return max_distance;
}
Better code would run the j loop in the opposite direction, from n-max_distance-1 down t i+1. But is sounds like OP needs a good, not so complex, starting point.
Deeper: The order of complexity above is O(n*n). A O(n*log(n)) solution exists by forming a list of (value, index) pairs, sort it by value (and then by index on ties), then walk the list once to find the max index difference.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
double value;
size_t index;
} pair;
int pair_cmp(const void *a, const void *b) {
const pair *pa = a;
const pair *pb = b;
int cmp = (pa->value > pb->value) - (pa->value < pb->value);
if (cmp == 0) {
cmp = (pa->index > pb->index) - (pa->index < pb->index);
}
return cmp;
}
size_t max_common_element_distance(size_t n, const double *x) {
size_t max_distance = 0;
if (n > 0) {
pair y[n];
for (size_t i = 0; i < n; i++) {
y[i].index = i;
y[i].value = x[i];
}
qsort(y, n, sizeof y[0], pair_cmp);
size_t from, to;
size_t first = 0;
for (size_t i = 1; i < n; i++) {
if (y[i].value == y[first].value) {
size_t distance = y[i].index - y[first].index;
if (distance > max_distance) {
max_distance = distance;
from = y[first].index;
to = y[i].index;
}
} else {
first = i;
}
}
if (max_distance > 0) {
printf("from:%zu to:%zu dist:%zu val:%g\n", from, to, max_distance, x[from]);
}
}
return max_distance;
}
int main() {
double val[] = {1, 3, 5, 3, 7, 9, 10, 5, 6, 7, 1};
size_t n = sizeof val/ sizeof val[0];
max_common_element_distance(n, val);
}
Output
from:0 to:10 dist:10 val:1

Sort 2 arrays in C by a joint logic

Given two arrays
a = [1,3,2,8,5,6]
b = [4,3,2,5,1,2]
I would like to sort them in "one pass" where the "logic" involves the two arrays, meaning:
if
int sortBySum(index i, index j){
if (a[i]+b[i] > a[j]+b[j]){
return 1;
}
return -1;
}
The output of the two arrays will be
a = [2,1,3,5,6,8]
b = [2,4,3,1,2,5]
Because the original arrays sum is a+b=[5,6,4,13,6,8]
When a task is about sorting, qsort is - in most cases - your friend.
But qsort can only sort one array. So you need to copy the elements from array a and b into an array of structs containing the data from a and b. Then use qsort and then copy the data back.
Like:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
} common_data;
// Compare function for qsort
int cmp(const void *p1, const void *p2)
{
common_data* pa = (common_data*)p1;
common_data* pb = (common_data*)p2;
return ((pa->a + pa->b) - (pb->a + pb->b));
}
int main(void)
{
int a[] = {1,3,2,8,5,6};
int b[] = {4,3,2,5,1,2};
size_t sz = sizeof(a)/sizeof(a[0]);
common_data carr[sz];
// Copy to common array
for (size_t i = 0; i < sz; ++i)
{
carr[i].a = a[i];
carr[i].b = b[i];
}
// Sort common array
qsort(carr, sz, sizeof(carr[0]), cmp);
// Copy to back to original array
for (size_t i = 0; i < sz; ++i)
{
a[i] = carr[i].a;
b[i] = carr[i].b;
}
// Print array a
for (size_t i = 0; i < sz; ++i)
{
printf("%d ", a[i]);
}
printf("\n");
// Print array b
for (size_t i = 0; i < sz; ++i)
{
printf("%d ", b[i]);
}
printf("\n");
return 0;
}
Output:
2 1 3 5 6 8
2 4 3 1 2 5
A primitive approach can look the following way.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a[] = { 1, 3, 2, 8, 5, 6 };
int b[] = { 4, 3, 2, 5, 1, 2 };
const size_t N = sizeof( a ) / sizeof( *a );
printf( "a: " );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
printf( "b: " );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", b[i] );
}
putchar( '\n' );
putchar( '\n' );
for ( size_t n = N, last; !( n < 2 ); n = last )
{
for ( size_t i = last = 1; i < n; i++ )
{
if ( a[i] + b[i] < a[i-1] + b[i-1] )
{
int tmp = a[i];
a[i] = a[i-1];
a[i-1] = tmp;
tmp = b[i];
b[i] = b[i-1];
b[i-1] = tmp;
last = i;
}
}
}
printf( "a: " );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
printf( "b: " );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", b[i] );
}
putchar( '\n' );
putchar( '\n' );
return 0;
}
The program output is
a: 1 3 2 8 5 6
b: 4 3 2 5 1 2
a: 2 1 3 5 6 8
b: 2 4 3 1 2 5
The code that sorts the arrays using the method bubble sort can be moved in a separate function.

Majority element in an array.It

#include <stdio.h>
void main()
{
int maj, count, n = 6;
int arr[] = {1, 2, 2, 2, 2, 3, 4};
for (int i = 0; i < n; i++) {
maj = arr[i];
count = 0;
for (int j = 9; j < n; j++) {
if (arr[j] == maj) count++;
}
if (count > n / 2) {
break; /* I think some problem is here ,if majority element not found then it takes last element as the majority element */
}
}
printf("%d", maj);
}
It is giving correct output if majority ellement is there but incorrect output if no majority element is there for example if array is {1,2,3,4} it is giving output as 4. please help!!
#include <stdio.h>
int main() {
int maj, count, n = 7; //n is size of arr
int arr[] = {1, 2, 2, 2, 2, 3, 4};
int isFound = 0; //0 -> false, 1 -> true
for (int i = 0; i < n; i++) {
maj = arr[i];
count = 1; //first elements is itself
isFound = 0; //by default we assume that no major elements is found
for (int j = i+1; j < n; j++) { //iterate from next elements onwards to right in array
if (arr[j] == maj) count++;
}
if (count > n / 2) {
isFound = 1;
break; //major elements found; no need to iterator further; just break the loop now
}
}
if(isFound) printf("%d ", maj);
else printf("no major element");
return 0;
}
For starters according to the C Standard function main without parameters shall be declared like
int main( void )
Try not to use magic numbers. Usually as in your program they are a reason for program bugs. For example you declared the array arr as having 7 elements however the variable n that should keep the number of elements in the array is initialized with the value 6. Another magic number 9 is used in the loop
for (int j = 9; j < n; j++) {
^^^
There is no need to write the outer loop that travers the whole array. Also the program does not report the case when the majority number does not exist in the array.
Using your approach with two loops the program can look the following way
#include <stdio.h>
int main( void )
{
int a[] = { 1, 2, 2, 2, 2, 3, 4 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t i = 0;
for ( ; i < ( N + 1 ) / 2; i++ )
{
size_t count = 1;
for ( size_t j = i + 1; count < N / 2 + 1 && j < N; j++ )
{
if ( a[i] == a[j] ) ++count;
}
if ( !( count < N / 2 + 1) ) break;
}
if ( i != ( N + 1 ) / 2 )
{
printf( "The majority is %d\n", a[i] );
}
else
{
puts( "There is no majority element" );
}
return 0;
}
Its output is
The majority is 2

How to remove neighbouring duplicate in array using recursion?

I have made the following function that will remove the neighboring duplicate. How to implement it using recursion??
example 1,1,5,4,7,7,9,9,8 will result to 1, 5, 4, 7, 9, 8
void remove() {
int arr[9]={1,1,5,4,7,7,9,9,8};
int newarr[9];
int counter=0;
for(int i = 0; i < 9; i++) {
if(arr[i] == arr[i + 1]) {
newarr[counter] = arr[i];
i += 1;
counter++;
} else {
newarr[counter] = arr[i];
counter++;
}
}
for(int z = 0; z < counter; z++){
printf("%d ", newarr[z]);
}
}
First of all your program has undefined behaviour because it tries to access memory beyond the array in the loop when i is equal to 8.
for(int i = 0; i < 9; i++) {
if(arr[i] == arr[i + 1]) {
^^^^^^
The element with index equal to 9 (arr[8 + 1]) does not exist.
Moreover the logic is wrong. You are incrementing i twice when arr[i] is equal to arr[i+1]
for(int i = 0; i < 9; i++) {
^^^^
if(arr[i] == arr[i + 1]) {
newarr[counter] = arr[i];
i += 1;
^^^^^^
counter++;
} else {
but the next element with index arr[i+2] also can be equal to arr[i]. So the same value will be written at least twice in the destination array.
Try for example to apply your program to an array like this
int arr[] = { 1, 1, 1, 1, 1, 1 };
So you need to rewrite your program entirely.:)
As for the recursive function then it can look the following way
#include <stdio.h>
int * unique( const int *a, size_t n, int *b )
{
if ( n == 0 ) return b;
if ( n == 1 || a[0] != a[1] ) *b++ = *a;
return unique( a + 1, n - 1, b );
}
int main( void )
{
int a[] = { 1, 1, 5, 4, 7, 7, 9, 9, 8 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
int b[N];
int *last = unique( a, N, b );
for ( int *first = b; first != last; ++first ) printf( "%d ", *first );
printf( "\n" );
}
Its output is
1 1 5 4 7 7 9 9 8
1 5 4 7 9 8
If you compiler does not support the C99 STandard then the program can look like
#include <stdio.h>
int * unique( const int *a, size_t n, int *b )
{
if ( n == 0 ) return b;
if ( n == 1 || a[0] != a[1] ) *b++ = *a;
return unique( a + 1, n - 1, b );
}
#define N 9
int main( void )
{
int a[N] = { 1, 1, 5, 4, 7, 7, 9, 9, 8 };
int b[N];
size_t i;
int *first, *last;
for ( i = 0; i < N; i++ ) printf( "%d ", a[i] );
printf( "\n" );
last = unique( a, N, b );
for ( first = b; first != last; ++first ) printf( "%d ", *first );
printf( "\n" );
}

Resources