450DSA Array in C - arrays

/**
#brief Move all negative elements to end
EX: Given an unsorted array arr[] of size N having both negative and positive integers.
The task is place all negative element at the end of array
without changing the order of positive element and negative element.
Example 1:
Input :
N = 8
arr[] = {1, -1, 3, 2, -7, -5, 11, 6 }
Output :
1 3 2 11 6 -1 -7 -5
Example 2:
Input :
N=8
arr[] = {-5, 7, -3, -4, 9, 10, -1, 11}
Output :
7 9 10 11 -5 -3 -4 -1
*/
#include<stdio.h>
void shortArray(int array[], int stack[]){
int size = 8;
int left = 0;
int right = size;
for(int i=0; i<size; i++){
if(left = right) break;
volatile int value = array[i];
if(array[i] > 0){
stack[left] = value;
left ++;
}
if(array[i] < 0){
stack[right] = value;
right--;
}
}
}
//printarray
void printArray(int array[], int size){
for(int i=0; i<size; i++){
printf(" %d", array[i]);
}
}
int main(){
int array[] = {-5, 7, -3, -4, 9, 10, -1, 11};
int size = 8;
int stack[size];
shortArray(array, stack);
printArray(stack, size);
return 0;
}
my output:
0 0 0 0 0 0 0 0
i try to assign value to stack[] but it don't work right.
i dont know what wrong with it? can you tell me why? thank you!
sorry for my bad english :<

For starters the assignment sounds like
The task is place all negative element at the end of array
It means that you need to change the source array in place not to build a new array.
In this if statement
if(left = right) break;
there is used the assignment operator = instead of the equality operator ==. So if right initially is not equal to 0 then the loop breaks at once.
Using the qualifier volatile in this declaration
volatile int value = array[i];
has no any sense.
If the first element of the source array is negative then this if statement
if(array[i] < 0){
stack[right] = value;
right--;
}
invokes undefined behavior because the index right points to memory after the last element of the array stack.
And moreover with this approach the order of negative values will be broken
And the function shall not use the magic number 8. It should be able to deal with arrays of various sizes. So the function must accept the number of elements in the passed to it array.
The function can be defined for example the following way as it is shown in the demonstration program below
#include <stdio.h>
void partition( int a[], size_t n )
{
for (size_t i = 0, j = 0; i < n; )
{
while (j != n && !( a[j] < 0 )) j++;
if (!( j < i )) i = j;
while (i != n && a[i] < 0) i++;
if (i != n)
{
int tmp = a[i];
for ( size_t k = i; k != j; --k )
{
a[k] = a[k - 1];
}
a[j] = tmp;
i++, j++;
}
}
}
int main( void )
{
int a[] = { 1, -1, 3, 2, -7, -5, 11, 6 };
const size_t N = sizeof( a ) / sizeof( *a );
for (size_t i = 0; i < N; i++)
{
printf( "%d ", a[i] );
}
putchar( '\n' );
partition( a, N );
for (size_t i = 0; i < N; i++)
{
printf( "%d ", a[i] );
}
putchar( '\n' );
}
The program output is
1 -1 3 2 -7 -5 11 6
1 3 2 11 6 -1 -7 -5

Related

reverse array in range in C

I have to solve it in C language. I have arrays with n integers. L and U are lower and upper bound. I have to reverse numbers in array which is in [L,U]. I tried it by this way, but in some cases the answer is wrong. What mist be changed in the code? Or is there any other logic to complete the task?
#include <stdio.h>
int main() {
int x, arr[100], n, l, u, a, temp, temp1;
scanf("%d%d%d", &n, &l, &u);
for (int i = 0; i < n; i++) {
scanf("%d", &x); // read elements of an array
arr[i] = x;
}
a = n / 2;
for (int i = 0; i < a; i++) {
for (int j = a; j < n; j++) {
if (arr[i] >= l && arr[i] <= u) {
if (arr[j] >=l && arr[j] < u) {
temp = arr[j];
temp1 = arr[i];
arr[i] = temp;
arr[j] = temp1;
}
}
}
}
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
}
sample input:
10(number of integers) -7(lower bound) 5(upper bound)
-10 -9 5 -2 -3 7 10 6 -8 -5
sample output:
-10 -9 -5 -3 -2 7 10 6 -8 5
my output:
-10 -9 -5 -2 -3 7 10 6 -8 5
There is an O(N) solution that does not require nesting of loops.
First, with the code as you as you have it, declare an additional array and some other helper variables that keeps track of what indices need to be swapped.
int left, right;
int swaplist[100] = {0};
int swapcount = 0;
Your can keep your initial intake loop exactly as you have it, but amended to append the index of the newly scanned value to the swaplist array if the value is between the lower and upper bounds.
for (int i = 0; i < n; i++) {
scanf("%d", &x); // read elements of an array
arr[i] = x;
if ((x >= l) && (x <= u)) {
swaplist[swapcount++] = i;
}
}
Then a single loop to iterate over "swaplist" and do the swaps against the original array.
left = 0;
right = swapcount-1;
while (left < right) {
int leftindex = table[left];
int rightindex = table[right];
int tmp = arr[leftindex];
arr[leftindex] = arr[rightindex];
arr[rightindex] = tmp;
left++; right--;
}
You made a valiant attempt. Your nested for() loops are appropriate for some kinds of sorting algorithms, but not for what seems to be the purpose of this task.
From the sample input and desired output, you really want to establish a 'bracket' at either end of the array, then shift both toward the centre, swapping elements whose value happens to satisfy low <= n <= high value. (In this case, -7 <= n <= 5).
Here's a solution:
#include <stdio.h>
int swap( int arr[], size_t l, size_t r ) { // conventional swap algorithm
int t = arr[l];
arr[l] = arr[r];
arr[r] = t;
return 1;
}
int main() {
int arr[] = { -10, -9, 5, -2, -3, 7, 10, 6, -8, -5, }; // your data
size_t i, sz = sizeof arr/sizeof arr[0];
for( i = 0; i < sz; i++ ) // showing original version
printf( "%d ", arr[i] );
putchar( '\n' );
#define inRange( x ) ( -7 <= arr[x] && arr[x] <= 5 ) // a good time for a macro
size_t L = 0, R = sz - 1; // 'L'eft and 'R'ight "brackets"
do {
while( L < R && !inRange( L ) ) L++; // scan from left to find a target
while( L < R && !inRange( R ) ) R--; // scan from right to find a target
} while( L < R && swap( arr, L, R ) && (L+=1) > 0 && (R-=1) > 0 );
for( i = 0; i < sz; i++ ) // showing results
printf( "%d ", arr[i] );
putchar( '\n' );
return 0;
}
-10 -9 5 -2 -3 7 10 6 -8 -5
-10 -9 -5 -3 -2 7 10 6 -8 5
If I have understood the assignment correctly you need to reverse elements of an array that satisfy some condition.
If so then these nested for loops
for (int i = 0; i < a; i++) {
for (int j = a; j < n; j++) {
if (arr[i] >= l && arr[i] <= u) {
if (arr[j] >=l && arr[j] < u) {
temp = arr[j];
temp1 = arr[i];
arr[i] = temp;
arr[j] = temp1;
}
}
}
}
do not make sense.
It is enough to use only one for loop as shown in the demonstration program below.
#include <stdio.h>
int main( void )
{
int a[] = { 1, 10, 2, 3, 20, 4, 30, 5, 40, 6, 7, 50, 9 };
const size_t N = sizeof( a ) / sizeof( *a );
for (size_t i = 0; i < N; i++)
{
printf( "%d ", a[i] );
}
putchar( '\n' );
int l = 10, u = 50;
for (size_t i = 0, j = N; i < j; i++ )
{
while (i < j && !( l <= a[i] && a[i] <= u )) ++i;
if (i < j)
{
while (i < --j && !( l <= a[j] && a[j] <= u ));
if (i < j)
{
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
}
for (size_t i = 0; i < N; i++)
{
printf( "%d ", a[i] );
}
putchar( '\n' );
}
The program output is
1 10 2 3 20 4 30 5 40 6 7 50 9
1 50 2 3 40 4 30 5 20 6 7 10 9
You could write a separate function as for example
#include <stdio.h>
void reverse_in_range( int a[], size_t n, int low, int upper )
{
for (size_t i = 0, j = n; i < j; )
{
while (i < j && !( low <= a[i] && a[i] <= upper )) ++i;
if (i < j)
{
while (i < --j && !( low <= a[j] && a[j] <= upper ));
if (i < j)
{
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
++i;
}
}
}
}
int main( void )
{
int a[] = { 1, 10, 2, 3, 20, 4, 30, 5, 40, 6, 7, 50, 9 };
const size_t N = sizeof( a ) / sizeof( *a );
for (size_t i = 0; i < N; i++)
{
printf( "%d ", a[i] );
}
putchar( '\n' );
reverse_in_range( a, N, 10,50 );
for (size_t i = 0; i < N; i++)
{
printf( "%d ", a[i] );
}
putchar( '\n' );
}
Thanks for everyone help. I read all of them, but I found another way to solve this problem. I will write it just in case. (some variable names are random, so in case of questions, comment).
#include <stdio.h>
int main() {
int x, main[100], n, l, u, a = 0, arr[100], temp, m = 0,f=0,c,d;
scanf("%d%d%d", &n, &l, &u);
for (int i = 0; i < n; i++) {
scanf("%d", &x); // read elements of an array
main[i] = x;
if (x >= l && x <= u) {
a++; //check if element is in range [l,u] and increasing a. later "a" will be used a length of the array "arr". this array cootains elements, which in in [u,l].
}
}
//add [u,l] elements in new array "arr"
for (int i = 0; i < n; i++) {
if (main[i] >= l && main[i] <= u) {
arr[m] = main[i];
m++; //index counter of "arr",
}
}
d=0;
for(int i=0;i<n;i++){
if(main[i]==arr[d]){
c=arr[a-d-1];
main[i]=c;
d++;
}
}
for(int i=0;i<n;i++){
printf("%d ",main[i]);
}
}
My best guess is that scanf is very annoying, on top of that, your format is ambiguous.
How will %d%d%d read 1234? Will it give you 12 3 and 4? 1 23 and 4? ...
try to do
scanf("%d %d %d" ...); // or
scanf("%d, %d, %d" ...);
something like that. Note that scanf is not recommended to be used, getc is a neat alternative, though also annoying when you want to read numbers with more than one digit, but you could create a function read_number, which, based on getc, will read a number as a string and return the int value with stoi.

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.

Copying an unsorted C array into another while avoiding duplicates

Hello everyone and thanks for your time.
For exercise, I wanted to write a program which copies all elements from an array to another array but without the duplicates. The only condition is that I cannot change the original array - so no sorting.
I tried making a function which checks if the current element of array1 is found in the array we copy to (array2). If no, we then copy the element to the second array and increase the size by one.
However, it does not work:
If I have
int array1[15] = {3,2,4,7,9,1,4,6,7,0,1,2,3,4,5};
int array2[15];
array2 should contain the following numbers: 3,2,4,7,9,1,6,0,5
But my output is as follows: 3,2,4,7,9,1,6
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int already_exists(int array2[], int size_arr2, int element)
{
int i;
for(i=0; i<size_arr2; i++)
{
if(array2[i] == element)
return 1;
}
return 0;
}
int main()
{
int array1[15] = {3,2,4,7,9,1,4,6,7,0,1,2,3,4,5};
int array2[15];
int i;
int size_arr2=0;
for(i=0; i<9; i++)
{
int element = array1[i];
if(already_exists(array2, size_arr2, element) == 1)
continue;
else
{
array2[size_arr2] = element;
size_arr2++;
}
}
for(i=0; i<size_arr2; i++)
{
printf("%d, ", array2[i]);
}
return 0;
}
You have a typo in the for loop
for(i=0; i<9; i++)
The array array1 contains 15 elements. So the loop should look like
for ( i = 0; i < 15; i++ )
The reason of the error is that you are using "magic numbers" instead of named constants.
Nevertheless the program in whole is inefficient because the function already_exists is called for each element of the array array1. At least you could declare it as an inline function.
Moreover it should be declared like
int already_exists( const int array2[], size_t size_arr2, int element );
Instead of this function it is better to write a function that performs the full operation.
Here is a demonstrative program.
#include <stdio.h>
size_t copy_unique( const int a1[], size_t n1, int a2[] )
{
size_t n2 = 0;
for ( size_t i = 0; i < n1; i++ )
{
size_t j = 0;
while ( j < n2 && a2[j] != a1[i] ) j++;
if ( j == n2 ) a2[n2++] = a1[i];
}
return n2;
}
int main(void)
{
enum { N = 15 };
int array1[N] = { 3, 2, 4, 7, 9, 1, 4, 6, 7, 0, 1, 2, 3, 4, 5 };
int array2[N];
for ( size_t i = 0; i < N; i++ ) printf( "%d ", array1[i] );
putchar( '\n' );
size_t n2 = copy_unique( array1, N, array2 );
for ( size_t i = 0; i < n2; i++ ) printf( "%d ", array2[i] );
putchar( '\n' );
return 0;
}
Its output is
3 2 4 7 9 1 4 6 7 0 1 2 3 4 5
3 2 4 7 9 1 6 0 5

Quicksort skipping one element

So today i tried to implement a quicksort. It's almost working but somehow skips one element.
example : 5 2 8 2 3 4 1 5 7 -5 -1 -9 2 4 5 7 6 1 4
output : -5 -1 -9 1 2 2 3 2 1 4 4 4 5 5 5 6 7 7 8
In this case it skips -9. Here is code of the function.
test = quicksort_asc(0,size,tab,size) // this is function call
int quicksort_asc(int l, int r, int tab[], int tabSize) //l is first index, r is last index, tabSize is tabsize-1 generally
{
int i,buffer,lim,pivot,flag=0;
if(l == r)
return 0;
lim = l-1;
pivot = tab[r-1];
printf("pivot:%d\n",pivot);
for (i = l; i <= r-1; ++i)
{
if(tab[i] < pivot) {
lim++;
buffer = tab[lim];
tab[lim] = tab[i];
tab[i] = buffer;
flag = 1;
}
}
if(flag == 0)
return 0;
buffer = tab[lim+1];
tab[lim+1] = pivot;
tab[r-1] = buffer;
quicksort_asc(l,lim+1,tab,lim+1);//left side
quicksort_asc(lim+1,tabSize,tab,tabSize);//right side
}
This is my array length count code. 100 is maximum size, 0 is a stop value.
Count is size.
int count=0;
for (int i = 0; i < 100; i++)
{
test = scanf("%d",&vec[i]);
if(vec[i] == 0) break;
count++;
}
return count;
It seems nobody hurries to help you.:)
For starters the last parameter is redundant.
int quicksort_asc(int l, int r, int tab[], int tabSize);
^^^^^^^^^^^
All you need is the pointer to the first element of the array and starting and ending indices.
Also instead of the type int for the indices it is better to use the type size_t. However as you are using the expression statement
lim = l-1;
then o'k let the indices will have the type int though you could use another approach without this expression statement.
So the function should be declared like
void quicksort_asc( int tab[], int l, int r );
The variable flag is redundant. When it is equal to 0 it means that all elements before the pivot value are greater than or equal to it. But nevertheless you have to swap the pivot value with the first element that is greater than or equal to the pivot.
This loop
for (i = l; i <= r-1; ++i)
has one iteration redundant. It should be set like
for (i = l; i < r-1; ++i)
This call
quicksort_asc(lim+1,tabSize,tab,tabSize);
^^^^^ ^^^^^^^
shall be substituted for this call
quicksort_asc( lim + 2, r, tab );
^^^^^^^ ^^
because the pivot value is not included in this sub-array.
Here is a demonstrative program.
#include <stdio.h>
void quicksort_asc( int tab[], int l, int r )
{
if ( l + 1 < r )
{
int lim = l - 1;
int pivot = tab[r - 1];
for ( int i = l; i < r - 1; ++i )
{
if ( tab[i] < pivot )
{
lim++;
int tmp = tab[lim];
tab[lim] = tab[i];
tab[i] = tmp;
}
}
tab[r - 1] = tab[lim + 1];
tab[lim + 1] = pivot;
quicksort_asc( tab, l, lim + 1 );
quicksort_asc( tab, lim + 2, r );
}
}
int main(void)
{
int a[] = { 5, 2, 8, 2, 3, 4, 1, 5, 7, -5, -1, -9, 2, 4, 5, 7, 6, 1, 4 };
const int N = ( int )( sizeof( a ) / sizeof( *a ) );
for ( int i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
quicksort_asc( a, 0, N );
for ( int i = 0; i < N; i++ )
{
printf( "%d ", a[i] );
}
putchar( '\n' );
return 0;
}
Its output is
5 2 8 2 3 4 1 5 7 -5 -1 -9 2 4 5 7 6 1 4
-9 -5 -1 1 1 2 2 2 3 4 4 4 5 5 5 6 7 7 8

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

Resources