Cannot insert and print out linked list - c++11

I'm trying to create a simple linked list class. The program runs but it gives me wrong output. And it seems like linked list doesn't insert the new nodes as I want.
class Node
{
public:
std::string name;
Node *next;
};
class ProductName
{
private:
Node *head;
public:
ProductName()
{
head = NULL;
}
void insertNode(std::string input)
{
Node *temp;
temp = new Node;
temp->name = input;
temp->next = head;
head = temp;
}
void printOut()
{
Node *p;
p = head;
while (p->next != NULL)
{
std::cout << p->name << " ";
p = p->next;
}
}
};
int main()
{
ProductName object;
object.insertNode("Hello");
object.insertNode("world!");
object.printOut();
}
I expect the output is Hello world!, but it prints out a string of random character 005C4BA0
Edit: I forgot the pointer... It's p->name not p in the print function. However, now my result is world!.

First issue: your are always inserting into the beginning by replacing the head. If you expect your nodes to appears in order of insertion you should insert them in the end:
class ProductName
{
private:
Node *head;
Node *tail; // additional member to track the last node
public:
ProductName()
: head(nullptr), tail(nullptr)
{ }
void insertNode(std::string input)
{
Node *temp = new Node{ std::move(input), nullptr };
if (tail) {
tail->next = temp;
tail = temp;
} else {
head = tail = temp;
}
}
}
Second issue: your are printing all the elements that have next which means that the last element won't be printed.
void printOut()
{
Node *p = head;
// print while p != nullptr
// this also properly handles the empty list when head == nullptr
while (p)
{
std::cout << p->name << " ";
p = p->next;
}
}

Related

Error in code when searching through the right subtree in my binary search tree

In one of my classes at Uni we are creating Binary search trees and inserting data and looking them up. My code make sense in my head and because of this I cannot find the error anywhere. I have spent ages trying to find the error but cannot find it anywhere. The only thing that might be causing an error is that the precompiled headers didn't work when I started so i removed them from my project. The error only occurrs when i try to use the BST.Lookup and choose a key that is on the right subtree.
This is my main cpp file:
// BinarySearchTrees.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include "BST.h"
#include <iostream>
#include <fstream>
#include <string>
void ReadFile(BST &Bst)
{
int iKey;
std::string Key;
std::string Data;
std::ifstream testFile("Test.txt");
if (testFile.is_open())
{
while (!testFile.eof())
{
getline(testFile, Key, ' ');
getline(testFile, Data);
iKey = stoi(Key);
Bst.Insert(iKey, Data);
}
}
}
int main()
{
std::string Option;
int Choice;
BST BST;
//ReadFile(BST);
BST.Insert(6, "Oscar");
BST.Insert(20, "Ben");
BST.Insert(99, "James");
BST.Insert(1, "Alex");
while (Option != "exit")
{
std::cout << "If you wish to Lookup a Node, Insert value to find. Enter 'exit' to close" << std::endl;
getline(std::cin, Option);
if (Option == "exit")
break;
else
{
Choice = stoi(Option);
BST.Lookup(Choice);
}
}
return 0;
}
I believe that the readfile code may be incorrect but am unsure.
My Binary Search Tree Class:
#include "BST.h"
struct BST::Node {
Key key;
Item item;
Node* leftChild;
Node* rightChild;
Node(Key, Item);
};
void BST::Insert(Key inputKey, Item inputItem)
{
Node* previousNode = nullptr;
if (root == nullptr)
{
root = new Node(inputKey, inputItem);
}
else
{
InsertRec(inputKey, inputItem, root, previousNode);
}
}
void BST::InsertRec(Key inputKey, Item inputItem, Node* & Current, Node* & previousNode)
{
if (Current != nullptr)
{
previousNode = Current;
}
bool isLeft = false;
if (!isLeaf(Current))
{
if (inputKey > Current->key)
{
isLeft = false;
InsertRec(inputKey, inputItem, Current->rightChild, previousNode);
}
else if (inputKey < Current->key)
{
isLeft = true;
InsertRec(inputKey, inputItem, Current->leftChild, previousNode);
}
else
{
Current->item = inputItem;
}
}
else
{
Current = new Node(inputKey, inputItem);
if (isLeft)
{
previousNode->leftChild = Current;
}
else
{
previousNode->rightChild = Current;
}
}
}
BST::Item* BST::Lookup(Key soughtKey)
{
Item* Item = LookupRec(soughtKey, root);
std::string Display = /*std::to_string(soughtKey) + ": " + */ *Item;
std::cout << Display << std::endl;
return Item;
}
BST::Item* BST::LookupRec(Key soughtKey, Node* currentNode)
{
if (!isLeaf(currentNode))
{
if ((currentNode->key > soughtKey))
{
LookupRec(soughtKey, currentNode->leftChild);
}
else if ((currentNode->key < soughtKey))
{
LookupRec(soughtKey, currentNode->rightChild);
}
else
{
return &currentNode->item;
}
}
else
{
return nullptr;
}
}
bool BST::isLeaf(Node* n)
{
if (nullptr == n)
{
return true;
}
else
{
return false;
}
}
BST::BST()
{
}
BST::Node::Node(Key K, Item I)
{
key = K;
item = I;
leftChild = nullptr;
rightChild = nullptr;
}
And finally my header file for the binary search tree:
#pragma once
#include "iostream"
#include "string"
class BST
{
public:
using Key = int;
using Item = std::string;
void Insert(Key, Item);
Item* Lookup(Key);
BST();
private:
struct Node;
Node* root = nullptr;
static bool isLeaf(Node*);
static Item* LookupRec(Key, Node*);
static void InsertRec(Key, Item, Node* &, Node* &);
};
Any help would be greatly appreciated. I've been stuck on this for too long and I cannot progress without fixing this first.
The Test.txt file is filled with keys and items that are read and inputted like how I do it manually at the start of my main function, so I dont think the error is the file data.
Thanks in advance
UPDATE: Have finally found the error. The problem was with the bool isLeft in my InsertRec function. The bool was always false due to the recursion so have changed the code to compare previousNode->Key with Current->Key to determine if the child goes left or right

Reversing singly linked list using recursion

I have written code to reverse singly linked list using recursion. It is working fine on lists of length less than or equal to 174725. But on lists of length greater than 174725 it gives a segmentation fault(Segmentation fault: 11) while reversing it via reverse() call. Can someone please explain this to me ?
#include <iostream>
using namespace std;
class Node
{
public:
int val;
Node *next;
};
class Sll
{
public:
Node *head;
private:
void reverse(Node *node);
public:
Sll();
void insert_front(int key);
void reverse();
void print();
};
void Sll::reverse(Node *node)
{
if (node == NULL) return;
Node *rest = node->next;
if (rest == NULL)
{
head = node;
return;
}
reverse(rest);
rest->next = node;
node->next = NULL;
return;
}
Sll::Sll()
{
head = NULL;
}
void Sll::insert_front(int key)
{
Node *newnode = new Node;
newnode->val = key;
newnode->next = head;
head = newnode;
return;
}
void Sll::print()
{
Node *temp = head;
while (temp)
{
temp = temp->next;
}
cout << endl;
return;
}
void Sll::reverse()
{
reverse(head);
return;
}
int main()
{
Sll newList = Sll();
int n;
cin >> n;
for (int i = 0; i < n; i++) newList.insert_front(i + 1);
newList.reverse();
// newList.print();
return 0;
}
List reversing function must be tail-recursive, otherwise it is going to overflow the stack when recursing over a long list, like you observe. Also, it needs to be compiled with optimisations enabled or with -foptimize-sibling-calls gcc option.
Tail-recursive version:
Node* reverse(Node* n, Node* prev = nullptr) {
if(!n)
return prev;
Node* next = n->next;
n->next = prev;
return reverse(next, n);
}
An iterative list reversion can be more easily inlined though and it does not require any optimization options:
inline Node* reverse(Node* n) {
Node* prev = nullptr;
while(n) {
Node* next = n->next;
n->next = prev;
prev = n;
n = next;
}
return prev;
}

Return first unique number in a stream in constant time

How to write a static function that returns first unique number in a stream of numbers if current number is a terminating number (e.g. zero). Otherwise, it should return zero.
static int firstUnique(int number);
Time complexity should be O(1). What data structure should I use?
Use map and doubly linkedlist :
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;
const int TERMINATOR = 0;
struct Node {
int data;
Node* next;
Node* prev;
};
int firstUnique(int number){
static unordered_map<int, Node*> numToIsUnique;
static Node* head = nullptr; // first unique
static Node* tail = nullptr; // last unique
if (number != TERMINATOR){
Node* newNode = new Node{number, nullptr, nullptr};
if (numToIsUnique.insert(make_pair(number, newNode)).second == false) {
// insert fails => number is not unique
// Need to delete from LinkedList
Node* nodeToDelete = numToIsUnique[number];
if (nodeToDelete != nullptr){ // delete only once
if (head == nodeToDelete && tail == nodeToDelete){
// head == tail - one node
head = nullptr;
tail = nullptr;
}
else if (head == nodeToDelete){
// head to delete
head = head->next;
head->prev = nullptr;
}
else if (tail == nodeToDelete){
// tail to delete
tail = tail->prev;
tail->next = nullptr;
}
else {
// delete node in the middle
nodeToDelete->prev->next = nodeToDelete->next;
nodeToDelete->next->prev = nodeToDelete->prev;
}
delete nodeToDelete;
numToIsUnique[number] = nullptr;
}
}
else {
// number is new => need to append at the end of link list (last unique)
if (head == nullptr){
// list is empty
head = newNode;
tail = head;
}
else if (head == tail){
// list has one node
tail = newNode;
newNode->prev = head;
head->next = tail;
}
else {
// list has more than one node
newNode->prev = tail;
tail->next = newNode;
tail = newNode;
}
}
return TERMINATOR;
}
else {
// Output head
if (head == nullptr){
return TERMINATOR;
}
else {
return head->data;
}
}
}

How to store an array of LinkedList heads in C++?

Given a binary tree, I'm trying to make a linked list of elements for each depth. That makes D lists for depth D. I'm doing a non-recursive implementation and using level order traversal in my C++ code. Though I don't see any error while compilation, I know that my heads are not storing in the array of pointers. Please have a look at my code. Any help or suggestion would be great since I'm new to data structures. Thanks!
#include <iostream>
#include <queue>
using namespace std;
struct BTnode
{
int data;
BTnode* left;
BTnode* right;
};
struct LLnode
{
int data;
LLnode* next;
};
BTnode* newNode(int data)
{
BTnode* node = new BTnode;
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
void MakeLL(LLnode* &head, int data)
{
LLnode* temp = new LLnode;
temp->data = data;
if (head == NULL)
{
head = temp;
temp->next = NULL;
}
else
{
temp->next = head;
head = temp;
}
}
LLnode** LevelElementsLinkedlist(BTnode* &root)
{
if (root == NULL)
return NULL;
queue<BTnode*>nodeQ;
nodeQ.push(root);
int level = 0;
LLnode **arr;
while(1)
{
int count = nodeQ.size();
if (count == 0)
break;
LLnode* head = NULL;
arr[level] = head;
level ++;
while (count > 0)
{
BTnode* node = nodeQ.front();
MakeLL(head,node->data);
nodeQ.pop();
if (node->left)
nodeQ.push(node->left);
if (node->right)
nodeQ.push(node->right);
count--;
}
}
return arr;
}
void printLL(LLnode* head)
{
if (head == NULL)
return;
LLnode* temp = head;
while (temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
}
int main()
{
BTnode* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(40);
root->left->right = newNode(5);
root->right->left = newNode(60);
root->right->right = newNode(7);
root->left->left->left = newNode(8);
root->left->left->right = newNode(9);
root->left->right->left = newNode(10);
root->left->right->right = newNode(11);
root->right->left->left = newNode(12);
root->right->left->right = newNode(13);
root->right->right->left = newNode(14);
root->right->right->right = newNode(15);
LLnode** arr = LevelElementsLinkedlist(root);
int n = sizeof(arr)/sizeof(arr[0]);
cout << n;
for (int i = 0; i < n; i++)
{
printLL(arr[i]);
cout << endl;
}
cout << endl;
return 0;
}
There are a few problem that I noticed in your code.
In the function LevelElementsLinkedlist, you are not allocating space for arr. It should be LLnode *arr = new LLnode *[100].
Check the line where you have written the following:
LLnode* head = NULL;
arr[level] = head;
You are assigning NULL to head and then adding it to the array. Your whole array will contain nothing else but NULLs.
Try fixing these issues and try executing your code again.

C++ Linked list insert back

I am trying to create a function that will insert a node to the back of the list using linked list. I am new to using linked list and I have tried many different ways of doing an insertion at the end of the list but nothing seems to be working. The main passes the values one at a time to be inserted 2 4 5 8 9, and the output is 2 0 0 0 0. I do not whats causing this problem.
.h
class Node
{
public:
Node() : data(0), ptrToNext(NULL) {}
Node(int theData, Node *newPtrToNext) : data(theData), ptrToNext(newPtrToNext){}
Node* getPtrToNext() const { return ptrToNext; }
int getData() const { return data; }
void setData(int theData) { data = theData; }
void setPtrToNext(Node *newPtrToNext) { ptrToNext = newPtrToNext; }
~Node(){}
private:
int data;
Node *ptrToNext; //pointer that points to next node
};
class AnyList
{
public:
AnyList();
//default constructor
void print() const;
//Prints all values in the list.
void destroyList();
//Destroys all nodes in the list.
~AnyList();
//destructor
int getNumOfItems();
void insertBack(int b);
void deleteFirstNode();
private:
Node *ptrToFirst; //pointer to point to the first node in the list
int count; //keeps track of number of nodes in the list
};
.cpp
void AnyList::insertBack(int b)
{
Node *temp = new Node;
if (ptrToFirst == NULL)
{
temp->setData(b);
ptrToFirst = temp;
}
else
{
Node *first = ptrToFirst;
while (first->getPtrToNext() != NULL)
{
first = first->getPtrToNext();
}
first->setPtrToNext(temp);
}
}
First, you really should be using the std::list or std::forward_list class instead of implementing the node handling manually:
#include <list>
class AnyList
{
public:
void print() const;
//Prints all values in the list.
void destroyList();
//Destroys all nodes in the list.
int getNumOfItems() const;
void insertBack(int b);
void deleteFirstNode();
private:
std::list<int> nodes; //nodes in the list
};
void AnyList::print() const
{
for (std::list<int>::const_iterator iter = nodes.begin(); iter != nodes.end(); ++iter)
{
int value = *iter;
// print value as needed...
}
}
void AnyList::destroyList()
{
nodes.clear();
}
void AnyList::getNumOfItems() const
{
return nodes.size();
}
void AnyList::insertBack(int b)
{
nodes.push_back(b);
}
void AnyList::deleteFirstNode()
{
if (!nodes.empty())
nodes.pop_front();
}
That being said, your manual implementation fails because you are likely not managing the nodes correctly (but you did not show everything you are doing). It should look something like this:
class Node
{
public:
Node() : data(0), ptrToNext(NULL) {}
Node(int theData, Node *newPtrToNext) : data(theData), ptrToNext(newPtrToNext) {}
~Node() {}
Node* getPtrToNext() const { return ptrToNext; }
int getData() const { return data; }
void setData(int theData) { data = theData; }
void setPtrToNext(Node *newPtrToNext) { ptrToNext = newPtrToNext; }
private:
int data;
Node *ptrToNext; //pointer that points to next node
};
class AnyList
{
public:
AnyList();
//default constructor
~AnyList();
//destructor
void print() const;
//Prints all values in the list.
void destroyList();
//Destroys all nodes in the list.
int getNumOfItems() const;
void insertBack(int b);
void deleteFirstNode();
private:
Node *ptrToFirst; //pointer to point to the first node in the list
Node *ptrToLast; //pointer to point to the last node in the list
int count; //keeps track of number of nodes in the list
};
AnyList:AnyList()
: ptrToFirst(NULL), ptrToLast(NULL), count(0)
{
}
void AnyList::print() const
{
for (Node *temp = ptrToFirst; temp != NULL; temp = temp->getPtrToNext())
{
int value = temp->getData();
// print value as needed...
}
}
AnyList::~AnyList()
{
destroyList();
}
void AnyList::destroyList()
{
Node *temp = ptrToFirst;
ptrToFirst = ptrToLast = NULL;
count = 0;
while (temp != NULL)
{
Node *next = temp->getPtrToNext();
delete temp;
temp = next;
}
}
int AnyList::getNumOfItems() const
{
return count;
}
void AnyList::insertBack(int b)
{
Node *temp = new Node(b, NULL);
if (ptrToFirst == NULL)
ptrToFirst = temp;
if (ptrToLast != NULL)
ptrToLast->setPtrToNext(temp);
ptrToLast = temp;
++count;
}
void AnyList::deleteFirstNode()
{
if (ptrToFirst == NULL)
return;
Node *temp = ptrToFirst;
ptrToFirst = temp->getPtrToNext();
if (ptrToLast == temp)
ptrToLast = NULL;
delete temp;
--count;
}

Resources