I was trying to implement the linked list stl but I always get runtime error if someone can help me solve this problem please.
What I was doing is when inserting an element I check if it's the first element if it is I make the head and tail point to it if not I use the node's next pointer to point to the new element and move the tail so it point to the last inserted element the error appears in the insert function.
#include <iostream>
using namespace std;
template<typename T>
struct Node {
T item;
Node *next = nullptr;
};
template<typename T>
class list {
static int sz;
Node<T> *head, *tail;
public:
void insert(T x) {
Node<T> new_node;
new_node.item = x;
if (!sz) {
*head = new_node;
*tail = new_node;
} else {
tail->next = &new_node;
*tail = new_node;
}
sz++;
}
int size() {
return sz;
}
friend ostream &operator<<(ostream &os, list<T> &o) {
while (o.head->next != nullptr) {
os << o.head->item << " ";
o.head = o.head->next;
}
return os;
}
};
template<typename T>
int list<T>::sz = 0;
int main() {
list<int> l;
l.insert(5);
l.insert(6);
l.insert(7);
cout << l.size() << endl;
cout << l << endl;
return 0;
}
Related
I am implementing a generic singly linked list. It works with char and int, but not for string. What mistake have I made? I get an error:
C2679 binary '<<': no operator found which takes a right-hand operand of type 'T' (or there is no acceptable conversion)
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
template <typename T>
struct Node
{
T data;
Node*next;
//friend class List<T>;
};
template<typename T>
class List
{
public:
List() :headNode{ nullptr } {} // empty list constructor
~List() // destructor
{
Node<T>*current = headNode;
while (current)
{
Node<T>*temp = current;
current = current->next;
delete temp; cout << "\nDeleting Nodes!!!";
}
}
bool empty() const // is list empty?
{
return headNode == nullptr;
}
const T& front() const // get front element
{
return headNode->data;
}
void addFront(const T& e) // add to front of list
{
Node<T>* tempNode= new Node<T>;
tempNode->data = e;
tempNode->next = headNode;
headNode = tempNode;
}
void removeFront()
{
if (empty()) cout << "List is empty" << endl;
else
{
Node<T> *tempNode = headNode;
headNode = tempNode->next;
delete tempNode; cout << "\nDeleting Node!!!";
}
}
void printList()const
{
Node<T>*current = headNode;
while (current)
{
cout << current->data<<" |-> ";
current = current->next;
}
}
private:
Node<T> *headNode;
};
int main()
{
srand(time(NULL));
List<int> mylist;
for (int i = 0; i < 15; ++i)
{
mylist.addFront(rand()%200 + 20);
}
mylist.printList();
mylist.removeFront(); cout << endl;
mylist.printList();
List<string>family;
family.addFront("aaa");
family.addFront("bbb");
family.addFront("ccc");
family.addFront("ddd");
family.printList();
List<char> charlist;
charlist.addFront('a');
charlist.addFront('b');
charlist.addFront('c');
charlist.addFront('d');
charlist.printList();
return 0;
}
You need to include the header <string>.
#include <string>
where the operator << for streams and the class std::string is declared.
I am trying to make a linked list and test it in c++ using nodes. I create six nodes and then I print them forward and backwards like this:
main.cpp
#include "LinkedList.h"
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
void TestAddHead();
int main()
{
TestAddHead();
system("pause");
return 0;
}
void TestAddHead()
{
cout << "Testing AddHead()" << endl;
LinkedList<int> data;
for (int i = 0; i < 12; i += 2)
data.AddHead(i);
cout << "Node count: " << data.NodeCount() << endl;
cout << "Print list forward:" << endl;
data.PrintForward();
cout << "Print list in reverse:" << endl;
data.PrintReverse();
}
LinkedList.h
#pragma once
#include <iostream>
#include <vector>
#include <array>
#include <stdexcept>
#include <string>
using namespace std;
template<typename T>
class LinkedList
{
public:
struct Node
{
T data_;
Node* next;
Node* previous;
};
void PrintForward() const;
void PrintReverse() const;
unsigned int NodeCount() const;
void AddHead(const T &data);
LinkedList();
LinkedList(const LinkedList<T> &list);
~LinkedList();
private:
Node* head = new Node;
Node* tail = new Node;
unsigned int count = 0;
};
template<typename T>
LinkedList<T>::LinkedList()
{
}
template<typename T>
LinkedList<T>::LinkedList(const LinkedList<T> &list)
{
}
template<typename T>
LinkedList<T>::~LinkedList()
{
}
template<typename T>
void LinkedList<T>::AddHead(const T &data)
{
Node* newNode = new Node;
newNode->data_ = data;
if (count == 0)
{
head = newNode;
tail = newNode;
head->next = nullptr;
head->previous = nullptr;
}
else
{
newNode->next = head;
head->previous = newNode;
head = newNode;
}
count = count + 1;
}
template<typename T>
void LinkedList<T>::PrintForward() const
{
Node* currentNode = head;
while (currentNode != nullptr)
{
cout << currentNode->data_ << endl;
currentNode = currentNode->next;
}
}
template<typename T>
void LinkedList<T>::PrintReverse() const
{
Node* currentNode2 = tail;
while (currentNode2 != nullptr)
{
cout << currentNode2->data_ << endl;
currentNode2 = currentNode2->previous;
}
}
template<typename T>
unsigned int LinkedList<T>::NodeCount() const
{
return count;
}
this should be the output of the program:
Testing AddHead()
Node count: 6
Print list forward:
10
8
6
4
2
0
Print list in reverse:
0
2
4
6
8
10
The program works and gives me the correct output but the problem is that it just crashes when it reaches the "10" at the bottom of the program and I don't know why, can anyone tell me why is this happening and a possible way to fix it? thank you
Your immediate problem, you never set the new node previous pointer to nullptr ( a problem that honestly should be rectified by a better constructed loop and/or a proper constructor for Node). Regardless, here...
template<typename T>
void LinkedList<T>::AddHead(const T &data)
{
Node* newNode = new Node;
newNode->data_ = data;
if (count == 0)
{
head = newNode;
tail = newNode;
head->next = nullptr;
head->previous = nullptr;
}
else
{
newNode->next = head;
newNode->previous = nullptr; // ADD THIS
head->previous = newNode;
head = newNode;
}
count = count + 1;
}
There are still several things wrong in this: memory leaks, empty copy-ctor and destructor, etc, but the above is the root of the current evil. That line could also be:
newNode->previous = head->previous;
but frankly that just confuses what you're doing. You're always landing your new nodes at the head of the list, so the previous member of said-same will always be nullptr (at least until you start studying circular lists).
I am trying to write a code making a single linked list. I want to put all my array elements into each node and link them. But when I run my code I keep getting the segmentation fault error. I do not get why I am getting this error.
Can anybody help?? Thanks!!
linked_list_main.cc
#include <iostream>
#include "linked_list.h"
int main() {
int array[5];
List<int> list(array, 5);
std::cout << list;
return 0;
}
template <class T>
class Node {
public:
T data;
Node<T>* next;
};
This is my linked_list.h file.
class List {
private:
Node<T> *head;
public:
List() : head(NULL) {};
~List() {
Node<T>* ptr;
for(ptr = head; ptr == NULL; ptr = head->next)
delete ptr;
}
List(T* arr, int n_nodes){
Node<T>* tmp = head;
for(int i = 0; i < n_nodes; i++ ) {
Node<T>* node = new Node<T>;
node->data = arr[i];
if(tmp != NULL) {
node->next = tmp;
tmp = node;
}
}
}
friend std::ostream& operator<<(std::ostream& out, List<T>& rhs) {
Node<T>* cur = rhs.head;
while(cur != NULL) {
if(cur->next == NULL)
out << cur->data << " ";
else
out << cur->data << ", ";
cur = cur->next;
}
}
};
You need to change this
List(T* arr, int n_nodes){
Node<T>* tmp = head;
...
}
to this
List(T* arr, int n_nodes){
Node<T>* tmp = NULL;
...
head = tmp;
}
Pointers are tricky, learn to use a debugger. Will be the best hour you've ever spent when learning how to program.
i'm trying to make a template class for a list in c++. This is something new for me, and i'm stuck. I've written add(T item) method and write() to write whole list on console, but i have random int as output.
Here's my code, if someone could tell me where my mistake is, i will be grateful.
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
template <class T> class Node {
private:
Node<T> * next;
Node<T> * prev;
T key;
public:
Node(T k) {
next =(Node *) malloc(sizeof(Node));
prev = (Node *)malloc(sizeof(Node));
key = k;
}
Node(T * n, T * p, T k) {
next = n;
prev = p;
key = k;
}
void setNext(Node<T> * n) {
next = n;
}
void setPrev(Node<T> * p) {
prev = p;
}
void show() {
cout << "key= " << key << endl;
}
};
template <class T> class List {
private:
Node<T> * head;
Node<T> * tail;
public:
List() {
head = nullptr;
tail = nullptr;
cout << "list created!" << endl;
}
void add(T item) {
Node<T> node(item);
node.setNext(head);
node.setPrev(nullptr);
if (head != nullptr)
head = &node;
else {
tail = &node;
}
head = &node;
}
void write() {
head->show();
}
};
int main()
{
List<int> lista;
lista.add(8);
lista.write();
return 0;
}
Your add() add a pointer to a Note<T> (node) in the list; but node is destroied when add() ends the execution.
So, when you call write(), that use show(), the pointed memory in undefined (random value).
To avoid this problem, you have to allocate the variable (with new! avoid malloc() with classes), so
Node<T> * nodePnt = new Node<T>(item);
and
head = nodePnt;
tail = nodePnt;
But remeber to delete it.
Head and tail are getting populated, and print out the values, but nodePtr stays empty for some reason. When I debug in VS2015, head and tail number is getting populated, while field this stays empty
Here's Linked_List
#ifndef _LINKED_LIST_
#define _LINKED_LIST_
#include <iostream>
class LinkedList
{
public:
struct Node
{
int number;
Node * next;
Node() : number(NULL), next(NULL) {};
Node(int number_, Node * next_ = NULL)
{
number = number_;
next = next_;
}
}*head, *tail, *nodePtr;
LinkedList();
~LinkedList();
void add(int num);
friend std::ostream& operator<<(std::ostream& out, LinkedList& list);
private:
int size;
};
#endif // _LINKED_LIST_
Implementation file
include "linkedlist.h"
#include <iostream>
using namespace std;
LinkedList::LinkedList() : head(NULL), tail(NULL), nodePtr(NULL)
{
nodePtr = new Node();
}
LinkedList::~LinkedList()
{
Node * curr, *temp;
curr = head;
temp = head;
while (curr != NULL)
{
curr = curr->next;
delete temp;
temp = curr;
}
}
void LinkedList::add(int num)
{
Node * newNode = new Node();
newNode->number = num;
cout << newNode->number;
if (head == NULL)
{
head = newNode;
tail = newNode;
size++;
}
else
{
tail->next = newNode;
newNode->next = NULL;
tail = newNode;
size++;
}
//cout << nodePtr->number; //empty, or some random
//just some tests
cout << head->number;
if (head->next != NULL)
{
cout << head->next->number;
}
cout << tail->number;
cout << endl;
}
std::ostream & operator<<(std::ostream & out, LinkedList & list)
{
out << list.nodePtr->number << endl;
return out;
}
Main.cpp
#include <iostream>
#include "linkedlist.h"
using namespace std;
int main()
{
int num;
LinkedList list;
list.add(1);
list.add(2);
list.add(3);
cout << list;
cout << "Press 1: ";
cin >> num;
return 0;
}
You're missing a fundamental concept here. nodePtr is not some magical node that knows about all your other nodes, or knows about linked lists, or can be used to print all their numbers.
When you do this:
out << list.nodePtr->number << endl;
All you are doing is outputting the value that you initialized when you allocated a new Node and stored a pointer in nodePtr:
nodePtr = new Node();
That called the default constructor for Node which set nodePtr->number to zero. (side-note, you initialized it to NULL, not 0 -- you should not mix integer types with pointer types, so change it to initialize the value to 0).
Its value stays 0 because you never modify it. And nodePtr always points at that single node because you never modified nodePtr.
What you're actually wanting to do is print out your list. Let me suggest the normal way to do this, by starting at head and following the node linkages:
std::ostream & operator<<(std::ostream & out, const LinkedList & list)
{
for( Node *node = list.head; node != nullptr; node = node->next )
{
out << node->number << std::endl;
}
return out;
}
And finally, I suggest you remove nodePtr from your class completely.
You only use nodePtr in the constructor, you never change it's values.