Initializing an Array C++ - c++

My code is trying to implement the union-find algorithm and I have the id[] array and the sz[] array. I initialize them in the Union-Find constructor, but once I try to use those arrays in the methods within the Union-Find class, it changes all the array values to 1. I don't understand why. Is there something obvious that I'm missing??
H File
class UnionFind{
public:
UnionFind(int size);
void join(int x, int y);
int connected(int x, int y);
int find(int x);
private:
int size;
int id[];
int sz[];
};
CPP File
UnionFind::UnionFind(int size){
this->id[size] = id[size];
for(int i = 0; i < size; i++){
id[i] = i;
}
for(int i = 0; i < size; i++){
sz[i] = 1;
}
}
int UnionFind::find(int l){
//Path Compression Finding the Root
for(int i = 0; i < 5; i++){
}
while(l != id[l]){
id[l] = id[id[l]];
l = id[l];
}
return l;
}
void UnionFind::join(int x, int y){
int m = find(x);
int n = find(y);
if(sz[m] < sz[n]){
id[m] = n;
sz[n] += sz[m];
}
else{
id[n] = m;
sz[m] += sz[n];
}
}
int UnionFind::connected(int x, int y){
if(find(x) == find(y)){
return 1;
}
else{
return 0;
}
}

From the comments.
you can't have int id[] as a class member,
use std::vector (resize and fill in constructor),
your forgot to set member size in constructor,
your find algorithm uses path halving not path compression (this does not affect the running time).
Side note: you can use a single array/vector to implement your disjoint set data structure.

Related

Structures in C++, initializations

class box{
int l,w,h;
box(int a,int b,int c){
l = a;w = b;h = c;
};
};
bool cmp(box a,box b){
return a.l*a.w<b.l*b.w;
}
class Solution{
public:
/*The function takes an array of heights, width and
length as its 3 arguments where each index i value
determines the height, width, length of the ith box.
Here n is the total no of boxes.*/
int maxHeight(int h[],int w[],int l[],int n)
{
//Your code here
struct box b[(3*n)]={};
int j = 0;
for(int i = 0 ; i< n; ++ i){
b[j++] = box(min(l[i],w[i]),max(l[i],w[i]),h[i]);
b[j++] = box(min(l[i],h[i]),max(l[i],h[i]),w[i]);
b[j++] = box(min(w[i],h[i]),max(w[i],h[i]),l[i]);
}
n*=3;
sort(b,b+n,cmp);
int dp[n];
for(int i = 0 ; i< n; ++ i){
dp[i] = b[i].h;
}
int ans = INT_MIN;
for(int i = 1; i< n; ++ i){
for(int j = 0; j< i; ++ j){
if(b[i].l>b[j].l and b[i].w>b[j].w and dp[i]<dp[j]+b[i].h)
dp[i] = b[i].h+dp[j];
}
ans = max(ans,dp[i]);
}
return ans;
}
};
The code above shows an error that struct variables takes 3 arguments and only 1 given as shown.
Please help me out of this. Thanks.
Also please provide some good references from where I could get more idea on these kinds of topics. Like sites from where I could learn these type of hints and secrets of language.
I got it. Here I had not written the default initializers functions and that is why it is showing this error.
Also I need to change the access modifier to public.
So I changed the code of struct declaration to something like this.

Extract pair numbers from array

Good evening, folks.
I'm currently experiencing difficulties with extracting pair numbers from an array. I have the following code:
#include <iostream>
using namespace std;
int *paire(int *d, int length) {
int counter = 0;
int position = 0;
for (int i=0; i<length; i++) {
if (d[i] % 2 ==0)
counter++;
}
int *k = new int[counter];
for (int i=0; i<length; i++) {
if (d[i] % 2 ==0) {
k[position] = d[i];
position++;
}
}
return k;
}
int main() {
int b[8] = {1,2,3,4,5,6,7,8};
int *array1 = paire(b,8);
for (int i=0; i<5; i++) { // how can I point here to the counter in paire() ?
cout<<array1[i];
}
delete[] array1;
return 0;
}
So I think I've got it right with initializing the new array in function paire, but I'm having difficulties to iterate through the array.
P.S. I'm first year in university, so I would really be thankful if you can keep the same simplicity in the answers. Thanks in advance!
It appears that you need to return 2 separate values: the number of even numbers in the array b, and the address of the newly allocated memory that is storing exclusively those even numbers.
Since you can not return multiple variables, one solution that does minimal modification to your code would be as follows.
int *paire(int *d, int length, int& counter) {
counter = 0;
// rest of your function remains unchanged
// ...
}
int main() {
int b[8] = {1,2,3,4,5,6,7,8};
int evenNumbers;
int *array1 = paire(b,8, evenNumbers);
for (int i=0; i<evenNumbers; i++) {
cout<<array1[i];
}
delete [] array1;
return 0;
}
Alternatively, you can return the value in counter and send the reference to the int* variable as an argument to paire function. Or, you can declare paire to have return type void and use references to pass back both the values.
You can further simplify your function by allocating to that of the length and returning the counter by an output parameter.
#include <iostream>
using namespace std;
int *paire(int *d, int length, int &counter) {
counter = 0;
int *k = new int[length]; // allocate for the maximum memory
for (int i = 0; i < length; ++i) {
if (d[i] % 2 == 0) {
k[counter++] = d[i];
}
}
return k;
}
int main() {
int b[8] = {1,2,3,4,5,6,7,8};
int counter = 0;
int *array1 = paire(b,8, counter);
for (int i=0; i<counter; i++) { // how can I point here to the counter in paire() ?
cout<<array1[i] << " ";
}
delete [] array1;
return 0;
}
But please note that as others have already pointed out this method is quite error prone in the sense that it leaves the responsibility to the client to delete the internal memory used by paire function.

C++ parameterized constructor makes code to stop working when large input's are passed

void initialize(int arr[], int size[], int n)
{
int i;
for(i = 1; i <= n; i++) {
arr[i] = i;
size[i] = 1;
}
}
class hell
{
public:
int edges;
int vertices;
pair<int , pair<int,int>> p[100000];
int disjoint_set[10000];
int cc_size[10000]; // size of connected components
hell(int e, int v)
{
edges = e;
vertices = v;
initialize(disjoint_set, cc_size, vertices);
}
};
In the following class when I create an object using vertices=100000 and edges=100000, the code stops working. But when we remove the initialize(disjoint_set, cc_size, vertices) it starts working. I don't have any clue to such behavior. Please guide me.
Arrays in C++ are zero indexed, which means that valid index is in [0..n[ range. Your code does it wrong:
for(i = 1; i <= n; i++) {
arr[i] = i;
size[i] = 1;
}
it should be:
for(i = 0; i < n; i++) {
arr[i] = i + 1;
size[i] = 1 + 1;
}
or better use algo std::iota() and std::fill():
std::iota( arr, arr + n, 1 );
std::fill( size, size + n, 1 );
and you better use std::vector, which will adjust its size properly, rather than have huge array.

arrays not being assigned properly

void sort(int* A,int l)
{
int j;
int B[l];
for(int i=0;i<l;i++)
{
j = largest(A,l);
B[l-i-1] = A[j];
A[j] = -1;
}
A = B;
}
int main()
{
.
int C[3] = {x,y,z};
...
sort(C,3);
cout<<C[0]<<C[1];
}
output is coming to be -1-1
But if we assign A[0] = B[0] and so on, then we are getting the right answer.
PS: I've tried using *A = *B, which is only giving the first element to be correct.
When you assign A = B, you re-assign a local variable that holds a pointer to the first element of your array. This assignment will not change anything in main. In particular, the contents of A will not be affected.
You must copy all the elements from B to A after you have finished your sorting:
void sort(int *A, int l)
{
int j;
int B[l];
// sort into temporary array B
for (int i = 0; i < l; i++) {
j = largest(A, l);
B[l - i - 1] = A[j];
A[j] = -1;
}
// copy temporary array B to result array A
for (int i = 0; i < l; i++) A[i] = B[i];
}
But if you look at it, Amol Bavannavar was basically right: You don't have to check the whole array for the largest element each time. It is enough to check the remaining elements. So instead of assigning a low value to "used" elements, you could swap the largest elements to the end. When you do that, you'll see that the processed elements are at the end, the unprocessed elements are at the beginning. Then you can do your sorting in place without the need of a temporary array:
void sort2(int *A, int l)
{
while (l) {
int j = largest(A, l--);
int swap = A[j]; A[j] = A[l]; A[l] = swap;
}
}
There are many wrong uses of code in your example, for instance:
int B[l];
cannot be done, if you do it like this l must have a constant value.
A = B;
will perform a shallow copy instead of a deep copy.
You can see the diffrence here: What is the difference between a deep copy and a shallow copy?
cout<<C[0]<<C[1];
will print the numbers joined together without parsing.
As to how to fix this code one implementation you might be aiming towards can be:
#include <iostream>
using namespace std;
int largest(int* A, int l)
{
int big=-1;
int i;
int index=0;
for(i=0;i<l;i++)
{
if(A[i]>big)
{
big=A[i];
index=i;
}
}
return index;
}
void sort(int* A,int l)
{
int j;
int *B=new int[l];
for(int i=0;i<l;i++)
{
j = largest(A,l);
B[l-i-1] = A[j];
A[j] = -1;
}
for(int i=0;i<l;i++)
{
A[i]=B[i];
}
}
int main()
{
int C[3] = {2,5,1};
sort(C,3);
cout<<C[0]<<" "<<C[1];
return 1;
}

Segfault error when calling a method through pointer

I have a baseclass called gridObject
Here's the header file:
#ifndef ITEM_H
#define ITEM_H
class gridObject
{
public:
gridObject();
virtual ~gridObject();
virtual int get_GridID() = 0;
virtual int get_x() = 0;
virtual int get_y() = 0;
virtual int get_direction() = 0;
void set_x(int x);
void set_y(int y);
void set_direction(unsigned int direction);
protected:
private:
int _x;
int _y;
unsigned int _direction;
};
#endif // ITEM_H
I have a subclass called player
Here's the get_GridID() method in the class file:
int player::get_GridID() { return 2; }
There's also a grid class that keeps track of all the objects on it via a 2d vector. In the header file, there's that vector:
private:
vector<vector<gridObject*> > _position;
Here are the methods for setting and getting an object at a specific position, respectively:
void grid::setGridPosition(int x, int y, gridObject* obj) { _position[y][x] = obj; }
gridObject* grid::getGridPosition(int x, int y) { return _position[y][x]; }
The problem I'm having is here:
int main()
{
grid * gr = new grid(10, 10);
player p(0, 0, 100);
gridObject * go = &p;
gr->setGridPosition(0, 0, go);
cout << gr->getGridPosition(0, 0)->get_GridID();
return 0;
}
It crashes at: cout << gr->getGridPosition(0, 0)->get_GridID();
I have included all of the appropriate header files.
EDIT: Here is the constructor for grid and the initialization of _position:
grid::grid(int width, int length)
{
setSize(width, length);
}
void grid::setSize(int width, int length)
{
setLength(length);
setWidth(width);
}
void grid::setLength(int val) { _position.resize(val); }
void grid::setWidth(int val)
{
for(unsigned int i = 0; i < _position.size() - 1; i++)
for(unsigned int j = 0; j < _position.at(i).size() - 1; j++)
_position.at(i).resize(val);
}
You're working with vector of vectors:
vector<vector<gridObject*> > _position;
but the way you initialize _position is following:
_position.resize(length);
for(unsigned int i = 0; i < _position.size() - 1; i++)
for(unsigned int j = 0; j < _position.at(i).size() - 1; j++)
_position.at(i).resize(width);
Note that the first resize constructs length objects of type vector<gridObject*>. Then you are iterating not through these newly-constructed vectors, but rather their elements (second nested loop), which in this case causes that the line _position.at(i).resize(width); is never executed and thus _position[y][x] = obj tries to access the invalid memory resulting in undefined behavior that you observe as segmentation fault.
Try this instead (in grid::setSize):
_position.resize(length);
for(unsigned int i = 0; i < _position.size() - 1; ++i)
_position[i].resize(width);
and also consider using typedef for creating an alias for std::vector<gridObject*> :)