struct BTreeNode {
bool is_leaf=true;
std::vector<int> elements;
std::vector<BTreeNode*> children;
BTreeNode() {}
BTreeNode (std::vector<int> v) {
this->elements = v;
}
};
void traverse(BTreeNode* root) {
for(int i = 0; i < (int)root->children.size(); ++i){
traverse(root->children[i]);
cout << root->elements[i] << endl;
}
traverse(root->children[root->children.size() -1]);
}
My method somehow segfaults. How do we write a correct inOrder Traversal for B-Tree?
It's probably the last traverse call when you are at a leaf. I don't think that this traverse is needed.
Assuming BTreeNode is a generic definition of your b-tree node, whereas T1 is the type of the keys and T2 is the type of the values in the tree, and sortedKeys is the list you are after, you can use the following recursive method. The idea is very similar to an inOrder traversal in binary search tree, first visit the left-most child, then visit the key- then continue, Since the number of children in B-tree is always one bigger than the number of keys, a check is needed before visiting the key [code is in c#, but can easily be converted to any other language, the purpose is to show the algorithm only].
public void InOrderTraversal(BTreeNode<T1, T2> node, List<KeyValuePair<T1, T2>> sortedKeys)
{
if (node != null)
{
for (int i = 0; i < node.Children.Count; i++)
{
InOrderTraversal(node.Children[i], sortedKeys);
if (i < node.KeyValues.Count)
sortedKeys.Add(node.KeyValues[i]);
}
}
}
Related
I'm working through a tree traversal problem and using 'push_back' vector function to update a vector with the in-order traversal. Alongside using this I am using cout to print out the solution to debug. The print output is correct but my returning vector doesn't match the print so I can only put this down to me not understanding how the push_back function works.
This is the function I am using:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> order {};
if (root != nullptr) {
inorderTraversal(root->left);
cout << "pushing back : " << root->val << std::endl;
order.push_back(root->val);
inorderTraversal(root->right);
}
return order;
}
For the input tree [1,null,2,3] My stdout is printing:
pushing back : 1
pushing back : 3
pushing back : 2
Which is correct but my returning array (order) is only [1].
You're ignoring the results from each recursion. You should be doing this:
vector<int> inorderTraversal(TreeNode *root)
{
vector<int> order;
if (root != nullptr)
{
order = inorderTraversal(root->left);
cout << "pushing back : " << root->val << std::endl;
order.push_back(root->val);
auto tmp = inorderTraversal(root->right);
order.insert(order.end(), tmp.begin(), tmp.end());
}
return order;
}
Much More Efficient
That said, if you counted the number of local vectors created in this, though short, they will be many (as many as there are nodes in your tree, in fact). You can eliminate all of those middle-men vectors by providing a shim between the actual traversal and the creation of the order vector:
void inorderTraversal_v(TreeNode const *root, std::vector<int>& order)
{
if (root != nullptr)
{
inorderTraversal(root->left, order);
order.push_back(root->val);
inorderTraversal(root->right, order);
}
return order;
}
std::vector<int> inorderTraversal(TreeNode const *root)
{
std::vector<int> order;
inorderTraversal_v(root, order);
return order;
}
Doing this creates a single vector, and in so doing eliminates (N-1) temporary vectors along the way, where N is the number of nodes in the tree.
I know similar questions have been asked but I can't seem to find an answer for printing via a recursively called function. I am trying to print preorder, postorder, and inorder traversals of an AVL tree and have implemented the functions recursively.
i.e.
void inOrder(Node* root)
{
if(root != nullptr) {
inOrder(root->left);
cout << root->data << ", ";
inOrder(root->right);
}
}
The data should print comma-separated except for the last value, but I am not sure how to do so. I've done research but can't find anything that seems to apply when traversing an AVL tree recursively. Is this possible or should I implement the functions without recursion?
The pattern I usually use for this sort of thing is to use a separator pointer that I change in the loop. The first iteration it's "", so prints nothing, and every subsequent iteration prints the separator. For your recursive case it would be passed as a parameter, and look like this:
void inOrder(Node* root, char ** sep)
{
if(root != nullptr) {
inOrder(root->left, sep);
cout << **sep << root->data;
*sep = ", ";
inOrder(root->right, sep);
}
}
Call it like:
char * sep = "";
inOrder(root, &sep);
It looks a lot nicer for loops. The main advantage is there is no if/else branch in every loop, just a fast pointer assignment to update the separator.
Make an internal implementation function that maintains a flag that indicates whether the data item to be output is the first one. Then prepend the output with a comma for all items but the first.
void inOrderImpl(Node* root, bool& first)
{
if(root != nullptr) {
inOrderImpl(root->left, first);
if (first)
first = false;
else
cout << ", ";
cout << root->data;
inOrderImpl(root->right, first);
}
}
void inOrder(Node* root)
{
bool first = true;
inOrderImpl(root, first);
}
As my comment suggested, an ambitious (and better) way to write the code to do any of the BST traversals would be to use a more generic approach:
template <typename Fn>
void inOrder(Node* root, Fn& func)
{
if(root != nullptr)
{
inOrder(root->left, func);
func(root);
inOrder(root->right, func);
}
}
So given the above, you can basically do anything, since func will be called using the current value of root.
So how does this help us? Consider now the following:
struct TreePrinter
{
bool initial = true;
void operator()(Node *root)
{
if ( initial )
initial = false;
else
std::cout << ",";
std::cout << root->data;
}
};
The above is a class that has overriden operator(). This allows us to pass this to the traversal function, and the traversal function simply calls it.
Note that the initial is a state that gets set in the TreePrinter object.
Then this is how it's implemented:
TreePrinter tp;
Node root;
//...
inOrder(&root, tp);
Here is a live example using a dummy BST.
So not only can you just print a comma, any callable object (function pointer, function object, lambda, etc.) can be provided that can basically use the passed in root to do whatever needs to be done.
std::list <int> q;
std::vector<bool> visited(cols + 1);
for(int i = 1; i <= cols; i++) visited[i] = false;
visited[x] = true;
if(!l[x].empty())
{
for(std::list<int>::iterator i = l[x].begin(); i != l[x].end(); i++)
{
q.push_back(x); q.push_back(* i);
}
while(!q.empty())
{
y = q.back(); q.pop_back();
x = q.back(); q.pop_back();
if(!visited[y])
{
visited[y] = true;
if(!l[y].empty())
for(std::list<int>::iterator i = l[y].begin(); i != l[y].end(); i++)
{
if(!visited[*i])
{q.push_back(y); q.push_back(* i);}
}
dfst[x].push_back(y);
if(flag != 0) dfst[y].push_back(x);
}
}
}
This is my DFS algorithm for finding the spanning tree in a graph. I need to convert it to the BFS algorithm finding the shortest path between two vertices. Well...how can I do this? Is the BFS algorithm somewhat similar to the one above? Or do I need to write it from the beginning?
l - adjacency list
dfst - array holding spanning tree at the end
x - starting vertex
y - helper variable
DFS and BFS are essentially the same algorithms. The trick is which data structure you use, or rather which nodes you are exploring first.
A depth-first search utilizes a stack and would thus go as far down as possible before moving back in the algorithm.
To utilize a breadth first search, you would need to use a queue of nodes, and explore each node, add their neighbors (if not visited already) to the queue, and then process the rest of the parent node's neighbors before continuing onwards.
It wouldn't be a drastic change of your code, just a change in how you get nodes from your list.
Rather than popping off the back you would simply use q.pop_front() to get your nodes.
BFS is similar to DFS. Instead of going as deep as you can, backtracking and repeating, you look at all nodes at depth 1, then all nodes of depth 2, etc, until you've visited all nodes.
Basic Algorithm:
-Choose a starting node and add to LookQueue
-look at all nodes directly touching and add them to LookQueue
-when you've looked at them all
-look at all nodes in LookQueue (removing them as you do)
and look at all nodes touching them (adding them as you do)
-repeat until all nodes are visited
For Finding Shortest Path
(Written in C++ / C++11)
I think this important to add here, especially because the title is on shortest paths! (the code below that actually allow you to find one)
In addition:
As mentioned above (in the comments to the second reply) DFS and BFS are pretty much not(!) the same algorithms, the similarity in the code in which replacing the stack with a queue and allowing you to jump from one to another does not make them "essentially the same". BFS is by far the better/right one (between the two) to find the shortest path in an unweighted graph. BFS is building layers from the source and DFS is going as deep as it can.
Actually when running BFS (to find the shortest path) you should initialize your nodes with a "distance" parameter with a very large number and instead using the visited DS, you update it to the parent's distance + 1 (only if it's still with the initialized value).
A simple example would be:
#include <iostream>
#include <vector>
#include <queue>
#include <limits>
using namespace std;
const int imax = std::numeric_limits<int>::max();
using vi = vector<int>;
/* printPath - implementation at the end */
void
printPath(int s, int t, const vi &path);
/*input:
* n is number of the nodes in the Graph
* adjList holds a neighbors vector for each Node
* s is the source node
*/
void dfs(int n, vector<vi> adjList, int s)
{
//imax declared above as the max value for int (in C++)
vector<int> distance(n, imax);
vi path;
queue<int> q; q.push(s); distance[s] = 0;
while (!q.empty()) {
auto curr = q.front(); q.pop();
for (int i = 0; i < (int)adjList[curr].size(); ++i) {
if (distance[i] == imax) {
distance[i] = distance[curr] + 1;
//save the parent to have the path at the end of the algo.
path[i] = curr;
}
}//for
}//while
/* t can be anything you want */
int t = 5;
printPath(s, t, path); cout << endl;
}
/* print the shortest path from s to t */
void
printPath(int s, int t, const vi &path)
{
if (t == s) {
return;
}
printPath(s, path[t], path);
cout << path[t];
}
Inspired by Steven & Felix, from:
Competitive Programming 3
No,you don't have to change much in your code. just replace replace stack in case of DFS with Queue and it will become BFS.
Difference in implementation of BFS and DFS is that "BFS is implemented using Queue and DFS is using Stack" (Reason is obvious that DFS does depth like in maze.)
SEE changes for yourself:
DFS:
void dfs(int start)
{
int j,temp;
stack<int> s; //STACK
s.push(start);
vector<int>:: iterator it;
while(s.empty()==0)
{
temp=s.top(); // Top element from Stack
s.pop();
status[temp]=1; // marked as visited , 0 means unvisited
cout<<temp<<endl; // visited element
for(it=list[temp].begin();it!=list[temp].end();it++)
{
j=*it;
if(status[j]==0)
{
s.push(j);
status[j]=2; // means that it is in stack
}
}
}
}
BFS:
void bfs(int start)
{
int j,temp;
queue<int> q; // QUEUE
q.push(start);
vector<int>:: iterator it;
while(q.empty()==0)
{
temp=q.front(); // Front element from Queue
q.pop();
status[temp]=1; // marked as visited , 0 means unvisited
cout<<temp<<endl; // visited element
for(it=list[temp].begin();it!=list[temp].end();it++)
{
j=*it;
if(status[j]==0)
{
q.push(j);
status[j]=2; // means that it is in queue
}
}
}
}
As you can see implementation of both just differ "in use of STACK and QUEUE".
Hope this helps !
I have a vector that that stores Node*. A Node has the member properties:row,col,value. In my vector, I have gotten it to where all the Nodes* within the same row but not necessarily in correct column order. So basically I want to sort it so it's truly in row-major form. Right now, the columns are out of order within each "row". I appreciate any help you could give!
Edit:
Here is the method I have that is sorting my vector by row. Is there a way to additionally sort the columns as well?
vector<Node*> vect;
int i,j,minIndex;
Node* temp = new Node(NULL,NULL,0,0,0);
for(i=0;i<vect.size()-1;i++)
{
minIndex = i;
for(j=i+1;j<vect.size();j++)
{
if(vect.at(j)->row<vect.at(minIndex)->row)
{
minIndex = j;
}
}
if(minIndex!=i)
{
temp = vect.at(i);
vect.at(i) = vect.at(minIndex);
vect.at(minIndex) = temp;
}
}
You don't really need to implement your own sorting algorithm here. You can just use the standard template library's sort() method and then override default the behavior for sorting your Node* vector.
// This returns true if Node* a should be considered "less than" Node* b.
struct less_node : binary_function <Node*,Node*,bool>
{
bool operator() (const Node*& a, const Node*& b) const
{
// sort by row first
if (a->row < b->row)
return true;
// then sort by col within each row
if (a->row == b->row && a->col < b->col)
return true;
return false;
}
};
Once you have this less_node structure defined, you would just call:
sort(vect.begin(), vect.end(), less_node());
I am trying to insert pointers into a list but every time I try to print the list, or check whats in the list it says its empty. This means that my insertion is incorrect, but I don't understand why, my following classes are:
namespace {
template <typename T>
pair < node<T>*, bool> addElement (const T& elem, btree<T>* bt) {
class list < node<T>* >::iterator itr = bt->level().begin();
if (bt->level().empty()) {
node <T>*n = new node<T>(elem, bt->max());
cout << n->getItem() << endl;
bt->addElem(itr, n);
return make_pair(n, true);
}
for (; itr != bt->level().end(); ++itr) {
if (elem < (*itr)->getItem()) {
node <T>* n = new node<T> (elem, bt->max());
(*itr)->previous()->addNext(n);
n->addPrev((*itr)->previous());
n->addNext(*itr);
(*itr)->addPrev(n);
bt->addElem(itr, n);
return make_pair(n, true);
} else if (elem == (*itr)->getItem()) return make_pair(*itr, false);
}
// other stuff + return statement
}
addElem does the following:
void addElem (std::_List_iterator<node<T>*>& itr, node <T>* n) {
neighbours.insert(itr, n);
if (neighbours.empty()) cout << "wa?";
}
where btree class consists of:
size_t maxNodeElems;
list < node<T>*> neighbours;
the other things like addPrev() and previous() are just getters and setters. Anyways, I ran a test file on it that pretty much constructs a btree, and calls an insert function which directly calls this addElement function. But whenever I try to print the list inside the btree, it says its empty and seg faults. I don't understand why it's not storing.
Any help would be appreciated!
NOTE: the "Wa?" keeps printing
It seems you are trying to keep a sorted list, that's why you have:
// find the place to insert elem
for (; itr != bt->level().end(); ++itr) {
if (elem < (*itr)->getItem()) {
// insert...
}
}
But if the list is empty (initial state), itr will be probably equal bt->level().end() in the first place, so you will never insert anything...
You also should consider the case when you are trying to insert element for which (elem < (*itr)->getItem()) is always false (the new greatest element in the list). You need to handle that case as well.