Convert A Given Binary Tree To Doubly Linked List - pointers

The problem statement is:
Given a Binary Tree, convert this binary tree to a Doubly Linked List.
A Binary Tree (BT) is a data structure in which each node has at most two children.
A Doubly Linked List contains a previous pointer, along with the next pointer and data.
The order of nodes in Doubly Linked List must be the same as Inorder of the given Binary Tree.
The doubly linked list should be returned by taking the next pointer as right and the previous pointer as left.
You need to return the head of the Doubly Linked List.
For example:
4
/ \
2 5
/ \
1 3
The doubly linked list would be: 1 2 3 4 5
My code is:
class BinaryTreeNode
{
public :
T data;
BinaryTreeNode<T> *left;
BinaryTreeNode<T> *right;
BinaryTreeNode(T data) {
this -> data = data;
left = NULL;
right = NULL;
}
};
void inorder(BinaryTreeNode<int>* root,BinaryTreeNode<int>* &prev,BinaryTreeNode<int>* &nroot){
if(!root) return;
inorder(root->left,prev,nroot);
if(prev == NULL) nroot=root;
else{
root->left = prev;
prev->right=root;
}
prev=root;
inorder(root->right,prev,nroot);
}
BinaryTreeNode<int>* BTtoDLL(BinaryTreeNode<int>* root) {
BinaryTreeNode<int>* prev=NULL;
BinaryTreeNode<int>* nroot=NULL;
inorder(root,prev,nroot);
return nroot;
}
I have doubt regarding root.
The root pointer works with passing by value and does not works when it is passed by reference.
When root is passed by reference, it does not work.
void inorder(BinaryTreeNode<int>*& root,BinaryTreeNode<int>*& prev,BinaryTreeNode<int>* &nroot){
if(!root) return;
inorder(root->left,prev,nroot);
if(prev == NULL) nroot=root;
else{
root->left = prev;
prev->right=root;
}
prev=root;
inorder(root->right,prev,nroot);
}
How can I know which variable should be passed by reference and which variable should by passed by value with regard to pointers?

At first glance, one problem is the API of inorder itself. You are assigning nroot = root; to see why this is a problem, consider this simpler example:
void set_x(int *x, int *y)
{
x = y;
}
Remember that pointers are really just memory addresses. So, the assignment of x = y says, "replace the memory address that x contains, and set it to whatever y contains". At no stage do you actually change the value at the memory address.
Now, considering nroot = root again, here you are just giving the local variable you have a new memory address, but not updating anything. So at your call side BTtoDLL, you provide it nullptr for the address, to which it never uses it, and never sets it. So, BTtoDLL will never see any change to nroot.

Related

Initialize pointer array - cannot make type *[]type

Its a simple code, saving car type objects into a car type array. I am trying to use pointer here to pass array reference.
There are 2 problems:
1 - I can't initialize it as empty array. When I use make, it says:
cannot make type *[]car
2 - If I don't use make, runtime error occurs:
panic: runtime error: invalid memory address or nil pointer dereference
Code:
import "fmt"
type car struct {
plate string
color string
}
func main() {
var _cars *[]car // list of cars
_cars = make(*[]car, 4) // initialize empty cars list
saveCar(_cars, car{"ABC-123", "Black"})
saveCar(_cars, car{"ABC-456", "Black"})
saveCar(_cars, car{"ABC-789", "Black"})
fmt.Println(_cars)
}
func saveCar(_cars_list *[]car, _car car) int {
for index, current := range *_cars_list {
// if empty place found, save car
if (car{}) == current {
// save car
(*_cars_list)[index] = _car
// return the saved index
return index
}
}
return -1
}
Changing this would make your code work:
tCars := make([]car, 4)
_cars = &tCars
1 - cannot make type *[]car
You observe it because make creates slice, map or chan. In the example you gave you tried to create pointer to a slice which is none of the typed make works with.
2 - If I don't use make, runtime error occurs:
that's another problem - you have type "pointer to a slice of car", not "a slice of car". And in general you need to initialize pointer types before using.
Overall there is no need to use pointer to a slice rather than plain slice in your case, because you don't use append, to there is no chance for reallocation of backed storage.
However, in a real world scenario, when you don't know amount of car instances you are going to add, is much better to use append instead of iterating through slice till the last non-initialized value.
summary:
to make your program work change *[]car to []car everywhere (example https://play.golang.org/p/lpCtvXqG6UY)
another (and probably better) way is to use append instead of saveCar (don't forget to use returned value in case of happened re-allocation, example: https://play.golang.org/p/L8V10tSb-IJ)

Recursion and a counter variable in a binary tree

Following are 2 codes:
1. Find the kth smallest integer in a binary search tree:
void FindKthSmallest(struct TreeNode* root, int& k)
{
if (root == NULL) return;
if (k == 0) return; // k==0 means target node has been found
FindKthSmallest (root->left, k);
if (k > 0) // k==0 means target node has been found
{
k--;
if (k == 0) { // target node is current node
cout << root->data;
return;
} else {
FindKthSmallest (root->right, k);
}
}
}
Find the number of nodes in a binary tree:
int Size (struct TreeNode* root)
{
if (root == NULL) return 0;
int l = Size (root->left);
int r = Size (root->right);
return (l+r+1);
}
My Question:
In both these codes, I will have to keep track of the number of nodes I visit. Why is it that code 1 requires passing a parameter by reference to keep track of the number of nodes I visit, whereas code 2 does not require any variable to be passed by reference ?
The first code (1) is looking for the smallest node in your BST. You search from the root down the left side of the tree since the smallest valued node will be found in that location. You make several checks:
root == null - to determine if the tree is empty.
k == 0 - zero in this case is the smallest element. You are making this assumption based on whatever principles are apart of this tree.
Then you recursively traverse the list to find the next smallest in the left side of the tree. You perform one more check that if k > 0 you decrement k <- this is why you need to pass by reference since you are making changes to some value k given by a separate function, global variable, etc. If k happens to be zero then you have found the smallest valued node, if not you go one right of the current node and then continue the process from there. This seems like a very arbitrary way of finding the smallest node...
For the second code (2) you are just counting the nodes in your tree starting at the root and counting each subsequent node (either left or right) recursively until no more nodes can be found. You return your result which is the total amount of left nodes,right nodes. and + 1 for the root since it was not counted earlier. In this instance no passed by reference variable is needed although you could potentially implement one if you choose to do so.
Does this help?
Passing the parameter by reference allows you to keep track of the count within the recursive process, otherwise the count would reset. It allows you to modify the data within the memory space, thus changing the former value not the current/local value.

D: Strange behaviour from std.container.BinaryHeap with custom function for comparison

I've written the following code for a heap of Node*s, which are found in module node:
import std.exception, std.container;
public import node;
alias NodeArray = Array!(const (Node)*);
alias NodeHeap = BinaryHeap!(NodeArray, cmp_node_ptr);
auto make_heap() {
return new NodeHeap(NodeArray(cast(const(Node)*)[]));
}
void insert(NodeHeap* heap, in Node* u) {
enforce(heap && u);
heap.insert(u);
}
pure bool cmp_node_ptr(in Node* a, in Node* b) {
enforce(a && b);
return (a.val > b.val);
}
I then tried running the following unit tests on it, where make_leaf returns a Node* initialized with the argument given:
unittest {
auto u = make_leaf(10);
auto heap = make_heap();
insert(heap, u); //bad things happen here
assert(heap.front == u);
auto v = make_leaf(20);
insert(heap, v);
assert(heap.front == u); //assures heap property
}
The tests make it to the line I comment-marked, and then throw an enforcement error on the line enforce(a && b) in cmp_node_ptr. I'm totally lost as to why this is happening.
you are doing wrong thing in this operator:
NodeArray(cast(const(Node)*)[])
you obviously want to create empty NodeArray, but what you really got is NodeArray with one null item. NodeArray constructor takes list of values for new array as arguments, and you passing one "empty array" (which is essentially null), thus creating NodeArray with one null element.
the correct way is just:
NodeArray()
i.e.:
auto make_heap() {
return new NodeHeap();
}
make this change and everything will be fine.
p.s. it seems that D notation for multiple arguments of type U (U[] values...) made you think that constructor accepts another array as initialiser.
p.p.s. sorry, fixed make_heap() code: accidentally forgot to write "NodeArray()" in it. and edited it again, as empty NodeArray() call is not necessary there. double fault!

Weird behaviour with struct constructors

I've written a basic Node struct in D, designed to be used as a part of a tree-like structure. The code is as follows:
import std.algorithm: min;
alias Number = size_t;
struct Node {
private {
Node* left, right, parent;
Number val;
}
this(Number n) {val = n;}
this(ref Node u, ref Node v) {
this.left = &u;
this.right = &v;
val = min(u.val, v.val);
u.parent = &this;
v.parent = &this;
}
}
Now, I wrote a simple function which is supposed to give me a Node (meaning a whole tree) with the argument array providing the leaves, as follows.
alias Number = size_t;
Node make_tree (Number[] nums) {
if (nums.length == 1) {
return Node(nums[0]);
} else {
Number half = nums.length/2;
return Node(make_tree(nums[0..half]), make_tree(nums[half..$]));
}
}
Now, when I try to run it through dmd, I get the following error message:
Error: constructor Node.this (ulong n) is not callable using argument types (Node, Node)
This makes no sense to me - why is it trying to call a one-argument constructor when given two arguments?
The problem has nothing to do with constructors. It has to do with passing by ref. The constructor that you're trying to use
this(ref Node u, ref Node v) {...}
accepts its arguments by ref. That means that they must be lvalues (i.e. something that can be on the left-hand side of an assignment). But you're passing it the result of a function call which does not return by ref (so, it's returning a temporary, which is an rvalue - something that can go on the right-hand side of an assignment but not the left). So, what you're trying to do is illegal. Now, the error message isn't great, since it's giving an error with regards to the first constructor rather than the second, but regardless, you don't have a constructor which matches what you're trying to do. At the moment, I can think of 3 options:
Get rid of the ref on the constructor's parameters. If you're only going to be passing it the result of a function call like you're doing now, having it accept ref doesn't help you anyway. The returned value will be moved into the function's parameter, so no copy will take place, and ref isn't buying you anything. Certainly, assigning the return values to local variables so that you can pass them to the constructor as it's currently written would lose you something, since then you'd be making unnecessary copies.
Overload the constructor so that it accepts either ref or non-ref. e.g.
void foo(ref Bar b) { ... }
void foo(Bar b) { foo(b); } //this calls the other foo
In general, this works reasonably well when you have one parameter, but it would be a bit annoying here, because you end up with an exponential explosion of function signatures as you add parameters. So, for your constructor, you'd end up with
this(ref Node u, ref Node v) {...}
this(ref Node u, Node v) { this(u, v); }
this(Node u, ref Node v) { this(u, v); }
this(Node u, Node v) { this(u, v); }
And if you added a 3rd parameter, you'd end up with eight overloads. So, it really doesn't scale beyond a single parameter.
Templatize the constructor and use auto ref. This essentially does what #2 does, but you only have to write the function once:
this()(auto ref Node u, auto ref Node v) {...}
This will then generate a copy of the function to match the arguments given (up to 4 different versions of it with the full function body in each rather than 3 of them just forwarding to the 4th one), but you only had to write it once. And in this particular case, it's probably reasonable to templatize the function, since you're dealing with a struct. If Node were a class though, it might not make sense, since templated functions can't be virtual.
So, if you really want to be able to pass by ref, then in this particular case, you should probably go with #3 and templatize the constructor and use auto ref. However, personally, I wouldn't bother. I'd just go with #1. Your usage pattern here wouldn't get anything from auto ref, since you're always passing it two rvalues, and your Node struct isn't exactly huge anyway, so while you obviously wouldn't want to copy it if you don't need to, copying an lvalue to pass it to the constructor probably wouldn't matter much unless you were doing it a lot. But again, you're only going to end up with a copy if you pass it an lvalue, since an rvalue can be moved rather than copied, and you're only passing it rvalues right now (at least with the code shown here). So, unless you're doing something different with that constructor which would involve passing it lvalues, there's no point in worrying about lvalues - or about the Nodes being copied when they're returned from a function and passed into the constructor (since that's a move, not a copy). As such, just removing the refs would be the best choice.

C++ Static vector loses data after exiting function

I have a static function:
void TextManager::printDialogue(vector<Button*>* options, int optionsCount, vector<string> outputDisplayText)
{
active = true;
buttons = *options;
buttonsCount = optionsCount;
outputText = outputDisplayText;
}
The "buttons" variable is static:
static vector<Button*> buttons;
I make a call to printDialogue in an execute function:
void WorldDoor::execute()
{
vector<Button*> buttons;
buttons.push_back(new CancelButton());
buttons.push_back(new ChangeRoomButton(room));
TextManager::printDialogue(&buttons, 2, messages); //<----
std::vector<Button*>::iterator i = buttons.begin();
for ( i = buttons.begin() ; i < buttons.end(); i++ )
{
delete * i;
}
}
For whatever reason, when I debug and have a break point inside of the printDialogue function, the values in "buttons" are perfectly fine. However, after I leave printDialogue, the strings contained in my buttons go from being readable to giving me an error message saying:
I tried passing a pointer to an array instead of using
vector<Button*>
but it was only reading the first variable. Now it is not reading anything. Could anyone please help?
There is a static member variable called buttons, and also a local variable inside execute() called buttons. You should rename to avoid confusion, otherwise, the local variable will be used instead of the static member variable inside execute().
Edit: Completely misunderstood the question.
When you do this:
vector<int*> vector1;
vector<int*> vector2;
vector1.push_back(new int(5));
vector2 = vector1;
It copies the pointers, not the value of the pointers.
So when you later iterate over the first vector and delete the dynamic memory, both vectors have pointers pointing to the same memory that you deleted, so your second vector is pointing to invalid memory.
If you are using C++11, you can use a vector of unique pointers, and std::move() one vector into another.
Otherwise, you can just call 'clear()' on the vector, without deleting the memory.
Here's how the function could be written:
void TextManager::printDialogue(vector<Button*>* options, int optionsCount, vector<string> outputDisplayText)
{
active = true;
buttons = *options;
options->clear(); //<--- Instead of crawling over it and delete-ing it.
buttonsCount = optionsCount;
outputText = outputDisplayText;
}
Everything below this was my misunderstanding the question: (contains other information that might be important)
When you do:
vector<Button*> buttons;
Inside the function, you are creating a new vector called 'buttons', which gets destroyed at the end of the function call.
If you want to access the global one, don't create a new one inside the function, or name them something different.
Example:
int myVar = 100; //Declares a variable called 'myVar' at global scope.
void func()
{
int myVar = 200; //Declares a *different* variable called 'myVar' at function scope.
std::cout << myVar << std::endl; //Prints the one inside the function, not the one outside it.
}
By the way, the variable 'static' shouldn't be used at global scope, unless the variable belongs to a class.
To make a variable global, you just put it outside of any function. To make a class member shared between all instances of that class, you declare it static so that class knows to have all instances share the one variable. It's a different thing. =)
If you have your code split into multiple files, to make a global really-truly global, you have to declare it 'extern' in your header, and not extern in one source file, and have other source files #include the header that externs it. Slightly clunky, but that's how it's done. They are working on a better system for it, but it'll be several years before it becomes standardized.

Resources