vector doesn't work in struct - c++

I have struct like this:
struct element{
char ulica[10];
vector<int> dane[3];
int wolne;
int w;
element *lewy, *prawy, *ojciec;
};
And I'm implementing kind of AVL tree. When key's are the same i need to put some int values to dane (dane[0], dane[1], dane[2] describe 3 different value) so I use
tmp2->dane[0].push_back(number)
EDIT. Here is code where I'm adding a values to this vector, it's half of the function because secod half is about rotations in AVL.
void wstaw_wezel(){
element *tmp2; //tmp2 bedzie ojcem nowo wstawionego elementu
tmp2=korzen;
while(tmp2!=NULL){
if(strcmp(tmp2->ulica, tmp->ulica)<0){
if(tmp2->prawy!=NULL){
tmp2=tmp2->prawy;
}
else{
tmp->ojciec=tmp2;
tmp2->prawy=tmp;
cout<<"Wstawiam pod prawy "<<tmp2->ulica<<endl;
if(tmp2->w!=0) tmp2->w=0;
else tmp2->w=-1;
break;
}
}
else if(strcmp(tmp2->ulica, tmp->ulica)>0){
if(tmp2->lewy!=NULL){
tmp2=tmp2->lewy;
}
else{
tmp->ojciec=tmp2;
tmp2->lewy=tmp;
if(tmp2->w!=0) tmp2->w=0;
else tmp2->w=1;
cout<<"Wstawiam pod lewy "<<tmp2->ulica<<endl;
break;
}
}
else{
cout<<"2 bloki na tej samej ulicy"<<endl;
for(int i=0; i<tmp2->dane[0].size(); i++) cout<<tmp2->ulica<<" "<<tmp2->dane[0][i]<<endl;
tmp2->numery.push_back(tmp->numery[0]);
tmp2->dane[0].push_back(tmp->dane[0][0]);
for(int i=0; i<tmp2->dane[0].size(); i++) cout<<tmp2->ulica<<" "<<tmp2->dane[0][i]<<endl;
tmp2->dane[1].push_back(tmp->dane[1][0]);
tmp2->dane[2].push_back(tmp->dane[2][0]);
tmp2->wolne+=tmp->dane[2][0];
break;
}
}
if(tmp->ojciec==NULL){
korzen=tmp;
return;
}
where tmp2 is a pointer to this struct (I checked adrres where it points and every time it's the same adrres).
Where is problem? If I add new value to vector it is until the loop where i do it ends. Finally instead having fe. 4 values in vector i have one, the last added value. Vector don't add new value to the end, just replacing it.

You declare the initial size of a std::vector in its constructor, so one way you can accomplish this is:
struct element
{
char ulica[10];
std::vector<int> dane;
int wolne;
int w;
element *lewy, *prawy, *ojciec;
element() : dane(3) {}
};
If you don't include the constructor, the initial size of the vector will be 0. In any event, to add an element to the back, just use tmp2->dane.push_back(number); This will add the value in number to the back of the vector tmp2->dane which may result in a change in the amount of allocated memory for the vector instance.
UPDATE: Based on the comment from the OP that he needs three vectors try this:
struct element
{
char ulica[10];
std::vector<std::vector<int> > dane;
int wolne;
int w;
element *lewy, *prawy, *ojciec;
element() : dane(3) {}
};
To add elements to the vectors, simply use tmp2->dane[i].push_back(number) where i is the index of the vector to use, and number is the new number to add to the ith vector, which is the same convention you seem to be using in your code segment above.
Update 2: Based on additional information below, I think a redesign of your data structure is called for. You're mixing the meaning of the various components and by more clearly delineating the functions of the data element and the AVL data structure management, you will be able to more clearly distinguish between the two. So try this instead. Have a data structure specifically for the "value" portion of your tree nodes, as in:
struct house
{
int house_number;
int unique_value0;
int unique_value1;
house(int hn, int uv0, int uv2)
: house_number(hn),
unique_value0(uv0),
unique_value1(uv1) {}
};
template <typename VALUE> struct node
{
std::string key;
std::vector<VALUE> values;
int left, right;
node<VALUE> *leftNode, *rightNode, *parentNode;
};
From here, you create a root node:
node<house> *root;
When you want to add a house to a street, node<house> *s, all you need to do is
s->values.push_back(house(a, b, c));
Of course a better alternative is to use what C++ already has for this. That is, there is a structure in the standard library called std::multimap which does pretty much what you're trying to do. In this case, you can simple declare
std::multimap<std::string, house> myMap;
This probably won't use AVL balancing. It more likely will be a Red-Black Tree, but it's all done for you.

How do you alloc the struct element?, it seems that the vector<int> dane[3]; has been initialized successful, but its inner vector does not been initialised.
try to add a ctor method to the struct element?
struct element
{
char ulica[10];
vector<int> dane[3];
int wolne;
int w;
element *lewy, *prawy, *ojciec;
element()
{
dane[0] = vector<int>();
dane[1] = vector<int>();
dane[2] = vector<int>();
}
};

Related

passing struct by reference in c++ doesnt update the value

i am passing a struct by reference to one function of a class treestr and storing it there in a vector.
Then passing the same struct by reference to another function and performing some computation on data member of struct. This data member gets updated in the original struct but not in the ones stored in the vector.
(Sorry for any mistakes, new to c++, new to stack overflow). Please help.
//Structure description
Struct point{
int x;
int y;
int cal{0};
};
Struct node{
point p;
int data; //value to be updated by func
};
int main(){
treestr * tree= new treestr(); //create object
int i=0,n=100;
vector<node> nob;
while(i<=n){
p={1,5}; //some values input by user
node n={p,i};
nob.push_back(n)//storing the struct node objects seperately in a
//vector
treestr->insert(n); //inserting into tree class
i++;
}
//calling func to do some computation on the struct objects inserted
for(i=0;i<n;i++){
int x=tree->func(nob[i]);
cout<<x.cal; //getting updated values from the function
}
for(i=0;i<N;i++){
tree->func2(nob[i]);
}
return 0;
}
//class description
class treestr{
vector<node> buck;
insert(node& n){
buck.push_back(n);
//store nodes
}
func(node& n){
//calculations
return n.cal; Value got updated in main.
}
func2(node &n){
int val1=n.cal; //this assigns updated value
int val2=buck[i].p.cal; //this assigns 0(default value)
if(val1==val2){ //never matches, val2 is 0 for all objects, val1 is
//not after getting updated
//do something
}
}
};
The cal gets updated in the main function but not in the class where I have stored. Please ignore grammatical and syntactical mistakes, the code returns correct output however this is something that I need to improve my code.
Any possible reasons??
Try changing
node n={1,5,0}
to
node * n;
node -> x = 1;
node -> y = 5;
node -> cal = 0;
From what I know of pointers you need to assign each value individually.
Also
tree->insert(n)
needs to be
tree.insert(n)
Another thing
int node.cal=tree->func(n);
Not sure what this is supposed to do, but I know it won't work. 'int' needs to be before a variable name. When accessing cal from node your call needs to be an -> and when accessing func from tree it needs to be a .

C++ insert an element to a vector

I am trying to build a priority queue using a vector that stores each element. Firstly, I wanna insert the element to the vector with its priority. I am not sure if it is possible, if not, Can someone give me another solution.
Here is my code:
template <typename E>
class PriorityQueue {
private:
std::vector<E> elements;
E value;
int pr;
public:
PriorityQueue() {}
void insert(int priority, E element) {
}
};
Here is how to create an element with priority for vector:
struct PriElement
{
int data;
int pri;
bool operator < ( const PriElement & other ) const
{
return pri < other.pri;
}
};
vector<PriElement> _vector;
However, the real problem is to keep the vector sorted per priority.
Here is a naive implementation showing the bubble up method:
class PriorityQueue{
public:
void insert( int data, int pri )
{
_vector.push_back(PriElement(data,pri));
int index = _vector.size() -1;
while ( ( index > 0 )&& (_vector[index] < _vector[index-1] ) )
{
swap(_vector[index],_vector[index-1]);
index--;
}
}
private:
vector<PriElement> _vector;
};
For any real world implementation, as mentioned, use priority_queue.
The standard algorithm (see Introduction To Algorithms chapter 6) for doing this is as follows:
When pushing an item, insert it to the end of the vector, then "bubble" it up to the correct place.
When popping the smallest item, replace the first item (at position 0) with the the item at the end, then "bubble" it down to the correct place.
It's possible to show that this can be done with (amortized) logarithmic time (the amortization is due to the vector possibly doubling itself).
However, there is no need to implement this yourself, as the standard library contains std::priority_queue which is a container adapter using std::vector as its default sequence container. For example, if you define
std::priority_queue<int> q;
then q will be a priority queue adapting a vector.

Scope of an Object in a Loop

I have a simple algorithm which returns a list of lists, where each inner list contains the nodes on a different level of a binary tree. I'm having trouble understanding how to "reset" the scope of my inner list (e.g. see below).
My tree is a simple toy tree like so:
struct Node {
int data;
Node *left, *right;
}
I use a simple bfs that should return a list of lists. I try to create a new list on each of the loops, but I'm not sure how to "clear" the list and start a new one.
std::vector< std::vector<Node *> > build_lists(Node *root) {
std::vector< std::vector<Node *> > result;
Node *newline = new Node { std::numeric_limits<int>::min(), nullptr, nullptr };
std::deque<int> q;
q.push_back(root);
q.push_back(newline);
Node *tmp;
std::vector<Node *> inner; // HERE IS WHERE IS SET THE FIRST INNER VECTOR
while(!q.empty()) {
tmp = q.front();
q.pop_front();
if (tmp == newline) {
result.push_back(inner);
std::vector<Node *> inner; // HERE IS WHERE I TRY TO ''RESET'' THE VECTOR
if (!q.empty())
q.push_back(newline);
} else {
inner.push_back(tmp);
if (tmp->left)
q.push_back(tmp->left);
if (tmp->right)
q.push_back(tmp->right);
}
}
}
Clearly, I have failed to understand scope and some basic language features. If anyone could help point me in the right direction, I would appreciate it.
You can't reset a variable by declaring it again, which is what your code is doing. You now have a second variable with the same name, that for the duration of the second variable that name points to the second variable.
Instead you need to use a method to clear the first variable.
vector does have a method to reset it's contents - vector::clear.
You should do this instead:
result.push_back(inner);
// std::vector<Node *> inner;
inner.clear();
If you need to clear something you've pushed inside a vector, you can do this:
vector< vector< int > > vvi;
vector< int > vi;
vi.push_back(1); // fill
vii.push_back(vi); // vii has a copy of vi as it is now.
auto & _v = vii[0]; // fetch a reference to the copy
_v.clear(); // clear it
vii[0].clear(); // same in one step
assert( vii[0].size() == 0 ); // still contains a vector at index 0 but it's empty
Notwithstanding the fact that you would be clearing vectors of pointers - as others have pointed out (ha) you need to be very careful not to 'lose track' of pointers.
Eg, this would be bad:
vector< int* > x;
x.push_back( new int(4) );
x.clear(); // leak
In order of an object to go out of scope, it has to be created INSIDE the loop, like this for example:
while(1) {
std::vector<int> v;
...
// at that point 'v' will go out of scope and thus destroyed
}
However, when you do this:
std::vector<int> v;
while(1) {
...
// 'v' is always the same at this point
}
You could use std::vector::clear() to reset your vector, but be careful, since you are using pointers. Unless you keeping track of the pointed objects, just clearing the vector would result to dangling pointers, thus Undefined Behavior and you don't want that to happen.
If you need to free the memory the pointers point to, then you should first delete the objects the pointers point to and then clear the vector.

Segmentation fault in dijkstra's algorithm

I am writing a c++ program to code for dijkstra's algorithm. Here is the code.
#include <iostream>
#include <vector>
#include <map>
using namespace std;
class vertex;
class node
{
public:
int value;
//bool exp=false;
char c;
};
class edge
{
public:
vertex* head;
vertex* tail;
int length;
edge(vertex*h,vertex* t, int l)
{
head=h;
tail=t;
length=l;
}
};
class vertex:public node
{
public:
vector<edge*> a;
vertex& operator|(vertex &p)
{
int l;
cout<<"Give the length of edge "<<this->c<<p.c<<endl;
cin>>l;
edge q(&p,this,l);
a.push_back(&q);
}
vertex(char a)
{
c=a;
}
};
int main()
{
vertex e('e');
vertex d('d');
vertex b('b');
vertex c('c');
vertex a('a');
vertex s('s');
s.value=1;
a.value=2;
b.value=3;
c.value=4;
d.value=5;
e.value=6;
s|a;
s|b;
a|c;
b|c;
b|d;
c|d;
c|e;
d|e;
cout<<"4";
map <char ,int >A;
vector<edge*>::iterator minin;
vector<edge*>::iterator j;
int min=0;
vector<vertex*> X;
X.push_back(&s);
A['s']=0;
vector<vertex*>::iterator i=X.begin();
for(; i<X.end(); i++)
{
cout<<"1";
j=((*i)->a).begin();
for(; j<((*i)->a).end(); j++)
{
cout<<"2";
if((*j)->length+A[((*j)->tail)->c]>min)
{
cout<<"3";
minin=j;
min=(*j)->length+A[((*j)->tail)->c];
}
}
}
X.push_back((*minin)->head);
A[((*minin)->tail)->c]=min;
cout<<((*minin)->head)->value;
}
The program returns a segmentation fault. I have used various cout statements to check where the fault occured but nothing is printed in console. However, I am able to input the edge length in the console but after giving the input it directly gives segmentation fault.
In
a.push_back(&q);
you are storing the address of a local object, which will cease to exist once the function terminates.
Why are you creating a class to keep your vertices/nodes?. I think you should use plain integers from 0 to N - 1 to avoid get things more complicated. If vertices are identified by a string or something else, you could use a hash/map data structure to transform the keys to an integer. That will help you to avoid moving complex vertex structures and using pointers.
The Edge class seems fine because the Dijkstra's algorithms needs all that data to work (start, end vertices, and the weight/cost of the path).
Having said that, the algorithm could be implemented using a binary heap data structure to prioritize the edge selection. You could also use a priority queue (http://en.cppreference.com/w/cpp/container/priority_queue) if you don't want to implement a binary heap.
Finally, I would use a Edge vector to iterate over the adjacent vertices of every vertex.

c++ push_back doesn't work as it is supposed

I have a class symbol_table that has a vector of objects of another class row_st.also I have an enter method where inserts objects of row_st with a passed name into the vector of desired symbol_table.but when I call the enter to enter objects with name :
a;b;c;Iwill get the following result: a,b,c;b,c;c.the first element of vector gets the name of all the entered objects. and the second element also gets the name of the later entries.
class row_st
{
public:
char* name;
type_u type;//int:0,flaot:1;char:2,bool:3,array:
int offset;
symbol_table *next;
symbol_table *current;
};
class symbol_table
{
public:
vector <row_st *> row;
int type;
int header;
int starting_stmt;
int index;
int i;
symbol_table *previous;
symbol_table(){ header=0;
previous=0; index=0;i=0;starting_stmt=0;}
};
and here it is the enter method:
int enter(symbol_table *table,char* name,type_u type){
row_st *t=new row_st;
t->name=name;
t->type=type;
t->offset=table->index;
t->current=table;
table->index++;
t->next=0;
table->row.push_back(t);
table->header +=1;
return table->row.size()-1;
}
the push_backed elements all points to the same address.the new call makes the same row_st every time it is called.what should I do?
You can't use character pointers like that - you need to allocate storage to them. But as you are using C++, you should remove them and replace them with instances of the std::string class, which will manage storage for you.
As Neil Butterworth's answer suggest, the trouble is probably not with this code, but the place where you call it. Using character pointers does not make it impossible to make things work, just harder.
The problem in this case is definitely not with push_back. If you posted the method where you call this code it might be possible to see exactly what goes wrong.