Linked Lists Class - c++

Okay I know this is a ridiculously easy question, but for some reason I cannot get a linked list to work. It may just be because I am really tired, because I've done them a million times before. Boiled my program down to the simplest possible implementation, still not working.
Very basic implementation, just make a LL of integers, something I have done a million times before but for whatever reason it's never progressing past head.
main.cpp
#include <iostream>
#include "ll.h"
using namespace std;
int main()
{
int x;
list ll;
int i =0;
while(i == 0)
{
cout << "Enter a value to add to the LL ";
cin >> x;
ll.add(x);
ll.display();
}
return 0;
}
ll.h
struct node
{
int val;
node * next;
};
class list
{
public:
list();
void add(int);
void display();
node * head;
};
ll.cpp
#include <iostream>
#include "ll.h"
using namespace std;
list::list()
{
head = NULL;
}
void list::add(int x)
{
if(!head)
{
cout << "First " << endl;
head = new node;
head->val = x;
head->next = NULL;
}
else
{
node * current = head;
while (current)
current = current->next;
current = new node;
current->val = x;
current->next = NULL;
}
}
void list::display()
{
node * current = head;
while(current)
{
cout << current->val << endl;
current = current->next;
}
}

It seems you want to append to the list. In this case, you loop condition shouldn't be
while (current)
but
while (current->next)
making sure is initially non-NULL (which you do with your check for the `head).
Actually, the logic for setting up the new node is also not quite right. You probably want to have the second branch of add() look something like this:
while (current->next) {
current = current->next;
}
current->next = new node(x);
... with a suitable constructor of node:
node::node(int x): val(x), next() {}

In addition to Dietmar's answer, you have an improper while loop:
while ( i == 0 ) {
...
}
In the body of the for loop, i is never changed, causing it to loop indefinitely. I'm not entirely sure what you want to use i for though.

Related

How to retrieve the value at a given index?

I am fairly new to programming and I am working on a project that involves shifting nodes. How can I get a node at a particular position denoted by user input and increase its value by one? To better explain:
here is my code...or my attempt:
#include <iostream>
struct Node {
int data;
struct Node* next;
};
class LinkedList {
private:
Node* head;
public:
LinkedList()
{
head = NULL;
}
void print()
{
Node* current = head;
if (head != nullptr)
{
do
{
std::cout << current->data << " ";
current = current->next;
}
while (current != head);
}
}
};
int main()
{
LinkedList link_one;
int nodes;
std::cout << "nodes ";
std::cin >> nodes;
for (int index = 0; index < nodes; index++){
link_one.print();
}
link_one.print();
std::cout << std::endl;
}
try traverse
actually there is no need to write a answer, but...I am a newcomer :)
your function place_node should add a parameter:
int place_node(int idx)
then...traverse from your head node for "idx" times, modify the value of current node, that's it.
here's the complete code for function place_node to achieve your goal:
int place_node(int idx) //no need to return
{
Node* current = head;
int count, index = 0;
for(int i=0;i<idx;++i) current = current->next;
current->data+=1;
return 1; // no need to return
}

Try tree inplementation

Try to make tree , have a some troubles, first it's print function - it's print not integers that i put, but print random numbers;
Another trouble its append child - its works only one times;
Will be happy if you will help me with this task.
And also give some good articles about linked lists, trees on c and c++;
#include <iostream>
#include <stdio.h>
using namespace std;
struct Node
{
void* m_pPayload;
Node* m_pParent;
Node* m_Children;
};
struct Person
{
int m_Id;
};
//typedef bool (*NodeComparator)(void* pValue, void* pPayload);
/*bool Comp(void* pValue, void* pPayload)
{
Person* pVal = (Person*)pValue;
Person* pPay = (Person*)pPayload;
if (pVal->m_Id == pPay->m_Id)
return true;
else
return false;
}
*/
Node* NewNode(void* pPayload)
{
Node* pNode = new Node;
pNode->m_pParent = nullptr;
pNode->m_Children = 0;
pNode->m_pPayload = pPayload;
return pNode;
}
Person* NewPerson(int id)
{
Person* p = new Person;
p->m_Id = id;
return p;
}
//Node* FindNode(Node* pParent, Node* m_pPayload, NodeComparator comparator);
void AppendChild(Node* pParent, Node* pNode)
{
if (pParent->m_Children == NULL)
pParent->m_Children = pNode;
}
void print(Node* head)
{
Node* current_node = head;
while (current_node != NULL)
{
printf("%d\n ", current_node->m_pPayload);
current_node = current_node->m_Children;
}
}
int main()
{
Node* T = new Node;
T = NewNode(NewPerson(5));
AppendChild(T, NewNode(NewPerson(11)));
AppendChild(T, NewNode(NewPerson(15)));
print(T);
}
printf("%d\n ", current_node->m_pPayload)
is incorrect. %d wants an integer and it's being given a pointer. The results will be unusual, and likely appear to be random garbage.
printf("%d\n ", ((Person*)current_node->m_pPayload)->m_Id);
^ ^
| Get id from Person
treat payload pointer as pointer to Person
will solve the immediate problem.
Your code actually seems to be pretty messed up with a lot of things going on, here sharing my own commented code from few years back, hope it helps
#include <bits/stdc++.h>
using namespace std;
// Single node representation
struct node {
int data;
node *left, *right;
};
// Declaring temp for refference and root to hold root node
node *root, *temp;
// This function only generates a node and return it to the calling function with data stored in it
node* generateNode(int data){
temp = new node();
temp->data = data;
temp->left = temp->right = NULL;
return temp;
}
// This function actually adds node to the tree
node* addNode(int data, node *ptr = root){
// If the node passed as ptr is NULL
if(ptr == NULL){
ptr = generateNode(data);
return ptr;
}
// Condition to check in which side the data will fit in the tree
else if(ptr->data < data)
//if its in right, calling this function recursively, with the right part of the tree as the root tree
ptr->right = addNode(data, ptr->right);
else
//In case the data fits in left
ptr->left = addNode(data, ptr->left);
//Note: if there is no data in left or roght depending on the data's valid position, this function will get called with NULL as second argument and then the first condition will get triggered
//returning the tree after appending the child
return ptr;
}
//Driver function
int main ()
{
int c, data;
for (;;){
cin >> c;
switch(c){
case 1:
cout << "enter data: ";
cin >> data;
//Updating root as the tree returned by the addNode function after adding a node
root = addNode(data);
break;
default:
exit(0);
break;
}
}
return 0;
}
Please find below a piece of code that should easily get you started. It compiles and it traverse the tree using recursion.
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace std;
struct Node
{
int m_Id;
vector<Node*> m_Children;
Node(const int& id){
m_Id = id;
}
void AppendChild(Node* pNode) {
m_Children.push_back(pNode);
}
void Print() {
printf("%d\n ", m_Id);
}
};
void traverse(Node* head)
{
Node* current_node = head;
current_node->Print();
for(int i = 0; i<current_node->m_Children.size(); i++) {
traverse(current_node->m_Children[i]);
}
}
int main()
{
Node* T0 = new Node(0);
Node* T10 = new Node(10);
T10->AppendChild(new Node(20));
Node* T11 = new Node(11);
Node* T12 = new Node(12);
Node* T22 = new Node(22);
T22->AppendChild(new Node(33));
T12->AppendChild(T22);
T0->AppendChild(T10);
T0->AppendChild(T11);
T0->AppendChild(T12);
traverse(T0);
}
First for printing the node value
Talking about the current mistake that you had committed is in the above code is:
You have not mentioned its pointer to its child (specifically right or left). Due to which it is showing garbage value every time.
For e.g.: print( node->left);
Since you need to type caste it properly to show the data of data.
For e.g.: printf("%d\n ", ((Person*)current_node->m_pPayload)->m_Id);
There is a specific direction in which you want to print data. For trees, there are three directions in which you can print the data of the node and they are as follow:
Left order or Inorder traversal
Preorder traversal
Postorder traversal
This can give you better information about traversal.
Secondly for adding the node to a tree
This might help explain it better.

getting user input to form linked list

I'm trying to create a linked list from user input but it's not printing anything when i try to print it. Not even the head. Also note, it is intentionally backwards.
Here is my function for getting user input, it returns the list. I know it is wrong but i've spent hours on it and can't get it to work...
#include <iostream>
#include <limits>
#include <ios>
struct Node {
int value;
Node *next;
}
Node* getInput() {
Node* head = nullptr;
Node* tmp;
while (true) {
int x;
if (!(cin >> x)) {
break;
} else if ( head == nullptr) {
head = new Node{x, nullptr);
} else {
tmp = new Node{x , nullptr};
tmp->next = head;
head = head->next;
}
}
return tmp;
}
int main() {
cout << getInput()->value;
}
A couple of good solutions up, but because the request was for a backward list, this can be really, really simple.
Node* getInput()
{
Node* head = nullptr;
int x;
while (std::cin >> x) // keep going until we can't get a good x.
{
head = new Node{x, head}; // point node at current head, assign new head
// head always points at the beginning of list because items are
// always inserted at the start of the list.
}
return head;
}
So to prove this list prints backward, here's a simple tester
int main()
{
Node* cur = getInput();
while (cur)
{
std::cout << cur->value << '\n';
cur = cur->next;
}
}
The return value of get input() is not the actual head/start of the list. Head will always point to null the moment you insert any node. Head value can be stored in a temporary pointer during first insert and return temporary pointer instead of head.
If you are trying to print the linked list in reverse order, here's a working version:
#include <iostream>
#include <limits>
#include <ios>
using namespace std;
struct Node {
int value;
Node *next;
Node(int val, Node *nextPtr) {
value = val;
next = nextPtr;
}
};
Node *getInput() {
Node *head = nullptr;
Node *tmp;
while (true) {
int x;
if (!(cin >> x)) {
break;
} else if (head == nullptr) {
head = new Node(x, nullptr);
} else {
tmp = new Node(x, nullptr);
tmp->next = head;
head = tmp;
}
}
return head;
}
int main() {
Node *head = getInput();
Node *tmp;
while (head != nullptr) {
cout << head->value << ", ";
tmp = head;
head = head->next;
delete tmp;
}
cout << endl;
return 0;
}
head = head->next; is the problem. You're allocating a Node correctly, but you immediately leak that Node and head is pointing to nullptr.
The simplest solution is to keep head pointed at the most recent Node. You'll need a special case for the first insertion since head will be uninitialized (fix that by the way), but that way you're always pointing at the most recent Node.
If you have trouble, draw your Nodes out on paper with arrows. Watch how the arrows change at each insertion, and you'll see what's happening.

Linked list code giving correct answer, but bringing up error message saying program has 'stopped working'

I was working on a homework assignment with linked lists, and while it seems that the code itself is spitting out the "right" answer (what the teacher wants it to), it brings up an error message when running that states "the program has stopped working (it will be forced closed, reported to windows, etc)". The program doesn't force close after closing this dialogue, and besides this, seems to be exactly what my teacher is looking for in the assignment. Any suggestions?
#include <iostream> // Provides cout
#include <cstdlib> // Provides EXIT_SUCCESS
using namespace std; // Allows all standard library items to be used
struct node
{
int data;
node* link;
};
void insert_at_head(node*& head, int entry)
//Precondition: head is the head pointer of a linked list, entry is
// a non-negative integer
//Postcondition: Inserts a new node with data field set to entry at the
// beginning of the linked list head
{
node* n;
n = new node;
n->data = entry;
n->link = head;
head = n;
}
void print(const node* head)
//Precondistion: head is the head pointer of a linked list
//Postcondition: Prints that linked list
{
const node* cursor;
cout << "The linked list is:" << endl;
for (cursor=head; cursor != NULL; cursor=cursor->link)
cout << cursor-> data << " ";
cout << endl;
}
void delete_last(node* & head)
{
while (head->link != NULL)
{
int i;
for(i = 0; 10 >= i; i++)
{
struct node* secondlast = head;
struct node* last = head->link;
while(last->link != NULL)
{ struct node* t = last;
secondlast = t;
last = last->link;
}
delete last;
secondlast->link = NULL;
cout << "I have deleted the last element in the linked list" << endl;
print(head);
}
}
while (head == NULL)
{
return;
}
}
int main( )
{ int i;
node* head;
head = NULL;
for(i = 1; 10 >= i; i++)
{
insert_at_head(head, i);
}
print(head);
delete_last(head);
return EXIT_SUCCESS;
}

C++ doubly linked list

I got a problem with my doubly linked list. How can i make the input unique ( i don`t want it to be repeated )
for example i can input 1 and then again 1 i will have a list of 1 and 1. I need to forbid this somehow :) so the list can contain only not repeating numbers.
#include <cstdlib>
#include <iostream>
using namespace std;
struct node
{
int data;
node* next;
node* prev;
};
class Node
{
public:
Node();
~Node();
void setKopa();
void printForward();
private:
node* head;
node* tail;
node* n;
};
Node::Node()
{
setKopa();
}
Node::~Node()
{
delete n;
}
void Node::setKopa()
{
int lenght;
do
{
cout << "Input list lenght (how many elements): ";
cin >> lenght;
if(lenght<2)
cout << "Error list has to have atleast 2 elements!" <<endl;
}
while(lenght<2);
int fill;
cout << "Input "<< lenght <<" elements: "<<endl;
for (int i=0; i<lenght; i++)
{
cin>>fill;
n = new node;
n->data = fill;
if (i==0)
{
n->prev = NULL;
head = n;
tail = n;
}
else if (i+1==lenght)
{
n->prev = tail;
tail->next = n;
tail = n;
tail->next = NULL;
}
else
{
n->prev = tail;
tail->next = n;
tail = n;
}
}
}
void Node::printForward()
{
node* temp = head;
while(temp != NULL)
{
cout << temp->data << " ";
temp = temp-> next;
}
cout << endl;
}
int main()
{
Node a;
a.printForward();
system("pause");
return 0;
}
When you read input, go through the list to see if the input is already there.
With that (simple) answer out of the way, I would like to address some other things regarding your code. The first is that you have a memory leak in that you never delete the list. The second is that you don't need the class member variable n, it might as well be a local variable inside the setKopa loop.
Your way of adding new nodes is also, well, weird. It should, in my opinion, be more general instead of using the loop counter to check what to do. What I suggest is that you make a member function to add new nodes, taking the integer data as argument. This way you can call this function to add nodes anywhere, and not just in the setKopa function. In fact, I think the list should not handle that input at all, instead it should be a free-standing function called from main and which calls the addNode function.
Also the node structure doesn't need to be in the global namespace, it could be a private structure in the Node class. And speaking of the Node class, shouldn't it really be called List instead?
So if I may suggest, you might want to do something like this:
#include <iostream>
class List
{
public:
List()
: head(nullptr), tail(nullptr)
{}
~List();
void addNode(const int data);
void printAll() const;
private:
struct node
{
node()
: next(nullptr), prev(nullptr)
{}
node* next;
node* prev;
int data;
};
node* head;
node* tail;
};
List::~List()
{
for (node* next, *cur = head; cur; cur = next)
{
next = cur->next;
delete cur;
}
}
void List::addNode(const int data)
{
node* n = new node;
n->data = data;
if (tail == nullptr)
{
// First node in list
head = tail = n;
}
else
{
n->prev = tail;
tail->next = n;
tail = n;
}
}
void List::printAll() const
{
std::cout << "{ ";
for (node* cur = head; cur != nullptr; cur = cur->next)
std::cout << cur->data << ' ';
std::cout << "}\n";
}
int main()
{
List list;
for (int i = 0; i < 10; ++i)
list.addNode(i);
list.printAll();
}
The above code should print
{ 0 1 2 3 4 5 6 7 8 9 }
Replace the node-adding loop with your own.