i'm looking at part of an algorithm, and most of my c knowledge comes from knowing java. i understand that this is a conditional, but what exactly is the order of execution here/what's happening step by step? Thanks!
int i, j, k;
int *x = malloc(n * sizeof (int));
for (i = 0, j = m, k = 0; k < n; k++) {
x[k] = j == n ? a[i++]
: i == m ? a[j++]
: a[j] < a[i] ? a[j++]
: a[i++];
}
free(x);
It is equivalent to:
for (i = 0, j = m, k = 0; k < n; k++) {
if (j == n) x[k] = a[i++];
else if (i == m) x[k] = a[j++];
else if (a[j] < a[i]) x[k] = a[j++];
else x[k] = a[i++];
}
you can rewrite this code to:
if (j == n)
x[k] = a[i++];
else if (i == m)
x[k] = a[j++];
else if (a[j] < a[i])
x[k] = a[j++];
else
x[k] = a[i++];
it looks like part of merge sort algorithm
m and n are variables that have presumably been set beforehand and are non-negative integers, and x and a are arrays that (should have) been allocated. In the case of a[] it presumably has some meaningful contents, and those contents, along with the values of m and n, will determine what x[] gets populated or updated with.
The purpose of the loop is completely opaque to me. What it does:
Sets i to 0, j to m, and k to 0.
Looping from k == 0 to k == (n-1) inclusive
Sets x[k] to the following:
if j is n: a[i], then increments i
if j is not n:
if i is m: a[j], then increments j
if i is not m:
if the value at a[j] is less than the value at a[i]: a[j], then increments j
if the value at a[i] is not less than the value at a[i]: a[i], then increments i
When the loop is complete, x[0] up to x[n-1] will have been populated with values from within a[], based on the contents of a, and the values of m and n.
I assume you are having trouble deciphering this code:
x[k] = j == n ? a[i++]
: i == m ? a[j++]
: a[j] < a[i] ? a[j++]
: a[i++];
Assuming so, this is the conditional operator, which -- as vsync demonstrates -- is very similar to an if-else statement. Essentially, this statement should be thought of as:
condition ? valueIfTrue : valueIfFalse;
This, it turns outs, is very similar but different from:
if (condition)
statementIfTrue;
else
statementIfFalse;
The difference is that the conditional operator always results in a value, which might be assigned to a variable, otherwise used in an operation, passed as an argument, etc.... For the if-then statement to be equivalent, the two statement blocks would need to include the assignment.
Finally, there are multiple conditional operations nested, such that the valueIfFalse is resolved with another conditional operation.
Related
I need to design an algorithm which will sort an array which contains numbers -1,0,1 only, without using any temp variable or array and by using only swapping I have come up with the following method I'm not sure if it is O(n).
#include <stdio.h>
#define MAXSIZE 10
int main()
{
int array[MAXSIZE];
int i, j, num = 8, temp;
int list[] = {-1,0,-1,0,1,1,0,1};
int size = sizeof(list)/sizeof(list[0]);
for (int i = 1; i < size; i++) {
if (list[i] < list[i - 1]) {
list[i] = list[i] + list[i - 1];
list[i - 1] = list[i] - list[i - 1];
list[i] = list[i] - list[i - 1];
i = 0;
}
}
printf("Sorted array is...\n");
for (int i = 0; i < size; i++)
{
printf("%d\n", list[i]);
}
}
The algorithm is definitely not O(n).
You are setting i to 0 when you do a swap. At worst, it is O(n^2).
The reason why your algorithm has been stated correctly by #RSahu, you are resetting the counter to 0 which means you can do as much as 1+2+...+n iterations.
Here is a small example exhibiting linear time to process the array:
#include <iostream>
#include <array>
using namespace std;
int main() {
array<int,10> A{-1, 0, -1, 0, 1, 1, 0, 1, 0, -1};
int i=0,j=0, k=9;
while(j!=k) {
if(A[j] == 0) {
++j;
}
else if(A[j] == -1) {
swap(A[i], A[j]);
++i; ++j;
}
else {
swap(A[j], A[k]);
--k;
}
}
for(auto ai : A)
cout << ai << " ";
cout << endl;
}
You can see it live there.
How does it work ? We maintain three counters i, j and k with the invariants that:
all items in the range: [0, i) are -1
all items in the range: [i, j) are 0
all items in the range: (k, n-1) are +1
Where [ means an inclusive bound, and ) or ( means an exclusive bound.
Initially
i=j=0 and 'k=n-1`. The invariants are respected.
First case
if(A[j] == 0) {
++j;
}
The value of A[j] is 0, so we can increment j and the invariants still hold.
Second case
else if(A[j] == -1) {
swap(A[i], A[j]);
++i; ++j;
}
As i is an exclusive bound, we are adding a -1 to the previous range of -1 and the increment of i is needed. If the range [i, j) was not empty, a 0 has been copied to position j and we must increment j. If the range was empty, then we had i==j, and as we increment i we must also increment j to keep the invariant. We can conclude that the invariants still hold after this step.
Third case
else {
swap(A[j], A[k]);
--k;
}
A[j] is 0 we can swap it with the value at A[k] and decrement k and the invariants will hold.
Termination and correctness
The final point is proving the program will terminate. Each step either:
- increment j
- decrement k
So the distance between j and k will decrease by 1 every step.
The distance between j and k is initially n-1, and decreases by one every step. So there will be at most n-1 steps. Each step does one swap. There will be at most n-1 swaps.
At the end of the program the invariants will hold:
from 0 to i excluded, all -1
from i to j==k excluded, all 0
from j==k to n-1 excluded, all +1
I'm writing a simple program to sort a small array but when I run my code for insertion sort the program just runs forever.
It's probably a problem with the while loop. I ran through the program on paper and looked over some other people's code but I can't figure out why it's not working.
void mySort(int d[], unsigned int n){
int i, j, k;
for (j = 1;j < n;i++){
k = d[j];
i = j-1;
while (d[i] > k && i >=0){
d[i+1] = d[i];
d[i] = k;
i = i - 1;
}
}
}
for (j = 1;j < n;i++){
You compare value j, but you increment value i.
If you Use a Debugger, you would immediately notice that the value j does not get updated, and you'd find your problem immediately!!
Always Use a Debugger
The error is in your for loop.
for (j = 1;j < n;i++){
So your terminating conditions of the for loop are that j >= n, except you never change j or n after this statement.
Try
for (j = 1;j < n;j++){
So I was trying to implement Cormen's pseudocode for bubble sorting but I can't seem to get it to work.
This is my approach on Cormen's pseudocode:
void BUBBLE_SORT(int a[200], int n) {
int i, j, aux;
for (i = 1; i <= n - 1; i++) {
for (j = n; j < i + 1; j++) {
if (a[j] < a[j - 1]) {
aux = a[j];
a[j] = a[j + 1];
a[j + 1] = aux;
}
}
}
}
I tried another piece of code found on the internet but the result was not different:
void bubbleSort(int arr[], int n) {
int i, j;
for (i = 0; i < n - 1; i++)
for (j = 0; j < n - i - 1; j++)
if (arr[j] > arr[j + 1])
swap(&arr[j], &arr[j + 1]);
}
I would love to know where my comprehension failed in understanding Cormen's implementation and to get the bubble sorting to work!
There are at least three issues:
The pseudocode assumes array indices go from 1 to length. In C arrays are indexed from 0 to length-1; your code doesn't correct for that.
The inner loop in the pseudocode goes downto i+1, but your inner loop tries to count up:
for(j=n;j<i+1;j++)
should be
for (j = n; j > i; j--)
The pseudocode swaps A[j] and A[j-1], but your C code swaps A[j] and A[j+1].
Mistakes in your implementation:
You start counting your array from 1th index. But in C programing a array start with 0th position. [you should right i = 0 instead of i = 1]
The inner loop must run from j = n-1 from j = i+1 and the value of j must be decreasing.
You compare a[j] with a[j-1] but u swap a[j] with a[j+1]. you should have swap a[j] with a[j-1]
See the changes in the code below. Hope it will be useful:
int i, j, aux;
for(i=0;i<n-1;i++){
for(j=n-1;j>=i+1;j--){
if(a[j]<a[j-1]){
aux=a[j];
a[j]=a[j-1];
a[j-1]=aux;
}
}
}
Q: Find all prime numbers between two given Numbers a and b, by using Sieve of Eratosthene.
Im using dynamic array to store prime numbers, but it does nt work.
After debug it, everything is ok untill the last
printf() that crashes.
Code
int main() {
int i, j, n, a, b, k;
int *tab;
scanf("%i", &n); // n is number of sets
for (i = 1; i <= n; i++){
scanf("%i %i", &a, &b);
tab = (int*) malloc(b * sizeof(int)); //allocating the memorry
for (j= 0; j < b; j++){ //seting all numbers to be prime
*(tab + j) = 1;
}
for (j = 2; j <= b; j++){
if (*(tab + j) == 1){
for(k = j; k <= b; k+=j)
*(tab + k) = 0; //seting 0 for all non prime numbers
}
}
for (j = a; j <= b; j++){
if (*(tab + j) == 1){
printf("%i", j); //printing prime numbers
}
}
free(tab);
}
return 0;
}
your second loop should be
for (j = 2; j <= b; j++){
if (*(tab + j) == 1){
for(k = j; k <= b; k += j)
*(tab + k) = 0; //seting 0 for all non prime numbers
}
}
the problem was that because you used multiplication, you tried to access an item in the tab array with index above its allocated size.
edit: and as #melpomene stated, the array is too short. therefore the allocation should be
tab = (int*) malloc((1+b) * sizeof(int));
The problem is, you're accessing array out of its bounds:
*(tab + k*j) = 0;
when
k <= b
j <= b
When you declare array of b elements, you can only access array from 0 to b-1 index.
BTW, as mentioned in comments, using tab[k*j] is more readable and shows clearly that tab is array.
I don't really understand what you mean by sets number, but pseudocode of Sieve of Eratosthenes taken from wiki is applied from 2 to n. So in your case 2 becomes a and n becomes b. You don't need checking all numbers from a to b, root of b will suffice.
Your algorithm should look like:
create array for holding b - a elements
make every element equals 1
make 0 elements which fulfill Eratosthenes rules for complex number
print indexes which contains 1.
I have already designed the following algorithm that determines the binomial coefficient using a two dimensional array. For example, to calculate the binomial coefficient of n choose k, we can create a two dimensional array like so:
int[][] arr = new int[n][k];
We can populate the array in the following way:
for(int i = 0; i <= n; i++){
for(int j = 0; j <= minimum(i, k); j++){
if(j == 0 || i == j){
arr[i, j] = 1;
} else{
arr[i, j] = arr[i - 1, j - 1] + arr[i - 1, j];
}
}
}
However, I need to redesign this algorithm to use a one dimensional array from indexes 0-k. I am having a lot of trouble pinpointing how to do this. I have started in small steps, and realized some common occurrences:
If k = 0, arr[0] will be 1, and that will be returned regardless of n.
If k = 1, arr[0] will be 1, arr[1] should be n, if I'm designing it in a loop.
When I say k = 2, this is where it gets tricky, because the value of arr[2] will really depend on the previous values. I believe that as I loop (say from i = 0 to i = n), the values of arr[] will change but I can't quite grasp how. I've started with something along these lines:
for(int i = 0; i <= n; i++){
for(int j = 0; j <= minimum(i, k); j++){
if(j == 0 || i == j){
arr[j] = 1;
} else if(j == 1){
arr[j] = i;
} else{
arr[j] = ??; // I can't access previous values, because I didn't record them?
}
}
}
How should I handle this?
Here is a code which uses only one one dimensional array:
int[] coefficients = new int[k + 1];
coefficients[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = k; j >= 1; j--) {
coefficients[j] += coefficients[j - 1];
}
}
Why is it correct? To compute coefficients[j] for a fixed i, we need to know the value of coefficients[j - 1] and coefficients[j] for i - 1. If we iterate from k down to 0, we can safely record a new value for the current position because we will never need its old value.