I'm trying to create simple stack using linked lists in C++. Suddenly I encountered the problem which is (I think) connected with templates. I lack knowledge in that structures thats why I tried to create something and learn with it.
My problem is with node * top; what should I change ? any idea?
My code is :
#include <iostream>
#include <cstdlib>
using namespace std;
template<typename T>
class node {
public:
T object;
node * next;
};
node *top = NULL;
template<typename T>
class Stack{
public:
void push(T obj);
void pop();
void display(ostream & out) const;
};
void Stack :: push(T obj){
node * tempNode = new node;
tempNode->object = obj;
tempNode->next = top;
top = tempNode;
}
void Stack :: display(ostream & out) const{
if(top == NULL){
cout << "Stack is Empty"<<endl;
return;
}
else{
node *temp = top;
while(temp!=NULL){
cout << "Here is your elements :"<<"\n";
cout << temp->object<<endl;
temp = temp->next;
}
cout <<endl;
}
}
void Stack :: pop(){
if (top = NULL){
cout << "List is Empty"<<endl;
return;
}
cout << "Your object: "<<top->object << " is removed"<<endl;
top = top->next;
}
ostream & operator << (ostream & out, const Stack & s){
s.display(out);
return out;
}
I'm guessing top should be a member of Stack not a global variable? You also need to specify the template type of node:
template<typename T>
class Stack{
node<T> *top = NULL;
public:
void push(T obj);
void pop();
void display(ostream & out) const;
};
When defining methods of templated classes out of line you need to specify the template type for the class:
template<typename T>
void Stack<T> :: push(T obj){
Your << operator also needs to be a template:
template<typename T>
ostream & operator << (ostream & out, const Stack<T> & s){
s.display(out);
return out;
}
Related
I am trying to learn data structures and I started with single linked list. I am first trying to just memorize and understand the code that Walter Savitch provided in Ch.13 of Absolute C++. I am having some trouble using the interface that the author designed for a single linked list. Specifically, I understand the code but I do not understand how to use the interface to create a single linked list in terms of the syntax needed.
Here is the interface:
#ifndef LinkedList_hpp
#define LinkedList_hpp
namespace LinkedList {
template<class T>
class Node {
private:
T data;
Node<T> *link;
public:
Node(const T& theData, Node<T>* theLink) : data(theData), link(theLink) {}
Node<T>* getLink() {return link;}
const T getData() const {return data;}
void setData(const T& theData) {data = theData;}
void setLink(Node<T>* pointer) {link = pointer;}
};
template<class T>
void headInsert(Node<T>*& head, const T& theData) {
head = new Node<T>(theData, head);
}
template<class T>
void insert(Node<T>* next, const T& theData) {
next->setLink(new Node<T>(theData, next->getLink( )));
}
template<class T>
void deleteNode(Node<T>* before) {
Node<T>* discard;
discard = before->getLink();
before->setLink(discard->getLink( ));
delete discard;
}
template<class T>
void deleteFirstNode(Node<T>*& head) {
Node<T>* discard;
discard = head;
head = head->getLink();
delete discard;
}
template<class T>
Node<T>* search(Node<T>* head, const T& target) {
Node<T>* here = head;
if(here == nullptr) {
return nullptr;
}
else {
while(here->getData() != target && here->getLink() != nullptr)
here = here->getLink();
if(here->getData() == target)
return here;
else
return nullptr;
}
}
}
#endif /* LinkedList_hpp */
Now I am trying to just use the interface to create a single linked list. But I am having some trouble. Here is how far I have gone.
#include <iostream>
#include "LinkedList.hpp"
using namespace LinkedList;
int main(int argc, const char * argv[]) {
Node<int> test(2,nullptr);
return 0;
}
Can anyone help me just show me what I need to write into the int main() body to create a single linked list and perhaps print its contents? Just for ease of simplicity I want to try to make a single linked list look like this:
Here's how that interface could be accessed:
Node<int> node(20,nullptr);
Node<int> *head = &node;
insert(head, 30);
prnt(head);
std::cout << "Searching for 10..." << search(head, 10) << std::endl;
headInsert(head, 10);
std::cout << "Searching for 10..." << search(head, 10) << std::endl;
prnt(head);
deleteFirstNode(head);
prnt(head);
deleteNode(head);
prnt(head);
Included is prnt method, which traverses the current list from the head until it finds a nullptr, printing the data at each node and helps demonstrate what each method does. The method is as follows:
template<class T>
void prnt(Node<T>* head) {
for (; head->getLink(); head=head->getLink()){
std::cout << head->getData() << " -> ";
}
std::cout << head->getData() << std::endl;
}
I'm trying to create a class template for a link-list implementation of a Stack. Now I've gotten the push, pop, peek, and tested the destructor. But I'm wondering how should I add the copy constructor, overloaded assignment operator, and the deepCopy on my code. Here is what I got so far:
// Lab3.cpp
//
// Created by IvanChak on 4/3/16.
// Copyright © 2016 Space. All rights reserved.
#include <iostream>
using namespace std;
template<class T>
struct Node {
T item;
Node* next = NULL;
Node(T t = {}, Node* link = nullptr) :item{t}, next{link} { }
~Node() { delete next; }
};
template<class T>
class Stack {
public:
bool empty() const { return n == 0; }
void push(const T&);
T pop();
T peek();
~Stack();
private:
Node<T>* top = NULL;
size_t n;
};
template <class T>
class A
{
public:
A(const A &){}
A & operator=(const A& a){return *this;}
};
template<class T>
Stack<T>::~Stack() {
cout<<"Destructor, deallocate..."<<endl;
}
template<class T>
void Stack<T>::push(const T& t) {
Node<T>* previous{top};
top = new Node<T>{t,previous};
++n;
}
template<class T>
T Stack<T>::pop() {
if (empty()) {
cout << "Empty" << endl;
}
Node<T>* oldnode = top;
T t = top->item;
top = top->next;
--n;
delete oldnode;
return t;
}
template<class T>
T Stack<T>::peek() {
if (empty()) {
cout << "Empty" << endl;
}
return top->item;
}
int main(int argc, const char * argv[]) {
Stack<string> x{};
x.push("Hello");
x.push("Second");
x.push("Bye");
cout << x.peek() << endl;
x.pop();
cout << x.peek() << endl;
}
I don't know if you still need an answer or not, but if you do, you would want something like this for you copy constructor and your assignment operator:
template<class T>
Stack<T>::Stack(const Stack<T>& rhs)
{
if (rhs.top)
{
this->top = new Node<T>(rhs.top->item);
Node<T>* rhsNode = rhs.top; // This pointer is used for iterating through the "rhs" argument.
Node<T>* currentNode = this->top; // This pointer is used for iterating through "this".
n = 1;
while (rhsNode->next) // Loop untill the end of the stack has been reached.
{
++n;
currentNode->next = new Node<T>(rhsNode->next->item);
currentNode = currentNode->next;
rhsNode = rhsNode->next;
}
}
else // "rhs" is empty
{
n = 0;
this->top = nullptr;
}
}
Note: I wrote this code in a "deep copy" fashion. I can't think of any situation where it would be good to do a "shallow copy" on this type of data structure; in fact, I think it would be a very bad idea to do so. I don't automatically assume that you are planning on making your copy constructor do a "shallow copy" on your stack, but since you named the copy constructor and something about "deep copying" separately, I see it as entirely possible that you are.
I tested this code, and it worked.
I'm trying to make a custom set of header files to use a generic List and use operator<< to make it print into a ostream object
There are a couple of errors which I cannot resolve.
I'm trying to make a generic List class using a generic Node class. The generic List should be printed using the operator<< . However I'm getting a lot of errors.
#include <iostream>
using std::cout;
using std::ostream;
class List;
template<class T>
class Node
{
friend class List<Node>;
private:
T data_;
Node *next_;
public:
Node(T data);
T get_data();
};
template<typename T>
Node<T>::Node(T data)
{
data_ = data;
next_ = 0;
}
template<typename T>
T Node<T>::get_data()
{
return data_;
}
template<typename T>
class Node;
template<typename T>
class List
{
template<typename T>
friend ostream& operator<<(ostream& o , const List<T> head);
private:
Node<T> *start_;
bool is_empty();
public:
List();
~List();
void insert(T data);
void remove();
};
template<typename T>
bool List<T>::is_empty()
{
if(start_ == 0)
return true;
return false;
}
template<typename T>
List<T>::List()
{
start_ = 0;
}
template<typename T>
List<T>::~List()
{
if( !is_empty())
{
Node<T> *current = start_;
Node<T> *temp;
while(current != 0)
{
temp = current;
current = current->next_;
delete temp;
}
}
}
template<typename T>
void List<T>::insert(T data)
{
if(is_empty())
{
Node<T> *temp = new Node<T>(data);
start_ = temp;
}
else
{
Node<T> *temp = start_;
while(temp->next_ != 0)
{
temp = temp->next_;
}
temp->next_ = new Node<T>(data);
}
}
template<typename T>
void List<T>::remove()
{
if(start_->next_ == 0)
{
Node<T> *temp = start_->next_;
start_->next_ = 0;
delete temp;
}
else if(!is_empty())
{
Node<T> *stay = start_;
Node<T> *remove = stay->next_;
while(remove->next_ != 0)
{
stay = remove;
remove = remove->next_;
}
stay->next_ = 0;
delete remove;
}
}
// Experimental Stuff out here
template<typename T>
ostream& operator<<(ostream& o , const List<T> *head)
{
Node<T> *temp = head->start_;
if(!is_empty<T>())
{
while(temp->next_ != 0)
{
o << temp.get_data() << "\t";
o << "\n";
temp = temp->next_;
}
}
return o;
}
// End of Experimental Stuff
Assuming clients of your class instantiate it like this:
List<int> my_list;
You need to define your operator << overload like this:
template <typename T>
std::ostream& operator << (std::ostream& os, const List<T>& list)
{
// I'm gonna assume you have C++11
auto node = list.start_;
while (node != nullptr)
{
os << '\t' << node->get_data() << '\n';
node = node->next_;
}
return os;
}
Additionally, there are loads of errors in your code regarding templates, so please fix them first.
I cannot use std::list. The goal is to create a user defined MyList that can handle any data type. My problem is with my nested iterator class and possibly my function for overloading operator<<. I have been at this for awhile and I am stuck. Since the deadline is pretty close, I figure that I should risk my neck and ask the question here. It will be great if someone can assist me with this.
I realized that there are memory leaks in my code, but thats not my main concern at the moment.
I also realized that having so many friend function is not a good programming practice, I am planning to use getData() and setData() function to get/set the private variable within node later.
So please overlook the above 2 problems...
Error message:
"MyList.h", line 67: Error: iterator is not defined.
I'll include the whole header file just so that in case people need to see it. I'll include a comment at line 67 where the error is. Then I'll also include a section of my main function that uses the iterator to show how I am trying to set the iterator and iterate through the list.
#include<iostream>
#include<cstddef>
template<class T>
class Node
{
friend void MyList<T>::push_front(T aData);
friend void MyList<T>::push_back(T aData);
friend void MyList<T>::pop_front();
friend T MyList<T>::front();
friend void MyList<T>::print();
friend MyList<T>::~MyList();
friend std::ostream& operator<<(std::ostream&, Node<T>&);
private:
T data;
Node *next;
Node *prev;
public:
Node(T aData);
};
template<class T>
class MyList
{
Node<T> *head;
Node<T> *tail;
public:
MyList();
~MyList();
void push_front(T aData);
void push_back(T aData);
T front();
void pop_front();
void operator=(MyList<T>& another_List);
void print(); //Test function. Delete later.
class iterator
{
private:
MyList& object;
Node<T> *current;
public:
iterator(MyList<T>&, Node<T>*); // iterator a(*this, head);
// MyList<int>::iterator a = list.Begin();
iterator operator++(); // a++
iterator operator++(int); // ++a
iterator operator--();
bool operator!=(iterator);
friend std::ostream& operator<<(std::ostream&, iterator&);
};
iterator Begin();
iterator End();
};
template<class T>
std::ostream& operator<<(std::ostream& out, Node<T>& n)
{
out << *n.current << ' ';
return out;
}
template<class T>
std::ostream& operator<<(std::ostream& out, iterator& i) //ERROR
{
out << i->current << ' ';
return out;
}
template<class T>
Node<T>::Node(T aData)
{
data = aData;
}
template<class T>
MyList<T>::MyList()
{
head = NULL;
}
template<class T>
MyList<T>::~MyList()
{
Node<T> *temp;
while(head != NULL)
{
temp = head;
head = head->next;
delete temp;
}
head = NULL;
}
template<class T>
void MyList<T>::push_front(T aData)
{
if(head == NULL)
{
head = new Node<T>(aData);
head->next = tail;
head->prev = NULL;
tail->prev = head;
}
else
{
head->prev = new Node<T>(aData);
head->prev->prev = NULL;
head->prev->next = head;
head = head->prev;
}
}
template<class T>
void MyList<T>::push_back(T aData)
{
if(head == NULL)
{
head = new Node<T>(aData);
head->prev = NULL;
head->next = tail;
tail->prev = head;
}
else
{
tail->prev->next = new Node<T>(aData);
tail->prev->next->prev = tail->prev;
tail->prev->next->next = tail;
tail->prev = tail->prev->next;
}
}
template<class T>
T MyList<T>::front()
{
return head->data;
}
template<class T>
void MyList<T>::pop_front()
{
if(head == NULL)
std::cout << "The List is empty!" << endl;
else
{
head = head->next;
head->prev = NULL;
}
}
template<class T>
void MyList<T>::print()
{
while(head != NULL)
{
std::cout << "Test print function" << std::endl;
std::cout << '[' << head->data << ']' << std::endl;
head = head->next;
}
std::cout << "End of test print function" << std::endl;
}
template<class T>
MyList<T>::iterator::iterator(MyList<T>& list, Node<T>* p)
{
object = list;
current = p;
}
template<class T>
typename MyList<T>::iterator MyList<T>::iterator::operator++()
{
if(current == object.tail)
{
}
else
current = current->next;
return this;
}
template<class T>
typename MyList<T>::iterator MyList<T>::iterator::operator++(int)
{
if(current == object.tail)
{
}
else
current = current->next;
return this->prev;
}
template<class T>
typename MyList<T>::iterator MyList<T>::iterator::operator--()
{
if(current == object.head)
{
}
else
current = current->prev;
return this;
}
template<class T>
bool MyList<T>::iterator::operator!=(iterator b)
{
return (this.current == b.current);
}
template<class T>
typename MyList<T>::iterator MyList<T>::Begin()
{
return iterator(object, head);
}
template<class T>
typename MyList<T>::iterator MyList<T>::End()
{
return iterator(object, tail);
}
main.cpp
MyList<int>::iterator i = aList.Begin();
while(i != aList.End())
{
cout << i;
i++;
}
Since the definition of your iterator class is nested inside the definition of your MyList class template, for all code outside out MyList, its name is MyList<whatever>::iterator.
Perhaps you intended something slightly different in the code that contains the error though. While you've defined it as a template:
template<class T>
std::ostream& operator<<(std::ostream& out, iterator& i) //ERROR
{
out << i->current << ' ';
return out;
}
You don't seem to be using its template parameter (T) at all. Perhaps you really intended something more like:
template<class iterator>
std::ostream& operator<<(std::ostream& out, iterator& i) //ERROR
{
out << i->current << ' ';
return out;
}
In this case you don't need to supply a qualifier, since the iterator here is just referring to the template parameter. When you use this, the compiler will normally deduce the type of the iterator you actually pass.
Note that it's unnecessary but somewhat traditional to specify the iterator category in a template parameter like this, so you'd typically use something like OutIterator instead of just iterator for the template parameter.
This isn't really very generic though -- in particular, the ->current means it'll only really work for your specific iterator type. More typical code would overload operator * for the iterator type, so client code will just dereference the iterator. Also note that iterators are normally assumed to be "lightweight" enough that they're normally passed by value, not by reference.
class iterator {
// ...
T operator*() { return *current; }
};
// ...
template<class OutIt>
std::ostream& operator<<(std::ostream& out, OutIt i)
{
out << *i << ' ';
return out;
}
Here's a template (queue) I'm trying to write:
#include <iostream>
using namespace std;
template <typename T>
class Queue
{
friend ostream& operator<< (ostream &, const Queue<T> & );
private:
template<class> class Node;
Node<T> *front;
Node<T> *back;
public:
Queue() : front(0), back(0) {}
~Queue();
bool Empty()
{
return front == 0;
}
void Push(const T& NewEl)
{
Node<T&> *El = new Node<T> (NewEl);
if (Empty())
front=back=El;
else
{
back-> next = El;
back = El;
}
}
void Pop()
{
if (Empty())
cout << "Очередь пуста." << endl;
else
{
Node<T> *El = front;
front = front -> next;
delete El;
}
}
void Clear()
{
while (! Empty())
Pop();
}
};
template <typename T>
class Node
{
friend class Queue<T>;
public:
Node() {next = 0;}
Node(T nd) {nd=node; next=0;}
T& getsetnode(){return node;}
Node<T>*& getsetnext(){return next;}
private:
T front;
T back;
T node;
Node<T> *next;
};
template <class T> ostream& operator<< (ostream &, const Queue<T> & );
int main()
{
Queue<int> *queueInt = new Queue<int>;
for (int i = 0; i<10; i++)
{
queueInt->Push(i);
cout << "Pushed " << i << endl;
}
if (!queueInt->Empty())
{
queueInt->Pop();
cout << "Pop" << endl;
}
queueInt->Front();
queueInt->Back();
queueInt->Clear();
cout << "Clear" << endl;
return 0;
}
At these lines:
Node<T&> *El = new Node<T> (NewEl);
front = front -> next;
delete El;
I get Implicit instantiation of undefined template 'Queue<int>::Node<int>'. What am I doing wrong? After reading this post I tried changing int to const int to see if that was the problem, but apparently it isn't, because I get the same error.
I'm using XCode with LLVM compiler 4.2. When I switch to GCC I get more errors:
template<class> class Node; gets Declaration of 'struct Queue<int>::Node<int>',
Node<T&> *El = new Node<T> (NewEl); gets Invalid use of incomplete type,
and anything dealing with assignment of anything to El can't convert <int&>* to <int>* (but deleting reference doesn't change anything for LLVM).
template <typename T>
class Queue
{
private:
template<class> class Node;
/* ... */
This is a forward declaration of Queue::Node. The latter defined class Node is in the global namespace, so they aren't the same and any usage of Queue::Node will result in an incomplete-type error. Since you don't provide an interface to the interior nodes anyway just scrap the global definition of Node and stick it into Queue:
template <typename T>
class Queue
{
private:
class Node
{
public:
Node() {next = 0;}
/* ... */
};
/* ... */
};