How to add elements to a vector and traverse it simultaneously? - c++

I want to perform BFS on a tree, to find out a certain leaf, but the graph is dynamic in nature, when I land on a leaf and that leaf isn't the one I am looking for, then its children are computed from the leaf (The leaf is no longer a leaf it is a node).
I tried two implementations , and both produced erronous results. I think the pointers are getting invalidated or this is an incorrect implementation. My code is as follows
int y=0;
while(graph.end() - graph.begin() < 262145 and graph.end() - graph.begin() < y){
if(found(graph[y])){
clock2 = graph[y];
break;
}
else{
if(graph[y].b[0] < 4) graph.push_back(move1(graph[y]));
if(graph[y].b[1] < 4) graph.push_back(move2(graph[y]));
}
y++;
}
and the next implementation was something like this
for(vector<foo> :: iterator i = graph.begin();i!=graph.end();i++){
if(found(*i)){
clock2 = *i;
break;
}
else{
if(i->b[0] < 4) graph.push_back(move1(*i));//move1 and move2 are
if(i->b[1] < 4) graph.push_back(move2(*i));//functions of return type foo
}
}
Both of these are causing the programme to crash. What is wrong with them, how to implement these? Please comment with additional queries.

I am a little confused as too what exactly is going on and what exactly you are asking. But if you are asking how to preform a simple BFS on a graph here is some sample code that I find pretty easy to read.
Comment further and I will change it to try and match the exact criteria of the question (once I have some more clarity that is)
struct node{
std::vector children<node*>;
int data;
}
void bfs(node* root, int value){ // THIS IS CHECK FOR INTS so change for whatever value
if(!root) return;
std::queue myq;
myq.push(root);
node* toCheck;
while(!myq.Empty()){
toCheck = myq.top();
myq.pop();
if(toCheck->data == value){
//do whatever you want with that information
}else{
/*
//forloop/whileloop as many times as necessary to set all the new children
//Example:
node* newNode = new node();
newNode->data = someValue; // just some information that you want to add
toCheck->children.push_back(newNode);
*/
}
for(int i = 0; i < toCheck->children.size(); i++){
myq.push(toCheck->children[i]);
}
}
}

Related

How to print a Binary Tree diagram (vertical) and ensure fairly unbalanced trees are not improperly printed?

I'm trying to write functionality to print a vertical binary tree diagram,
I've got the correct breadth-first search algorithm written, and it outputs the BFS-ordered tree traversal to an integer vector. The code can be seen below:
void bst::printlist(Node* node)
{
std::queue<Node*> travQueue;
std::vector<int> result;
travQueue.push(node);
while (!travQueue.empty())
{
result.push_back(node->val);
if (node->prev != NULL)
{
travQueue.push(node->prev);
}
if (node->next != NULL)
{
travQueue.push(node->next);
}
travQueue.pop();
node = travQueue.front();
}
}
However, I am completely stumped on how to convert the resultant vector to one that accurately represents all missing nodes that exist as gaps in a fairly unbalanced tree,
For this example, the vector would only be filled with the integers in the left-to-right order, when it would need to contain information for every missing node all the way down to the bottom level. When going to write the actual code to print the tree with ASCII characters, I will need this information if I am to be able to determine where to and where not to draw nodes -- so, I planned to include dummy values at these gaps to distinguish.
Does anyone have any recommendations for ways to solve this issue?
Thanks!
Here's a great answer, thanks to #NicoSchertler:
"You can push prev and next to travQueue even if they are nullptr. When you reach a nullptr in your iteration, add the dummy value to the result and two more nullptr to travQueue for the non-existing children."
And here's my code for it:
std::queue<Node*> travQueue;
std::vector<int> result;
int h = treeheight(root) + 1;
travQueue.push(node);
for (int i = 0; i < pow(2, h) - 1; i++)
{
node = travQueue.front();
if (node != nullptr)
{
if (node->prev != nullptr)
{
travQueue.push(node->prev);
} else
{
travQueue.push(nullptr);
}
if (node->next != nullptr)
{
travQueue.push(node->next);
} else
{
travQueue.push(nullptr);
}
} else
{
travQueue.push(nullptr);
travQueue.push(nullptr);
}
if (node != nullptr)
{
result.push_back(node->val);
} else
{
result.push_back(-1);
}
travQueue.pop();
}
return result;

How do I count nodes in a B-tree?

I am struggling to count nodes in a B-tree. Here keys refer to an array of values and num_keys refers to the valid number of keys currently. How do I approach this to make it work?
int BTree::count_nodes(shared_ptr<btree> root){
int count = 0;
int i =0;
if (root == NULL) {
return 0;
}
for (i = 0; i < root->num_keys; i++) {
count +=root->keys[i];
}
return count;
}
Here, you can iterate over all nodes in the tree, incrementing the counter each time.
int BTree::count_nodes(shared_ptr<btree> root) {
int count = 0;
std::stack<shared_ptr<btree> > traversal_stack;
traversal_stack.push(root);
while (!traversal_stack.empty()) {
shared_ptr<btree> top = traversal_stack.top();
traversal_stack.pop();
++count;
for (shared_ptr<btree> child : top->children) {
traversal_stack.push(child);
}
}
return count;
}
This uses depth-first search. To do breadth-first search, change the std::stack into an std::queue and use .peek() instead of .top().
Note that it may be more efficient to have each node keep track of its subtree's number of nodes, and for the counts to be updated whenever nodes move around, instead of having a function like this.

Trying to find two random nodes and swap them in a doubly linked list

This program is basically just suppose to shuffle a deck of cards. The cards are stored in a doubly linked list, so 52 nodes. I'm getting a read access error in the getNode function, but I'm pretty sure my loop is correct, so I think the error is stemming from somewhere else. Maybe the swap function. My first step is getting pointers to the nodes that I'm trying to swap.
So I made a function, and I'm pretty sure it's right, except I'm wondering if I should be returning *traverseP instead of just traverseP. I don't think so, because I want to return a pointer to the node, not the value inside the node.
template<class T>
typename ReorderableList<T>::Node *ReorderableList<T>::getNode(int i) const
{
int count = 0;
for (Node *traverseP = firstP; traverseP != NULL; traverseP = traverseP->nextP) {
if (count == i)
return traverseP;
count++;
}
return NULL;
}
Next I made a swap function that take two ints, they represent the values I'm passing into the getNode function
template<class T>
void ReorderableList<T>::swap(int i, int j)
{
// Get pointers to ith and jth nodes.
Node *iPtr = getNode(i);
Node *jPtr = getNode(j);
//create temp Node and store the pointers
Node *temp = new Node;
temp = iPtr->prevP;
temp = iPtr->nextP;
//adjust the iPtr next/prev pointers
iPtr->prevP = jPtr->prevP;
iPtr->nextP = jPtr->nextP;
//adjust the jPtr next/prev pointers
jPtr->prevP = temp->prevP;
jPtr->nextP = temp->prevP;
//I'm a little unclear on these lines. I think they're checking if
//iPtr and jPtr have null pointers. I've tried making them equal jPtr and
//iPtr and that strangly didn't make any difference.
if (iPtr->prevP)
iPtr->prevP->nextP = jPtr;
if (iPtr->nextP)
iPtr->nextP->prevP = jPtr;
if (jPtr->prevP)
jPtr->prevP->nextP = iPtr;
if (jPtr->nextP)
jPtr->nextP->prevP = iPtr;
delete temp;
}
This is the shuffle function where this whole shabang kicks off
template<class T>
void randomShuffle(ReorderableList<T> &list, int n)
{
int randNum = 0;
for (int i = n-1; i > 0; i--)
{
randNum = (rand() & (i + 1));
if (randNum > i)
std::swap(randNum, i);
list.swap(randNum, i);
}
}
I've checked a couple different resources for the swap function and found two that both claimed they were correct, but they looked different to me.
Resource 1
Resource 2

Problems implementing A star search C++

I am trying to implement an A star algorithm with C++ in a game that I am creating and it is not working, I don't really know if there's something I've missed about the code or the algorithm. I've used sets because they are sorted and the return value is a vector with the nodes I've got to visit. I've never used this algorithm before so probably I've got some kind of error.
struct node {
Pos pos;
int f; //the sum of the distance from the goal to succcessor
int g; // the sum of the cost of the current plus the one from the successor
int h; //distance from goal to successor
friend bool operator< (node right, node left) {
return (right.f < left.f);
} };
vector<node> search(Pos inicio,Pos desti){
set<node> opennodes;
vector<node> closednodes;
node inici;
node successor;
inici.pos = inicio;
inici.h = heuristic(inicio,desti);
inici.g = getcost(inicio);
inici.f = inici.g + inici.h;
opennodes.insert(inici);
closednodes.push_back(inici);
while(not opennodes.empty()){
node current = *(opennodes.begin());
opennodes.erase(opennodes.begin());
if(current.pos == desti) cerr<<"encontrao";
Dir direccio;
for(int i = 0; i < 4;++i){
if(i==0){
direccio = LEFT;
}
else if(i==1){
direccio = RIGHT;
}
else if(i==2){
direccio = TOP;
}
else {
direccio = BOTTOM;
}
successor.pos = current.pos + direccio;
if(successor.pos == desti) return closednodes;
if(pos_ok(successor.pos)){
successor.g = current.g + getcost(successor.pos);
successor.h = heuristic(successor.pos,desti);
successor.f = successor.g + successor.h;
node n1 = checkposition(successor.pos, opennodes); //I had to create two checkposition just to know if there's the node in the set or in the vector
node n2 = checkposition2(successor.pos, closednodes);
if (n1.f != -1 and n1.f < successor.f);
else if (n2.f != -1 and n2.f < successor.f);
else opennodes.insert(successor);
}
}
closednodes.push_back(current);
}
return closednodes;
}
So, first:
if(current.pos == desti) cerr<<"encontrao";
Shouldn't there be a break statement here? the cerr function doesn't break your loop, just throws and error message to your stdout.
And the for statement inside your while is always running up to 4, so direccio is always set to BOTTOM.
Other than that, I think the heuristic is fine, the problem is within the code structure, I'd suggest debugging it and posting here your results.

Issue with recursive function C++

I have a short recursive function to write, and I am having an issue with my function returning seg fault 11 when I run it through g++. I am pretty bad at recursion, and just starting to learn it. Please let me know if you have any suggestions! The goal is to count how many nodes have a value larger than the inputed value "m" .Here is my code:
int LinkedList::countOccurrencesMoreThanRec(int m)
{
// first do the base cases that do not require recursion
if (head == NULL)
return -1;
int answer = 0;
if ((head -> getNext()) == NULL)
{
if ((head -> getValue()) > m)
answer ++;
return answer;
}
// if none of those were true, call the recursive helper method
Node *BatMan = head;
answer = countOccurrencesMoreThan(BatMan, m);
return answer;
}
/* countOccurrencesMoreThan
*
* private recursive method.
* TODO: fill in this method
*/
int LinkedList::countOccurrencesMoreThan(Node *h, int m)
{
// check for the base case(s)
int answer = 0;
if ((h -> getNext()) == NULL)
{
if ((h -> getValue()) > m)
answer++;
return answer;
}
// smaller case
Node *Bane = h;
answer = countOccurrencesMoreThan(Bane, m);
return answer;
// general case
}
Your comments are lying.
// smaller case
Node *Bane = h;
Here, you're setting Bane to the same value that was passed in to your function. You're not actually testing the next item in the list, you're doing the same list again.
This isn't the only problem in your code, but it will at least help with the question you asked.
One of the first questions with recursion should always be, do I need recursion? When iterating elements of a LinkedList there is absolutely no need to recurse.
Secondly, I strongly advise against rolling your own linked list class as the time it takes to write your own would be better spent learning libraries such as the STL which give you great data structures out of the box for free (that other colleagues understand!).
However to accomplish what you are trying to achieve recursively, you could either make the "answer" int a class member, a global variable (shudder) or pass the answer to each invocation of the function (passing zero in the first instance), but I cannot stress enough that the recursive approach is not the right approach for this problem. The answer variable has no place in a LinkedList class for a start, global variables are almost always evil, and passing around a value you're simply incrementing is inefficient and confusing.
int LinkedList::countOccurrencesMoreThan(Node *h, int m, int answer)
{
if( h->getValue() > m ) {
++answer;
}
if (h -> getNext() == NULL)
{
return answer;
}
countOccurrencesMoreThan( h->getNext(), m, answer);
}
Here is a better non recursive implementation with a simple LinkedList class:
void LinkedList::countOccurrencesMoreThan(int value) {
Node* node = this->head;
int occurrences = 0;
while(node != NULL) {
if( node->getValue() > v ) {
++occurrences;
}
node = node->getNext();
}
std::cout << "occurrences = " << occurrences << std::endl;
}