I'm trying to implement my own linked list using vectors and pointers. The problem I'm have is that I can't get the first node to point to the second node.
Here's my code and what I've tried:
struct Node {
Node* previous;
Node* next;
int data;
};
// Initialize: Create Vector size 20 and first node
void LinkedList::init() {
vecList.resize(20, NULL); // Vector of size 20
Node* head = new Node(); // Create head node
head->previous = NULL; // Previous point set to null
head->next = vecList[1]; // Next pointer set to next position
head->data = 0; // Data set at value 0
vecList[0] = head; // Put head node in first position
count = 1; // Increase count by 1
}
// Add Node to array
void LinkedList::push_back(Node* node, int data) {
count += 1;
node = new Node();
node->next = vecList[count + 1];
node->previous = vecList[count - 1];
node->data = data;
vecList[count - 1] = node;
}
The data has been passed in and will displayed using:
cout << linkedlist.vecList[1]->data << endl;
But if I try this way to display I get error saying the next pointer is <Unable to read memory>
cout << linkedlist.vecList[0]->next->data << endl;
You forgot to set the next pointer of the previous Node in the push_back method.
If count is a member variable of the list containing the number of entries you have to change the method like this:
EDIT: actually you have to increment count in the end because array indices start with zero.
void LinkedList::push_back(Node * node, int data){
node = new Node();
node->next = NULL; // NULL because next element does not exist yet
node->previous = vecList[count - 1];
node->data = data;
vecList[count] = node;
vecList[count-1]->next = vecList[count];
count++;
}
Still it's a bit strange that you try to implement a linked list with a vector or array because that actually defeats the advantages of a list...
It looks like vecList is a vector/array of pointers to Node.
When you init, you let the first element point to the second element:
void LinkedList::init(){
...
head->next = vecList[1];
But at this point, the second element does not exist yet. So you cannot point to it yet. Something similar is wrong at the push_back function.
Related
I have to face this problem: I have a doubly linked list and I have to make insertion at the tail. My list is made of Nodes such as
struct Node {
int val; // contains the value
Node * next; // pointer to the next element in the list
Node * prev; // pointer to the previous element in the list
};
and my class list declares only
private:
Node * first; // Pointer to the first (if any) element in the list
at first.
Now, I wrote such a method for inserting:
void List::insert(int n){
Node * tmp = new Node;
tmp->val = n;
tmp->next = 0;
if (!first) {
first = tmp;
}
else {
Node * p = new Node;
p = first;
while (p->next) {
p = p->next;
}
p->next = tmp;
tmp->prev = p;
}
};
and if I take several numbers from cin (say, 1 2 3 4), I call insert but I end up not having all the elements I wanted to store. I have only first and tmp, which contains the last number from the input (e.g. 4).
I struggle to figure out what's wrong - my first suggestion is variable scope.
Or is there anything wrong during the pointer setting?
OBS: I'd use a tail pointer of course, but the aim is traversing the list.
Any feedback is really appreciated.
Thanks in advance.
I am making a doubly linked list.
Everything was working fine, but I realized that when I added a new class node somewhere in the middle, the left pointer would still be pointing at the node previously before it (now two spaces away).
So I added a new node pointer on line 46.
Then on line 51 I told that node to now point to the new node.
So :
First I had new node temp off in space
Then I make pointer temp2 loop through the list
Lastly I tell temp3 to point to the node after temp2's node
After the function runs, the order should be temp2->temp->temp3
My main point: After I added line 51, my program core dumps(segmentation fault) and closes out.
How can I fix this? It only happens when I add something that isn't taking place of the head pointer.
void add(node *&head, node *&tail, node *¤t)
{
node *temp = new node; //creates a pointer pointing to a new class node
cin >> temp->letter; // user input
current = head; // creates a pointer to point at the first node
while (current != NULL) // while list isn't empty
{
if (current->letter == temp->letter)
{ // letter already exists
cout << "DUPLICATE: " << temp->letter << endl << endl;
return;
}
else
{ // loop through list moving tail pointer to the end while checking for duplicates
tail = current;
current = current->right_link;
}
}
current = temp; // current = new added node
if (isEmpty(head))
{ // if first node
temp->left_link = NULL;
temp->right_link = NULL;
head = temp; // head and
tail = temp; // tail both point to first and only node.
}
else
{ // if new letter value is less than head value
if(temp->letter < head->letter)
{
temp->right_link = head; // node points (right) to head
temp->left_link = NULL; // left most node point to nothing.
head->left_link = temp; // head (currently the second node) points (left) to first node
head = temp; // head pointer moves to the first position
}
else
{ // if new node goes anywhere other than head
node *temp2 = head; // new node to cycle through list
while(temp2->right_link != NULL && temp2->right_link->letter < temp->letter)
{ // if temp2 points to a node and that node's value is less than temp node value
temp2 = temp2->right_link;
}
node *temp3 = temp2->right_link;
temp->right_link = temp2->right_link; // when temp2 stops looping, temp will point to
// the same node as temp2.
temp2->right_link = temp; // temp2's current node will point to temp, causing temp
// to be added into the list (after temp2)
temp3->left_link = temp; // point the node (after the newly inserted node) left to new node
temp->left_link = temp2; // connects the left pointer between temp and temp2
if(temp->right_link == NULL)
tail = temp;
}
}
cout << "ADDED : " << temp->letter << endl << endl;
}
if temp2->right_link == NULL
46 node *temp3 = temp2->right_link;
is a NULL pointer, so you can't
51 temp3->left_link = temp;
which should have been obvious if you used a debugger.
I'm currently learning how to work with linked lists, specifically, doubly linked lists, and I have come across a problem with my program when I attempt to print it backwards.
Here is the portion of the code that I need help with:
#include <iostream>
using namespace std;
struct node
{
int data; //int to store data in the list
node *next; //pointer to next value in list
node *prev; //pointer to previous value in list
};
node *appendList(node *current, int newData) //Function to create new nodes in the list
{
node *newNode; //create a new node
newNode = new node;
newNode->data = newData; //Assign data to it
newNode->next = NULL; //At end of list so it points to NULL
newNode->prev = current; //Link new node to the previous value
current->next = newNode; //Link current to the new node
return newNode; //return the new node
}
node *createList(int maxLoop, node *begin, node *current, node *end) //Function to create list
{
//Allocate the starting node
current = new node;
current -> data = 1; //First data value is 1
current -> next = NULL; //next value is NULL
current -> prev = NULL; //previous value is NULL
begin = current; //This is the beginning of the list
for (int count = 2; count <= maxLoop; count++) //Loop to fill the list
{
current = appendList(current, count*count); //Create new nodes and fill with square numbers
}
end = current; //Now we are at the end of the list
return begin; //Return begin, this is the problem; I can't return end as well
}
void printForward (node *p) //Function to print the list forwards
{
node *curr = p; //current is the beginning value of the list
while (curr != NULL) //Continue while current is not at the end of the list
{
cout << curr->data << " "; //Print out the data of current
curr = curr->next; //Move one value along in the list
}
}
void printBackward (node *p) //Function to print the list backwards
{
node *curr = p; //current is the end value of the list
while (curr != NULL) //Continue while current is not at the beginning of the list
{
cout << curr->data << " "; //Print out the data of current
curr = curr->prev; //Move one value back in the list
}
}
int main()
{
//Initialize current, begin, and end
node *current = NULL;
node *begin = NULL;
node *end = NULL;
int maxLoop = 10; //The number of items in the list
cout << "The list has now been created." << endl;
begin = createList(maxLoop, begin, current, end); //function to create the list
cout << "Printed forwards, this list is: ";
printForward(begin); //Function to print the list forwards
cout << endl;
cout << "Printed backwards, this list is: ";
printBackward(end); //Function to print the list backwards
cout << endl;
return 0;
}
The purpose of this program is to create a list, print it forwards, backwards, insert an element, erase an element, and then destroy the list. I have chopped it down to just the create, print forward, and print backward functions.
The issue I have is that in the createList function I am modifying both begin and end but I can only return one or the other. This means that whichever I don't return is still NULL in the main function and therefore does not point to anything. I've tried setting the begin/current/end to not equal NULL but createList won't work if I do that.
Does anyone have any ideas for how I could modify both? Just to be clear, the list HAS TO be created in a function, it would be very easy to just initialize it in the main.
Thanks,
Tristan
Your problem is you're copying the pointers, when you should be passing them by reference, i.e., using a pointer-to-pointer or reference-to-pointer rather than just copying the value the pointer in main is originally pointing to. With what you're doing, you're unable to modify the original pointer variable that was declared in main ... passing-by-reference will allow you to-do that while also keeping all list setup code within your functions.
So for instance, change
node* createList(int maxLoop, node *begin, node *current, node *end)
to
void createList(int maxLoop, node** begin, node** current, node** end)
and then make sure to take the extra dereference into account in the body of your function
Finally, you would call it like:
createList(maxLoop, &begin, ¤t, &end);
And do the final assign to begin inside the body of the function of createList rather than in main.
#include <iostream>
using namespace std;
struct Node
{
int item; // storage for the node's item
Node* next; // pointer to the next node
};
Node* addNode(Node*& head, int data , int& count)
{
Node * q; // new node
q = new Node; // allocate memory for the new mode
q->item = data; // inserting data for the new node
q->next = head; // point to previous node ?? how would i do that? ( am i doing it correctly?)
count++; // keep track of number of node
head = q;
return q;
}
int main()
{
int a, count=0;
int data;
bool repeat;
Node *head= NULL;
//^^ assuming thats creating the first node ^^
do
{
cout << "please enter the data for the next node" <<endl;
cin >> data;
addNode(head, data, count);
cout << "do you wish to enter another node? (enter true or false)" << endl;
cin >>repeat;
}
while (repeat == true);
// assuming this is the print function
while(head != NULL)
{
cout << "output" << temp->item << endl;
cout << temp->next << endl;
}
system("pause");
return 0;
}
okey i tried adding a new element in the list how would i move the head around like a LIFO memory (stack) so the last element is on the very top..
any help would be appreciated ! The pointers and the nodes are messing with my brain lately ....
temp is an uninitialized pointer. So -
temp-> item = a; // temp is not initialized or pointing to a memory location
// that has Node object to use operator ->
First, temp needs to be allocated memory location using new.
temp = new Node;
temp -> item = a;
And now assign it head. Similarly allocate memory for the child nodes too in the while loop. And return all the resources acquired from child to head using delete before program termination.
You seem to have some misunderstandings here:
Your "head" is the start of the list. It's always the start.
You add append elements to a linked list by assigning them to the last node's next pointer.
Third, you're not allocating anything.
Node *head= new Node();
Node *temp = new Node();
cout<<"enter something into data"<<endl;
cin >> a ;
temp->item = a;
head->next = temp;
Now ... to add the next thing, you either need to keep track of the last node (tail), or traverse the list to find the last node.
Node *nextNode = new Node();
nextNode->item = 0.0;
Node *i;
for (i = head; i->next != null; i = i->next);
i->next = nextNode;
This is O(n) execution time. By keeping track of the tail you make it O(1):
Node *head= new Node();
Node *tail = head;
Node *temp = new Node();
cout<<"enter something into data"<<endl;
cin >> a ;
temp->item = a;
tail->next = temp;
tail = temp;
Node *nextNode = new Node();
nextNode->item = 0.0;
tail->next = nextNode;
tail = nextNode;
EDIT: As pointed out, if you want to prepend to the list, you would:
temp->next = head;
head = temp;
Since I'm not sure every answer completely answers it, here's a linked list implementation (written without testig:
// your (correct) structure
struct Node
{
float item; // storage for the node's item
Node* next; // pointer to the next node
};
Now we need two pointers somewhere to look after the list:
/* some pointers */
struct List
{
Node* head;
Node* tail;
};
Now we need to create some elements. As others have said, you can do that with new:
/* create some elements we want to link in */
Node* elem1 = new Node();
Node* elem2 = new Node();
Node* elem3 = new Node();
/* maybe even set their properties! */
elem1->item = 3.14;
elem2->item = 3.14;
elem3->item = 3.14;
Notice how I didn't try to add these elements to a list yet? That's because I've got a function in mind which looks like this:
void addtolist(List &list, Node* node)
{
/* if no head, initialise the list */
if ( list->head == NULL )
{
list->head = node;
list->tail = node;
}
else if ( list->head != NULL && list->tail != NULL )
{
/* access the tail element and set its
next to this ptr.
Move tail to this node */
list->tail->next = node;
list->tail = node;
}
else
{
/* probably raise an exception! */
}
}
You can call this by doing this:
List l;
addtolist(l, elem1); /* etc */
Deleting elements is somewhat more tricky, since you have to go to that element, remember its previous element, grab it's next element, join them up and delete the Node* you're on.
Now for traversing lists... your terminology HEAD|TAIL reminds me of Erlang and tail recursion, where the current element is referred to as the head and the remainder the tail. If I write:
Node* cur = l.head;
while ( cur != NULL )
{
// do something with cur.item ?
cur = cur->next;
}
You can see this happening. Replacing cur with head here would be harmless thanks to the List struct.
Finally, I've used a very C-like approach here, but there's scope for templates:
template<typename T>
struct node
{
T item; // storage for the node's item
Node<T>* next; // pointer to the next node
};
and encapsulating the List struct as a class:
template<typename T>
class List
{
protected:
Node<T>* head;
Node<T>* tail;
public:
void addtolist(Node<T>* node);
Node<T>* gethead();
Node<T>* gettail();
}
Which brings you a little bit closer to std::list.
Additionally note that you are doing an implicit cast from int to float on
temp-> item = a;
as a is an int, while temp->item is a double.
To solve your problem: You want to allocate a new structure before accessing temp, thus
temp = new Node();
I am trying to create my own datatype that is like a vector or an array.
I am having troubles with my print function; When I go to print the list, it only prints the last item in the list.
// LinkedListClass.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <iostream>
class Node
{
public:
int value;
Node* next;
Node::Node(int val)
{
value = val;
};
};
class List
{
public:
Node* firstNode;
Node* currentNode;
int size;
List::List()
{
firstNode = NULL;
currentNode = firstNode;
size = 0;
};
void push(Node* node)
{
if(firstNode == NULL)
{
firstNode = node;
firstNode->next = currentNode;
size++;
}
else
{
currentNode = node;
currentNode = currentNode->next;
size++;
}
};
void print()
{
if(firstNode != NULL)
{
Node* printNode = firstNode;
while(printNode->next != NULL)
{
std::cout << "List Item " << printNode->value << std::endl;
printNode = printNode->next;
}
}
};
};
int _tmain(int argc, _TCHAR* argv[])
{
List ll = List();
for(int i = 0; i < 10; ++i)
{
Node val = Node(i);
ll.push(&val);
}
std::cout << ll.firstNode->value << std::endl;
ll.print();
std::cout << "Size " << ll.size << std::endl;
std::cin.ignore();
return 0;
}
/* Output
9
Size 10
*/
I know this is nowhere near completed, but if you have any other pointers (lol), please feel free to suggest.
There are three important errors:
push() --- fixed
void push(Node* node)
{
if(firstNode == NULL)
{
firstNode = node;
currentNode = node;
// firstNode->next = currentNode; --> this does nothing useful!
size++;
}
else
{
currentNode->next = node;
currentNode = node;
//currentNode = node; -|
//currentNode = currentNode->next; -|----> why? what? Do explain.
size++;
}
}
I think by assigning firstNode->next = currentNode; you expected the next time currentNode was updated, it would update firstNode->next as well.
It doesn't work that way.
firstNode->next = currentNode; implies that the address stored in currentNode is now in firstNode->next. So next time you store something in currentNode = node; you're not storing it in firstNode->next. So you have a broken linked list --- which is why your output didn't go very far.
Also, this is really bad. By setting currentNode=node before setting the current node's next pointer to node, you've broken the list again. You should first point currentNode->next to node and then set the currentNode as node (node being the node which you're pushing onto your list).
Node val = Node(i);
The scope of val is only within that iteration of your loop. Once you loop around, it's off the stack and doesn't exist anymore. But you've copied the pointer of val to your list --- so now with the right push method, you're just adding a dangling pointer.
Node *val = new Node(i);
ll.push(val);
You need to put it on the heap so it stays on till you don't need it anymore.
... which leads us to your destructor!
Since you've allocated a node, you'll need to deallocate it. So do that in your destructor --- traverse your list and deallocate all those nodes.
The following lead to undefined behavior:
Node val = Node(i);
ll.push(&val); // take address of temporary
...
firstNode = node; // store address of temporary here
...
ll.print(); // temporary `val` was destroyed, but all nodes are point to it
You could change your code as follows:
Node* val = new Node(i);
ll.push( val );
And don't forget to delete all nodes later.
Your push() method is incorrect. The first time you push a node, it correctly assigns it to firstNode, but every subsequent push() just sets currentNode to the new node, and then sets currentNode to NULL -- you're not actually adding anything to your list.
I think it bears mentioning that pointers are not reference-by-name in C++. For instance, setting firstNode->next = currentNode doesn't make currentNode the next element in the list; it just makes firstNode->next point to the same address that currentNode does (in this case, NULL).
I'm not going to write the code for you, but here's how your push() function should work. The key is that you should be setting the 'next' field of an existing node to your new node, rather than currentNode to the new node:
In the case where firstNode is NULL,
set firstNode to the new node and
set firstNode->next to NULL (since
it has no next element). You can
also set currentNode = firstNode
here for convenience.
In the case where firstNode is not
NULL, we need to walk from firstNode
down the chain until we find a node
whose next field is NULL, then set
its next field to the new node.
Alternatively, we can use that
currentNode pointer to access the
last element in list and do the same
thing, being sure to set currentNode
to point to the new node when we're
done.
You basically have part 1 done, but part 2 still needs to be implemented. Feel free to ask for clarification/give criticism. :)
try it like Node* val=new Node(i)
previously u were storing the temporary variable. so no store the ndoe in dynamic memory so seprate memory can be given.
when u were creating the node it is create for temparary purpose
&temporary address were stored so when u traverse back the temporary memory had been released u will find there some garbage. value.