i want to make a linked list ..
but the first node with a data and null link
if i input a string (123)
linked list be like this:
1/null - 2/point to the last one(1) - 3/point to the last one(2)
#include <iostream>
#include <string>
using namespace std;
struct link
{
int data;
link* next;
};
class LinkedList
{
private:
link* first;
public:
LinkedList(){}
void Add(string s)
{
for (int i = 0; i > s.length(); i++)
{
if (i == 0)
{
first->data = s[i];
first->next = NULL;
}
else
{
link* NewOne = new link;
NewOne->data = s[i];
NewOne->next = first;
first = NewOne;
}
}
}
void display()
{
cout << first->data;
}
};
int main()
{
LinkedList l1;
l1.Add("2734");
l1.display();
return 0;
}
what's the wrong in the code
You forget to allocate memory for first.
Following may help (using std::unique_ptr for free/correct memory management):
struct link{
char data;
std::unique_ptr<link> next;
};
class LinkedList {
private:
std::unique_ptr<link> first;
public:
void Set(const std::string& s){
for (auto c : s) {
std::unique_ptr<link> node = std::move(first);
first = std::make_unique<link>();
first->data = c;
first->next = std::move(node);
}
}
Live example
It also looks like you're storing characters in an int. Your output will be the ASCII value of the character rather than the raw int values.
I would recommend using unique pointers as Jarod42 has done. Having said that, this quick example below does not use them so you will need to call delete appropriately or use unique_ptr.
I added a last pointer to help traversal of the list as we make new links.
private:
Link * first;
Link *last;
int numLinks;
public:
LinkedList()
{
first = NULL;
last = NULL;
numLinks = 0;
}
Now for Add
void Add(string s)
{
for (int i = 0; i < s.length(); i++)
{
if (numLinks == 0)
{
first = new Link;
first->data = (s[i] - '0');
first->next = NULL;
last = first;
numLinks++;
}
else
{
Link * newLink = new Link;
newLink->data = (s[i] - '0');
newLink->next = NULL;
last->next = newLink;
last = newLink;
numLinks++;
}
}
}
The constructor does not initialize the first member. Subsequently, in Add():
for (int i = 0; i > s.length();i++){
if (i == 0){
first->data = s[i];
first->next = NULL;
}
This ends up dereferencing an uninitialized pointer, leading to undefined behavior.
There's also a problem with your display() too, but this is the main problem.
Related
I'm new to c++ and I use c++ to learn data structure recently. I stuck when the error occurs, I've tried to debug but It's still confused me. So, this error is I try to implement two operations concatenate and merge, my terminal shows the result that seems to successful on logical. However, the error is coming in the next second.
Just like img:enter image description here call stack
Here is my code. Hopefully, someone can help me solve this issue, thanks!
#pragma once
#include <iostream>
using namespace std;
class LinkedList;
class Node
{
private:
int data;
Node* next;
public:
friend class LinkedList;
};
class LinkedList
{
private:
Node* first;
Node* last;
Node* third;
public:
LinkedList()
{
first = nullptr;
last = nullptr;
third = nullptr;
}
LinkedList(int A[], int n);
~LinkedList();
void Display();
void RDisplay();//Recursive
void RDisplay(Node* p);
Node* getFirstNode();
int Count();
int RCount(Node* p);//Recursive
int Sum();
int RSum(Node* p);//Recursive
int Max();
int RMax(Node* p);//Recursive
int LSearch(int key); //linear search
int RSearch(int key);
int RSearch(Node* p, int key);
void Insert(int position, int x);
void InsertLast(int x);
void SortedInsert(int x);
int Delete(int position);
int isSorted();
void RemoveDuplicate();
void ReverseE();//Elements
void ReverseL();//Links
void RReverse();//Recursive
void RReverse(Node* q,Node *p);
void Concatenate(Node* second);
void Merge(Node *second);
int Mid();
int isLoop();
};
//cpp file
#include "Linkedlist.h"
#include <iostream>
using namespace std;
LinkedList::LinkedList(int A[], int n)
{
Node* t ;
first = new Node;
first->data = A[0];
first -> next = nullptr;
last = first;
for (int i = 1; i < n; i++)
{
t = new Node;
t->data = A[i];
t->next = nullptr;
last->next = t;
last = t;
}
}
LinkedList ::~LinkedList()
{
Node* p = first;
while (first)
{
first = first->next;
delete p;
p = first;
}
}
void LinkedList::Merge(Node* second)
{
Node* last;
if (first->data < second->data)
{
third = first;
last = first;
first = first->next;
last->next = nullptr;
}
else
{
third = last = second;
second = second->next;
last->next = NULL;
}
while (first != NULL && second != NULL)
{
if (first->data < second->data)
{
last->next = first;
last = first;
first = first->next;
last->next = NULL;
}
else
{
last->next = second;
last = second;
second = second->next;
last->next = NULL;
}
}
if (first != NULL)
{
last->next = first;
first = third;
}
else
{
last->next = second;
first = third;
}
}
//concatenate
void LinkedList::Concatenate(Node* second)
{
Node* p = first;
while (p->next != NULL)
{
p = p->next;
}
p->next = second;
}
void LinkedList::Display()
{
Node* p = first;
while (p != nullptr)
{
cout << p->data << " -> ";
p = p->next;
}
}
Node* LinkedList::getFirstNode()
{
return first;
}
#include <iostream>
#include "Linkedlist.h"
#include "Circular.h"
#include "Doubly.h"
#include "CircularDoubly.h"
int main()
{
int A[] = { 1,2,3,4,6,7 };
int B[] = { 5,6,7,8 };
LinkedList c1(A,6);
LinkedList c2(B, 4);
c1.Concatenate(c2.getFirstNode());
c1.Display();
}
Should I offer more detail?
stack call
stack call2
Yes it's the problem in destructor, after Concatenate, the c2 list has been appended to c1 list, the elements are destroyed twice, once in c1's destructor, the second time in c2's destructor. This is a memory issue that may lead to a crash.
I suggest fix it like this:
Transfer the ownership to c1, then we avoid destroy twice
Node* LinkedList::ReleaseFirst() {
Node* tmp = first;
first = nullptr;
return tmp;
}
c1.Concatenate(c2.ReleaseFirst());
Online demo
I had to implement a Linked HashTable for a project. Now I have to come up with an excercise and a solution to it using my hashtable. Everything works just fine, except I get random Segfault errors.
By Random I mean: It is the same line of code that causes it, but always at different times, calls.
I tested my code in Atom, Codeblocks and in Visual Studio Code. Both Atom and CB threw SegFault error, but VS Code ran it just fine without a problem.
NOTE: THIS IS NOT THE FULL/REAL CODE. It's part of a header file that is included in the main.cpp file which is then compiled and ran.
The Code:
#include <iostream>
#include <typeinfo>
#include <string>
using namespace std;
//List:
template<class T>
struct Node
{
string data;
Node *next;
};
class List
{
private:
Node *head, *tail;
int length;
friend class HashTable;
public:
List();
List(const List &L);
//~List() {delete this;};
List& operator =(List L);
int find(string);
void insert(string value);
void remove_head();
void remove_poz(int);
void remove_tail();
void clear();
void display();
};
List::List()
{
head = NULL;
tail = NULL;
length = 0;
}
template<>
string List<string>::findByIndex(int ind)
{
int i = 0;
Node<string>* temp = new Node<string>;
temp = head;
while (temp != NULL)
{
i++;
if (i == ind) return temp->data;
temp = temp->next;
}
delete temp;
return "-1";
}
template<class T>
void List<T>::remove_head()
{
Node<T>* temp = new Node<T>;
temp = head;
head = head->next;
delete temp;
length--;
}
template<class T>
void List<T>::remove_pos(int pos)
{
int i;
Node<T>* curr = new Node<T>;
Node<T>* prev = new Node<T>;
curr = head;
for (i = 1; i < pos; ++i)
{
prev = curr;
curr = curr->next;
}
if (curr)
{
prev->next = curr->next;
length--;
}
else cout << "Error" << endl;
}
template<class T>
void List<T>::remove_tail()
{
Node<T>* curr = new Node<T>;
Node<T>* prev = new Node<T>;
curr = head;
while (curr->next != NULL)
{
prev = curr;
curr = curr->next;
}
tail = prev;
prev->next = NULL;
delete curr;
length--;
}
//HashTable:
class HashTable
{
private:
List *table;
float load, stored;
int slots;
friend class List;
public:
HashTable();
HashTable(int);
~HashTable();
int hashFunc(string key);
int findTable(string);
int findList(string);
HashTable& operator =(const HashTable&);
void resize(); //I need this one
void insert(string);
void remove(string);
void clear(int);
void clear();
void display();
};
HashTable::HashTable()
{
stored = 0;
load = 0.00;
slots = 15;
table = new List[slots];
}
int HashTable::hashFunc(string key)
{
int g, h = 0;
unsigned int i;
for (i = 0; i < key.size(); ++i)
{
h = (h << 4) + (int)(key[i]);
g = h & 0xF0000000L;
if (g != 0)
{
h = h ^ (g >> 24);
}
h = h & ~g;
}
return h % slots;
}
template<class T>
void HashTable<T>::remove(T value)
{
int ind = hashFunc(value);
int findInd = table[ind].findByValue(value);
if (findInd == 0)
table[ind].remove_head();
else if (findInd < table[ind].length)
table[ind].remove_pos(findInd);
else table[ind].remove_tail();
if (table[ind].isEmpty()) occupied--;
stored--;
load = stored / slots;
}
The function that would cause the segfault:
(This would be called over and over again in a loop till I don't have more elements in my table)
string reakcio(HashTable<string>& HT, int tarolok)
{
const int anyagszam = rand() % 4 + 2; //Min 2, Max 5 anyag hasznalodik
int i = 0, j;
string anyagok[5];
string eredmeny;
for(j = 0; j < tarolok && i < anyagszam; ++j) //elemek kivetele
{
while(!HT.table[j].isEmpty())
{
anyagok[i++] = HT.table[j].findByIndex(1); //This line right here is the culprit :(
HT.remove(anyagok[i-1]);
}
}
const int siker = rand() % 4 + 0; //75% esely a sikerre
if (siker)
{
eredmeny = anyagok[0];
for(i = 1; i < anyagszam; ++i)
eredmeny += " + " + anyagok[i];
}
else
eredmeny = "Sikertelen reakcio";
return eredmeny;
}
(Note: only the functions that might be needed are shown here)
Every element of my hashtable, or of my lists is a 10 character long random string value.
srand(time(NULL)) is used before the function call in main.cpp
Any help or advice would be much appreciated, as I'm stuck at this and I really need to move on to the next portion of my exercise, but I can't without this.
The main.cpp file:
#include <iostream>
//#include "LinkedHash.h"
#include "functions.cpp"
int main()
{
HashTable<string> Anyagok;
int tarolok;
tarol(Anyagok); //Stores the data from file, no problem here, functions.cpp
tarolok = Anyagok.getSlots();
srand(time(NULL));
int i = 1;
while (Anyagok.getStored() > 5 )
cout<<reakcio(Anyagok, tarolok)<<" "<<i++<<endl;
return 0;
}
The LinkedHash.h contains the hashtable and the list, the functions.cpp contains the problematic function.
EDIT:
By suggestion I changed out the
Node<string>* temp = new Node<string>;
temp = head;
part to
Node<string>* temp = head;
Also removed the delete line.
But my problem is still the same :/
Everything works just fine, except I get random Segfault errors
Then nothing works at all.
A first review show little care to the cornercases in the list class. You need to define a correct behavior for
operation on empty lists
operation on first and last element
key not found during search
Notable errors found:
remove_head, remove_tail will segfault on empty list. head is NULL. head->next is invalid memory access. Similar errors are all over the implementation.
HashTable<T>::remove(T value) will always remove something. Even if the value argument is not in the hashtable. This is deeply flawed
findByIndex returning "-1" make no sense. "-1" is a valid input.
Node<T>* temp = new Node<T>;temp = head;. You just leaked memory. You need a pointer to manipulate node addresses. You should not instantiate Nodes to get a pointer. This is not an issue (ie not noticeable) for a small projet, but unacceptable for a real implementation.
During debugging the second execution of while loop the code below produces an out_of_range exception. I noticed that:
before stack.top():
after stack.top():
Does anyone know why this happens and how to fix it?
#include <iostream>
#include <stack>
#include <vector>
#include <memory>
#include <functional>
int replacement;
int toreplace;
class Node
{
public:
int id_;
std::vector<Node*> children;
Node* at(int i)
{
return children.at(i);
}
std::vector<Node*> GetChildren() {
return children;
}
Node(int id_) {
this->id_ = id_;
}
};
class CPreorderStackFrame
{
public:
Node* node_;
CPreorderStackFrame* root_;
int index_;
explicit CPreorderStackFrame(Node* node_, CPreorderStackFrame* root_, int index_)
{
this->node_ = node_;
this->root_ = root_;
this->index_ = index_;
}
void replaceChildrenByIndex(Node* replace, int index)
{
replace->id_ = node_->at(index)->id_;
delete node_->GetChildren()[index];
node_->GetChildren()[index] = replace;
}
bool hasChildren() {
return !(node_->GetChildren().empty());
}
};
void pre_order_traverse(Node* root,
std::function<std::unique_ptr<Node>(Node*)> visit)
{ // always: root != NULL
std::stack<CPreorderStackFrame> mystack;
mystack.push(CPreorderStackFrame(root, NULL, NULL));
while (!mystack.empty())
{
CPreorderStackFrame cur = mystack.top();
mystack.pop();
std::unique_ptr<Node> replace = visit(cur.node_);
if (replace)
{
cur.root_->replaceChildrenByIndex(replace.release(), cur.index_);
}
else if (cur.hasChildren())
{
for (int i = cur.node_->GetChildren().size() - 1; i >= 0; --i)
{ //preorder requires right to left
Node *topush = cur.node_->at(i);
if (topush)
{
CPreorderStackFrame nextFrame(topush, &cur, i);
mystack.emplace(nextFrame); //hier ist noch alles richtig
}
}
}
}
}
std::unique_ptr<Node> print_visit(Node* node) {
std::cout << node->id_ << ' ';
return NULL;
}
std::unique_ptr<Node> replace_visit(Node* node) {
std::cout << node->id_ << ' ';
if (node->id_ == toreplace) {
std::unique_ptr<Node> retval(new Node(replacement));
return retval;
}
return NULL;
}
int main() {
toreplace = 3;
replacement = 8;
Node *a = new Node(1);
Node *b = new Node(2);
Node *c = new Node(3);
Node *d = new Node(4);
Node *e = new Node(5);
Node *f = new Node(3);
Node *g = new Node(3);
Node *h = new Node(42);
Node *i = new Node(42);
a->children.push_back(b);
a->children.push_back(c);
a->children.push_back(d);
a->children.push_back(e);
b->children.push_back(f);
b->children.push_back(g);
b->children.push_back(h);
b->children.push_back(i);
pre_order_traverse(a, replace_visit);
return 0;
}
One problem is
std::vector<Node*> GetChildren()
which means that
delete node_->GetChildren()[index];
node_->GetChildren()[index] = replace;
is destroying an object, but only replacing its address in a copy of the vector.
Dereferencing that element in the original vector is undefined.
You need to return by reference, or move the removal code into Node.
Another problem, and the immediate cause of your observations, is that
CPreorderStackFrame nextFrame(topush, &cur, i);
mystack.emplace(nextFrame);
is storing a pointer to the automatic object cur, whose lifetime ends with the end of the iteration.
Dereferencing the pointer after that is undefined.
Most (probably all) compilers will reuse that object's storage for the next iteration, which means that all your CPreorderStackFrames store the same pointer, and not a single one of them is valid by the time you dereference it.
It looks like the root doesn't need to be a pointer at all.
I was trying to create a linked list using a for loop but the 'new' in the for loop in the create() method didn't quite allocate a new slot to store new data. As a result, when I tried to print the list, I got an infinite loop. Can somebody tell me what's wrong here?
struct node
{
double value;
node * next_ptr;
node(){}
node(double val, node * p): value(val), next_ptr(p) {}
~node(){}
};
node * create()
{
using namespace std;
node temp = {0, nullptr};
node * result;
for(int i=1; i<5; ++i)
{
result = new node;
result->value = i;
result->next_ptr = &temp;
temp = *result;
}
return result;
};
The reason you are probably getting an infinite loop is because in:
temp = *result;
you are copying the value of *result into a new object of type node, which is unrelated to the one you created.
What you want to do is store a pointer instead:
node* temp = nullptr;
node* result;
for(int i=0; i<5; ++i)
{
result = new node;
result->value = i;
result->next_ptr = temp;
temp = result;
}
return result;
Live demo
A part from the learning value, just stick to std::forward_list or std::list, for lists, instead. Or even better just use std::vector or other containers (depending on the use that you make of the container).
a simple one to create linked in for loop
#include <iostream>
class LinkedList {
public:
int value;
LinkedList * next;
};
int main()
{
LinkedList *List = nullptr;
LinkedList *head = List;
LinkedList *prev;
for (int i=0; i< 3;i++)
{
LinkedList *temp = new(LinkedList);
temp->value = i;
temp->next = nullptr;
if (head == nullptr)
{
head = temp;
prev = head;
}
else
{
prev->next = temp;
prev = temp;
}
}
}
I tried to implement by myself a single linked list. For now, I only wrote an addition of an element to the end of the list, and a function which prints lists content. But when I want to print out a list my program gives me a segmentation fault. Heres my code:
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
class Stuff;
class List
{
private :
Stuff *first, *last;
public :
List();
void addfront(Stuff *s);
void print();
~List();
};
class Stuff
{
private :
string name;
double price;
public :
Stuff();
Stuff(string, double);
void print();
Stuff *next;
};
Stuff::Stuff()
{
name = "";
price = 0;
next = NULL;
}
Stuff::Stuff(string n, double p)
{
name = n;
price = p;
}
void Stuff::print()
{
cout << name << " " << price << "\n";
}
List::~List()
{
}
void List::addfront(Stuff *s)
{
if(first == NULL )
first = s;
last->next = s;
s->next = NULL;
last = s;
}
void List::print()
{
Stuff *p;
if(last == first == NULL)
cout << "list is empty!\n";
else
for (p = first; p != NULL; p = p->next)
p->print();
}
List::List()
{
first = last = NULL;
}
int main(int argc, char **argv)
{
List l;
Stuff *s1 = new Stuff("Coffe", 4.50);
Stuff *s2 = new Stuff("Apple", 2.50);
l.addfront(s1);
l.addfront(s2);
l.print();
return 0;
}
It seems like you forgot to check if last != NULL before setting last->next to s.
Deferencing a NULL pointer results to an undefined behaviour.
Your addFront function should look like that:
void List::addfront(Stuff *s) {
if(!first)
first = s;
if (last)
last->next = s;
s->next = NULL;
last = s;
}
Btw: Use if(last == first && last == NULL) instead of if(last == first == NULL).
One issue is
if(last == first == NULL)
make it
if(last == NULL && first == NULL)
also you need to do,
void List::addfront(Stuff *s)
{
if(!first)
first = s;
if (last)
last->next = s;
s->next = NULL;
last = s;
}
It is because of this line in addfront method
last->next = s;
Here last is a NULL pointer.
(gdb) p last
$1 = (Stuff *) 0x0
Deferencing a NULL pointer will cause memory fault/segmentation violation.
Always check whether it is NULL and then deference.
if (last)
last->next = s;
If you are in Linux machine, then you can run the program in gdb. Once segmentation violation happens put use backtrace command to see the call stack to understand which statement is crashed.