How to access an array in all functions in my C program? - c

I am trying to create a segment tree for a competitive coding problem and this tree is represented using an array. I have functions namely, rangeMinQuery and updateTree which perform intermediate jobs on the array. I am unable to figure out how to manipulate the said array using the functions.
#include <stdio.h>
#include <stdlib.h>
#define bool int
#define MAX(a,b) (((a)>(b))?(a):(b))
int upper_power_of_two(int v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
int getMid(int s, int e)
{
return s + (e -s)/2;
}
void updateValueUtil(int segTree[], int ss, int se, int i, int diff, int si)
{
// Base Case: If the input index lies outside the range of
// this segment
if (i < ss || i > se)
return;
// If the input index is in range of this node, then update
// the value of the node and its children
st[si] = st[si] + diff;
if (se != ss)
{
int mid = getMid(ss, se);
updateValueUtil(st, ss, mid, i, diff, 2*si + 1);
updateValueUtil(st, mid+1, se, i, diff, 2*si + 2);
}
}
void updateValue(int arr[], int segTree[], int n, int i, int new_val)
{
// Get the difference between new value and old value
int diff = new_val - arr[i];
// Update the value in array
arr[i] = new_val;
// Update the values of nodes in segment tree
updateValueUtil(st, 0, n-1, i, diff, 0);
}
int rangeMinquery(int segTree[],int qlow,int qhigh,int low,int high,int pos)
{
if(qlow<=low && qhigh >=high)
return segTree[pos];
if(qlow>high || qhigh <low)
return 9999999999;
int mid=(low+high)/2;
return MAX(rangeMinquery(segTree,qlow,qhigh,low,mid,2*pos+1),rangeMinquery(segTree,qlow,qhigh,mid+1,high,2*pos+2));
}
int main()
{
int n,q,x,l,r,i;
scanf("%d %d %d %d",&n,&q,&l,&r);
int a[n];
int segTree[upper_power_of_two(n)];
printf("%d\n",upper_power_of_two(n));
while(q--)
{
int cmd,pos1,pos2;
scanf("%d %d %d",&cmd,&pos1,&pos2);
if(cmd==1)
{
a[pos1]+=pos2;
updateValue(a,segTree,n,1,0);
}
if(cmd==2)
{
x=rangeMinquery(segTree,pos1,pos2,0,n,0);
printf("%d\n",x);
}
}
return 0;
}
As you can see, I am trying to manipulate the array segTree and retain the values there itself. I would also like to know if there's a method to achieve the same on JAVA perhaps?

You can make global pointer...
//in global scope
int *segTree;
... and create array using malloc() operator:
//in main()
segTree = malloc(upper_power_of_two(n) * sizeof(int));
And now your array is global. But remember to free(segTree) before you end your program.
Btw. You should never create local arrays (on stack) with variable size like you did in given code.

Related

Methods of tracking pointer objects through functions in C

I'm stuck trying to implement pseudocode from an algorithm book. My code compiles and prints out the correct answer, except some of the information I want to print out is not displaying correctly. Here's what the console output looks like:
Correct Solution Tested:
max_left= 7
max_right= 10
sum= 43
Failing Outputs:
curr_cross_low = 17; curr_cross_high = -1; curr_cross_sum = 38
curr_cross_low = -1; curr_cross_high = -1; curr_cross_sum = 18
curr_cross_low = 32766; curr_cross_high = -272632720; curr_cross_sum = 43
max_left_full= 32766
max_right_full= -272632512
sum_full= 43
Program ended with exit code: 0
The first three values printed are the correct results arrived by brute implementation of one part of the algorithm. In the code, this is the function "findMaxCrossingSubarray" all by itself. The second part printed out is when I execute the full algorithm "findMaximumSubarray". I believe it should be printing out results that show approaching the solution. The final answer given by the variable "sum_full" appears to be correct since it matches the brute force solution which the book says is the correct answer.
I've been trying to find how I can print the correct max_left_full and max_right_full values and not what I believe is the memory address. I'm at a point where if I change a pointer in one place it makes the solution incorrect or print out a memory address as well.
Is there a simple way to find where I may be dropping the ball?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//returns a pointer to a value equal to the set of changes
int * returnPriceChanges(int sz, int A[]){
int MAX_SIZE = 256;
static int* C;
C = malloc(MAX_SIZE *sizeof(int));
int i;
for(i=0;i<sz-1;i++){
C[i]=A[i+1]-A[i];
}
return C;
}
int findMaxCrossingSubarray(int A[], int low, int mid, int high, int* max_left, int* max_right){
double left_sum = -INFINITY;
int sum = 0;
for(int i=mid;i>=low;i--){
sum=sum+A[i];
if(sum > left_sum){
left_sum = sum;
*max_left = i;
}
}
double right_sum = -INFINITY;
sum = 0;
for(int j=mid+1; j<=high;j++){
sum=sum+A[j];
if(sum > right_sum){
right_sum = sum;
*max_right = j;
}
}
return (*max_left, *max_right, left_sum+right_sum);
}
int findMaximumSubarray(int A[], int low, int high){
int curr_left_low, curr_left_high, curr_left_sum;
int curr_right_low, curr_right_high, curr_right_sum;
int curr_cross_low, curr_cross_high, curr_cross_sum;
int mid = 0;
int* temp_max_left, temp_max_right;
if(high==low){
return(low, high, A[low]);
}
else{
mid =floor((high+low)/2);
curr_left_low, curr_left_high, curr_left_sum = findMaximumSubarray(A, low, mid);
curr_right_low, curr_right_high, curr_right_sum = findMaximumSubarray(A, mid+1,high);
curr_cross_low, curr_cross_high, curr_cross_sum = findMaxCrossingSubarray(A, low, mid, high, &temp_max_left, &temp_max_right);
if(curr_left_sum>=curr_right_sum && curr_left_sum>=curr_cross_sum){
return (curr_left_low, curr_left_high, curr_left_sum);
}
else if(curr_right_sum>= curr_left_sum && curr_right_sum>=curr_cross_sum){
return (curr_right_low, curr_right_high, curr_right_sum);
}
else{
printf("curr_cross_low = %d; curr_cross_high = %d; curr_cross_sum = %d\n", curr_cross_low, curr_cross_high, curr_cross_sum);
return (curr_cross_low, curr_cross_high, curr_cross_sum);
}
}
}
int main(){
int prices[] = {100,113,110,85,105,102,86,63,81,101,94,106,101,79,94,90,97};
int szPrices = sizeof(prices)/sizeof(prices[0]);
int changes[szPrices-1];
int *P;
P = returnPriceChanges(szPrices,prices);
//set C = to list of changes
for(int i=0; i<szPrices-1; i++){
changes[i]=*(P+i);
}
int max_left, max_right, sum;
max_left, &max_right, sum = findMaxCrossingSubarray(changes, 0, 8, 16, &max_left, &max_right);
printf("\nCorrect Solution Tested: \nmax_left= %d \nmax_right= %d \nsum= %d\n\n", max_left, max_right, sum);
printf("\nFailing Outputs:\n");
int max_left_full, max_right_full, sum_full;
max_left_full, &max_right_full, sum_full = findMaximumSubarray(changes, 0, 16);
printf("\nmax_left_full= %d \nmax_right_full= %d\nsum_full= %d\n\n", max_left_full, max_right_full, sum_full);
return 0;
}
You cannot return tuples from functions in C. When you separate values using a comma in C, the whole expression simply evaluates to the last member.
So when you write:
a, b, c = some_function();
It really means:
/* do nothing */, /* do nothing */, c = some_function();
If you want to return a composite data structure, use a struct, i.e.
struct subarray
{
int low;
int high;
int sum;
};
void findMaximumSubarray(int A[], int low, int high, struct subarray * result);
If the struct is small and you are using a modern compiler, and not running on an embedded system, then you can also return the struct by value:
struct subarray findMaximumSubarray(int A[], int low, int high);
The latter syntax simplifies usage, but it can become an issue if you start returning huge structs this way.

How to sort dates from an array in c

I'm trying to sort dates from an array i've got the following code (without including the array and the file that i'm trying to read and the other with the sorted dates that i'm trying to write.
int aniomayor=tot[0].anio;
int diamayor=tot[0].dia;
int mesmayor=tot[0].mes;
while (i<nf) {
if (tot[i].anio > aniomayor) {
int aniomayor=tot[i].anio;
int diamayor=tot[i].dia;
int mesmayor=tot[i].mes;
}
else if (tot[i].anio == aniomayor && tot[i].mes > mesmayor) {
int aniomayor=tot[i].anio;
int diamayor=tot[i].dia;
int mesmayor=tot[i].mes;
}
else if (tot[i].anio == aniomayor && tot[i].mes == mesmayor && tot[i].dia > diamayor) {
int aniomayor=tot[i].anio;
int diamayor=tot[i].dia;
int mesmayor=tot[i].mes;
}
i++;
}
fprintf(f, "%s ", diamayor);
fprintf(f, "%s ", mesmayor);
fprintf(f, "%s \n", aniomayor);
I think it would work but in the 2,3,4.. line it will print always the same date and i don't know how to do for it to ignore the dates that already had been sorted. Thanks in advance.
The original int declaration establishes variables. The subsequent ones create "shadow" variables that have the same name but are not the same variable.
Here's a demonstration:
#include <stdio.h>
int main() {
int x = 1;
if (x == 1) {
int x = 2;
printf("x=%d\n", x);
}
printf("x=%d\n", x);
return 0;
}
This prints:
x=2
x=1
The top-level x never gets modified, so it appears to revert to the original value.
You should remove the int prefix from those, just assign to the existing variable.
When you say int x = y; in C you are declaring a variable and assigning a value. To assign to an existing variable x = y; is sufficient.
The int prefix is only necessary on the first instance of the variable so the compiler knows what type to use for that and all subsequent references inside the same scope.
Now normally the compiler would complain about creating another variable with the same name if it's done in the same scope. In your case because you're doing it inside an if, technically that's a different scope so you can have duplicates.
As has been mentioned in the comments, it is preferable to use qsort, (if one doesn't care about stability.) One needs a function pointer, which is compare_dates in the code below.
#include <stdlib.h> /* EXIT*, rand, qsort */
#include <stdio.h> /* *printf */
#include <time.h> /* clock */
#include <assert.h> /* assert */
struct Date { int anio, mes, dia; };
/** Random [i, j]. https://stackoverflow.com/a/6852396/2472827
This is just used for test purposes. */
static int rand_range(const int i, const int j) {
const unsigned long max = (unsigned long)j - i,
num_bins = max + 1l,
num_rand = (unsigned long)RAND_MAX + 1,
bin_size = num_rand / num_bins,
defect = num_rand % num_bins;
unsigned long x;
assert(i <= j && num_bins <= RAND_MAX);
do { x = 1l * rand(); } while (num_rand - defect <= x);
return i + x / bin_size;
}
/** Initiaises the date with random. */
static void init_date(struct Date *const date) {
assert(date);
date->anio = rand_range(1950, 2050);
date->mes = rand_range(1, 12);
date->dia = rand_range(1, 30); /* Approximately. */
}
/** Prints the date in a static string.
Assumes the date is sanitised, or else this presents a risk of overflow. */
static const char *print_date(const struct Date *const date) {
static char print[128]; /* Should be 11 if -999 <= year < 9999. */
assert(date);
sprintf(print, "%4.4d-%2.2d-%2.2d", date->anio, date->mes, date->dia);
return print;
}
/** The arguments must be const struct Date *.
#return -, =, + */
static int compare_dates(const void *p, const void *q) {
const struct Date *x = (const struct Date *)p, *y = (const struct Date *)q;
assert(p && q);
if(x->anio > y->anio) return 1;
if(x->anio < y->anio) return -1;
if(x->mes > y->mes) return 1;
if(x->mes < y->mes) return -1;
if(x->dia > y->dia) return 1;
if(x->dia < y->dia) return -1;
return 0;
}
int main(void) {
struct Date dates[64];
const size_t dates_size = sizeof dates / sizeof *dates;
size_t i;
/* Generate dates. */
srand((unsigned)clock());
for(i = 0; i < dates_size; i++) init_date(dates + i);
/* Sort it using compare_dates. */
qsort(dates, dates_size, sizeof *dates, &compare_dates);
/* Print. */
for(i = 0; i < dates_size; i++) printf("%s.\n", print_date(dates + i));
return EXIT_SUCCESS;
}
See How to generate a random integer number from within a range.

C Binary & Linear Search

Hello i want to draw the time/array size graph for binary and linear search algorithms.(Worst, best and average case for array size = 1 000, 10 000,100 000,1 000 000). I'm using DEV C++. However, when i run the code for array size = 1 000 000, the program crashes. Here is the code :
#include <stdio.h>
int binarySearch(int arr[], int l, int r, int x)
{
if (r >= l)
{
int mid = l + (r - l)/2;
if (arr[mid] == x) return mid;
if (arr[mid] > x) return binarySearch(arr, l, mid-1, x);
return binarySearch(arr, mid+1, r, x);
}
return -1;
}
int main(void)
{
int arr[10] = {2,5,8,9,15,18,19,25,34,50};
int n = sizeof(arr)/ sizeof(arr[0]);
int x = 10;
int result = binarySearch(arr, 0, n-1, x);
(result == -1)? printf("Element is not present in array")
: printf("Element is present at index %d", result);
return 0;
}
You are allocating array arr on stack. For 1 000 000 elements you need 4 MB of memory (assuming that sizeof(int) == 4). On Windows for example most of cases stack has default limit of 1 MB. For quick fix define arr as static
static int arr[size];
or put in global scope outside function body or as others said, use dynamic allocation.

Extracting bytes in C

I'm making a program in C. I am to extract bytes. un8 extractbyte (int r, int pos) should return byte number pos from number r. As example, I use as input: 0x7788AABB. Output then should be:
Part number 0 is BB
Part number 1 is AA
Part number 2 is 88
Part number 3 is 77
I am stuck at the last part of the program, where I have put the question marks in the comments. Those lines aren't right and I am confused in how I should make it work... The output I get now is bb at every part. I am pretty new at C by the way.
#include <stdio.h>
#include <stdlib.h>
typedef unsigned int un32;
typedef unsigned char un8;
un8 extractbyte (un32 r, un8 pos);
int main ()
{
un32 number;
un8 k;
printf("Enter a number:\n");
scanf("%x",&number);
for (k=0; k<=3;k++)
printf ("Part number %d is: %x \n", k , extractbyte(number, k) );
return 0;
}
un8 extractbyte (un32 r , un8 pos)
{
un32 mask;
un32 size = pos*8;
un32; // ??
un8; // ??
return (un8) r; // ??
}
un8 extractbyte(un32 r, un8 pos)
{
return (r >> (8 * pos)) & 0xFF;
}
I would make your extractbyte function something like this.
int extractbyte(int n, int pos)
{
return (n >> (pos * 8)) & 0xff;
}
#include <stdio.h>
char extractbyte(int number, int v) {
char *x=(char *)&number;
return x[3-v];
}
int main() {
int n=0x7788aabb;
int i;
for (i=0; i<4; i++) {
printf("%d) %x\n",i,(unsigned char)extractbyte(n,i));
}
return 0;
}

What should i do to remove a value from min heap when the left and right child are equal and smaller than their parent

What should i do to remove a value from min heap when the left and right child are equal and smaller than their parent. For example i have a value 0 on the root of my min heap and want to remove it. I'll swap 0 with the last element of my vector(value=12), after that, i need to run the function that turns the vector into a min-heap again(min-heapfy), but in my example i exchanged 0 with 12, and now 12 is on the root and 0 will be soon returned. I have to swap 12 with the left child(1) or right child(1), how can i know which of this number 1 entered in the vector first?
#include <stdio.h>
#include <stdlib.h>
int left(int i){
return 2*i;
}
int right(int i){
return 2*i +1;
}
void swap_pos(int *vi, int *vm){
int aux;
aux = *vi;
*vi = *vm;
*vm = aux;
}
void heapify(int *v, int i,int heap_size){
int l,r,menor_ind = i;
l = left(i);
r = right(i);
if(l<=heap_size && v[l]<v[i]) menor_ind = l;
if(r<=heap_size && v[r]<v[menor_ind]) menor_ind = r;
if(menor_ind!= i){
swap_pos(&v[i],&v[menor_ind]);
heapify(v,menor_ind,heap_size);
}
}
void build_min_heap(int v[],int heap_size){
int i;
for(i=heap_size/2; i>=1; i--){
heapify(v,i,heap_size);
}
}
int extract(int *v, int *heap_size){
int ret = v[1];
if(*heap_size==0) return -1;// erro
swap_pos(&v[*heap_size],&v[1]); // swap root with the last element
(*heap_size)--;
heapify(v,1,*heap_size);
return ret;
}
void heap_sort(int *v, int *heap_size){
while(*heap_size>=2){
swap_pos(&v[1],&v[*heap_size]);
(*heap_size)--;
heapify(v,1,*heap_size);
}
}
int main(void){
int heap_size = 9;
int i, v[] = {-1,6,12,3,1,5,0,1,9,7};
build_min_heap(v,heap_size);
printf("%d\n",extract(v,&heap_size));
//heap_sort(v,&heap_size);
for(i=1; i<=heap_size; i++){
printf("%d ",v[i]);
}
return 0;
}
As far as the heap goes, 1 and 1 are equal. (Indeed, that is generally true.) So it doesn't matter which 1 becomes the new root. The 12 will percolate up the heap until it finds some place to rest, possibly at the fringe but not necessarily. There's nothing which requires it to get back to where it came from, and it's very likely that it won't.
Why do you think the code you present isn't correct?

Resources