I want my code have multi-thread to solve it, but I don’t know if my idea can be implemented . Does anyone can help me? Thank you.
I have a binary tree structure. It is a representation to rectangle packing. I use DFS(preorder) to traversal my tree. Root node be placed on the bottom left. Depends on the left or right node, place the node(block). Use the following rules to determine the x coordinate:
(1)left node: place it in the right hand of parent(x=xparent+Wparent)
(2)right node: place it on the upper of parent(x = xparent)
By the way, the y coordinate be determined by the contour line. The contour line is the shape constructed by the previous nodes(block).
Now I want to divide my tree into two parts, one is left subtree, another is right subtree. I use two threads to traversal respectively, so I can place two blocks in the same time. After get the "x" respectively, I should check if they will overlap each other. If they don't overlap I can place two block in once, or I should do place in sequential. What I try to do is adding some comparison to check before function checkY.
I am very grateful for your patience.
void dfsContour(NODE* node, NODE* parent, int x, char type){
if(node == nullptr) return;
else{
if(type == 'R'){
//std::cout << "left child" << std::endl;
node->block->x = x + parent->getWidth();
checkY(node->getX(), node);
}
else{
//std::cout << "right child" << std::endl;
node->block->x = x;
checkY(node->getX(), node);
}
}
dfsContour(node->left, node, node->getX(), 'R');
dfsContour(node->right, node, node->getX(), 'U');
return;
}
void dfsContour(){
/*Clear all the contour?*/
CONTOURNODE* temp = new CONTOURNODE();
while(head->next != nullptr){
temp = head;
head = head->next;
free(temp);
}
root->block->x = 0;
checkY(root->getX(), root);
NODE* leftnode = root->left;
NODE* rightnode = root->right;
omp_set_num_threads(2);
#pragma omp parallel
{
if(omp_get_thread_num() ==0 ){
dfsContour(leftnode,root,root->getX(),'R');
}
else{
dfsContour(rightnode,root,root->getX(),'U');
}
}
#pragma omp barrier
return;
}
Related
I am creating a planet simulation which makes use of a doubly linked list and several loops to calculate forces, collisions and so on. The issue I am having is a read access violation error when trying to delete a planet due to a collision.
When checking for a collision the smaller of the two planets is deleted, and the way I wrote it is that the smaller planet in the equation can be from the encompassing loop, which if deleted breaks the loop.
A combination of being new to C; staring at the same issue for days now; and that my lecturer for the class is making us use a C/C++ hybrid, is resulting in me struggling to think of an efficient way to fix the issue. Moving the loops out can and has solved the issue, but has a drastic effect on performance of the simulation.
The code can be seen below:
struct planet *head; //Head of list
struct planet *tail; //Tail of list
struct planet {
//Data
float mass;
struct planet *next;
struct planet *prev;
};
planet *remove(struct planet* p) {//Breaking the tree
if (p == head) {
removeHead(); //Method not included in sample due to size and it is sound.
}
else if (p == tail) {
removeTail();//Method not included in sample due to size and it is sound.
}
else {
p->prev->next = p->next;
p->next->prev = p->prev;
}
return p;
}
planet *destroy(struct planet* p) {
if (p) {
if (p != head || p != tail || (!p->next && p->prev)) {
delete p;
printf("Deleted\n");
return 0;
}
else {
printf("Not deleted\n");
return 0;
}
}
}
for (struct planet *p1 = head; p1 != 0; p1 = p1->next)
{
for (struct planet *p3 = head; p3 != 0; p3 = p3->next)
{
//Collision logic
if(p1 != p3){
if(p1->mass >= p3->mass){
destroy(remove(p3)); //Does not cause an error
break;
}else{
destroy(remove(p1)); //Causes the error.
break;
//Deleting p1 here means the for loop can't move on
}
}
}
}
What I am looking for is some advice on how to delete p1 efficiently and without breaking the loop.
Any help is greatly appreciated, and please forgive my less than clean code.
Breaking out of the inner loop when p1 is destroyed, will not break the outer loop, where p1 is dereferenced by the loop control, after it was deleted.
You can avoid it with code perhaps like this. I don't like using for loops with a linked list, and the while makes it easy to set up the next link.
struct planet *p1link, *p3link;
p1 = head;
while(p1 != NULL) {
p1link = p1->next; // collect next link now
p3 = p1->next; // avoid detecting B-A as well as A-B
while(p3 != NULL) {
p3link = p3->next; // collect next link now
//Collision logic
if(p1->mass >= p3->mass){
destroy(remove(p3));
} else {
destroy(remove(p1));
}
p3 = p3link; // next
}
p1 = p1link; // next
}
However the whole concept is flawed, because the p3 you delete might be the next p1 planet. So I suggest including a struct member pending and you make another parse of the list afterwards, to remove dead planets.
I have these functions to remove a node from my binary search tree:
bool collection::removeFromTree(const char name[])
{
for (treeNode * curr = root; curr;)
{
int8_t result = strcmp(name, curr->item->getName());
if (result == 0)
{
deleteNode(curr);
return true;
}
else if (result < 0)
curr = curr->left;
else if (result > 0)
curr = curr->right;
}
return false;
}
void collection::deleteNode(treeNode *& goneNode)
{
//if it's a leaf
if (!goneNode->left && !goneNode->right)
{
delete goneNode; //node's destructor gets invoked
goneNode = nullptr;
}
//if it has right child
else if (!goneNode->left)
{
goneNode = goneNode->right;
}
//if it has left child
else if (!goneNode->right)
{
goneNode = goneNode->left;
}
//if it has both children
else
{
treeNode * prev = nullptr;
treeNode * curr = goneNode->right;
while (curr->left)
{
prev = curr;
curr = curr->left;
}
//prev points to the copy over data
delete goneNode->item;
if (!prev)
{
goneNode->item = curr->item;
goneNode->right = curr->right;
curr->item = nullptr;
}
else
{
goneNode->item = curr->item;
curr->item = nullptr;
prev->left = curr->right;
}
}
}
This runs fine, but when I try to list all the elements in my tree after deleting a node (with these functions):
void collection::displayByName() const
{
std::cout << std::endl
<< "========================================" << std::endl;
//display the tree inorder
listAll(root);
}
void collection::listAll(const treeNode * const & root) const
{
if (root)
{
std::cout << *(root->item) << std::endl
<< "========================================" << std::endl;
listAll(root->left);
listAll(root->right);
}
}
I receive this error:
And when I quit the program after deleting a node (invoking these destructors):
collection::~collection()
{
delete root;
}
collection::treeNode::~treeNode()
{
delete left;
delete right;
}
I recieve this error:
Any suggestions would be greatly appreciated because I see no reason for my listAll() function to be calling nodes that I've already deleted.
By the way, this is my struct for my treeNode:
struct treeNode
{
treeNode();
treeNode(vendor *& item);
~treeNode();
vendor * item;
treeNode *left, *right;
};
treeNode * root; //the bst
hashNode ** table; //the hash table
uint8_t capacity;
uint8_t size;
const static uint8_t INIT_CAP = 20;
When you need to remove a node from a singly linked list or a tree, I find using a pointer to pointer is handy. Namely, if we have a treeNode** ptr;, then *ptr is the pointer to our node. So, if ptr = &root, then *ptr = nullptr sets root to nullptr.
I removed the deleteNode function and threw its logic in the removeFromTree function.
bool collection::removeFromTree(const char name[])
{
treeNode** ptr = &root;
Instead of being a pointer to treeNode, ptr will point to a treeNode* inside the tree structure. This way, we can modify the pointer that led us to the current node. The lines marked //same as before have the same logic you were using, just possibly modified to account for the fact ptr has another level of dereferencing to do.
int result; //same as before
while (*ptr) //While we haven't hit a dead end
{
result = strcmp(name, (*ptr)->item->getName()); //same as before
if (result < 0) //same as before
ptr = &((*ptr)->left); //same as before
else if (result > 0) //same as before
ptr = &((*ptr)->right); //same as before
else //begin deleteNode() logic
{
if ((*ptr)->left && (*ptr)->right) //two children
{
Here, we use pointers to member because the alternative was a conditional operator on every line. If a node has two children, we need to find either the rightmost node on the left side, or the leftmost node on the right side. That's the node we can replace the current node with.
treeNode* treeNode::*dir = some_condition ? &treeNode::right : &treeNode::left; //pointer to treeNode member of type treeNode*
treeNode* treeNode::*ndir = some_condition ? &treeNode::left : &treeNode::right; //pointer to treeNode member of type treeNode*
dir now either points to left or right, which is the direction we are searching the tree for. ndir is the opposite direction. So, if we want the rightmost node on the left side, (*ptr)->*dir == (*ptr)->left and (*ptr->*ndir == (*ptr)->right. If we want the leftmost right node, it would be reversed. This is just a more complicated way to do less work, really. It shouldn't be hard to remove. some_condition is just either true or false. true means the left side of the tree (from the current node) loses a node, and false means the right side does.
treeNode** replacement = &((*ptr)->*ndir); //the node to replace the current one with
while ((*replacement)->*dir) //While we aren't at the edge
replacement = &((*replacement)->*dir);
This loops until *replacement is the node we need to replace *ptr with.
treeNode* rep_branch = (*replacement)->*ndir; //If the replacement node had a child, this is now it
(*replacement)->left = (*ptr)->left; //Copy current to replacement
(*replacement)->right = (*ptr)->right; //Copy current to replacement
(*ptr)->left = nullptr; //null out current in case of destructor
(*ptr)->right = nullptr; //null out current in case of destructor
Now, the replacement node is pointing to the node-to-be-deleted's children, and our soon to be expired node has no children anymore. Now, it's safe to delete the unwanted node. If the node class had a destructor to delete its children, the left and right pointers were set to nullptr just in case.
delete *ptr; //delete unwanted node
*ptr = *replacement; //replacement node has taken the unwanted node's place in the tree
*replacement = rep_branch; //The replacement's child takes its own place
}
This completes the tree's structure. Wherever the unwanted node was, the replacement node has taken its place. And because the replacement node was required to be an edge node, it had at most one child. We just replace it with the child.
else if ((*ptr)->left) //one child on left
{
treeNode* current = *ptr;
*ptr = (*ptr)->left; //replace current with left
current->left = nullptr; //null out for safety
delete current;
}
else if ((*ptr)->right) //one child on right
{
treeNode* current = *ptr;
*ptr = (*ptr)->right; //replace current with right
current->right = nullptr; //null out for safety
delete current;
}
else //no children
{
delete *ptr;
*ptr = nullptr;
}
return true; //yay it's over
}
}
return false; //never found it
}
The rest is fairly straightforward, just replacing easier nodes and returning. Hopefully this gives you some ideas about how to approach problems like this, and the occasional uses of some of these structures. This is what I meant about using treeNode** over treeNode* for operations like this.
Hi!
I would like to know what can be the if statement's condition so all left branches of a binary tree could be printed using postorder traverse.
template <class dataType>
void PrintLeft (BinaryTree <dataType> * bt) {
if (!(bt == NULL))
{
//traverse left child
PrintLeft (bt->left());
//traverse right child
PrintLeft (bt->right());
//visit tree
if(/*no idea what goes here*/)
cout << bt->getData() <<"\t";
}
}
I understand that you want to visit only the nodes that were seen from a left branch. Since it is postorder, you must visit them when you get back on the right branch. So, such as said by πάντα ῥεῖ, you can use a boolean flag indicating from which type of branch you have discovered the node.
So a possible way would be as follows:
using Node = BinaryTree <int>; // or another type supporting << operator
void printLeft(Node * root, bool from_left)
{
if (root == nullptr) // empty tree?
return;
printLeft(root->left, true); // this node must be visited in postorder
printLeft(root->right, false); // this one must not be visited in postorder
if (from_left) // was root seen from a left arc?
cout << root->getData() << "\t"; // visit only if was seen from a left branch
}
There is an ambiguity with the root. I assume that it must not be printed because it is not reached from a left branch (nor right too).
So the first call should be:
printLeft(root, false);
Just as verification, for this tree:
The algorithm produces as left postorder traversal the following sequence
0 1 4 3 8 9 12 11 16 18
here goes code for postorder traversing
void postorder(BinaryTree *bt)
{
if(bt!=NULL)
{
postorder(t->lp);
postorder(t->rp);
//No Code Goes Here
cout<<bt->data<<"\t";
}
}
Try This One
void leftViewUtil(struct node *root, int level, int *max_level)
{
// Base Case
if (root==NULL) return;
// If this is the first node of its level
if (*max_level < level)
{
printf("%d\t", root->data);
*max_level = level;
}
// Recur for left and right subtrees
leftViewUtil(root->left, level+1, max_level);
leftViewUtil(root->right, level+1, max_level);
}
// A wrapper over leftViewUtil()
void leftView(struct node *root)
{
int max_level = 0;
leftViewUtil(root, 1, &max_level);
}
// Driver Program to test above functions
int main()
{
struct node *root = newNode(12);
root->left = newNode(10);
root->right = newNode(30);
root->right->left = newNode(25);
root->right->right = newNode(40);
leftView(root);
return 0;
}
if(!bt->left()==NULL)
cout << bt->left()->getData() << "\t";
So I have this small program that creates a min heap and insert values based on user input. If the users says change value 10 to 20, the program should change all occurrences of 10 to 20 and then heapify. When the user gives the print command the program should traverse the tree in postorder and print all the values. So I have written program but its giving me the incorrect output when I print. What am I doing wrong here:
int pArray[500];
int i = 0;
//Definition of Node for tree
struct TNode {
int data;
TNode* left;
TNode* right;
};
void Heapify(TNode* root, TNode* child);
// Function to create a new Node in heap
TNode* GetNewNode(int data) {
TNode* newNode = new TNode();
newNode->data = data;
newNode->left = newNode->right = NULL;
return newNode;
}
// To insert data in the tree, returns address of root node
TNode* Insert(TNode* root,int data) {
if(root == NULL) { // empty tree
root = GetNewNode(data);
}
// if the left child is empty fill that in
else if(root->left == NULL) {
root->left = Insert(root->left,data);
}
// else, insert in right subtree.
else if(root->right == NULL){
root->right = Insert(root->right,data);
}
else {
root->left = Insert(root->left,data);
}
Heapify(root, root->left);
Heapify(root, root->right);
return root;
}
void Heapify(TNode* root, TNode* child){
if(root != NULL && child != NULL){
if(root->data > child->data){
int temp = child->data;
child->data = root->data;
root->data = temp;
}
}
}
void Change(TNode* root,int from, int to) {
if (root == NULL)
return;
else if (root->data == from)
root->data = to;
Change(root->left, from, to);
Change(root->right, from, to);
}
void postOrder(TNode* n){
if ( n ) {
postOrder(n->left);
postOrder(n->right);
pArray[i] = n->data;
i++;
}
}
What am I doing wrong here?
I'm going to assume that you've verified the heap before you print it. Your tree implementation is a bit confusing, but it looks like it should work. I would suggest, however, that the first thing you do is print the tree before calling your Change method, just to make sure that you have a valid heap.
Assuming that you have a valid heap, your Change method has a problem: it never calls Heapify. You end up changing values in the heap and not rearranging. So of course it's going to be out of order when you output it.
When you change an item's value, you have to move that node (or the node's value) to its proper final position in the tree before you change any other value. You can probably make that work with your current model (by calling Heapify repeatedly until the node is in its proper position). Provided that you're increasing the value. If you're decreasing the value (i.e. changing 20 to 10), then you have a problem because your code has no way to move an item up the tree.
As #noobProgrammer pointed out in his comment, a binary heap typically is implemented as an array rather than as a tree. It's a whole lot easier to implement that way, uses less memory, and is much more efficient. If you're interested in how that's done, you should read my multi-part blog series on heaps and priority queues. The first entry, Priority queues, describes the problem. From there you can follow the links to learn about binary heaps and how they're implemented. The code samples are in C#, but if you read the first two introductory articles and understand the concepts, you'll be able to convert to C++ without trouble.
Ok so, I have a read method that is reading the values in correctly (all 7000), (hand written 15 values as a tree structure), doesn't create any errors.
However, when it comes to the output of the binary tree I am using the method as stated on several websites.
The error I am getting is a stack overflow, and I am assuming its due to the recursive calls and never breaking out, But I have no idea why this isn't working.
Any help is appreciated, thanks.
Code Listed Below:
// Read
void BinaryTreeStorage::read(ifstream& _fin)
{
// Get first line with number of names in it
string numberOfNamesString;
getline(_fin, numberOfNamesString);
// Loop through all the names
string line;
int num = 0;
while (!_fin.eof())
{
getline(_fin, line);
if (line != "")
{
// Insert Value Here
if (root != NULL)
{
insert(line, root);
}
else
{
insert(line);
}
}
}
}
// Write
void BinaryTreeStorage::write(ofstream& _out) const
{
inorderPrint(_out, root);
}
// inorderPrint
void BinaryTreeStorage::inorderPrint(ofstream& _out, node *_root) const
{
if (_root != NULL)
{
// Inorder
inorderPrint(_out, root->left);
_out << root->nodeValue;
cout << root->nodeValue << " ";
inorderPrint(_out, root->right);
}
}
// Insert if root is null
void BinaryTreeStorage::insert(string _nodeValueIn)
{
if(root!=NULL)
insert(_nodeValueIn, root);
else
{
root=new node;
root->nodeValue=_nodeValueIn;
root->left=NULL;
root->right=NULL;
}
}
// Insert when root is not null
void BinaryTreeStorage::insert(string _nodeValueIn, node *leaf)
{
if(_nodeValueIn< leaf->nodeValue)
{
if(leaf->left!=NULL)
insert(_nodeValueIn, leaf->left);
else
{
leaf->left=new node;
leaf->left->nodeValue=_nodeValueIn;
leaf->left->left=NULL; //Sets the left child of the child node to null
leaf->left->right=NULL; //Sets the right child of the child node to null
}
}
else if(_nodeValueIn>=leaf->nodeValue)
{
if(leaf->right!=NULL)
insert(_nodeValueIn, leaf->right);
else
{
leaf->right=new node;
leaf->right->nodeValue=_nodeValueIn;
leaf->right->left=NULL; //Sets the left child of the child node to null
leaf->right->right=NULL; //Sets the right child of the child node to null
}
}
}
You have a bug in BinaryTreeStorage::inorderPrint,
your param _root is not used where intended: You always loop on root instead.
hint: Avoid using similar names!
hint: Avoid using std to avoid bugs, unless you write std:: too often in nested templates.
hint: Do not use _ at the beginning or end of names.
hint: Do not compare with NULL: Write if(n) instead of if(n!=NULL).
hint: Do not nest blocks when not needed:
void BinaryTreeStorage::inorderPrint(std::ofstream& out, node *n) const
{
if(!n) return;
inorderPrint(out, n->left);
out << n->nodeValue; // no separator??
std::cout << n->nodeValue << " ";
inorderPrint(out, n->right);
}
void BinaryTreeStorage::inorderPrint(ofstream& _out, node *_root) const
{
if (_root != NULL)
{
// Inorder
inorderPrint(_out, root->left);
In the above code, I can see _root defined but you're using root in your call (last line above). I think that is causing the infinite loop.
When you constructed your tree nodes did you ensure that the left and right pointers are initialized to NULL?
The depth of the call tree of inorderPrint is the same as the depth of the tree itself. It looks like you don't try to keep the tree balanced, so the depth can get as large as the size of the tree.
There are a few ways of fixing this. You can make sure that the tree always remains balanced so that the depth grows logarithmically with the size of the tree. Or you can make the tree threaded, which lets you visit the nodes iteratively.