Insert function recreates root node - c++

I'm trying to create a non-recursive insert() function. The only example I have in the book is a recursive one and I'm trying to convert it. Just so you have an idea of what I'm trying to accomplish and why I'll include the instructions.
Write a class for implementing a simple binary search tree capable of storing numbers. The class should have member functions:
void insert(double x)
bool search(double x)
void inorder(vector <double> & v)
The insert function should not use recursion directly or indirectly by calling a recursive function.
There is more, but I think this gives the idea behind what I'm asking about. As of now the function just keep recreating the root node. Here is what I have.
#include "stdafx.h"
#include <iostream>
#include <vector>
class BinaryTree {
private:
struct TreeNode {
double value;
TreeNode *left;
TreeNode *right;
TreeNode(double value1,
TreeNode *left1 = nullptr,
TreeNode *right1 = nullptr) {
value = value1;
left = left1;
right = right1;
}
};
TreeNode *root; //pointer to the root of the tree
bool search(double x, TreeNode *t) {
while (t) {
std::cout << "running through t." << std::endl;
if (t->value == x) {
return true;
}
else if (x < t->value) {
std::cout << "wasn't found, moving left." << std::endl;
search(x, t->left);
}
else {
std::cout << "wasn't found, moving right." << std::endl;
search(x, t->right);
}
}
std::cout << "wasn't found." << std::endl;
return false;
}
public:
std::vector<TreeNode> v;
BinaryTree() {
root = nullptr;
}
void insert(double x) {
TreeNode *tree = root;
if (!tree) {
std::cout << "Creating tree." << x << std::endl;
root = new TreeNode(x);
return;
}
while (tree) {
std::cout << "Adding next value." << std::endl;
if (tree->value == x) return;
if (x < tree->value) {
tree = tree->left;
tree->value = x;
}
else {
tree = tree->right;
tree->value = x;
}
}
}
bool search(double x) {
return search(x, root);
}
/*void inOrder(TreeNode *v) const {
while (root != nullptr) {
inOrder(root->left);
v.push_back(root->value);
inOrder(root->right);
v.push_back(root->value);
}
}*/
};
int main() {
BinaryTree t;
std::cout << "Inserting the numbers 5, 8, 3, 12, and 9." << std::endl;
t.insert(5);
t.insert(8);
t.insert(3);
t.insert(12);
t.insert(9);
std::cout << "Looking for 12 in tree." << std::endl;
if (t.search(12)) {
std::cout << "12 was found." << std::endl;
}
std::cout << "Here are the numbers in order." << std::endl;
return 0;
}

You have to add one more level of dereference if you want your code to work. And of course create the new node at the end of the function. The following code should work:
void insert(double x) {
TreeNode **tree = &root;
while (*tree) {
std::cout << "Adding next value." << std::endl;
if ((*tree)->value == x) return;
if (x < (*tree)->value) {
tree = &(*tree)->left;
} else {
tree = &(*tree)->right;
}
}
if (!(*tree)) {
std::cout << "Creating tree." << x << std::endl;
*tree = new TreeNode(x);
return;
}
}
And your search method should looks like:
bool search(double x) {
TreeNode *node = root;
while (node) {
if (node->value == x) {
return true;
} else if (x < node->value) {
node = node->left;
} else {
node = node->right;
}
}
std::cout << "wasn't found." << std::endl;
return false;
}
Result of your main function, with my code:
Inserting the numbers 5, 8, 3, 12, and 9.
Creating tree.5
Adding next value.
Creating tree.8
Adding next value.
Creating tree.3
Adding next value.
Adding next value.
Creating tree.12
Adding next value.
Adding next value.
Adding next value.
Creating tree.9
Looking for 12 in tree.
12 was found.

Related

Getting segmentation fault when trying to print binary tree nodes in C++ [duplicate]

This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
What is a segmentation fault?
(18 answers)
Why dereferencing a null pointer is undefined behaviour?
(13 answers)
Closed 7 months ago.
I have an implementation of a binary tree using pointers. I am trying to print its nodes using preorder depth first traversal using recursion. When the program gets to right nodes it says segmentation fault. The problem is that I cannot find the error/mistake in the binary tree implementation. Program works when i use different btree implementation, so I assume the problem is in this btree implementation using pointers.
Below is my binary tree implementation
#include "../data-structures/trees/binary-tree-pointers/tree.h"
using namespace std;
void PrintTree(BinaryTree<int> tree, BinaryTree<int>::node node) {
cout << tree.Label(node) << endl;
if (tree.LeftChild(node) != tree.lambda) PrintTree(tree, tree.LeftChild(node));
if (tree.RightChild(node) != tree.lambda) PrintTree(tree, tree.RightChild(node));
}
int main() {
BinaryTree<int> tree;
BinaryTree<int>::node node;
tree.CreateRoot(1);
tree.CreateLeftChild(tree.Root(), 2);
tree.CreateRightChild(tree.Root(), 3);
node = tree.Root();
node = tree.LeftChild(node);
tree.CreateLeftChild(node, 4);
tree.CreateRightChild(node, 5);
node = tree.LeftChild(node);
tree.CreateLeftChild(node, 7);
node = tree.Root();
node = tree.RightChild(node);
tree.CreateRightChild(node, 8);
PrintTree(tree, tree.Root());
return 0;
}
Here is my binary tree implementation:
#include <iostream>
#include <cstdlib>
template <typename nodeType>
class BinaryTree {
private:
struct Tnode {
Tnode *parent, *left, *right;
nodeType label;
};
Tnode *B;
public:
typedef Tnode* node;
const node lambda = NULL;
void Del(node n) {
if (n->left != NULL) Del(n->left);
if (n->right != NULL) Del(n->right);
delete n;
}
void Prnt(node n) {
std::cout << n->label << " ";
if (n->left != NULL) Prnt(n->left);
if (n->right != NULL) Prnt(n->right);
}
BinaryTree() {
B = NULL;
}
BinaryTree(nodeType x) {
B = new Tnode;
B->parent = B->left = B->right = NULL;
B->label = x;
}
bool IsEmpty() {
return B == lambda;
}
nodeType Label(node n) {
if (n == lambda) {
std::cout << "That node doesn't exist!" << std::endl;
exit(EXIT_FAILURE);
}
return n->label;
}
node Root() {
return B;
}
node Parent(node n) {
if (n == lambda) {
std::cout << "That node doesn't exist!" << std::endl;
exit(EXIT_FAILURE);
}
return n->parent;
}
node LeftChild(node n) {
if (n == lambda) {
std::cout << "That node doesn't exist!" << std::endl;
exit(EXIT_FAILURE);
}
return n->left;
}
node RightChild(node n) {
if (n == lambda) {
std::cout << "That node doesn't exist!" << std::endl;
exit(EXIT_FAILURE);
}
return n->right;
}
void ChangeLabel(node n, nodeType x) {
if (n == lambda) {
std::cout << "That node doesn't exist!" << std::endl;
exit(EXIT_FAILURE);
}
n->label = x;
}
void CreateRoot(nodeType x) {
if (!this->IsEmpty()) {
std::cout << "Can't create root! Tree is not empty!" << std::endl;
exit(EXIT_FAILURE);
}
B = new Tnode;
B->parent = B->left = B->right = NULL;
B->label = x;
}
void CreateLeftChild(node n, nodeType x) {
if (n == lambda) {
std::cout << "That node doesn't exist!" << std::endl;
exit(EXIT_FAILURE);
}
if (n->left != lambda) {
std::cout << "Can't create left node! It already exists" << std::endl;
exit(EXIT_FAILURE);
}
Tnode *newNode = new Tnode;
newNode->left = newNode->right = NULL;
newNode->parent = n;
newNode->label = x;
n->left = newNode;
}
void CreateRightChild(node n, nodeType x) {
if (n == lambda) {
std::cout << "That node doesn't exist!" << std::endl;
exit(EXIT_FAILURE);
}
if (n->right != lambda) {
std::cout << "Can't create right node! It already exists" << std::endl;
exit(EXIT_FAILURE);
}
Tnode *newNode = new Tnode;
newNode->label = x;
newNode->left = newNode->right = NULL;
newNode->parent = n;
n->right = newNode;
}
void Delete(node n) {
if (n == lambda) {
std::cout << "That node doesn't exist!" << std::endl;
exit(EXIT_FAILURE);
}
if (n->parent != NULL) {
if (n->parent->left == n) n->parent->left = NULL;
else n->parent->right = NULL;
Del(n);
}
else {
Del(n);
B = NULL;
}
}
void Print() {
Prnt(B);
std::cout << std::endl;
}
~BinaryTree() {
if (B != lambda) Del(B);
}
};

Implementing Queue Using LinkedList [duplicate]

This question already has answers here:
How come a non-const reference cannot bind to a temporary object?
(11 answers)
Closed 5 years ago.
So, i'm attempting to implement this Queue using my LinkedList that I previously created. I've provided the code for both classes. Currently, I'm work on attempting to get pop and push to work without changing the function prototype (it's for an assignment).
When looking specifically at peek(I haven't quite finished pop), for some reason, when I run the code, I get strange pointer error.
Error C2440 'default argument': cannot convert from 'int' to 'int &'
I'm not sure exactly what that means in this context. The function is suppose to look at the object at the top of the queue without removing it, and return true or false based upon if the operation was successful or not.
Here is the info for QUEUE.
#ifndef _QUEUE_H
#define _QUEUE_H 1
#include "QueueInterface.h"
#include "LinkedList.hpp"
template <typename T>
class Queue : public QueueInterface<T>
{
protected:
LinkedList<T> _list;
int count;
public:
unsigned size() const
{
return count;
}
bool push(const T& val = T{})
{
_list.push(val);
count++;
return true;
}
bool empty() const
{
return _list.isEmpty();
}
bool pop(T& val = T{})
{
return true;
}
bool peek(T& val = T{}) const
{
std::cout << _list.last() << std::endl;
return true;
}
void clear()
{
_list.clear();
}
int search(const T& target = T{}) const
{
return _list.search(target);
}
//
// Internal consistency check
//
void toString()
{
_list.toString();
}
public:
virtual bool check() const
{
return _list.check();
}
};
#endif
Here is Linked List.
#ifndef _LINKED_LIST_GUARD
#define _LINKED_LIST_GUARD 1
#include <iostream>
#include "ListInterface.h"
template <typename T>
class LinkedList : public ListInterface<T>
{
public:
int count = 0;
LinkedList()
{
_head = new Node;
_tail = new Node;
_head->_next = _tail;
}
private:
//
// Private node class to facilitate linked list
//
class Node
{
public:
T _data;
Node* _next;
// Constructor: default
Node(T d = T{}, Node* n = nullptr) : _data(d), _next(n) {}
~Node() { _next = nullptr; }
};
//
// Prevent copying and assigning
//
LinkedList(const LinkedList& rhs) {}
const LinkedList& operator=(const LinkedList& rhs) {}
public:
//
// LinkedList instance variables; we use dummy head and tail nodes in this implementation
unsigned _size;
Node* _head;
Node* _tail;
// Returns the first element in the list
T& first() const
{
return _head->_next->_data;
}
// Adds an item to the LEFT side of the linked list
void push(const T& x)
{
// Creates a new node with the user input data.
Node* current = new Node;
current->_data = x;
current->_next = _head->_next;
_head->_next = current;
count++;
}
// ASK ABOUT
T& operator[](unsigned n)
{
int position = 1;
if (n != count)
{
throw("Invalid Position");
}
for (Node* current = _head->_next; current != _tail; current = current->_next, position++)
{
if (position == n)
{
return current -> _data;
}
}
}
void clear()
{
do
{
pop();
} while (count != 0);
}
bool contains(const T& target) const
{
for (Node* current = _head->_next; current != _tail; current = current->_next)
{
if (current->_data == target)
return true;
}
return false;
}
bool pop()
{
if (_head->_next == _tail)
{
std::cout << "unable to pop, list is empty";
return false;
}
if (_head->_next != _tail)
{
Node* deleteNode = _head->_next;
_head->_next = _head->_next->_next;
delete deleteNode;
count--;
return true;
}
return false;
}
T& last() const
{
if (_head->_next == _tail)
{
std::cout << "LIST IS EMPTY" << std::endl;
}
if (_head->_next != _tail)
{
for (Node* current = _head->_next; current != _tail; current = current->_next)
{
if (current->_next == _tail)
return current->_data;
}
}
}
// ASK ABOUT
int search(const T& target = T{}) const
{
int position = 1;
for (Node* current = _head->_next; current != _tail; current = current->_next)
{
if (current->_data == target)
{
return position;
}
else position++;
}
return -1;
}
bool isEmpty() const
{
if (_head->_next == _tail)
{
return true;
}
return false;
}
unsigned size() const
{
return count;
}
bool remove(const T& target)
{
Node* deleteNode = nullptr;
Node* trailer = _head;
Node* current = _head->_next;
while (current != _tail && current-> _data != target)
{
trailer = current;
current = current->_next;
}
if (current->_data == target)
{
deleteNode = current;
current = current->_next;
trailer->_next = current;
delete deleteNode;
count--;
return true;
}
else
std::cout << "unable to remove, item not in list" << std::endl;
return false;
}
//FOR TESTING
void toString()
{
for (Node* current = _head->_next; current != _tail; current = current->_next)
{
std::cout << current->_data << std::endl;
}
}
//
// Internal consistency check
//
public:
virtual bool check() const
{
bool sizeConsistent = isSizeConsistent();
bool headTailConsistent = isEndConsistent();
if (!sizeConsistent) std::cerr << "Size inconsistent" << std::endl;
if (!headTailConsistent) std::cerr << "Head / Tail inconsistent" << std::endl;
return sizeConsistent && headTailConsistent;
}
//
// Stated size is accurate to the entire list
//
bool isSizeConsistent() const
{
int count = 0;
for (Node* current = _head->_next; current != _tail; current = current->_next)
{
count++;
}
return size() == count;
}
//
// Checks that the head and tail are defaulted properly and the
// respective next pointers are appropriate.
//
bool isEndConsistent() const
{
if (_head->_data != T{}) return false;
if (_tail->_data != T{}) return false;
if (_head->_next == nullptr) return false;
if (_tail->_next != nullptr) return false;
if (isEmpty() && _head->_next != _tail) return false;
if (!isEmpty() && _head->_next == _tail) return false;
return true;
}
};
#endif
And finally, here is my main. The top portion is to test the functionality for LinkedList. The bottom portion is what I was working with to test queue.
#include "Queue.hpp"
#include "LinkedList.hpp"
#include <string>
#include <iostream>
int main()
{
LinkedList<int> list;
LinkedList<int> listEmpty;
Queue<int> list2;
list.push(1);
list.push(2);
list.push(3);
list.push(4);
list.push(5);
list.remove(1);
std::cout << "List contains 4? " << list.contains(4) << std::endl;
std::cout << "List empty? " << list.isEmpty() << std::endl;
std::cout << "List size: " << list.size() << std::endl;
std::cout << "Last in list? " << list.last() << std::endl;
std::cout << "What is in position 4? " << list[4] << std::endl;
std::cout << "Search " << list.search(10) << std::endl;
//std::cout << "3 is in position " << list.search() << std::endl;
std::cout << " " << std::endl;
list.toString();
list.clear();
std::cout << "///////////////////////////////////////////////////////////////////////////////" << std::endl;
list.push(4);
list.toString();
std::cout << "///////////////////////////////////////////////////////////////////////////////" << std::endl;
std::cout << "QUEUE STUFF" << std::endl;
std::cout << "///////////////////////////////////////////////////////////////////////////////" << std::endl;
list2.push(1);
list2.push(2);
list2.push(6);
list2.push(3);
list2.push(4);
list2.push(5);
std::cout << "Queue empty? " << list2.empty() << std::endl;
std::cout << "Queue size: " << list2.size() << std::endl;
std::cout << "First in Queue? " << list2.peek() << std::endl;
std::cout << "What position is 6 in? : " << list2.search(6) << std::endl;
list2.toString();
std::cout << " " << std::endl;
system("pause");
I guess my question is this, what steps can I take to go about fixing this particular function?
Thanks in advance!
The problem with your code is that peek, as you said, should not modify the Queue and neither take any parameter because it merely looks at the top of the structure and returns either true or false.
So a solution is to remove the parameter in peak as follows and everything compiles and runs.
bool peek() const
{
std::cout << _list.last() << std::endl;
return true;
}
Specifically, the error you get is because you cannot assign to a non-const lvalue reference an rvalue reference.
This is exactly what you are doing in T& val = T{}. T{} is an rvalue and clearly, val is a non-const reference to T.
You can try using bool peek(const T& val = T{}) const and see by yourself that everything compiles fine.

Why is my splay tree not saving any values?

I am just looking for an explanation as to why my tester is saying that my nodes are not being saved. The tester says that inserting is fine, and it tests to see if they are properly lined up. But when it goes back to count the nodes it's saying that only two of them are linked. I've provided what the output is and my code below. I think there is a problem with my rotate function but when I drew a diagram and went step by step it seemed fine. Is it possible that my splay function is wrong? The "Testing tree insertion..." thinks that it's fine so I don't know what to do.
---- Beginning tree tests ----
Testing tree insertion...21 23 27 38 32 33 16 11 26 8 15 6 30 13 0 40 20 3 9 34 14 17 37 18 28 24 2 10 7 35 19 29 25 22 36 39 1 4 12 31 5
FAILED: tree does not have the correct number of nodes. (expected 41, found 2)
--- Tree structure ---
5
├─ 31 [p = 5]
└─(null)
/*
* assign4_test.cc
* Assignment 4 (BST) test runner.
*/
#include <algorithm>
#include <cassert>
#include <iostream>
#include <random>
#include <set>
#include <vector>
using namespace std;
using std::cout;
std::vector<unsigned> make_random_permutation(
std::size_t len,
int seed = 1)
{
std::default_random_engine generator(seed);
std::vector<unsigned> ret(len, 0);
// Initialize vector to 0...len-1
for(std::size_t i = 0; i < len; ++i)
ret.at(i) = i;
std::shuffle(ret.begin(), ret.end(), generator);
return ret;
}
// Node structure
struct node {
int key;
node* left;
node* right;
node* parent;
};
/*
* User-implemented functions
*/
void rotate(node* child, node* parent); // Rotation
bool find(node*& root, int value); // Search
node* insert(node* root, int value); // Insertion
node* insertRec(node*root, int value);
//node* remove(node* root, int value); // Deletion
node* splay(node* t); // Splay
void rotate(node* child, node* parent){
if(parent->left == child){
child->parent = parent->parent;
if(parent->parent != nullptr){
if(child->key < parent->parent->key){
parent->parent->left = child;
}
else
parent->parent->right = child;
}
parent->parent = child;
parent->left = child->right;
if(child->right != nullptr)
child->right->parent = parent;
child->right = parent;
}
else{
child->parent = parent->parent;
if(parent->parent != nullptr){
if(child->key < parent->parent->key){
parent->parent->left = child;
}
else
parent->parent->right = child;
}
parent->parent = child;
parent->right = child->left;
if(child->left != nullptr)
child->left->parent = parent;
child->left = parent;
}
}
node* insertRec(node* root, int value){
node* newNode = new node();
newNode->key = value;
if(root == nullptr)
return newNode;
else if(value < root->key){
root->left = insertRec(root->left, value);
root->left->parent = root;
}
else{
root->right = insertRec(root->right, value);
root->right->parent = root;
}
}
node* insert(node* root, int value){
root = splay(insertRec(root,value));
return root;
}
bool find(node*& root, int value){
node* temp = root;
if(temp == nullptr)
return false;
else if(temp->key == value){
root = splay(temp);
return true;
}
else if(value > temp->key)
return find(temp->right, value);
else
return find(temp->left, value);
}
node* splay(node* t){
while(t->parent != nullptr){
if(t->parent->parent == nullptr)
rotate(t, t->parent);
else{
rotate(t,t->parent);
rotate(t,t->parent);
}
}
return t;
}
/******************************************************************************
Tree structure checking
******************************************************************************/
// Balance measurement, returns a balance factor between 0 (not possible) and 1
// (perfectly balanced).
float balance(node* root) {
if(!root)
return 1.0; // Empty tree is perfectly balanced
else if(!root->left) {
// One subtree, on the right
return 0.5 * balance(root->left);
}
else if(!root->right) {
return 0.5 * balance(root->right);
}
else // Two subtrees
return (balance(root->right) + balance(root->left)) / 2;
}
// Safe find, that does not modify the tree structure
bool safe_find(node* root, int value) {
if(!root)
return false;
else if(root->key == value)
return true;
else if(value < root->key)
return safe_find(root->left, value);
else // value < root->key
return safe_find(root->right, value);
}
int count_nodes(node* root) {
if(!root)
return 0;
else
return 1 + count_nodes(root->left) + count_nodes(root->right);
}
int tree_height(node* root) {
if(!root)
return 0;
else
return 1 + std::max(tree_height(root->left), tree_height(root->right));
}
// Pretty-print a tree. This does cycle-checking at the same time, so that if
// there's a cycle in the tree we won't get stuck in a loop.
void print(node* root, int level, int parents, bool left_child, std::set<node*>& nodes) {
if(level == 0)
cout << "--- Tree structure ---\n";
// Print indent for node
for(int i = 0; i < level-1; ++i)
if(parents & (1 << i))
cout << " │ ";
else
cout << " ";
if(level > 0)
cout << (left_child ? " ├─" : " └─");
if(root == nullptr) {
cout << "(null)" << std::endl;
}
else if(nodes.count(root) > 0) {
// Already printed this node somewhere else
cout << "CYCLE (" << root->key << ")" << std::endl;
}
else {
nodes.insert(root); // Visit root
// Print children
cout.width(3);
cout << root->key;
if(root->parent != nullptr)
cout << " [p = " << root->parent->key << "]";
cout << std::endl;
// Print children
if(root->left || root->right) {
// We only print both children if one of them is non-null.
// If both are null we don't print anything, to avoid making a huge
// mess.
// We print the children in the order right, left so that you can
// turn your head (or your screen) to the left and the tree will
// be correct.
print(root->right, level+1, parents | (1 << level), true, nodes);
print(root->left, level+1, parents, false, nodes);
}
}
}
void print(node* root) {
std::set<node*> nodes;
print(root, 0, 0, true, nodes);
}
/* check_for_cycles(n)
Traverse the tree (preorder) starting at n, checking for cycles of nodes.
Note that this does not check for parent-pointer cycles, only child-pointer
cycles.
*/
bool check_for_cycles(node* n, std::set<node*>& nodes) {
if(nodes.count(n) > 0)
return false;
else {
nodes.insert(n); // Mark n as seen
// Explore left and right subtrees
bool ret = true;
if(n->left)
ret = ret && check_for_cycles(n->left, nodes);
if(n->right)
ret = ret && check_for_cycles(n->right, nodes);
return ret;
}
}
bool check_for_cycles(node* n) {
std::set<node*> nodes;
if(!check_for_cycles(n, nodes)) {
cout << "FAILED: tree structure contains a cycle.\n";
return false;
}
else
return true;
}
// Check the pointer structure of the tree (parent/child) to make sure it is
// correct.
bool check_tree_pointers(node* root, bool is_root = true) {
if(!root)
return true;
else {
if(is_root && root->parent != nullptr) {
cout << "FAILED: root->parent should always be null.\n";
return false;
}
// Child child nodes (if they exist) to make sure their parents
// point back to root.
if(root->left) {
if(root->left->parent != root) {
cout << "FAILED: found node " << root->left->key
<< " with incorrect parent pointer.\n";
return false;
}
if(root->left->key >= root->key) {
cout << "FAILED: found node " << root->left->key
<< " which is on the wrong side of parent.\n";
return false;
}
}
if(root->right) {
if(root->right->parent != root) {
cout << "FAILED: found node " << root->right->key
<< " with incorrect parent pointer.\n";
return false;
}
if(root->right->key <= root->key) {
cout << "FAILED: found node " << root->right->key
<< " which is on the wrong side of parent.\n";
return false;
}
}
if(root->right && root->left) {
// Both children, if they exist, have valid parent pointers.
// So now we check both subtrees recursively.
return check_tree_pointers(root->left, false) &&
check_tree_pointers(root->right, false);
}
return true;
}
}
bool check_tree_values(node* root,
int low = std::numeric_limits<int>::min(),
int high = std::numeric_limits<int>::max()) {
if(!root)
return true;
else if(root->key <= low) {
cout << "FAILED: found node " << root->key << " improperly placed.\n";
return false;
}
else if(root->key >= high) {
cout << "FAILED: found node " << root->key << " improperly placed.\n";
return false;
}
else { // root->key is in the correct range
return check_tree_values(root->left, low, root->key) &&
check_tree_values(root->right, root->key, high);
}
}
bool check_tree(node* root) {
if(root->parent != nullptr) {
cout << "FAILED: Root of tree must have null parent pointer";
cout << " (root->parent->key = " << root->parent->key << ")\n";
return false;
}
return check_for_cycles(root) &&
check_tree_pointers(root) &&
check_tree_values(root);
}
/******************************************************************************
Tree testing
******************************************************************************/
template<typename Func>
struct scope_exit {
scope_exit(Func f) : exit(f)
{}
~scope_exit() {
exit();
}
Func exit;
};
template<typename Func>
scope_exit<Func> make_scope_exit(Func f) {
return scope_exit<Func>(f);
}
// To test the tree functions, we generate a random permutation of the integers
// from -20 to 20 and insert them into the tree. Then, we generate another
// permutation and find them in that order. Finally, we generate another
// permutation and remove them in that order. After every operation, we perform
// a full check of the tree structure. The test stops if the tree structure is
// not valid at any point.
bool test_rotate() {
// This is a huge mess. I need to come up with a better way to test
// left/right rotations. Maybe use member-pointers to abstract over
// the orientation?
// Root of the pseudo-tree
node* root = new node{10000, nullptr, nullptr, nullptr};
/* Left-rotation tree:
p
/ \
c Z
/ \
X Y
*/
node* X = new node{-10, nullptr, nullptr, nullptr};
node* Y = new node{-20, nullptr, nullptr, nullptr};
node* Z = new node{-30, nullptr, nullptr, nullptr};
node* child = new node{2, X, Y, nullptr};
node* parent = new node{1, child, Z, root};
// This is to avoid memory leaks: the function will be called when this
// function returns.
auto exiter = make_scope_exit([&]() {
delete X;
delete Y;
delete Z;
delete child;
delete parent;
});
child->parent = parent;
X->parent = Y->parent = child;
Z->parent = parent;
rotate(child, parent);
/* New structure should be
c
/ \
X p
/ \
Y Z
*/
if(child->parent != root) {
cout << "FAILED: parent's parent is not preserved.\n";
return false;
}
if(child->right != parent) {
cout << "FAILED: rotate did not make parent into child.\n";
return false;
}
if(child->left != X) {
cout << "FAILED: left child of child should be unchanged\n";
return false;
} else if(parent->left != Y) {
cout << "FAILED: child's right child should become right-child of parent.\n";
return false;
} else if(parent->right != Z) {
cout << "FAILED: right child of parent should be unchanged.\n";
return false;
}
else if(parent->parent != child) {
cout << "FAILED: parent->parent is not original child.\n";
return false;
}
else if(!check_for_cycles(child)) {
cout << "FAILED: rotation created a cycle\n";
print(child);
return false;
}
// Right-rotation
delete child; delete parent;
child = new node{2, Y, Z, nullptr};
parent = new node{1, X, child, root};
child->parent = parent;
X->parent = parent;
Y->parent = Z->parent = child;
rotate(child, parent);
if(child->parent != root) {
cout << "FAILED: parent's parent is not preserved.\n";
return false;
}
if(child->left != parent) {
cout << "FAILED: rotate did not make parent into child.\n";
return false;
}
if(parent->left != X) {
cout << "FAILED: left child of parent should be unchanged.\n";
return false;
}
else if(child->right != Z) {
cout << "FAILED: right child of child should be unchanged.\n";
return false;
}
else if(parent->right != Y) {
cout << "FAILED: left child of child should become right child of parent\n";
return false;
}
else if(parent->parent != child) {
cout << "FAILED: parent->parent is not original child.\n";
return false;
}
else if(!check_for_cycles(child)) {
cout << "FAILED: rotation created a cycle\n";
print(child);
return false;
}
// Do a quick test with null children and null root
// If the user made a mistake here, this will most likely segfault.
delete child;
delete parent;
child = new node{1, nullptr, nullptr, nullptr};
parent = new node{0, child, nullptr, nullptr};
child->parent = parent;
rotate(child, parent);
if(parent->parent != child) {
cout << "FAILED: parent did not become the child\n";
return false;
}
else if(child->right != parent) {
cout << "FAILED: parent did not become right child\n";
return false;
}
return true;
}
bool test_tree() {
node* t = nullptr; // Empty tree
// Generate test data
std::vector<unsigned> test = make_random_permutation(41, 12);
// Insert a random permutation
cout << "Testing tree insertion...";
for(unsigned u : test) {
const int i = static_cast<int>(u);
cout << u << " ";
t = insert(t, i);
if(!check_tree(t)) {
print(t);
return false; // Stop if the check fails.
}
if(t->key != i) {
cout << "FAILED: After inserting " << i << " it should be splayed to the root\n";
print(t);
return false;
}
}
cout << std::endl;
int cn = count_nodes(t);
if(cn != 41) {
cout << "FAILED: tree does not have the correct number of nodes. ";
cout << "(expected 41, found " << cn << ")\n";
print(t);
return false;
}
else {
cout << "OK so far...\n";
print(t);
}
// Find a random permutation
cout << "Testing tree find()...";
for(unsigned u : test) {
const int i = static_cast<int>(u);
cout << i << " ";
if(!find(t, i)) {
cout << "FAILED: find() couldn't find " << i << "\n";
return false;
}
if(t->key != i) {
cout << "FAILED: find() did not splay target to the root.\n";
print(t);
return false;
}
if(!check_tree(t)) {
print(t);
return false;
}
}
cout << std::endl;
print(t);
// We no longer test removal, because students are not required to implement
// remove(). It's too fiddly to get right, too many edge cases.
/*
// Remove a random permutation
cout << "Testing tree removal...\n";
for(unsigned u : test) {
const int i = static_cast<int>(u);
t = remove(t, i);
if(!check_tree(t)) {
print(t);
return false;
}
if(safe_find(t,i)) {
cout << "FAILED: removed element " << i << " is still present in the tree\n";
print(t);
return false;
}
}
if(t != nullptr) {
cout << "FAILED: Tree not empty after removing all elements.\n";
print(t);
return false;
}
*/
return true;
}
int main() {
cout << "---- Beginning tree tests ----\n";
if(test_rotate() && test_tree())
cout << "---- All tests successful ----\n";
return 0;
}

How to implement insert function, with no pointer node as a parameter, in binary tree?

tree.h file that implements all the methods. The insert function is in this file. Everything I try requires a the use of a tree pointer node to be passed as a parameter but we cant change the method headers at all for this assignment so Im lost as to how to implement it. Any help is greatly appreciated thanks!!
#include "treeNode.h"
#include <iomanip>
template <class V>
class tree {
TreeNode<V> * root;
int size;
public:
// default constructor
// by default, the tree is empty
tree(){
root = nullptr;
size = 0;
}
// search value x in tree rooted at node t
bool treeSearch(V x, TreeNode<V>* t){
if(t == nullptr) return false;
if(t->getDatum() == x) return true;
return treeSearch(x, t->getLeft()) || treeSearch(x, t->getRight());
}
bool treeSearch(V x){
treeSearch(x, root);
}
// binary search value x in tree rooted at node t
bool treeBSearch(V x, TreeNode<V>* t){
if(t == nullptr) return false;
if(t->getDatum() == x) return true;
if(t->getDatum() > x)
return treeBSearch(x, t->getLeft());
else
return treeBSearch(x, t->getRight());
}
bool treeBSearch(V x){
return treeBSearch(x, root);
}
// check node t is leaf
bool isLeaf(TreeNode<V>* t){
if(t != nullptr && t->getLeft() == nullptr && t->getRight() == nullptr){
return true;
}else{
return false;
}
}
// find the height of the tree rooted at node t
int height(TreeNode<V>* t){
if(t == nullptr) return -1;
if(isLeaf(t)) return 0;
return 1 + std :: max(height(t->getLeft()), height(t->getRight()));
}
int height(){
return height(root);
}
// find the number of nodes of tree rooted at t
int nNodes(TreeNode<V>* t){
if(t == nullptr) return 0;
return 1 + nNodes(t->getLeft()) + nNodes(t->getRight());
}
int nNodes(){
return nNodes(root);
}
// insert value x to the current tree object
void insert(V x){
}
// print out the values of tree rooted at x
// it shows the hierarchy of the tree
// it will be useful for debugging
void print(TreeNode<V> * x, int indent){
if(x == nullptr) return;
if (x->getRight() != nullptr) {
print(x->getRight(), indent+4);
}
if (indent != 0) {
cout << std::setw(indent) << ' ';
}
if(x->getRight() != nullptr){
cout << " /\n" << std::setw(indent) << ' ';
}
cout << x->getDatum() << endl;
if (x->getLeft() != nullptr) {
cout << std::setw(indent) << ' ' <<" \\\n";
print(x->getLeft(), indent+4);
}
}
void print(){
int count = 0;
print(root, count);
}
};
treeNode.h file that has declares methods
#include
#include
#include
using namespace std;
template <class T>
class TreeNode{
T datum;
TreeNode<T>* left, * right;
public:
// constructor with datum value, left and right are nullptr
TreeNode(T x){
datum=x;
left = nullptr;
right = nullptr;
}
// constructor with datum value, left and right values
TreeNode(T x, TreeNode<T>* lft, TreeNode<T>* rgt){
datum = x;
left = lft;
right = rgt;
}
//destructor releases left and right nodes, if not nullptr
~TreeNode(){
if (left) {
delete left;
}
if (right) {
delete right;
}
}
// get datum value
T getDatum(){
return datum;
}
// get left pointer
TreeNode<T>* getLeft(){
return left;
}
// get right pointer
TreeNode<T>* getRight(){
return right;
}
// set the left pointer
void setLeft(TreeNode<T>* p){
left = p;
}
// set the right pointer
void setRight(TreeNode<T>* p){
right = p;
}
};
test.cpp file that tests whether or not the methods work
#include "tree.h"
int main(){
tree<int> myTree;
myTree.insert(5);
myTree.insert(3);
myTree.insert(2);
myTree.insert(4);
myTree.insert(8);
myTree.insert(6);
myTree.insert(7);
myTree.insert(9);
cout << myTree.treeBSearch(9) << endl;
cout << myTree.treeBSearch(11) << endl;
cout << myTree.nNodes() << endl;
cout << "The Tree Looks Like: " << endl;
myTree.print();
tree<int> myTree2;
myTree2.insert(4);
myTree2.insert(2);
myTree2.insert(1);
myTree2.insert(3);
myTree2.insert(7);
myTree2.insert(5);
// myTree2.print();
}

Still can't find largest number in binary tree

I still can't find the largest number in my tree, but now I am really not complicating it, I think it should work, there is no error, but it just won't show me in the console. Anyone got an idea? I am getting really frustrated.
Here is my entire code:
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
template<class T>
class BinaryTree
{
struct Node
{
T data;
Node* lChildptr;
Node* rChildptr;
Node(T dataNew)
{
data = dataNew;
lChildptr = NULL;
rChildptr = NULL;
}
};
private:
Node* root;
void Insert(T newData, Node* &theRoot)
{
if(theRoot == NULL)
{
theRoot = new Node(newData);
return;
}
if(newData < theRoot->data)
Insert(newData, theRoot->lChildptr);
else
Insert(newData, theRoot->rChildptr);;
}
void PrintTree(Node* theRoot)
{
if(theRoot != NULL)
{
PrintTree(theRoot->lChildptr);
cout<< theRoot->data<<" \n";;
PrintTree(theRoot->rChildptr);
}
}
T Largest( Node* theRoot)
{
if ( root == NULL ){
cout<<"There is no tree";
return -1;
}
if (theRoot->rChildptr != NULL)
return Largest(theRoot->rChildptr);
else
return theRoot->data;
cout<<theRoot->data;
};
public:
BinaryTree()
{
root = NULL;
}
void AddItem(T newData)
{
Insert(newData, root);
}
void PrintTree()
{
PrintTree(root);
}
T Largest()
{
return Largest(root);
}
};
int main()
{
BinaryTree<int> *myBT = new BinaryTree<int>();
myBT->AddItem(2);
myBT->AddItem(5);
myBT->AddItem(1);
myBT->AddItem(10);
myBT->AddItem(15);
myBT->PrintTree();
myBT->Largest();
}
and here is the part that is supposed to find the largest number (the child that is far right down):
T Largest( Node* theRoot)
{
if ( root == NULL ){
cout<<"There is no tree";
return -1;
}
if (theRoot->rChildptr != NULL)
return Largest(theRoot->rChildptr);
else
return theRoot->data;
cout<<theRoot->data;
};
There are two problems in your code in Largest():
It looks like you wanted to execute two statements in the else clause, but you didn't use braces.
You wanted to execute the cout print after returning, which is impossible. Switch the order around.
So you should replace your fragment of code with this:
else {
cout << theRoot->data;
return theRoot->data;
}
Incidentally, don't let double semicolons (;;) stay in your code. It's harmless in most cases, but it's always bad style.
Here's a fixed and slightly cleaned-up version that works:
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
template<class T>
class BinaryTree
{
struct Node
{
T data;
Node* lChildptr;
Node* rChildptr;
Node(T dataNew)
{
data = dataNew;
lChildptr = 0;
rChildptr = 0;
}
};
private:
Node* root;
void Insert(T newData, Node** theRoot)
{
if (*theRoot == 0)
{
*theRoot = new Node(newData);
}
else if (newData < (*theRoot)->data)
Insert(newData, &((*theRoot)->lChildptr));
else
Insert(newData, &((*theRoot)->rChildptr));
}
void PrintTree(Node* theRoot)
{
if (theRoot != 0)
{
PrintTree(theRoot->lChildptr);
cout << theRoot->data << " " << endl;
PrintTree(theRoot->rChildptr);
}
}
T Largest(Node* theRoot)
{
if (root == 0)
{
throw "There is no tree";
}
if (theRoot->rChildptr != 0)
return Largest(theRoot->rChildptr);
else
return theRoot->data;
}
public:
BinaryTree()
{
root = 0;
}
void AddItem(T newData)
{
Insert(newData, &root);
}
void PrintTree()
{
PrintTree(root);
}
T Largest()
{
return Largest(root);
}
};
int main()
{
BinaryTree<int> *myBT = new BinaryTree<int>();
cout << "The tree is empty. Trying to find the largest element." << endl;
try
{
cout << "Largest element: " << myBT->Largest() << endl;
}
catch (const char* e)
{
cout << "Exception caught: " << e << endl;
}
myBT->AddItem(15);
myBT->AddItem(2);
myBT->AddItem(5);
myBT->AddItem(1);
myBT->AddItem(10);
cout << "Tree:" << endl;
myBT->PrintTree();
cout << "Largest element: " << myBT->Largest() << endl;
}
Output:
The tree is empty. Trying to find the largest element.
Exception caught: There is no tree
Tree:
1
2
5
10
15
Largest element: 15