Attempting to create a pointer to previous object inside object - c++

I'm attempting to create a vector of pointers to Nodes, where each node stores a pointer to the previous Node in the list.
I made a small test program to see if I could access a variable gscore in the previous object to the one I call.
#include <iostream>
#include <vector>
using namespace std;
struct Node
{
Node(int gscore1)
{
gscore = gscore1;
}
Node *previous;
int gscore;
};
int main()
{
std::vector<Node*> nodeVec;
Node *tempnode;
tempnode = new Node(10);
Node *tempnode2;
tempnode = new Node(11);
nodeVec.push_back(tempnode);
nodeVec.push_back(tempnode2);
nodeVec[1]->previous = tempnode;
cout << nodeVec[1]->previous->gscore << endl;
return 0;
}
However this results in a crash. What is the correct way to do this?

You never initialize tempnode2. You initialize tempnode twice.
int main()
{
std::vector<Node*> nodeVec;
Node *tempnode;
tempnode = new Node(10);
Node *tempnode2;
tempnode2 = new Node(11); // <<---- HERE
nodeVec.push_back(tempnode);
nodeVec.push_back(tempnode2);
nodeVec[1]->previous = tempnode;
cout << nodeVec[1]->previous->gscore << endl;
return 0;
}

Looks like a typing error. The third line in main() should be tempnode2 not tempnode.

Related

insertion function to insert elements in a linked list at tail

I want to implement insertion of element at tail of linked list, I want to do it using member function, currently I'm able to do it by creating a function outside of struct, please help me what should be modified to implement it as member function.
my conventional approach:
#include<iostream>
using namespace std;
struct node{
int data;
node *next;
};
node * Insert(int v,node *head){
if(head==NULL){
node *temp=new node;
head=temp;
temp->data=v;
temp->next=NULL;
return head;
}
else{
node *temp=head;
while(temp->next!=NULL){
temp=temp->next;
}
node *temp_new=new node;
temp_new->data=v;
temp_new->next=NULL;
temp->next=temp_new;
return head;
}
}
This is a working example. The idea is that, from the member function, you recursively call node::Insert until you reach the last element, and then only there you create the next one.
#include <iostream>
struct node{
int data;
node *next = nullptr;
node *Insert(int v);
};
node *node::Insert(int v)
{
if (next == nullptr)
{
next = new node;
next->data = v;
return next;
}
else
{
return next->Insert(v);
}
}
int main()
{
node a{3};
a.Insert(2);
a.Insert(5);
std::cout << a.data << ' ' << a.next->data << ' ' << a.next->next->data << ' ' << std::endl;
return 0;
}
See it live on Coliru.
Also: avoid using namespace std.
Addition
As noted in the comment, it is probably a good idea to unroll the recursion. Here is a nonrecursive version of the above code:
#include <iostream>
struct node{
int data;
node *next = nullptr;
node *Insert(int v);
};
node *node::Insert(int v)
{
if (next == nullptr)
{
next = new node;
next->data = v;
return next;
}
else
{
auto p = next;
while (p->next != nullptr)
p = p->next;
p->next = new node;
p = p->next;
p->data = v;
return p;
}
}
int main()
{
node a{3};
a.Insert(2);
a.Insert(5);
std::cout << a.data << ' ' << a.next->data << ' ' << a.next->next->data << ' ' << std::endl;
return 0;
}
See it live on Coliru.
Just by looking at what your insert currently does, it does not make sense to make it a member of node. You can call your insert like this:
node* root = nullptr;
root = Insert(42,root);
to create a list with a single element. On the other hand, you cannot call a member function of node before you have an instance of type node.
The transition is simpler if you write a class that represents the list, not only a single node. Start with this:
struct node{
int data;
node *next;
};
struct linked_list {
node* head;
};
Now the above two lines could look like this:
linked_list l;
l.insert(42);
All you need to do is to move the free function into the class and instead of using the parameter head you use the member head. Also there is no need to return the head anymore:
#include<iostream>
using namespace std;
struct node{
int data;
node *next;
};
struct linked_list {
node* head = nullptr;
void Insert(int v){
if(head==nullptr){
head =new node;
head->data=v;
head->next=nullptr;
}
else{
node *temp=head;
while(temp->next!=nullptr){
temp=temp->next;
}
node *temp_new=new node;
temp_new->data=v;
temp_new->next=nullptr;
temp->next=temp_new;
}
}
};
Note that I did not change anything on the implementation (only NULL -> nullptr and void return, if it had a bug then it still has a bug now ;). You should also provide appropriate constructors for node and linked_list and destructors, because currently this leaks all allocated memory. And last but not least you need to read about the rule of 3/5: What is The Rule of Three?

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.

I have written a code for creating a linked list. While printing the list items I am getting SIGSEV error. How do we fix it?

I know I have done a silly mistake and to not make it again in the future I want to know why this error is showing up in the following code. I have already read on the internet that it is caused when our program is trying to access memory block which is not yet created but I cannot find where it is occurring in my program.
Thank You, Guys.
struct node
{
int value;
struct node *next;
};
typedef struct node Node;
Node *createNewNode(int value)
{
Node *result = new Node;
result->value = value;
result->next = NULL;
return result;
}
Node *insertHeadNode(Node **head, Node *nodeToInsert)
{
nodeToInsert->next = *head;
*head = nodeToInsert;
return nodeToInsert;
}
void print_list(Node *head)
{
Node *temp = head;
while (temp != NULL)
{
cout << temp->value << "->";
temp = temp->next;
}
cout << endl;
}
int main()
{
int value, i;
Node *head;
Node *tmp;
while (i < 5)
{
cout << "Enter the value of the linked list: ";
cin >> value;
tmp = createNewNode(value);
insertHeadNode(&head, tmp);
i++;
}
print_list(head);
return 0;
}
One more thing. I have dynamically created a struct in the createNewNode function. So we do delete it at the end of our program, right?
You have multiple parts in your code that result in undefined behavior.
You never initialize i so doing i < 5 isn't valid.
You never initialize Node *head so that one also holds an indeterminate value, that value is assigned to nodeToInsert->next in insertHeadNode.
So also cout << temp->value << "->"; would be invalid, at the point when temp = temp->next has reaced the node for which you assinged that indeterminate to next.

How to dynamically create new nodes in linked lists C++

Could anyone tell me if this is the basic idea of linked lists? What are the pros and cons to this method and what are best practices when implementing linked lists in C++? Im new to data structures so this is my first approach. If there is a better way to do this same thing, please let me know. Additionally, how would you create the nodes dynamically without hard coding it? Thanks.
#include <iostream>
#include <string>
using namespace std;
struct node {
int x;
node *next;
};
int main()
{
node *head;
node *traverser;
node *n = new node; // Create first node
node *t = new node; // create second node
head =n; //set head node as the first node in out list.
traverser = head; //we will first begin at the head node.
n->x = 12; //set date of first node.
n->next = t; // Create a link to the next node
t->x = 35; //define date of second node.
t->next = 0; //set pointer to null if this is the last node in the list.
if ( traverser != 0 ) { //Makes sure there is a place to start
while ( traverser->next != 0 ) {
cout<< traverser->x; //print out first data member
traverser = traverser->next; //move to next node
cout<< traverser->x; //print out second data member
}
}
traverser->next = new node; // Creates a node at the end of the list
traverser = traverser->next; // Points to that node
traverser->next = 0; // Prevents it from going any further
traverser->x = 42;
}
for tutorial purpose, you can work out this example:
#include <iostream>
using namespace std;
struct myList
{
int info;
myList* next;
};
int main()
{
//Creation part
myList *start, *ptr;
char ch = 'y';
int number;
start = new myList;
ptr = start;
while (ptr != NULL)
{
cout << "Enter no. ";
cin >> ptr->info;
cout << "Continue (y/n)? ";
cin >> ch;
if (ch == 'y')
{
ptr->next = new myList;
ptr = ptr->next;
}
else
{
ptr->next = NULL;
ptr = NULL;
}
}
//Traversal part begins
cout << "Let's start the list traversal!\n\n";
ptr = start;
while (ptr!=NULL)
{
cout << ptr->info << '\n';
ptr = ptr->next;
}
}
It allocates memory dynamically for as many elements as you want to add.
I'd prefer to make a linked list class. This eliminates the need to call 'new' more than once. A nice implementation with examples can be found here.
You are in fact already doing dynamic allocation. So, not sure what you are asking for. But if you want to define functions to add new nodes to your linked list (or delete a node etc.), this can be a probable solution:
The location nodes get inserted/deleted is dependent on the type of data-structure. In a queue, new nodes will get added to the end; at the top in case of a stack. A function that adds a node to the top, simulating STACK push operation:
void pushNode(node **head, int Value) {
node *newNode = new node;
newNode->x = Value;
newNode->next = *head;
*head = newNode;
}
It would be called like pushNode(&head, 15) where 'head' would be defined as node *head = NULL. The root head should initially be set to NULL. After this operation head will point to the newly added node (top of stack).
The approach would be very similar for other data-structures (viz. queues) and works fine. But as you are using C++, I would suggest to define a class for your linked-list and define these functions as methods. That way, it will be more convenient and less error-prone.
Even better use std::list. It's the standard thing, so much portable and robust than a custom implementation.
You can also do it in this way
#include <iostream>
using namespace std;
struct Node{
int data;
Node* next;
};
void createList(Node** head ,Node* temp){
int n;
char ch;
temp = *head;
while(temp != NULL){
cout<<"Enter The Value ";
cin>>temp->data;
cout<<"DO you want to continue(y/n)";
cin>>ch;
if(ch=='Y' || ch == 'y'){
temp->next = new Node;
temp = temp->next;
}else{
temp->next = NULL;
temp = NULL;
}
}
}
void ShowList(Node* head){
cout<<"your list :"<<endl;
while(head != NULL){
cout<<head->data<<" ";
head = head->next;
}
}
int main()
{
//Creation part
Node *head, *temp;
createList(&head,temp);
ShowList(head);
}

Create and Display Linked List

I am a beginner in C++ and need help in many things. Well, for the starters, I have been working on Linked List and not really getting why my header(the first pointer which points towards first node) keep on rotating. I am just pointing it towards first node plus my display node is just displaying last node, why is it so?. Please tell me where I am wrong. Thank you in advance
#include <iostream>
#include <conio.h>
using namespace std;
struct Node
{
int data;
Node *link;
};
Node* create_Node()
{
int no_of_nodes;
Node *header = new Node;
Node *ptr = new Node;
header = ptr;
cout << "Enter no of nodes:";
cin >> no_of_nodes;
cout << "Enter data:";
for(int n = 0; n < no_of_nodes; n++)
{
cin >> ptr->data;
Node *temp = new Node;
ptr->link = temp;
temp = ptr;
}
ptr->link = NULL;
return ptr;
}
void display_link_list(Node * list)
{
Node *temp = new Node;
temp = list;
while(temp != NULL)
{
if(temp->link != NULL)
{
cout << "List:" << list->data << endl;
temp = temp->link;
}
}
}
int main()
{
Node *n = new Node;
n = create_Node();
display_link_list(n);
getch();
return 0;
}
Welcome to C++. My advice here is to break the Linked list into two. First the Nodes and then a List struct.
struct Node
{
int data;
Node *next;
Node(int data) : data(data), next(NULL) {}
};
struct List {
Node* tail;
Node* head;
List() : head(NULL), tail(NULL) {}
void insert(int data) {
if(head==NULL) {
head = new Node(data);
tail = head;
} else {
tail->next = new Node(data);
tail = tail->next;
}
}
};
Now you can insert one element into the list at a time and use head to print the list from beginning to end.
Something basic that you need to understand:
When you do Node* p = new Node, you are setting variable p to point to the start address of a piece of memory, the size of which being equal to sizeof(Node).
Now, when you then do p = something else (which often appears in your code), you are essentially overriding the previous value of p with some other value. It is like doing:
int i = 5;
i = 6;
So your code does not do what you're expecting to begin with.
In addition to that, what's bad about overriding the first value with a second value in this case, is the fact that the first value is the address of a dynamically-allocated piece of memory, that you will need to delete at a later point in your program. And once you've used p to store a different value, you no longer "remember" that address, hence you cannot delete that piece of memory.
So you should start by fixing this problem in each of the following places:
Node *header = new Node; // Variable 'header' is assigned
header = ptr; // Variable 'header' is reassigned
Node *temp = new Node; // Variable 'temp' is assigned
temp = list; // Variable 'temp' is reassigned
Node *n = new Node; // Variable 'n' is assigned
n = create_Node(); // Variable 'n' is reassigned