I'm trying to incorporate push/pop into a linked list and I can't seem to get it to work. When I run my test function, I set my linked list to zero and I try to push on values but the list keeps getting returned with no values in it. Could anyone possibly tell me what I'm doing wrong?
if (top == NULL){
current = top;
current->next = NULL; //NULL->next : will cause segfault
}
if top is NULL, you set current = top [which is NULL], and then you access current->next, which will cause a segfault, you are trying to access NULL..
EDIT: follow up to comments:
your if statement seems redundant, you should probably only need to set: current->next = head; and head = current; [in addition to the current allocation]
Instead of
if (top == NULL){
current = top;
current->next = NULL;
}
you want
if (top == NULL){
top = current;
current->next = NULL;
}
And of course, after this, you have to make sure that you actually set head to top again.
Now that you've made this change, it should be clear that both cases do the same thing -- so no case distinction is actually necessary. So the function can be simplified to
void push(Data * newPushData){
LinkNode * current = new LinkNode(newPushData);
current->next = head;
head = current;
}
The top variable is local variable for push(...) function. You can use head instead, and I'd rather modify the if statement.
I think that function should look like this:
void push(Data * newPushData){
LinkNode * current = new LinkNode(newPushData);
if (head != NULL){
current->next = head;
head = current;
}
else{
head = current;
current->next = NULL; // if you haven't done it in LinkNode constructor
}
}
can you please specify the attributes of the linked list class ? [ is there slightly chance you are doing something wrong]
Instead of you , I'd do :
void push(Data * newPushData){
if (head == NULL)
head->data = newPushData
tail = head ;
else // regular situation
{
Node * node = new Node() ;
tail->next = node;
node->data = newPushData;
node->next = NULL ;
tail = node ;
}
}
In a linked list you have got to maintain the head pointer point on the head of the list , maintain that the tail pointer is point on the tail of the list ,
You must take care of the 2 cases of enlarging the list.
the best way for learning is to illustrate an insertion on a blank linked list.
Take care
S
void push(Data * newPushData)
{
if( head != NULL )
{
LinkNode current = new LinkNode(newPushData);
current->next = head;
head = current;
}
else
{
head = new LinkNode(newPushData);
}
}
Try this code...
void push(data * newpushdata){
if(head !=null){
linkednode current = new linkednode(newpushdata);
current->next = head;
head = current;
}
else {
head = new linkednode(newpushdata);
}
}
that is my working solution for a Stack containing int elements, but maybe it's better to create a void pushStack using Stack **S instead of Stack *S.
in pop(Stack **S) i created a sentinel, so if the stack is empty -1 is returned.:
typedef struct StackT {
int val;
struct StackT *next;
} Stack;
int isStackEmpty (Stack *S) {
if (S == NULL)
return 1;
else
return 0;
}
int *pop(Stack **S) {
Stack *tmp = *S;
int i = -1;
if (isStackEmpty(tmp) == 0) {
i = tmp->val;
*S = tmp->next;
}
return i;
}
Stack *pushStack (Stack *S, int x) {
Stack *node = (Stack *) malloc (sizeof (Stack));
node->val = x;
node->next = S;
return node;
}
you can call pop and stack easly:
Stack *S = NULL;
int x = somevalue;
int y;
S = pushStack(S, x);
y = pop(&S);
Related
I am trying to delete a node from a linked list using this function:
void del_node(int del_data)
{
node* temp = NULL;
node* trail = NULL;
node* del_ptr = NULL;
temp = head;
trail = head;
while (temp != NULL && temp->data != del_data)
{
trail = temp;
temp = temp->next;
}
if (temp != NULL) {
del_ptr = temp;
temp = temp->next;
trail->next = temp;
delete(del_ptr);
}
}
It seems like it deletes it fine until i print the linked list using this:
void print()
{
node* temp = NULL;
temp = head;
while (temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
and it starts outputting seemingly random numbers, can anybody help me with this, really confused as this code comes from a tutorial.
Your algorithm doesn't manage the head pointer correctly whatsoever. Any changes that ultimately should modify the head pointer don't, and that's a huge problem. A pointer to pointer algorithm not only solves this problem, it also delivers a considerably more succinct solution:
void del_node(int del_data)
{
struct node **pp = &head;
while (*pp && (*pp)->data != del_data)
pp = &(*pp)->next;
if (*pp)
{
node *tmp = *pp;
*pp = tmp->next;
delete tmp;
}
}
This will work for any list condition including:
An empty list. i.e. head is null.
A single-node list. If the value matches head->data it will properly delete and reset the node pointer.
A multi-node list. The first matching node will be removed, and it will properly fix up the head node pointer if that was the matching location.
All of the above, in cases where there is no matching node, the list remains unchanged.
Fulfilling all of that in such a short algorithm + implementation is beneficial.
I'll comment on your code inline:
void del_node(int del_data)
{
node* temp = NULL;
node* trail = NULL;
node* del_ptr = NULL;
temp = head;
trail = head;
// This is fine, but recommend you use nullptr instead of NULL.
// This will find the first instance of data matches del_data,
// But if you are trying to delete all instances of del_data,
// You'll need to do this a little differently.
while (temp != NULL && temp->data != del_data)
{
trail = temp;
temp = temp->next;
}
// This if is fine, but see previous comment about using nullptr
// instead of NULL.
if (temp != NULL) {
del_ptr = temp;
temp = temp->next;
// Problematic: What if trail is null?
trail->next = temp;
delete(del_ptr);
}
}
Your code isn't bad. I wouldn't have written exactly like this, but I'm going to replace your if-statement:
if (temp != nullptr) {
// If trail is nullptr, then we're deleting from the head
if (trail == nullptr) {
head = temp->next;
}
else {
trail->next = temp->next;
}
delete(temp);
}
There's no need for the temporary. Just point around temp as you see in the if-else block and then delete temp.
i need to make a function to sum 2 piecewise linear functions (both decreasing or increasing) and insert them into a third list in an ascending order based on the x-axis coordinates of each point. So i have created multiple functions, all seem to check out except this one yet i do not know what's the problem. It's not inputting anything at all.
struct coords has double x,y;
dList has : coords pt;
node has : node *head, *tail;
node *prev, *next;
dList insert(dList L, coords point) {
node *temp;
temp = new node;
if (temp == NULL) {
cout << "error";
exit(1);
}
temp->next = NULL;
temp->prev = NULL;
temp->pt = point;
if (L.head == NULL || L.tail == NULL) {
L.head = temp;
L.tail = temp;
return L;
}
if (L.head->pt.x > temp->pt.x) {
temp->next = L.head;
L.head->prev = temp;
L.head = temp;
return L;
}
if (L.tail->pt.x < temp->pt.x) {
temp->prev = L.tail;
L.tail->next = temp;
L.tail = temp;
return L;
}
node *cur;
cur = L.head->next;
while (cur->pt.x < temp->pt.x)
cur = cur->next;
temp->next = cur->next;
temp->prev = cur;
cur->next->prev = temp;
cur->next = temp;
return L;
}
The case in which the node to be inserted is in the middle is the problem. You should be looking one node ahead instead of looking at the current one. Try working it out on paper and you will see how that makes a difference:
node * cur;
// also start at head here
cur=L.head;
while(cur->next->pt.x<temp->pt.x)
cur=cur->next;
temp->next=cur->next;
temp->prev=cur;
cur->next->prev=temp;
cur->next=temp;
You should also consider passing a dList L as a pointer to the function and also returning it as a pointer:
// this way you won't be making a copy of it, you may run into trouble if you don't have your copy constructor implemented
dList* insert(dList* L,coords point)
I hope that this helps you.
This is the first question that I'm posting on StackOverflow, so forgive me if it seems kinda choppy.
For my computer science class, we're working with a double linked list for the current assignment. One of the functions required is an insert function.
I actually found an insert function on StackOverflow earlier this week, but it was set up to use structures inside of the main file instead of separate class files like this project is using. I think the function can work, but I'm not sure what alterations I need to make so that it can work with class files instead.
LinkedList.h member data
private:
Node *head, *tail;
mutable Node *it;
int count;
Insert function
bool LinkedList::insert(const string & str) const
{
LinkedList * tempVar;
if (hasMore) {
resetIterator();
}
else {
Node * temp = new Node;
//temp = str;
temp->data = str;
temp->next = it;
temp->prev = nullptr;
it->prev = temp;
it = temp;
}
if (it != nullptr) {
Node * current = it;
Node * previous = nullptr;
Node * tempNode = nullptr;
while (current->next != nullptr) {
tempNode = current->next;
if (current->data > tempNode->data) {
swap(current->data, tempNode->data);
}
else {
previous = current;
current = current->next;
}
}
tempVar->count += 1;
}
return false;
}
I haven't been able to test it yet due to not knowing what alterations are needed, but the function should insert strings that are passed into the argument into the linked list, as well as sort them in a dictionary style. Right now the only error is that temp = str; not working, and I'm not entirely sure what I need to do to get it to work.
Try something more like this:
bool LinkedList::insert(const string & str)
{
Node * current = head;
while ((current) && (current->data < str))
current = current->next;
Node *newNode = new Node;
newNode->data = str;
newNode->next = nullptr;
newNode->prev = nullptr;
if (current)
{
if (current->previous)
{
current->previous->next = newNode;
newNode->previous = current->previous;
}
current->previous = newNode;
newNode->next = current;
if (current == head)
head = newNode;
}
else
{
if (!head)
head = newNode;
if (tail)
{
tail->next = newNode;
newNode->previous = tail;
}
tail = newNode;
}
count += 1;
return true;
}
That being said, you really should be using the standard std::list container instead of implementing a double-linked list manually.
I'm trying to insert an object (bird) that holds a name and an ID number
I'm having problems inserting the object into my linked list
bool List342::Insert(Bird *obj)
{
Node *insNode = new Node;
insNode->data = obj;
if (head == NULL)
{
head = insNode;
return true;
}
//cout << head->data->getID();
if ((insNode->data->getID()) <= (head->data->getID()))
{
insNode->next = head;
head = insNode;
return true;
}
Node *pNode = head;
while ((pNode->next != NULL) && ((pNode->next)->data->getID() <= insNode->data->getID()))
{
pNode = pNode->next;
}
insNode->next = pNode->next;
pNode->next = insNode;
return true;
}
It doesn't seem to insert correctly
I tried putting a cout code to see what numbers are being compared
for example
cout << head->data->getID()
and it seems to output the current id of the current bird
and not the id of the head (should be the lowest ID)
please and thank you!
I do not see where the function would return false. So I think there is no any sense to declare the function as having return type bool because it always returns true.
I have declared the functtion as having return type void though you may declare the function as having return type bool as before but in this case you need to add last statement that will return true.
Maybe it would be better to declare the function as returning a reference to the list itself.
The function could be defined the following way
void List342::Insert( Bird *bird )
{
Node *prev = NULL;
Node *current = head;
while ( current != NULL && !( bird->getID() < current->data->getID() ) )
{
prev = current;
current = current->next;
}
Node *newnode = new Node { bird, current };
if ( prev != NULL ) prev->next = newnode;
else head = newnode;
}
I suppose that Node has the following definition
struct Node
{
Bird *data;
Node *next;
};
You may substitute statement
Node *newnode = new Node { bird, current };
for
Node *newnode = new Node;
newnode->data = bird;
newnode->next = current;
The function is working fine for me.
I hope, the head is change outside of the insert function.
Shall you check the calling portion of the insert or any other places modifying the head value.
I was trying to write a code to reverse the linked list but getting wrong output.
Is there something I am missing.
Here is the function
void reverselinklist( struct node **headreverse)
{
struct node *p = *headreverse;
if(p->next == NULL)
{
*headreverse = p;
return;
}
reverselinklist(&(p->next));
p->next->next = p;
p->next = NULL;
}
After display function
Input 409765
Output 4
*headreverse = p is meaningless. You should set *headreverse = p->next each time to move forward, until the last node is reached.
Anyway, I changed your code to make it work:
void reverselinklist(struct node **headreverse)
{
struct node *p = *headreverse;
if(p->next == NULL){
return;
}
*headreverse = p->next;
reverselinklist(headreverse);
p->next->next = p;
p->next = NULL;
}
For single list use two two pointers, to update list as you can not go back.
Here is my code. Hope it will help you to understand concept.
void reverselinklist(struct node** head_ref)
{
struct node* first;
struct node* rest;
first = *head_ref;
rest = first->next;
if (rest == NULL)
return;
reverselinklist(&rest);
first->next->next = first;
first->next = NULL;
*head_ref = rest;
}
If it could me more precise please provide suggestions.
Your headreverse is not being assigned to the new head of the list. Be sure to use 2 arguments for your function, 1) head of the initial list 2) current node(same as your headreverse)
if(p->next == NULL)
{
*head = p; //instead of headreverse use head
return;
}