I am trying to sort an array of structs (A SJF Scheduler). I am using the qsort library function to sort the structs in increasing order according to the attribute bursttime. However, the output is not correct. I've checked some SO questions about the same but they served no use.
struct job
{
int jobno;
int bursttime;
};
typedef struct job job_t;
int mycompare(const void* first, const void* second)
{
int fb = ((job_t*)first)->bursttime;
int sb = ((job_t*)second)->bursttime;
return (fb - sb);
}
int main()
{
int n;
printf("Enter number of jobs: ");
scanf("%d", &n);
job_t* arr = (job_t*)malloc(sizeof(job_t) * n);
for(int i = 1; i <= n; ++i)
{
printf("Enter Burst time for Job#%d: ",i);
scanf("%d", &(arr[i].bursttime));
arr[i].jobno = i;
}
printf("\n");
printf("Order of the Jobs before sort:\n");
for(int i = 1; i <= n; ++i)
{
printf("%d\t", arr[i].jobno);
}
qsort(arr, n, sizeof(job_t), mycompare);
printf("\n");
printf("Order of the Jobs after sort:\n");
for(int i = 1; i <= n; ++i)
{
printf("%d\t", arr[i].jobno);
}
printf("\n");
printf("\n");
return 0;
}
This is my inputfile:
4
7
2
9
4
The output I'm getting is:
Order of the Jobs before sort:
1 2 3 4
Order of the Jobs after sort:
2 1 3 4
The expected order should be: 2,4,1,3. Am I missing anything?
At least this problem
for(int i = 1; i <= n; ++i) // bad
Use zero base indexing.
for(int i = 0; i < n; ++i)
You could change the indexing scheme to start from zero, as others have suggested, and this would certainly be the idiomatic way to do it.
But if you want to use 1-based indexing, you'll need to allocate an extra place in the array (position 0 that will never be used):
job_t* arr = (job_t*)malloc(sizeof(job_t) * (n + 1));
Then you'll need to start your sort at position 1 in the array:
qsort(&arr[1], n, sizeof(job_t), mycompare);
And, of course, you'll have to write your code to index from 1 -- but you've already done that.
The problem is that so many standard functions in C use zero-based indexing that doing anything else is inexpressive. That's a bigger problem than wasting one array position. But, for better or worse, I've had to convert to C a load of code from Fortran, so I've gotten used to working both ways.
Related
this question been asked a few times but cannot find anything specific, the topic is I'm trying to perform a merge sort using 2 threads for sorting each sub list, each thread taking a half, and a third thread to merge the two lists afterwards,
but I'm having difficulty, understanding the merge sort, (first time trying to write a sort algorithm in
c)
i know i need to lets say take "apart" the merge sort and perform only each half in two separate functions, that I can pass into the thread, then perform the final merging process, but lets say I have lists
list1 11 22 1 6 9
list2 99 33 4 5 7
I know I could write a simple sort algorithm to put each in order, but the merging process is throwing me for a loop soheres what im thinking or visualizing the error, and what i am lost on, say i sort the two lists with their different thread functions
list1 1 6 9 11 22
list2 4 5 7 33 99
I keep thinking this will be the result if I go ahead and merge them at this stage
1 6 9 11 22 4 5 7 33 99
that isn't exactly in order is it?
and if I sort them in the final merger using a sort, I mean what was the point of sorting them initially? that kind of just makes the point of sorting them in the two subthreads pointess, when my goal is to use the 2 threads and 2 threads only, then use the final thread to merge like a merge sort would sort each array
can anyone help me visualize this better, either with code, or pseudocode?, assume that in my code I already have the array split and ready to be passed into the functions in my main(void) function, with pointers named first_half, second_half, the starter array is constructed, by taking a user input and passing that into a malloc function, and filled using random limited to 0-99
The way merge sort is working is by comparing the sorted element of each list together, it does not concatenate one array after another, see example code below (singlethreaded):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define _DEBUG 1
void insertion_sort(int n, int a[n])
{
int i, tmp, j;
for (i = 1; i < n; i++) {
tmp = a[i];
j = i - 1;
while (j >= 0 && a[j] > tmp) {
a[j + 1] = a[j];
--j;
}
a[j + 1] = tmp;
}
#ifdef _DEBUG
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
putchar('\n');
#endif
}
void merge_sort(int n, int a[n], int x, int b[x], int y, int c[y])
{
for (int i = 0; i < x; i++) // split values of a into two arrays
b[i] = a[i];
for (int i = 0; i < y; i++)
c[i] = a[i+x];
insertion_sort(x, b); // sort each of the sub arrays, you multithread this part.
insertion_sort(y, c);
int i = 0;
int j = 0;
int k = 0;
while (i < n) {
if (b[j] < c[k]) // you add to a the smallest between b and c.
a[i++] = b[j++];
else
a[i++] = c[k++];
if (x == j) { // if all the elements of b have filled a:
do {
a[i++] = c[k++]; // we proceed to fill a with c
} while (y != k);
break ; // the merge sorting is completed.
}
else if (y == k) {
do {
a[i++] = b[j++];
} while (x != j);
break ;
}
}
#ifdef _DEBUG
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
putchar('\n');
#endif
}
int main(void) {
srand ( time(NULL) );
const int n = 100;
int a[n];
int b[n/2];
int c[(n+1)/2];
for (int i = 0; i < n; i++) // initialize with random values
a[i] = rand() % 1000;
merge_sort(n, a, n/2, b, (n+1)/2, c);
}
I am trying to implement Insertion sort algorithm in C.
But all I get is SIGSEGV error in online IDEs and the output doesn't show up in Code::Blocks. How to avoid Such errors.
#include <stdio.h>
#include <stdlib.h>
int main()
{
/* Here i and j are for loop counters, temp for swapping
count for total number of elements,array for elements*/
int i, j, temp, count;
printf("How many numbers are you going to enter");
scanf("%d", &count);
int n[20];
printf("Enter %d elements", count);
// storing elements in the array
for(i = 0; i < count; i++) {
scanf("%d", n[i]);
}
// Implementation of insertion sort algorithm
for(i = 0; i < count; i++) {
temp = n[i];
j = i - 1;
while(temp < n[j]) {
n[j+1] = n[j];
j = j - 1;
}
n[j+1] = temp;
}
printf("Order of sorted elements");
for(i = 0; i < count; i++) {
printf("%d", n[i]);
}
return 0;
}
There are a couple of problems with your code. First of all, what is a SIGSEGV error? Well, it's another name for the good old Segmentation fault error, which is basically the error you get when accessing invalid memory (that is, memory you are not allowed to access).
tl;dr: change scanf("%d",n[i]); to scanf("%d",&n[i]);. You're trying to read the initial values with scanf("%d",n[i]);, this raises a segmentation fault error because scanf expects addresses in which put the values read, but what you're really doing is passing the value of n[i] as if it were an address (which it's not, because, as you did not set any value for it yet, it's pretty much just memory garbage). More on that here.
tl;dr: change int n[20]; to int n[count]. Your array declaration int n[20]; is going to store at most 20 integers, what happens if someone wants to insert 21 or more values? Your program reserved a certain stack (memory) space, if you exceed that space, then you're going to stumble upon another program's space and the police (kernel) will arrest you (segmentation fault). Hint: try inserting 21 and then 100 values and see what happens.
tl;dr: change for(i = 0; i < count; i++) { to for(i = 1; i <= count; i++) {. This one is a logic problem with your indexes, you are starting at i = 0 and going until i = count - 1 which would be correct in most array iteration cases, but as j assumes values of indexes before i, you need i to start from 1 (so j is 0, otherwise j = -1 in the first iteration (not a valid index)).
My final code is as follows. Hope it helped, happy coding!
#include <stdio.h>
#include <stdlib.h>
int main() {
/*Here i and j are for loop counters,temp for swapping
count for total number of elements,array for elements*/
int i, j, temp, count;
printf("How many numbers are you going to enter?\n");
scanf("%d",&count);
int n[count];
printf("Enter %d elements\n",count);
//storing elements in the array
for(i = 0; i < count; i++) {
scanf("%d", &n[i]);
}
//Implementation of insertion sort algorithm
for(i = 1; i <= count; i++) {
temp = n[i];
j = i-1;
while(temp < n[j]) {
n[j+1] = n[j];
j--;
}
n[j+1] = temp;
}
printf("Order of sorted elements\n");
for(i = 0; i < count; i++) {
printf("%d\n",n[i]);
}
return 0;
}
Edit: If you're having trouble with online IDEs, consider running your programs locally, it saves a lot of time, plus: you never know what kernel version or magic the online IDEs are using to run your code (trust me, when you're coding in C -- fairly low level language, these things make a difference sometimes). I like to go all root style using Vim as text editor and gcc for compiling as well as gdb for debugging.
I'm trying to create a hash table. Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define N 19
#define c1 3
#define c2 5
#define m 3000
int efort;
int h_table[N];
int h(int k, int i)
{
return (k + i*c1 + i*i*c2) % N;
}
void init()
{
for (int i = 0; i < N; i++)
h_table[i] = -1;
}
void insert(int k)
{
int position, i;
i = 0;
do
{
position = h(k, i);
printf("\n Position %d \n", position);
if (h_table[position] == -1)
{
h_table[position] = k;
printf("Inserted :elem %d at %d \n", h_table[position], position);
break;
}
else
{
i += 1;
}
} while (i != N);
}
void print(int n)
{
printf("\nTable content: \n");
for (int i = 0; i < n; i++)
{
printf("%d ", h_table[i]);
}
}
void test()
{
int a[100];
int b[100];
init();
memset(b, -1, 100);
srand(time(NULL));
for (int i = 0; i < N; i++)
{
a[i] = rand() % (3000 + 1 - 2000) + 2000;
}
for (int i = 0; i < N ; i++)
{
insert(a[i]);
}
print(N);
}
int main()
{
test();
return 0;
}
Hash ("h") function and "insert" function are took from "Introduction to algorithms" book (Cormen).I don't know what is happening with the h function or insert function. Sometimes it fills completely my array, but sometimes it doesn't. That means it doesn't work good. What am I doing wrong?
In short, you are producing repeating values for position often enough to prevent h_table[] from being populated after only N attempts...
The pseudo-random number generator is not guaranteed to produce a set of unique numbers, nor is your h(...) function guaranteed to produce a mutually exclusive set of position values. It is likely that you are generating the same position enough times that you run out of loops before all 19 positions have been generated. The question how many times must h(...) be called on average before you are likely to get the value of an unused position? should be answered. This may help to direct you to the problem.
As an experiment, I increased the looping indexes from N to 100 in all but the h(...) function (so as not to overrun h_table[] ). And as expected the first 5 positions filled immediately. The next one filled after 3 more tries. The next one 10 tries later, and so on, until by the end of 100 tries, there were still some unwritten positions.
On the next run, all table positions were filled.
2 possible solutions:
1) Modify hash to improve probability of unique values.
2) Increase iterations to populate h_table
A good_hash_function() % N may repeat itself in N re-hashes. A good hash looks nearly random in its output even though it is deterministic. So in N tries it might not loop through all the array elements.
After failing to find a free array element after a number of tries, say N/3 tries, recommend a different approach. Just look for the next free element.
I was trying to do an exercise in Hacker Rank but found that my code(which is below) is too linear. To make it better I want to know if it is possible to break an array in to little arrays of a fixed size to complete this exercise.
The Exersise on HackerRank
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int N, M, Y, X;
scanf("%d %d %d %d", &N, &M, &Y, &X);
int max = 0;
int total = 0;
int data[N][M];
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
scanf("%d",&(data[i][j]));
}
}
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
total = 0;
for(int l = 0; (l < Y) && (i + Y) <= N; l++)
{
for(int k = 0; (k < X) && (j + X <= M); k++)
{
total += data[i+l][j+k];
}
if(total > max)
max = total;
}
}
}
printf("%d",max);
return 0;
}
While "breaking" it into pieces implies that we'd be moving things around in memory, you may be able to "view" the array in such a way that is equivalent.
In a very real sense the name of the array is simply a pointer to the first element. When you dereference an element of the array an array mapping function is used to perform pointer arithmetic so that the correct element can be located. This is necessary because C arrays do not natively have any pointer information within them to identify elements.
The nature of how arrays are stored, however, can be leveraged by you to treat the data as arbitrary arrays of whatever size you'd like. For example, if we had:
int integers[] = {1,2,3,4,5,6,7,8,9,10};
you could view this as a single array:
for(i=0;i!=10;i++){ printf("%d\n", integers[i]); }
But starting with the above array you could also do this:
int *iArray1, *iArray2;
iArray1 = integers;
iArray2 = integers + (5 * sizeof(int));
for(i=0;i!=5;i++){ printf("%d - %d\n", iArray1[i], iArray2[i]);}
In this way we are choosing to view the data as two 5 term arrays.
The problem is not in the linear solution. The main problem is in your algorithm complexity. As it's written it's O(N^4). Also I think your solution is not correct since:
The ceulluar tower can cover a regtangular area of Y rows and X columns.
It does not mean exactly Y rows and X columns IMHO you could find a solution where the are dimension is less than X, Y.
The problems like that are solvable in reasonable time using dynamic programming. Try to optimize your program using dynamic programming to O(N^2).
I am participating in Harvard's opencourse ware and attempting the homework questions. I wrote (or tried to) write a program in C to sort an array using bubble sort implementation. After I finished it, I tested it with an array of size 5, then 6 then 3 etc. All worked. then, I tried to test it with an array of size 11, and then that's when it started bugging out. The program was written to stop getting numbers for the array after it hits the array size entered by the user. But, when I tested it with array size 11 it would continuously try to get more values from the user, past the size declared. It did that to me consistently for a couple days, then the third day I tried to initialize the array size variable to 0, then all of a sudden it would continue to have the same issues with an array size of 4 or more. I un-did the initialization and it continues to do the same thing for an array size of over 4. I cant figure out why the program would work for some array sizes and not others. I used main to get the array size and values from the keyboard, then I passed it to a function I wrote called sort. Note that this is not homework or anything I need to get credit, It is solely for learning. Any comments will be very much appreciated. Thanks.
/****************************************************************************
* helpers.c
*
* Computer Science 50
* Problem Set 3
*
* Helper functions for Problem Set 3.
***************************************************************************/
#include <cs50.h>
#include <stdio.h>
#include "helpers.h"
void
sort(int values[], int n);
int main(){
printf("Please enter the size of the array \n");
int num = GetInt();
int mystack[num];
for (int z=0; z < num; z++){
mystack[z] = GetInt();
}
sort(mystack, num);
}
/*
* Sorts array of n values.
*/
void
sort(int values[], int n)
{
// this is a bubble sort implementation
bool swapped = false; // initialize variable to check if swap was made
for (int i=0; i < (n-1);){ // loops through all array values
if (values[i + 1] > values [i]){ // checks the neighbor to see if it's bigger
i++; // if bigger do nothing except to move to the next value in the array
}
else{ // if neighbor is not bigger then out of order and needs sorting
int temp = values[i]; // store current array value in temp variable for swapping purposes
values[i] = values[i+1]; //swap with neighbor
values[i+1] = temp; // swap neighbor to current array value
swapped = true; // keep track that swap was made
i++;
}
// if we are at the end of array and swap was made then go back to beginning
// and start process again.
if((i == (n-1) && (swapped == true))){
i = 0;
swapped = false;
}
// if we are at the end and swap was not made then array must be in order so print it
if((i == (n-1) && (swapped == false))){
for (int y =0; y < n; y++){
printf("%d", values[y]);
}
// exit program
break;
}
} // end for
// return;
}
You can easily use 2 nested for loops :
int i, j, temp ;
for ( i = 0 ; i < n - 1 ; i++ )
{
for ( j = 0 ; j <= n - 2 - i ; j++ )
{
if ( arr[j] > arr[j + 1] )
{
temp = arr[j] ;
arr[j] = arr[j + 1] ;
arr[j + 1] = temp ;
}
}
}
also you should now it's a c++ code not a c, because c doesn't have something like :
int mystack[num];
and you should enter a number when you're creating an array and you can't use a variable (like "int num" in your code). This is in C, but in C++ you're doing right.
The first thing to do when debugging a problem like this is ensure that the computer is seeing the data you think it should be seeing. You do that by printing out the data as it is entered. You're having trouble with the inputs; print out what the computer is seeing:
static void dump_array(FILE *fp, const char *tag, const int *array, int size)
{
fprintf(fp, "Array %s (%d items)\n", tag, size);
for (int i = 0; i < size; i++)
fprintf(fp, " %d: %d\n", i, array[i]);
}
int main(void)
{
printf("Please enter the size of the array \n");
int num = GetInt();
printf("num = %d\n", num);
int mystack[num];
for (int z = 0; z < num; z++)
{
mystack[z] = GetInt();
printf("%d: %d\n", z, mystack[z]);
}
dump_array(stdout, "Before", mystack, num);
sort(mystack, num);
dump_array(stdout, "After", mystack, num);
}
This will give you direct indications of what is being entered as it is entered, which will probably help you recognize what is going wrong. Printing out inputs is a very basic debugging technique.
Also, stylistically, having a function that should be called sort_array_and_print() suggests that you do not have the correct division of labour; the sort code should sort, and a separate function (like the dump_array() function I showed) should be used for printing an array.
As it turns out the reason why it was doing this is because when comparing an array's neighbor to itself as in:
if (values[i + 1] > values [i])
The fact that I was just checking that it is greater than, without checking if it is '=' then it was causing it to behave undesirably. So if the array is for example [1, 1, 5, 2, 6, 8] then by 1 being next to a 1, my program did not account for this behavior and acted the way it did.