We were instructed to implement a class that uses a vector to store a queue. I came up with the following but it's not really working. Can anyone tell me what went wrong?
The values of the numbers are correctly pushed into the vec, and the first pop() works. But if I check head->getElement(), it gives a strange number. Subsequent calls to pop() also fail.
#include <iostream>
#include <vector>
using namespace std;
template<class T>
class node{
T element;
node* next;
public:
node(): next(nullptr){};
T getElement() {return element;}
void setElement(T newElement) {element=newElement;}
node* getNext() {return next;}
void setNext(node* newNext) {next = newNext;}
};
template<class T>
class queue{
vector<node<T>> vec;
node<T>* head;
int size;
public:
queue(): head(nullptr){}
void push(node<T> newNode);
node<T> pop();
int getSize() {return unsigned(vec.size());}
vector<T> getVec()const {return vec;}
node<T>* getHead() {return head;}
void setHead(node<T>* newHead) {head = newHead;}
vector<node<T>> getVec() {return vec;}
};
int main() {
queue<int> v;
for (int i=0;i<5;i++){
node<int>* newNode = new node<int>;
newNode->setElement(i);
v.push(*newNode);
}
cout<<"The elements in the vector are initially:\n";
for (int i=0; i<v.getSize();i++)
cout<<v.getVec()[i].getElement()<<" ";
cout<<"\nAfter popping, the popped element is "<<v.pop().getElement()<<endl;
}
template<class T>
node<T> queue<T>:: pop(){
node<T>* tmp = new node<T>;
tmp->setNext(head->getNext());
head=head->getNext();
return *tmp;
}
template<class T>
void queue<T>:: push(node<T> newNode){
if (head==nullptr){
node<T>* newPtr = new node<T>;
newPtr = &newNode;
newPtr->setNext(head);
head=newPtr;
}
else{
node<T>* newPtr = new node<T>;
newPtr->setElement(newNode.getElement());
node<T>* end = head;
while (end->getNext() != nullptr)
end->setNext(end->getNext());
end->setNext(newPtr);
}
vec.push_back(newNode);
}
There are many issues with your code.
First, lets fix pop. You are creating a new node tmp, setting the next and returning the same without setting the element. To fix this, you just need it to set it to head and move the head to its next.
template<class T>
node<T> queue<T>:: pop(){
node<T>* tmp = head;// = new node<T>;
//tmp->setNext(head->getNext());
head=head->getNext();
return *tmp;
}
After this you will get your element with pop. But you will get wrong element. As queue is FIFO based, you should get '0' at first pop but in your case you will not get 0. Because, your push function is also incorrect. In push, when you are pushing the first element, then you are taking the address of the node object passed which is passed by value, this leads to undefined behavior, since the node object passed would be destroyed once the function finishes. Also, in the else part of your push you are setting the next of end to its own next and hence it will go into infinite loop. Below is the corrected implementation.
template<class T>
void queue<T>:: push(node<T> newNode){
if (head==nullptr){
node<T>* newPtr = new node<T>;
newPtr->setElement(newNode.getElement());
//newPtr = &newNode;
//newPtr->setNext(head);
head=newPtr;
}
else{
node<T>* newPtr = new node<T>;
newPtr->setElement(newNode.getElement());
node<T>* end = head;
while (end->getNext() != nullptr)
end = end->getNext();
end->setNext(newPtr);
}
vec.push_back(newNode);
}
Lastly, there are many memory leaks in your code. You are creating a new node far more number of times than needed and also not deleting them. As, you can see now that in case of push, you just need to pass the element T and it would suffice. You don't need to pass a new node every time.
Also, try using smart pointers as it will manage a lot of things on its own.
Related
I'm new to C++ and have been trying to implement a Singly Linked List, that provides an implementation the destructor, copy constructor and assignment operator. I'm running into compilation issues when trying to implement the copy constructor and the assignment operator.
Here's node.hpp
#ifndef LINKED_LIST_NODE_HPP
#define LINKED_LIST_NODE_HPP
template <typename T>
class Node{
public:
T data;
Node* next;
Node();
Node(T);
Node(const Node&);
~Node();
};
template <typename T>
Node<T>::Node(){}
template <typename T>
Node<T>:: Node(const T data): data(data), next(nullptr){}
template <typename T>
Node<T>::Node(const Node<T>& source) : data(source.data),
next(new Node)
{
(*next) = *(source.next) ;
}
template <typename T>
Node<T>::~Node(){}
#endif //LINKED_LIST_NODE_HPP
This is singly_linked_list.hpp
#ifndef LINKED_LIST_SINGLYLINKEDLIST_HPP
#define LINKED_LIST_SINGLYLINKEDLIST_HPP
#include <iostream>
#include "node.hpp"
template <typename T>
class SinglyLinkedList {
private:
Node<T>* head;
std::size_t count;
public:
SinglyLinkedList();
SinglyLinkedList(const SinglyLinkedList& source);
SinglyLinkedList& operator=(const SinglyLinkedList& source);
~SinglyLinkedList();
void insert(T);
void remove(T);
bool isEmpty();
int length();
void print();
};
template <typename T>
SinglyLinkedList<T>::SinglyLinkedList() : head(nullptr), count(0){}
template <typename T>
template <typename T>
SinglyLinkedList<T>::SinglyLinkedList(const SinglyLinkedList& source){
Node<T>* curr = source.head;
while(curr != nullptr){
Node<T>* p = new Node<T>;
p->data = curr->data;
curr = curr->next;
}
}
//template <typename T>
//SinglyLinkedList<T>::SinglyLinkedList& operator=(const SinglyLinkedList<T>& source){
// //not sure how to implment this.
//}
template <typename T>
SinglyLinkedList<T>::~SinglyLinkedList() {
if(!isEmpty()){
Node<T>* temp = head;
Node<T>* prev = nullptr;
while(temp->next != nullptr){
prev = temp;
temp = temp->next;
delete prev;
}
delete temp;
}
}
template <typename T>
bool SinglyLinkedList<T>::isEmpty() {
return head == nullptr;
}
template <typename T>
void SinglyLinkedList<T>::insert(T item) {
Node<T>* p = new Node<T>(item);
p->next = head;
head = p;
count += 1;
}
template <typename T>
void SinglyLinkedList<T>::remove(T item) {
bool present = false;
if (head->data == item){
Node<T>* temp = head;
head = head->next;
delete(temp);
count -= 1;
return;
}
Node<T>* temp = head;
while (temp->next != nullptr){
if (temp->next->data == item){
Node<T>* removable = temp->next;
temp->next = temp->next->next;
delete(removable);
present = true;
count -= 1;
break;
} else{
temp = temp->next;
}
}
if(!present){
throw std::invalid_argument("item not present in list");
}
}
template <typename T>
int SinglyLinkedList<T>::length() {
return count;
}
template <typename T>
void SinglyLinkedList<T>::print() {
if(isEmpty()){
throw std::invalid_argument("Can't print an empty list!");
}
Node<T>* temp = head;
while(temp != nullptr){
if(temp->next != nullptr){
std::cout<<temp->data;
std::cout<<"->";
}else{
std::cout<<temp->data;
}
temp = temp->next;
}
std::cout<<std::endl;
}
#endif //LINKED_LIST_SINGLYLINKEDLIST_HPP
I've commented out the copy constructor code to make this compile. What is the correct way of doing this? I'm just learning C++.
One issue that introduces complexity is that it is not well defined what the copy constructor of a node should do? Should the next field of the copy point to the next of the original, or it should create a copy of the next and point to that? The former is inadequate and error-prone, the latter would recursively create a copy of the whole list, one node at a time. This will work for lists of small size but will cause stack overflow for lists with many elements due to the depth of the recursive calls.
So to keep things simple, I wouldn't bother with copy constructor of a node.
template <typename T>
class Node {
public:
T data;
Node* next = nullptr;
Node() = default;
Node(const Node&) = delete; // since copying is not well defined, make it impossible to copy a node.
};
Copying a list is a well defined operation, so implementing the copy constructor makes sense. A mistake with your current implementation is that you allocate a new node, only to leak it later (nothing keeps track of the newly allocated node p). What you need looks more like this:
template <typename T>
SinglyLinkedList<T>::SinglyLinkedList(const SinglyLinkedList<T>& source)
: head(nullptr)
, count(0)
{
// deal with the trivial case of empty list
if (source.head == nullptr)
return;
// deal with the case where count >= 1
head = new Node<T>;
head->data = source.head->data;
head->next = nullptr;
count = 1;
Node<T>* lastCopied = source.head; // last node to be copied
Node<T>* lastAdded = head; // last node to be added to the current list
while (lastCopied->next != nullptr)
{
// create new node
Node<T>* p = new Node<T>;
p->data = lastCopied->next->data;
p->next = nullptr;
// link the newly created node to the last of the current list
lastAdded->next = p;
lastAdded = p;
// advance lastCopied
lastCopied = lastCopied->next;
count++;
}
}
Now regarding the assignment operator, luckily you can use the 'copy and swap' idiom that greatly simplifies things.
template <typename T>
SinglyLinkedList<T>& SinglyLinkedList<T>::operator =(SinglyLinkedList<T> source) // note that you pass by value.
{
std::swap(head, source.head);
std::swap(count, source.count);
return *this;
}
My answer would become too long if I tried to explain the copy and swap technique. It is a clever trick to write exception safe code and avoid duplication (implements assignment by using the copy ctor) at the same time. It is worth reading about it here.
Btw, the declaration of your class should look like this
template <typename T>
class SinglyLinkedList
{
private:
Node<T>* head = nullptr;
std::size_t count = 0;
public:
SinglyLinkedList(const SinglyLinkedList& source);
SinglyLinkedList& operator=(SinglyLinkedList source);
// other members here...
};
PS. My code assumes you are using c++11 or a later standard.
I don't like the direction this is headed. I'm going to explain how to do this approach right because it is an excellent lesson on recursion, but because it's recursion it can run the program out of Automatic storage (march off the end of the stack, most likely) with a sufficiently large list. Not cool.
The logic:
Copying a node copies the next node if there is one. This looks something like
template <typename T>
Node<T>::Node(const Node<T>& source) : data(source.data)
{
if (source.next) // if there is a next, clone it
{
next = new Node<T>(*source.next);
}
else
{
next = nullptr;
}
}
This reduces the linked list copy constructor to
template <typename T>
SinglyLinkedList<T>::SinglyLinkedList(const SinglyLinkedList& source){
head = new Node<T>(*source.head); //clone the head. Cloning the head will clone everything after
count = source.count;
}
A helper function may, uh... help here to make the Node copy constructor a bit more idiomatic
template <typename T>
Node<T> * initnext(const Node<T> & source)
{
if (source.next)
{
return new Node<T>(*source.next);
}
else
{
return nullptr;
}
}
template <typename T>
Node<T>::Node(const Node<T>& source) : data(source.data),
next(initnext(source))
{
}
but I don't think you gain much.
So... I don't like the above. What would I do instead? Something a lot like opetroch's solution above, but different enough that I'll write this up.
The node stays brutally stupid. As far as I'm concerned all a Node should ever know is how to store the payload and find other Nodes. This means the linked list should do all of the heavy lifting.
Concept 1: head is nothing but a next pointer. Once you abstract away its differences, unimportant here, you can use it exactly the same way you would next.
Concept 2: If you only know where next points, you have to do a bunch of extra book-keeping to track the previous node to update it's next. But if you take advantage of the previous's next pointing to the current node, you can throw out even more code. By tracking the previous node's next you have all of the information you need.
Concept 3: If you keep a pointer to the previous node's next, you can update that previous node's next any time you want by dereferencing it.
template <typename T>
SinglyLinkedList<T>::SinglyLinkedList(const SinglyLinkedList& obj)
{
Node<T>* tocopy = obj.head;
Node<T>** nextpp = &head; // head is a next. We are now pointing to a pointer to next
while (tocopy) // keep looping until there is no next node to copy
{
*nextpp = new Node<T>(tocopy->data); // copy source and update destination's next
nextpp = &(*nextpp)->next; // advance to point at the next of the node we just added
tocopy= tocopy->next; // get next node to copy
}
count = obj.count;
}
Because this iterates rather than recurses it doesn't eat up Automatic storage (probably the stack) and can keep going until the cows come home.
This logic can also be applied to remove
template <typename T>
void SinglyLinkedList<T>::remove(T item) {
Node<T>** temp = &head; //head is nothing but a next pointer.
// by pointing to where the next is, we don't
// need to track a previous or have special handling
// for the head node
while (*temp){ // because we now have a pointer to a pointer, we need an
// extra dereference
if ((*temp)->data == item){
Node<T>* removable = *temp;
*temp = (*temp)->next;
delete(removable);
count -= 1;
return; // no need for any special magic. Just get out.
} else{
temp = &(*temp)->next; // update the pointer to the next
}
}
// if we got here the node was not found.
throw std::invalid_argument("item not present in list");
}
And following through on head is just a next, we can also gut the destructor:
template <typename T>
SinglyLinkedList<T>::~SinglyLinkedList() {
while(head){ // if head null, list empty
Node<T>* temp = head; // cache so we can delete
head = head->next; // move head
delete temp; //delete removed node
}
}
I'm trying to figure out how to remove all memory leaks from this code. I know this issue probably stems from the push(T value) function when using new Node<T>(value) but I don't know how to fix this.
#ifndef MYSTACK_H
#define MYSTACK_H
#include <stdexcept>
using namespace std;
template <class T> class MyStack{
template <class G> class Node{
public:
G value;
Node* next;
Node(T val, Node* n = NULL): value(val), next(n){};
};
public:
MyStack(){
head = NULL;
tail = NULL;
my_size = 0;
};
~MyStack(){
delete head;
}
void push(T value){
if(head == NULL){
head = new Node<T>(value);
tail = head;
my_size++;
}
else{
Node<T> *temp = new Node<T>(value);
temp->next = head;
head = temp;
my_size++;
}
}
// . . . (removed - brevity)
private:
unsigned int my_size;
Node<T> *head;
Node<T> *tail;
};
#endif
Any help would be appreciated! Thanks!
You need to delete all the elements in your stack. Here are a couple of ways to do this:
In your destructor, loop through all elements in your stack and delete them.
In your destructor, repeatedly call pop until the stack is empty.
Option 2 is probably simpler to code, assuming that you already have a pop function, but potentially less efficient as it will be doing extra work to ensure the stack structure is maintained while it is being destroyed.
I'm building my own linked list class and I'm having some issues figuring out how to write some functions to help me traverse this list. This is my first time building a linked list from scratch, so if my approach is unconventional please let me know what might be more conventional.
I'd like write a function, within the List class that allows me to increment to the next element called getNext() as well as one that getPrev();
I wrote getNext like this:
T* getNext(){return next;}
However it tells me next is not declared within the scope. I'd also like to write a function that lets me access and modify the object within the list. I was considering using the bracket operator, but first I need to write a function to return the data member. Perhaps If I take a similar approach as I did within my pop functions.. thinking about it now. However, I'd still appreciate any advice.
Here is my List class:
#ifndef LIST_H
#define LIST_H
//List Class
template <class T>
class List{
struct Node {
T data;
Node *next;
Node *prev;
//Constructs Node Element
Node(T t, Node* p, Node* n) { data = (t); prev = (p); next = (n); }
// T *getNext() {return next;}
};
Node *head;
Node *tail;
public:
//Constructor
List() { head = NULL; tail=NULL; }
//Destructor
~List() {
while(head){
Node * temp(head);
head = head->next;
delete temp;
}
}
//is empty
bool empty() const {return (!head || !tail ); }
operator bool() const {return !empty(); }
//Push back
void push_back(T data) {
tail = new Node(data, tail, NULL);
if(tail->prev) //if the node in front of tail is initilized
tail->prev->next = tail;
if( empty() )
head = tail;
}
//Push front
void push_front(T data) {
head = new Node(data, NULL, head);
if(head->next)//if the node following head is initilized
head->next->prev = head;
if( empty() )
tail = head;
};
T pop_back() {
if( empty() )
throw("Error in List: List is empty\n");
Node* temp(tail);
T data(tail->data);
tail = tail->prev;
if( tail )
tail->next = NULL;
else
head = NULL;
delete temp;
return data;
}
T pop_front() {
if (empty())
throw("Error in List: List is empty\n");
Node* temp(head);
T data(head->data);
head = head->next;
if(head)
head->prev=NULL;
else
tail = NULL;
delete temp;
return data;
}
T getNext(){return next;}
};
#endif
getNext should be part of the struct Node and return a Node*
Node* getNext() { return next; }
Then from that you can get the value.
If you have to have it part of the list itself, which I would not recommend it will need to take a parameter of what Node you would like the next of:
Node* getNext(Node* n) {return n->next;}
Again, I recommend the first option.
Here is an approximate whole class with both of these:
template<typename T>
class List {
public:
struct Node {
Node* next, prev;
T data;
//some constructor and stuff
Node* Next() {return next;}
}
//some constructors and other functions
Node* getNext(Node* _n) {return _n->Next();}
}
then to use:
int main() {
List<int> l;
//add some stuff to the list
//get the head of the list
List<int>::Node* head = l.head; //or some corresponding function
//then
List<int>::Node* next = head->Next();
//or
List<int>::Node* next2 = l.getNext(head);
}
for starters getNext() should not return a pointer to the template class, it should return a pointer to the Node structure.
So it should be
Node* getNext(){return next;}
Because it's a member of Node struct and getNext is member of List. You should access it from an object of type Node.
Suppose I have the following definition of List and Node:
template <class T>
class List {
public:
class Iterator;
class ConstIterator;
//Constructors and Destructors.
List() : head(NULL), tail(NULL), size(0) {}
List(const List& list);
~List();
//Methods
Iterator begin();
ConstIterator begin() const;
Iterator end();
ConstIterator end() const;
void insert(const T& data);
void insert(const T& data, const Iterator& iterator);
void remove(const Iterator& iterator);
int getSize() const;
Iterator find(const T& item);
ConstIterator find(const T& item) const;
void sort();
//Operators
List operator = (const List& list);
private:
class Node;
Node* head;
Node* tail;
int size;
};
template <class T>
class List<T>::Node
{
public:
//Constructors and destructors
Node(const T& _data, const Node* _next) : data(_data), next(_next) {}
~Node(); //Destructor
//Methods
//Operators
Node operator = (const Node& node);
private:
T data;
Node* next;
};
I'm writing a function to insert data into a list like this:
template<class T>
void List<T>::insert(const T& data)
{
Node newNode = new Node(data, NULL);
if (head == NULL)
{
head = &newNode;
tail = &newNode;
}
else
{
(*tail)->next = &newNode;
tail = &newNode;
}
size++;
}
However what I find strange is that if I swap (*tail)->next = &newNode; to (*tail).next = &newNode; it still compiles. Why, and what is the correct way of doing it?
The definitions of your classes can be (for the purposes of this question) simplified into:
class List {
...
private:
Node* head;
Node* tail;
};
class Node {
...
private:
Node* next;
};
Now in your List::insert method:
Node newNode = new Node(data, NULL);
(*tail)->next = &newNode;
...when you use new expression, the result will be pointer to the newly allocated memory.
What you should do is:
Node* newNode = new Node(data, NULL);
tail->next = newNode; // <-- equivalent to (*tail).next = newNode;
Using Node->tail is short form of writing (*Node).tail. Both forms are valid. Strangeus is the fact that you say that (*Node)->tail compiles. To this happens, Node must be defined as a double pointer, i.e.:
Node **tail;
But your code has some others bugs in. In this line:
Node newNode = new Node(data, NULL);
you are define a local object and assing a dynamic memory to it. The correct way is:
Node *newNode = new Node(data, NULL); // defining it as a pointer
and instead of assing as:
head = &newNode;
do:
head = newNode;
As a final note, consider using smart pointer instead of raw pointer. The former is safer than the last
The -> operator will automatically derefference a pointer for you then call the method to the right. So:
tail->next
would also work but
tail.next
wouldn't because tail is a pointer. To use the . operator you have to defrence the pointer first as in
(*tail).next
(*tail)
turns your pointer into an object. At that point you can use either -> or .
A . will not work on a pointer but -> will.
Generally, just for easy of typing I use -> because it is shorter then using (*) to turn a pointer into an object just so I can use a dot but they are equivalent operations.
You have noticed that (*tail)->next = &newNode and (*tail).next = &newNode both compile, which strikes you as odd.
But somehow you might also have noticed that this line also compiles!
Node newNode = new Node(data, NULL);
That is the thing that you should give you pause.
You are inside of a template here. Lots of things "compile".
Did you try instantiating the template?
ADDENDUM:
Here just to show you how crazy things can be, check out this program:
#include <iostream>
using namespace std;
template <class T>
class C {
void f();
};
template <class T>
void C<T>::f() {
int x = new int;
}
int main() {
std::cout << "Hello, world\n";
}
Now check this out:
$ g++ template-example.cpp && ./a.out
Hello, world
But now notice
#include <iostream>
using namespace std;
int main() {
int x = new int;
std::cout << "Hello, world\n";
}
which yields:
$ g++ hello.cpp
hello.cpp: In function ‘int main()’:
hello.cpp:4: error: invalid conversion from ‘int*’ to ‘int’
TL;DR: WHEN YOU ARE IN A TEMPLATE, THINGS THAT SHOULD NOT COMPILE SOMETIMES "DO"! (They're not really compiling -- YET!)
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);
}
};