Binary Search Tree: Issue with Insert Function - c++

I've been researching how to create binary search trees and i have run into a problem when trying to create my own. I have to use the following private structure to create the tree. Every example that i have looked at uses left and right pointers pointing to the structure and i have to use left and right pointers pointing to my template class. I have been trying to figure out how to write the insert function for adding a new node into my tree but i keep running into problems because of the way these two pointers are setup. Does anyone have a clue on how to make it work with these two pointers below?
private:
struct BinaryNode
{
Comparable element;
BinarySearchTree<Comparable> *left;
BinarySearchTree<Comparable> *right;
};
BinaryNode *root;
};
This is my constructor
BinarySearchTree<Comparable>::BinarySearchTree() {
BinaryNode *temp;
temp = new BinaryNode;
temp->left= NULL;
temp->right= NULL;
root = temp;
}

Try the following:
public:
template <typename Comparable>
void insert(const Comparable& key)
{
root = insert(root, key);
}
private:
template <typename Comparable>
BinaryNode* insert(BinaryNode*& current_node, const Comparable& key)
{
if (current_node == nullptr)
{
// Create a leaf node and return it, thus attaching
// it to the node we last called the function with
return new BinaryNode{key, nullptr, nullptr};
}
if (key == current_node->element)
// duplicate element, take some action
else if (key < current_node->element)
current_node->left = insert(current_node->left, key);
else
current_node->right = insert(current_node->right, key);
return current_node;
}

Related

Simplest binary tree insertion is not working

#include<iostream>
using namespace std;
struct node{
int data;
node *left;
node *right;
node(int value = 0);
};
node::node(int value){
data = value;
left = NULL;
right = NULL;
}
class LinkedList{
public:
node *root;
LinkedList();
bool isEmpty();
void insertInto(int value, node *key);
};
LinkedList::LinkedList(){
root = NULL;
}
bool LinkedList::isEmpty(){
if(root == NULL) return true;
}
void LinkedList::insertInto(int value, node* root){
if (root == NULL)
{
node *n = new node(value);
root = n;
}
else if(value <= root->data){
insertInto(value, root->left);
}
else if(value > root->data){
insertInto(value,root->right);
}
}
int main() {
cout<<"I am gonna write the insertion of a binary tree"<<"\n";
LinkedList sample;
if(sample.isEmpty()) cout<<"THe tree is empty"<<endl; else cout<<"The tree is NOT empty"<<endl;
sample.insertInto(5,sample.root);
if(sample.isEmpty()) cout<<"THe tree is empty"<<endl; else cout<<"The tree is NOT empty"<<endl;
return 1;
}
I have been working on this for quite some time, I dont seem to understand why the result is showing that the tree is empty even after adding the value 5. ALso please give tips on how I can improve. Thanks
Ignoring the comments that I could make about the style/structure of the code you've posted:
void LinkedList::insertInto(int value, node* root){
if (root == NULL)
{
node *n = new node(value);
root = n;
}
You're not passing the node* root variable by reference here. Instead, you're changing a copy of the node* root to point to the new node object you constructed. If you want this code to actually change the value of the sample.root variable that you passed in from the main, you must pass root by reference.
void LinkedList::insertInto(int value, node* &root){
Since LinkedList::insertInto is a member function anyway, why pass in root at all?
You have access to the member variable root, just use that instead. If you still want to be able to use it recursively, you could make a public function with just the value, and have that call a private version that also takes in a node* is a parameter.
Here are some coding style suggestions, since you asked for them:
Best coding practice dictates that you make member variables of your class private, and use public member functions to manipulate your class instead. This is for a variety of different reasons. One explanation is here:
https://softwareengineering.stackexchange.com/questions/143736/why-do-we-need-private-variables
So your class (and let's call it BinaryTree instead), would look something like this:
class BinaryTree{
public:
/* functions */
private:
node *root;
};
So instead of making the user of the class provide the root of the BinaryTree (which doesn't make sense since we know it anyway), we just ask them for the value to insert, and provide the root ourselves.
class BinaryTree{
public:
/* other functions */
void insertInto(int value);
private:
void insertInto(int value, node* &n);
node *root;
};
// Public version of the insertInto function
void insertInto(int value) {
insertInto(value, root);
}
// Private helper function for insertInto
void insertInto(int value, node* &n) {
if (n == NULL)
{
n = new node(value);
}
else if(value <= root->data){
insertInto(value, root->left);
}
else if(value > root->data){
insertInto(value,root->right);
}
}
int main() {
BinaryTree sample;
sample.insertInto(5);
}

(C++) Doubly Linked List Template - Access Problems

I am very new to C++ templates. I am currently working on a project where I need to implement a Doubly Linked List using a template. Here is currently what I have so far:
template<class ItemType>
class SortedList
{
public:
SortedList();
~SortedList();
bool Insert (ItemType toAdd);
bool Delete (ItemType toDelete);
void Print();
private:
SortedList ( const SortedList & copyFrom );
SortedList & operator= ( const SortedList & assignFrom );
struct Node
{
Node ( ItemType item, Node * p = NULL, Node * n = NULL )
{ data = item; prev = p; next = n; }
ItemType data;
Node * prev, * next;
};
Node * list;
};
template<class ItemType>
SortedList<ItemType>::SortedList()
{
list == NULL;
}
template<class ItemType>
SortedList<ItemType>::~SortedList()
{
Node * curr = list;
while ( curr != NULL )
{
Node * tempNext = curr->next;
delete current;
current = tempNext;
}
}
However, in my destructor for example, why can't I access the node elements? The code that is inside that method right now compiled, but does not throw errors. However if I try to use -> on curr, next or prev do not appear. Why do I not have access to these? I feel like I am missing something very obvious here to get started.
Also, how can I initialize list == NULL in the function head, instead of doing it outside of the class?
Don't know why it compiles, but you are using
delete current;
current = tempNext;
Instead of:
delete curr;
curr = tempNext;
Use inline initializer syntax:
class SortedList
{
public:
SortedList()
:
list(nullptr)
{ }
Use the same syntax to initialize Node (it's more optimal)

Class Pointer Losing Members?

I have a binary tree, that I am searching:
TreeNode<Vessel*>* node = this->tree_->search("PotatoFace");
string mystring = node->print();
when I run it, node contains the correct data, but when I go to print that data as soon as I enter:
string TreeNode<T>::print()
{
return data_->toString();
}
'this' (which should be the 'node' and has the same memory address as 'node') has all of its data members including the Vessel* set to null.
Any ideas?
Thank you!
Full Tree Node:
#pragma once
#include <cstring>
#include <fstream>
#include <iostream>
using namespace std;
template <class T>
class TreeNode
{
private:
TreeNode<T>* greaterNode_;
TreeNode<T>* lessNode_;
TreeNode<T>* parentNode_;
TreeNode<T>* getLowest_();
T data_;
public:
TreeNode();
TreeNode(T data);
void add(T data);
bool operator==(const string &rhs);
TreeNode* search(T data);
void seqSearch(string data, TreeNode<T>* node);
void del(TreeNode<T>* root);
void toFile(ofstream& BSTFile);
TreeNode* compare(int sig[4]);
TreeNode* getRoot();
TreeNode* forward(TreeNode<T>* node);
string print();
};
template <class T>
TreeNode<T>::TreeNode(T data)
{
data_ = data;
greaterNode_ = lessNode_ = parentNode_= NULL;
}
template <class T>
TreeNode<T>::TreeNode()
{
}
template <class T>
void TreeNode<T>::seqSearch(string data, TreeNode<T>* node )
{
if(*data_ == data)
{
*node = this->data_;
}
if(this->lessNode_)
{
this->lessNode_->seqSearch(data, node);
}
if(this->greaterNode_)
{
this->greaterNode_->seqSearch(data, node);
}
}
template <class T>
string TreeNode<T>::print()
{
return data_->toString();
}
Still not entirely sure how to explain why it wasn't working, but it was a scope issue, outside the binary tree class tree nodes lost data. Taken out all tree functions that returned nodes and everything works now.
are you sure you wanted to write:
string mystring = node->print();
not
string mystring = hello->print();
If yes, it seems like 'this' of
string mystring = node->print();
is null (node is null). This may have several reasons:
node never gets initialized
node should be set by search("something") but search returns null
It would be really helpful if you paste more code.
Still not entirely sure how to explain why it wasn't working, but it was a scope issue, outside the binary tree class tree nodes lost data.
It was rectified by ensuring that the Binary Tree class doesn't return anything of type TreeNode*, and running whatever other function I wanted once I had the value of the node was done inside the binary tree class. This works now.
Thank you for the help!

Returning a pointer to a struct defined of a class, multiple scope operators

My header file for a basic binary tree includes the following:
template<typename T>
class Btree{
// OVERVIEW: a binary tree with flexible structure that is not sorted
private:
struct node { //a container object
node *left; //left and right tree
node *right;
T *o; // pointer to object of node
};
public:
node *root; //pointer to the root of the tree (NULL if empty)
node* insert (node *parent, T *child, int child);
//MODIFIES: this
//EFFECTS: creates a node that stores a pointer to the new child
// and returns the pointer to the node of the new child
// the integer child is either 0, for left child,
// or anything else for right child
// void printTree (node * root);
//EFFECTS: takes the root of a tree and prints the tree's
// coordinates
Btree(){}; //ctor
Btree(){} //dtor
};
#include "btree.cpp"
My .cpp looks like this, and note that it is included at the bottom of my header to avoid template compiler errors:
template <typename T>
Btree<T> :: node * Btree<T>::insert (node *parent, T *child, int child)
{
node *np = new node;
np-> o = child;
np->left = NULL;
np->right = NULL;
if (child == 0)
parent->left = np;
else
parent->right = np;
return np;
}
however, I get the following compiler error:
btree.cpp:3: error: expected constructor, destructor, or type conversion before ‘*’ token
I'm compiling with g++, version 4.1.2.
Can anyone help?
First of all, your destructor should have a ~ in front of it, so change
Btree(); //ctor
Btree(){} //dtor
to
Btree(); //ctor
~Btree(){} //dtor
Second, you need typename before the return type of insert because it is a dependent type:
template <typename T>
typename Btree<T>::node* Btree<T>::insert(node *parent, T *child, int child)
// ^^^^^^^^ <- needed
{
node *np = new node;
np-> o = child;
np->left = NULL;
np->right = NULL;
if (child == 0)
parent->left = np;
else
parent->right = np;
return np;
}
Also you need to rename one of your arguments, you have two named child.

C++ new pointer from pointer to pointer?

I have a template linkedList that I would like to dynamically create "head" pointers for...
I seem unable to get any syntax to work.. my best guess is:
linkedList<int>** ptr;
ptr = new (linkedList<int>*)[1];
But it doesn't work. I'm fairly new to C++ so any help is appreciated! Thanks!
To get a pointer, do:
T* ptr = new T;
where T is your type.
For a pointer-to-pointer, do:
T** ptrptr = new T*;
allocating the space for one pointer, which still needs to be filled like the first method:
*ptrptr = new T;
Now you got a valid pointer-to-pointer.
Is there some reason you are not using std::list? (or std::forward_list)
Check out the header files for std::list, or your nearest C++ book, or in fact
cppreference.com
Your linked list class template should have a function to return the head of the list. Look at std::list::begin() in your compiler's c++ library. The std::list::iterator type is a pointer to whatever goes in the list. (ie T*)
Though I'm not sure pointer array is really needed for your linked
list, as for just new construct, the following form will be compiled.
ptr = new (linkedList<int>*[1]);
EDIT:
This allocates pointer array:
linkedList<int>** ptr = new (linkedList<int>*[1]);
This allocates array:
linkedList<int>* ptr = new linkedList<int>[1];
This allocates one element:
linkedList<int>* ptr = new linkedList<int>;
Normally the head of a linked list would look something like:
node<int> *head = NULL;
When you want to create and insert a node, you'd use something like:
insert(node<int> *&list, int value) {
// insert new node containing `value` at head of `list`.
node<int> *temp = new node(value);
temp->next = list;
list=temp;
}
You could use this something like:
node<int> *list = NULL;
for (int i=0; i<10; i++)
insert(list, i);
Of course, unless this is for homework (or something on that order), you should stop working on this immediately, and just std::list (or boost::slist, if you want a singly-linked list).
Edit: I'm adding more detail mentioned by the OP in comment. For the moment, the avl_tree::insert does not attempt to maintain balance. It's just a plain-jane un-balanced insert, but it should be adequate to demonstrate what we care about at the moment.
template <class T>
struct linked_list {
node *head;
void insert(T v) {
node<T> *n = new node(v, head);
head = n;
}
linked_list() : head(NULL) {}
template <class T>
struct node {
node *next;
T data;
node(T const &v, node *n=NULL) : data(v), next(n) {}
};
};
template <class keyType, class dataType>
class avl_tree {
struct node {
node *left, *right;
char balance;
keyType key;
dataType data;
node(keyType const &k, dataType const &d)
: left(NULL), right(NULL), balance(0), key(k), data(d)
{ }
bool operator<(node const &other) {
return key < other.key;
}
} *root;
bool insert(node const *new_node, node *&tree) {
if (tree == NULL) {
tree = new_node;
return true;
}
else if (*new_node < *tree)
return insert(new_node, tree->left);
else if (*new_node > *tree)
return insert(new_node, tree->right);
else // new_node == tree
return false; // couldn't insert -- already present.
}
public:
avl_tree() : root(NULL) {}
void insert(keyType const &key, dataType const &data) {
node *temp = new node(key, data);
insert(temp, root);
}
};