Manipulating data in struct format ends up weird - c++

So I am working on a maze generator program as a dfs practice.
struct Point{
Point *left,*right,*up,*down;
int x,y;
bool visited;
Point(int n,int m)
:x(n),y(m),visited(false),left(NULL),right(NULL),up(NULL),down(NULL)
{}
};
and I have used a for loop to initialize a vector of vector of Point,
each with a unique address and the visited value assigned as false.
vector<vector<Point*> > board;
for(i=0;i<row;i++){
for(j=0;j<col;j++){
Point *temppt=new Point(j,i);
tempv.push_back(temppt);
}
board.push_back(tempv);
}
for(i=0;i<row;i++){
for(j=0;j<col;j++){
if(i!=0)board[i][j]->up=board[i-1][j];
if(i!=row-1)board[i][j]->down=board[i+1][j];
if(j!=0)board[i][j]->left=board[i][j-1];
if(j!=col-1)board[i][j]->right=board[i][j+1];
}
}
However, something weird happens when I manipulate them during a dfs search...
whenever I execute this segment of code
board[now->y][now->x]->visited=true;
each of the first value of the vector of board (board[x][0]) are also changed to true, as a checked it with this for loop.
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
cout<<board[i][j]->visited;
}
cout<<endl;
}
What should I do to manipulate the points one of one instead of column by column
The full dfs function:
void dfs(Point* now,Point* prev,int cnt){
int dir,back;
if(now->visited!=true){
cnt++;
if(prev!=NULL){
if(prev->up==now){
hwall[now->x][now->y]=false;
}
else if(prev->down==now){
hwall[prev->x][prev->y]=false;
}
else if(prev->right==now){
vwall[prev->y][prev->x]=false;
}
else vwall[now->y][now->x]=false;
}
board[now->y][now->x]->visited=true;
}
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
cout<<board[i][j]->visited;
}
cout<<endl;
}
if(cnt<row*col){
back=rand()%10;
vector<Point*> temp;
if(back<5){
A:;
if(now->up!=NULL)temp.push_back(now->up);
if(now->right!=NULL)temp.push_back(now->right);
if(now->down!=NULL)temp.push_back(now->down);
if(now->left!=NULL)temp.push_back(now->left);
dfs(temp[rand()%temp.size()],now,cnt);
}
else{
if(now->up!=NULL&&now->up->visited!=true)temp.push_back(now->up);
if(now->right!=NULL&&now->right->visited!=true)temp.push_back(now->right);
if(now->down!=NULL&&now->down->visited!=true)temp.push_back(now->down);
if(now->left!=NULL&&now->left->visited!=true)temp.push_back(now->left);
if(temp.size()==0)goto A;
dfs(temp[rand()%temp.size()],now,cnt);
}
}
}
The full constructor:
Maze(int n,int m):row(n),col(m){
int i,j;
vector<Point*> tempv;
for(i=0;i<row;i++)vwall.push_back(vector<bool>(col-1,true));
for(i=0;i<col;i++)hwall.push_back(vector<bool>(row-1,true));
for(i=0;i<row;i++){
for(j=0;j<col;j++){
Point *temppt=new Point(j,i);
tempv.push_back(temppt);
}
board.push_back(tempv);
}
for(i=0;i<row;i++){
for(j=0;j<col;j++){
if(i!=0)board[i][j]->up=board[i-1][j];
if(i!=row-1)board[i][j]->down=board[i+1][j];
if(j!=0)board[i][j]->left=board[i][j-1];
if(j!=col-1)board[i][j]->right=board[i][j+1];
}
}
dfs(board[0][0],NULL,0);
}

You aren't clearing tempv after you push it back into board. So each entry of board is receiving an extended copy of tempv. (Specifically, the first col entries will be identical in each row.)
Just call tempv.clear() right after board.push_back(tempv), so that each row starts with an empty vector.

Related

Why am I gettnig runtime error: load of null pointer of type '_Bit_type' (stl_bvector.h)?

Can anyone tell me why I get this error for this code? The error is on the flower bracket on line 81.
Error: runtime error: load of null pointer of type '_Bit_type' (stl_bvector.h)
I don't know why I get this error. The question is a word search. I am familiar with Python, and am a beginner in C++.
#include<bits/stdc++.h>
using namespace std;
class Solution {
public:
int h=0;
vector<vector<bool>> visited;
void see(int i,int j,int m,int n,string word,vector<vector<char>> &board,int l){
if(l==word.size()){
h=1;
//cout<<s<<endl;
return;
}
if(i-1>=0 and i-1<m and j>=0 and j<n){
if(visited[i-1][j]==false){
visited[i-1][j]=true;
this->see(i-1,j,m,n,word,board,l+1);
visited[i-1][j]=false ;
}
}
if(i>=0 and i<m and j+1>=0 and j+1<n){
if(visited[i][j+1]==false){
visited[i][j+1]=true;
this->see(i,j+1,m,n,word,board,l+1);
visited[i][j+1]=false ;
}
}
if(i+1>=0 and i+1<m and j>=0 and j<n){
if(visited[i+1][j]==false){
visited[i+1][j]=true;
this->see(i+1,j,m,n,word,board,l+1);
visited[i+1][j]=false ;
}
}
if(i>=0 and i<m and j-1>=0 and j-1<n){
if(visited[i][j-1]==false){
visited[i][j-1]=true;
this->see(i,j-1,m,n,word,board,l+1);
visited[i][j-1]=false ;
}
}
}
bool exist(vector<vector<char>>& board, string word) {
visited.resize(board.size());
for(int i=0;i<board.size();i++){
for(int j=0;j<board[0].size();j++){
visited[i][j]=false;
}
}
int m=board.size(),n=board[0].size();
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(board[i][j]==word[0]){
visited[i][j]=true;
this->see(i,j,m,n,word,board,1);
if(h==1){
return(true);
}
visited[i][j]=false;
}
}
}
return(false);
}
};
The problem is in your exist function. You start with a visited.resize(), which will resize visited to have board.size() empty vectors. When you attempt to write to visited[i][j] in the following loop, you'll get this error.
The simplest fix is to also create all the subvectors when you resize visited:
visited.resize(board.size(), vector<bool>(board[0].size());
That does have one issue with it, though: if board is empty, you'll access out of bounds for the default value for all the subvectors.
Once you have that, the following loops are not needed, since the vectors will have all elements set to false.
You can also move the declarations for m and n up to the start of exist, and use them when resizing visited.

c++ question:After assigning value to a variable,the other variable changed

Following codes are my own API for index prior queue.When I test insert function,I get wrong answer.Then I debug codes,I found that the value of array qp changed after executing sentence----item[k]=vwhich is in insert function.Why the value of array qp changed after assigning value to array item?
template <class T>
class IndexPriorQueue{
private:
int index;//the num of items
int size;//capacity
int* pq;//index binaryheap
int* qp;//qp[pq[i]]=pq[qp[i]]=i
T* item;//item array;
public:
IndexPriorQueue(int qsize){//constructor function
size=qsize;
index=0;
pq=new int(size+1);
qp=new int(size+1);
item=new T(size+1);
for(int i=0;i<size+1;i++)
qp[i]=-1;
}
void insert(int k,T v){
if(contain(k)){
cout<<"index is already in queue"<<endl;
return;
}
//cout<<"insert"<<endl;
item[k]=v;//debug,after excuting this sentence,the value of qp exchanged??
pq[++index]=k;
qp[k]=index;
swim(index);
}
bool contain(int k){
return qp[k]!=-1?1:0;
}
void swim(int j){
while(j>1){
if(item[pq[j/2]]<item[pq[j]]){
exch(j/2,j);
j=j/2;
}else{
break;
}
}
}
void exch(int m,int n){
int temp=pq[m];
pq[m]=pq[n];
pq[n]=temp;
qp[pq[m]]=m;
qp[pq[n]]=n;
}
void display(){
cout<<"item:";
for(int i=1;i<size+1;i++){
cout<<item[i]<<" ";
}
cout<<endl;
cout<<"pq:";
for(int i=1;i<size+1;i++){
cout<<pq[i]<<" ";
}
cout<<endl;
cout<<"qp:";
for(int i=1;i<size+1;i++){
cout<<qp[i]<<" ";
}
cout<<endl;
}
};
Following codes are main function
int main(){
cout<<"before insert:"<<endl;
IndexPriorQueue<char> ipq(10);
ipq.display();
ipq.insert(1,'a');
cout<<"after insert:"<<endl;
ipq.display();
return 0;
}
The problems is your allocations. Take for example
new T(size+1)
That allocates one object of type T and initializes it to the value size + 1 (i.e. it calls the T constructor with size + 1).
If you need to allocate an "array" you should use square brackets [] as in
new T[size+1]
That will allocate an array of size + 1 number of T objects.
A much better solution though, is to use std::vector instead of doing it all manually yourself.

Unable to access vector value by index

#include<iostream>
#include<vector>
using namespace std;
class Stack
{
public:
int top;
vector<int> v;
Stack(int size)
{
top=0;
cout<<"Enter the values"<<endl;
for(int i=0; i<size; i++)
{
int val;
cin>>val;
v.push_back(val);
top++;
}
}
void push(int val)
{
v.push_back(val);
top++;
}
int pop()
{
int x=v[top];
top--;
return x;
}
void disp()
{
for(int j=top; j<=0; j--)
cout<<v[j]<<' ';
}
};
int main()
{
Stack s(3);
int k=s.pop();
cout<<k;
return 0;
}
I am trying to learn the basics of OOP.
Here, my Stack constructor and push function are working fine, but there is a problem with the pop and disp functions.
I'm assuming that I am using an incorrect syntax to access the elements of a vector(maybe?). Can anyone tell me where I am going wrong?
Also, the value of k always comes out to be 0.
You can use the vector functions
int k = s.back();
s.pop_back();
cout << k;
more informationhttp://www.cplusplus.com/reference/vector/vector/back/
You have a off-by-one index error.
The way you have implemented your class, when there are N items in the stack, the value of top is N.
Hence, top is not a valid index to access the elements of v. You can use:
int pop()
{
int x=v[top-1];
top--;
return x;
}
or
int pop()
{
top--;
int x=v[top];
return x;
}
As some of the other answers say, you can use the built-in vector functions to do these things (see pop_back and back.
However, if you want to define your own, I would use the vector.at(index) function. Addressing the values with the index as you have works, but it doesn't do any bounds checking at() does. Which would solve your problem above where your index isn't correct for the zero-based indexing of a vector.

How to swap elements in 2d array c++

I'm trying to make a 15 puzzle game by swapping an element with the position of a blank element. I've made this code, but it only swaps when the tile is to the right or below for some reason.
void moveTile(int gameBoard[][SIZE], int nextMove, int &blanki, int &blankj)
{
int temp=nextMove;
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
if(gameBoard[i][j]==nextMove)
{
gameBoard[i][j]=gameBoard[blanki][blankj];
gameBoard[blanki][blankj]=temp;
blanki=i;
blankj=j;
}
}
}
}
Walk thru it in a debugger. You'll see that after a swap is made, you keep going and searching. In the case where the tile is above or left, you'll swap a second time.
You need to stop searching once you've made a swap.
I have updated it to include a stop, now the code does not iterate.
void moveTile(int gameBoard[][SIZE], int nextMove, int &blanki, int &blankj)
{ bool stop=false;
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
while(!stop)
{if(gameBoard[i][j]==nextMove)
{
int temp=gameBoard[i][j];
gameBoard[i][j]=gameBoard[blanki][blankj];
gameBoard[blanki][blankj]=temp;
blanki=i;
blankj=j;
stop=true;
}
}
}
}
}

Different output when set different breakpoints

I just wrote a code to build a Huffman Tree using MinHeap. When testing I want to output its traversal result.
The algorithm is simple, but my code can't get the right answer. It's strange that the output was different when I set different breakpoints. For instance, it depends on if I set a break point in the loop, such as line 165 input_list.insert(*parent);.
The test input was
4 //number of nodes.
1 1 3 5 //weight of each node.
and the output when debugging it with a breakpoint in the loop is
5
10
1
2
1
5
3
that is correct. But when I just run it without debug, it even didn't have any output. Does anyone know how to explain it?
#include <iostream>
#include <vector>
using namespace std;
#define max_size 100
int sum=0;
class huffman_node
{
public:
int weight;
huffman_node* left_child;
huffman_node* right_child;
huffman_node(){}
huffman_node(int w, huffman_node* l, huffman_node* r):
weight(w),left_child(l),right_child(r) {}
};
vector <huffman_node> node_list;
class minheap
{
public:
minheap()
{
heap=new huffman_node [max_size];
current_size=0;
}
~minheap()
{
delete []heap;
}
void siftdown(int start, int m)
{
int i=start;
int j=2*i+1;
huffman_node temp=heap[i];
while(j<=m)
{
if(j<m && heap[j+1].weight<heap[j].weight)
{
++j;
}
if(temp.weight<=heap[j].weight)
{
break;
}
else
{
heap[i]=heap[j];
i=j;
j=2*i+1;
}
}
heap[i]=temp;
}
void siftup(int start)
{
int j=start;
int i=(j-1)/2;
huffman_node temp=heap[j];
while(j>0)
{
if(heap[i].weight<=temp.weight)
{
break;
}
else
{
heap[j]=heap[i];
j=i;
i=(j-1)/2;
}
heap[j]=temp;
}
}
bool insert(const huffman_node& input)
{
if(current_size==max_size)
{
cout<<"minheap full"<<endl;
return false;
}
heap[current_size]=input;
siftup(current_size);
++current_size;
return true;
}
bool remove_min(huffman_node& output)
{
if(!current_size)
{
cout<<"minheap empty"<<endl;
return false;
}
output=heap[0];
heap[0]=heap[current_size-1];
--current_size;
siftdown(0,current_size-1);
return true;
}
private:
huffman_node* heap;
int current_size;
};
void route_length(huffman_node* &root,int depth)
{
if(root!=NULL)
{
// if(root->left_child==NULL&&root->right_child==NULL)
// {
// sum+=depth*root->weight;
// }
route_length(root->left_child,depth+1);
cout<<root->weight<<endl;
route_length(root->right_child,depth+1);
}
else
{
return;
}
}
int main()
{
minheap input_list;
int n;
cin>>n;
for(int i=0;i<n;++i)
{
int key;
cin>>key;
huffman_node input(key,NULL,NULL);
input_list.insert(input);
cin.get();
}
huffman_node* root;
for(int i=0;i<n-1;++i)
{
huffman_node* parent;
huffman_node out1;
huffman_node out2;
input_list.remove_min(out1);
input_list.remove_min(out2);
node_list.push_back(out1);
node_list.push_back(out2);
parent=new huffman_node(out1.weight+out2.weight,&node_list[node_list.size()-2],&node_list[node_list.size()-1]);
input_list.insert(*parent);
root=parent;
}
route_length(root,0);
// cout<<sum<<endl;
return 0;
}
The problem is that you are using pointers to elements of a vector<huffman_node> and storing these in your data structure (i.e. left and right members of the huffman_node object).
The thing that is randomly killing your program is that std::vector moves values around in memory when you append to it. The contents of the elements of the vectors are preserved, but the location is not. Once it moves the elements, the memory where the vector used to be can be overwritten by whatever (i.e. gdb needs heap memory too) and now the pointers are pointing to garbage.
As a quick sanity check, you can make your code not crash by reserving space in your node_list by calling
node_list.reserve(max_size*2);
in the beginning of main. This is not the right way of developing this piece of code further, but should illustrate the problem.
It would be better if your node_list was a vector<huffman_node*> instead. Or if you changed the left/right members to be vector indices instead of pointers.