Im trying to implement a generic BST using template in c++.
However,
when I use gdb debug it. I find out that the whenever i called InsertNode,
it treat t as NULL.
When I step through the insertFunction, It runs correctly.
Is there any problem for declaration of tree when using template.
//
// main.cpp
// c++_project
//
// Created by Timothy Leung on 5/5/13.
// Copyright 2013 __MyCompanyName__. All rights reserved.
//
#include <iostream>
using namespace std;
template <typename data_t>
struct nodeT{
data_t data;
nodeT *left, *right;
};
template <typename data_t>
nodeT<data_t> *FindNode(nodeT<data_t> *t, data_t data);
template <typename data_t>
void InsertNode(nodeT<data_t> *t, data_t data);
template <typename data_t>
void display_tree(nodeT<data_t> *t);
int main (int argc, const char * argv[])
{
cout << "Welcome to my BST! " << endl;
nodeT<int> *tree;
cout << "How many items do you have? \n";
int num, temp;
cin >> num;
for (int i=0; i<num; ++i) {
cout << "Number please :) \n";
cin >> temp;
InsertNode(tree, temp);
}
cout << "In order treeeeeee \n"<<endl;
display_tree(tree);
}
template <typename data_t>
nodeT<data_t> *FindNode(nodeT<data_t> *t, data_t data){
if(t==NULL) return NULL;
if(data==t->data) return t;
if (data < t->data) {
FindNode(t->left, data);
} else
FindNode(t->right, data);
}
template <typename data_t>
void InsertNode(nodeT<data_t> *t, data_t data){
if(t==NULL){
t = new nodeT<data_t>;
t->data = data;
t->left = NULL;
t->right = NULL;
return;
}
if(t->data < data){
InsertNode(t->right, data);
} else
InsertNode(t->left, data);
}
template <typename data_t>
void display_tree(nodeT<data_t> *t){
if (t!=NULL) {
display_tree(t->left);
cout << t->data << endl;
display_tree(t->right);
}
}
InsertNode(tree, temp); passes tree by value, which means the changes you make occur a copy of tree that was set to its same value. It's the same reason that if you were to change data in the function, you would not be changing temp.
You either need to change InsertNode to take a reference or double pointer (so you pass by reference/address so the changes to the node are made obvious), or change InsertNode to return the newly created node (and assign it to tree (but make sure you only assign it the first time)).
When you invoke insertNode(t->right and t->left...), the right and left are always null.
You should create an instance for them first, like this:
t->right = new nodeT<data_t>;
insertNode(t->right,data);
Related
Code for Reversing Linked List with Recursion, using STL
#include<iostream>
#include<conio.h>
#include<list>
using namespace std;
template<typename T>
class node
{
public:
T data;
node<T> *next;
node(){ next = NULL; }
node(const T& item, node<T> *nextnode = NULL)
{
data = item;
next = nextnode;
}
};
template<typename T>
class Reverse_list
{
private:
node<T> *head;
void reverse(node<T> *front);
public:
Reverse_list(){ head = NULL; }
//template<typename T>
void Reverse();
template<typename T>
void Display( list<T>& alist );
};
int main()
{
Reverse_list <int> rl;
list<int> intlist;
int size, no;
cout << "Size of List ?? ";
cin >> size;
for (int i = 1; i <= size; i++)
{
cout << "Enter the " << i <<" "<< "element";
cin >> no;
intlist.push_front(no);
}
rl.Display(intlist);
rl.Reverse();
rl.Display(intlist);
_getch();
return 0;
}
template<typename T>
void Reverse_list<T>::Display(list<T>& alist)
{
list<int>::iterator iter = alist.begin();
while (iter != alist.end())
{
cout << *iter << " ";
iter++;
}
}
template<typename T>
void Reverse_list<T>::reverse(node<T> *front)
{
if (front->next == NULL)
{
head = front;
return;
}
reverse(front->next);
node<int> *back = front->next;
back->next = front;
front->next = NULL;
}
template<typename T>
void Reverse_list<T>::Reverse()
{
reverse(head);
}
The above code generates 2 errors.
Error 1) No instance of function template matches the argument list. ( No error number.)
If I remove line 1 ( mentioned in a code ) then above error is no more. ( Why? )
Error 2) C2783: 'void Reverse_list::Reverse1(void)' : could not deduce template argument for 'T'
How to solve above errors.
In above program , I wanted to pass " head" node ( which is private ) as
argument to Reverse function. But we can not access private member outside of the class. So I passed indirectly. Is this a correct way of passing ?? Or there is some other way of accessing private data ??
I'm not sure to understand your intentions but...
You're trying to declare a method (reverse()) inside another method (Reverse()) ? Uhmmm....
We return to this later.
Imagine that the following instruction is correct instruction of Reverse_list<T>::Reverse()
node<T> *back = front->next;
Why you declare back as a pointer to a generic Node<T> when you assign front->next (so a specific Node<int>) to it?
If you define back as a node<int> pointer, the method Reverse() has no longer reason to be a template (dependant from T) method. And you can avoid both errors.
With your actual code, when you call
rl.Reverse();
you call a template method but the compiler doesn't know how to determine the type T. You could explicit it in this way
rl.Reverse<int>();
but, as written before, I thik it's better if you remove the whole template part.
Or, alternatively, you can transform the whole class in a template class; where head is a pointer to a generic Node<T>, not a specifica Node<int>.
Something like (if I understand correctly your intentions)
template <typename T>
class Reverse_list
{
private:
node<T> *head;
void reverse (node<T> * front);
public:
Reverse_list() : head(NULL)
{ }
void Reverse();
void Display(list<T>& alist);
};
template<typename T>
void Reverse_list<T>::reverse (node<T> * front)
{
if (front->next == NULL)
{
head = front;
return;
}
reverse(front->next);
node<T> *back = front->next;
back->next = front;
front->next = NULL;
}
template<typename T>
void Reverse_list<T>::Reverse()
{ reverse(head); }
In this case, in main(), rl should be declared as
Reverse_list<int> rl;
fixing T as int, and the call to Reverse() should be
rl.Reverse();
--- EDIT 2016.05.10 ---
With the "template Reverse_list" solution, you should correct three points (at last).
1) in Reverse_list class declaration, you have commented the template<typename T> row before void Reverse(); good; you should delete (comment) the same line (for the same reason) before void Display( list<T>& alist );; so the class become
template<typename T>
class Reverse_list
{
private:
node<T> *head;
void reverse(node<T> *front);
public:
Reverse_list(){ head = NULL; }
//template<typename T>
void Reverse();
//template<typename T>
void Display( list<T>& alist );
};
2) Display() now is a method of a templated class; so the line
list<int>::iterator iter = alist.begin();
become
list<T>::iterator iter = alist.begin();
3) reverse() now is a method of a templated class; so the line
node<int> *back = front->next;
become
node<T> *back = front->next;
I'm new to working with class templates and am simply trying to define a temporary node 'temp' in a class associated with the Linked List, which sets the string that the node stores to some temporary string that is created in the function TowerHanoi::set_Discs(size_t disc) via user input. When I call the function temp->set_data(tmp_str) i get a segmentation fault. I tried calling temp->set_data("hello"); on its own and i still get the error.
I'm not sure what's going on here and i've tried researching into it but to no avail. I'm probably missing something obvious, but i'm just quite lost now. Let me know if you need more code. Thanks.
TowerHanoi.cpp:
#include "TowerHanoi.h"
#include <iostream>
#include <cstdlib>
using namespace std;
using oreilly_A2::node;
namespace oreilly_A2 {
TowerHanoi::TowerHanoi() {
for (int i=0;i<2;i++) {
rod[i] = LStack<node<std::string> >();
}
}
TowerHanoi::TowerHanoi(size_t numDiscs) {
for (int i=0; i < 2; i++) {
rod[i] = LStack<node<string> >();
}
discs = numDiscs;
}
void TowerHanoi::set_Discs(size_t disc) {
node<string>* temp=NULL;
while (disc != 0) {
string tmp_str;
for (size_t i=0; i<disc; i++) {
tmp_str.append("x");
}
disc--;
temp->set_data(tmp_str);
rod[0].push(temp);
}
void TowerHanoi::print_Game() {
for (size_t s=1; s<discs; s++) {
cout << " ";
for (size_t o=1; o<discs-s;o++) {
cout << " ";
}
//cout << tmp_node->data() << endl;
cout << "x" << endl;
}
}
}
node.h file:
#ifndef NODE_CAMERON_H
#define NODE_CAMERON_H
#include <string>
namespace oreilly_A2 {
template <typename Item>
class node {
public:
node(); //constructor for node
node(const Item val, node* newNext); //constructor with parameters
~node(); //destructor
void set_data(Item new_data); //set the word that this node contains
void set_link(node* new_link); //set the 'next' node
void set_previous(node* new_prev);
Item data() const; //return this node's word
const node* link() const; //return next
const node* back() const;
node* link(); //return next
node* back();
private:
node* next; //the next node
node* previous;
Item word; //the word this node contains
};
}
#include "Node.template"
#endif
node.template file:
namespace oreilly_A2 {
template <typename Item>
node<Item>::node() {
next=NULL;
previous=NULL;
}
//Node.template
template <typename Item>
node<Item>::node(const Item val, node* newNext=NULL) {
word = val;
next = newNext;
}
template <typename Item>
node<Item>::~node() {
delete next;
delete previous;
delete word;
}
template <typename Item>
void node<Item>::set_data(Item new_data){
word = new_data;
}
template <typename Item>
void node<Item>::set_link(node* new_link){
next = new_link;
}
template <typename Item>
void node<Item>::set_previous(node* new_back) {
previous = new_back;
}
template <typename Item>
Item node<Item>::data() const { //return the word
return word;
}
template <typename Item>
const node<Item>* node<Item>::link() const { //return next node (const function)
return next;
}
template <typename Item>
const node<Item>* node<Item>::back() const { //return previous node (const)
return previous;
}
template <typename Item>
node<Item>* node<Item>::link() {
return next; //return next node (non-const)
}
template <typename Item>
node<Item>* node<Item>::back() { //return previous node (const)
return previous;
}
}
Unless I have missed something the temp variable is NULL at the time of calling set_data. As any regular object you need to first initialized it.
node<string>* temp=new node<string>();
And then freeing it when appropriate to avoid memory leaks.
This is not the case with temp_str because the later is not a pointer, it's a value so it gets initialized automatically (and also freed automatically when it gets out of scope).
You have initialized temp as NULL. So when you are trying to do temp->set_data(tmp_str); you are actually trying to access NULL pointers.
All you need to do is initialize temp. I have correct the code below
void TowerHanoi::set_Discs(size_t disc) {
node<string>* temp=new node<string>();
while (disc != 0) {
string tmp_str;
for (size_t i=0; i<disc; i++) {
tmp_str.append("x");
}
disc--;
temp->set_data(tmp_str);
rod[0].push(temp);
}
To avoid memory leak you need to delete all the memory allocated after you are done.
Here is a cut-down version of a template List code (adapted from http://www.daniweb.com/software-development/cpp/threads/237391/c-template-linked-list-help)
List complains (compile error) that "Node is not a type". Why is this, and what is the fix?
I tried replacing the "class Node" with a "struct Node" (and related changes), and the struct version worked fine. So the main question seems to be: how does a template-class access another template-class?
#include <iostream>
using namespace std;
template <typename T>
class Node
{
public:
Node(){}
Node(T theData, Node<T>* theLink) : data(theData), link(theLink){}
Node<T>* getLink( ) const { return link; }
const T getData( ) const { return data; }
void setData(const T& theData) { data = theData; }
void setLink(Node<T>* pointer) { link = pointer; }
private:
T data;
Node<T> *link;
};
template <typename T>
class List {
public:
List() {
first = NULL;
last = NULL;
count = 0;
}
void insertFirst(const T& newData) {
first = new Node(newData, first);
++count;
}
void printList() {
Node<T> *tempt;
tempt = first;
while(tempt != NULL){
cout << tempt->getData() << " ";
tempt = tempt->getLink();
}
}
~List() { }
private:
Node<T> *first;
Node<T> *last;
int count;
};
int main() {
List<int> myIntList;
cout << "Inserting 1 in the list...\n";
myIntList.insertFirst(1);
myIntList.printList();
cout << endl;
List<double> myDoubleList;
cout << "Inserting 1.5 in the list...\n";
myDoubleList.insertFirst(1.5);
myDoubleList.printList();
cout << endl;
}
You are using
new Node(newData, first);
within the List template. At that point, Node does not refer to a type, but to a template. But of course to create an instance of a type with new, you need a type there.
The most probable thing you want to do is to make it a type by instantiating the template, i.e.
new Node<T>(newData, first);
I was using eclipse to code up a queue, one function called getFirst is defined as:
template<class T>
T getFirst(){
return head->data;
}
in the main, after declaring the queue Q and input some valid data like:
Queue<int> Q;
Q.add(2);
cout << Q.getFirst() << endl;
The output is 2, which is just what I desired;
But!!! If I change the code to:
Queue<int> Q;
Q.add(2);
cout << Q.getFirst() << endl;
cout << Q.getFirst() << endl;
the output is not:
2
2
but something like:
2
2657382
after a few thoughts, I modified the code to:
Queue<int> Q;
Q.add(2);
cout << Q.getFirst();
cout << Q.getFirst() << endl;
this time it worked!! Just fine!! the output is 22, which make sense.
Can anybody kindly explain to me the problem here?
The definition of Node and Queue is generic and general :
template<typename T>
class Node{
public:
Node(T data, Node* left = 0, Node* right = 0): _data(data), _left(left), _right(right){
if(left)
left->_right = this;
if(right)
right->_left = this;
}
Node(): _right(0){}
private:
T _data;
Node<T>* _left;
Node<T>* _right;
friend class Queque<T>;
};
template<typename T>
class Queque{
public:
Queque(): _first(new Node<T>), _size(0){
_first->_right = _first;
_first->_left = _first;
}
void addFirst(T item){
Node<T>(item, _first, _first->_right);
_size++;
}
T examineFirst(){
return _first->_right->_data;
}
private:
Node<T>* const _first;
int _size;
};
void addFirst(T item){
Node<T>(item, _first, _first->_right);
_size++;
}
Node is a stack variable, and it's constructor will change _first, and first->_right to be pointing to some stack address, which will lead for unpredicted results, in your example usage << endl; modified stack, leading to some garbage output. To fix this you need to use new for new nodes allocation and, of course free them later with delete.
$ I have the following error:
44 E:\Assignment 2.cpp no match for 'operator<<' in 'std::cout < (&number)->newstack::push(x)'
$ I'm using a linked list to put numbers in a class stack that contains a struct. The stack that contains these numbers are printed out. But the error will not allow me to print them out.
#include <iostream>
using namespace std;
typedef int itemType;
class newstack
{
private:
Using a struct of nodes which contains a item and pointer to the next node.
struct node
{
itemType item;
node *next;
};
node *top; //pointer to the top node.
public:
void push(itemType newItem); //adds items to newstack
};
int main()
{
newstack number;
int x;
cout<< "Number Stack" <<endl;
for (x=0;x<=9;x++)
cout<<(number).push(x)<<endl; //ERROR LINE
//Takes 9 integers and adds them to the stack by printing them out.
return 0;
}
void newstack::push(itemType newItem)
// Precondition: Stack is empty.
//Postcondition: Stack contains a itemType at the top and list or stack implements by 1.
{
if(top!=NULL)
node *newTop;
newTop=new node;
(*newTop).item=newItem;
(*newTop).next=top;
top=newTop;
}
IN your push() function you are returning Void.
Yet you try and write the value the function returns
to the command prompt - either change your push function
to return a value or cout << stack.pop();
Further On:
You need to overload the << operator for your newstack class to be able to write something like:
newstack obj;
cout<<obj;
<< is overloaded for only built-in data types not custom class types.
You need to overload it something like this:
std::ostream& operator<<(std::ostream& os, const newstack& obj);
cout<<(number).push(x)<<endl;
First, you don't need the () around number
cout << number.push(x) << endl;
That still won't work, because newstack::push returns void.
Either change newstack::push to return the value added, or print the number in a separate step.
See The Following
#include <iostream>
using namespace std;
//Defenitions
template <class T>
struct Node
{
T DataMember;
Node* Next;
};
template <class T>
class NCA
{
public:
NCA();
~NCA();
void push(T);
T pop();
void print();
void Clear();
private:
Node<T>* Head;
void* operator new(unsigned int);
};
//Imp.
template <class T>
NCA<T>::NCA()
{
Head = NULL;
}
template <class T>
NCA<T>::~NCA()
{
Clear();
}
template <class T>
void NCA<T>::push(T value)
{
Node<T>* Temp = new Node<T>;
Temp->DataMember = value;
Temp->Next = Head;
Head = Temp;
}
template <class T>
T NCA<T>::pop()
{
Node<T>* n;
T i;
n = Head->Next;
i = Head->DataMember;
delete Head;
Head = n;
return i;
}
template <class T>
void NCA<T>::print()
{
Node<T>* MockHead = Head;
while (MockHead != NULL)
{
cout << MockHead->DataMember;
MockHead = MockHead->Next;
}
}
template <class T>
void NCA<T>::Clear()
{
while(Head != NULL)
pop();
}
//Main Execution
int main()
{
NCA<char> Array;
Array.push('c');
cout << Array.pop();
return 0;
}
You haven't override the operator << for your newstack which is causing the error. If you printed x, then did the push afterwards, you wouldn't receive an error. If you want cout to be able to print your stack you need to define HOW the << operator works.
The real problem here is how you're expecting your code to work. First, push shouldn't return a value to begin with, that's not how a stack works. You could implement pop which would pop off and return the top value of the stack, however then you're losing that value. You need to implement peek. Because this is homework I wont give you a direct answer on how to write peek but this should be a better way of executing your code.
for (x=0; x<=9; x++)
{
number.push(x);
cout << number.peek() << endl;
}