Inserting inside a Linked List - c++

My insertAfter function in the LinkedList is not working right.
I would really appreciate if someone could point out what's wrong with my code.
Thanks :)
Here is the list struct:
struct ListItem
{
T value;
ListItem<T> *next;
ListItem<T> *prev;
ListItem(T theVal)
{
this->value = theVal;
this->next = NULL;
this->prev = NULL;
}
};
and here is my function to insert inside the list:
template <class T>
void LinkedList<T>::insertAfter(T toInsert, T afterWhat)
{
if(head!=NULL)
{
ListItem<T>*p;
p=head;
while(p->next!=NULL)
{
if(p->value==afterWhat)
{
ListItem<T>*k;
k=new ListItem<T>(toInsert);
k->next=p->next;
p->next=k;
k->prev=p;
k->next->prev=k;
}
else
p=p->next;
}
}
else
{
head= new ListItem<T>(toInsert);
}
//p=NULL;
}

Firstly, no insertion should be made if, afterWhat is not found.
So, there will be no insertion when either: the list is empty, or afterWhat does not exist in the list.
Secondly, while(p->next!=NULL) loop will never check the last element of the list for afterWhat, because it ends its iterations one before the last.
So, if afterWhat is the last element in the list, it will go undetected.
Thirdly, the loop should be broken as soon as the insertion is done. Later the value of p can also determine whether afterWhat was found or not, and appropriate result can be displayed, if need be.
Fourth, now since the case of afterWhat being the last element is also being handled, we also need to check p->next!=NULL before making any changes to it, because it p could be the last element, in which case, nothing needs to be done for p->next.
Note that, you cannot insert an element in the head position using the insertAfter function, because nothing is before head, which can be used as afterWhat in this case.
The insertAfter function, should go like this:
template <class T>
void LinkedList<T>::insertAfter(T toInsert, T afterWhat)
{
if(head != NULL)
{
ListItem<T>*p;
p=head;
while(p != NULL)
{
if(p->value==afterWhat)
{
ListItem<T>*k;
k = new ListItem<T>(toInsert);
k->next = p->next;
p->next = k;
k->prev=p;
if(k->next != NULL)
k->next->prev = k;
break;
}
else
p = p->next;
}
if(p == NULL)
cout<<"afterWhat, not found, hence no insertion made\n");
else
cout<<"Inserted!\n";
}
else
{
cout<<"List is empty, hence afterWhat, not found\n");
}
}

Related

Deleting nodes of a value in a Linked List in C++

I'm practicing coding with some exercises from a website and I can't figure out what I'm doing wrong in this implementation. Can someone please let me know where I'm going wrong in my code?
The function removeElements should delete all the elements with the given value from the list. I'm trying to obtain that by using another function called removeElement (singular), and running that until it isn't able to remove anything.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool removeElement(ListNode* head, int val) {
if (!head)
return false;
ListNode* iterator = head;
//deal with case where head is value to be deleted
if (head->val == val) {
head = head->next;
delete iterator;
if (head == NULL)
delete head;
return true;
}
//head didn't match so iterate through list
while (iterator->next) {
if (iterator->val == val) {
ListNode* temp = iterator->next;
delete iterator;
iterator = temp;
return true;
}
iterator = iterator->next;
}//end while loop
//case where tail is value
if (iterator->val == val) {
delete iterator;
return true;
}
//otherwise return false
return false;
}//end function removeElement
ListNode* removeElements(ListNode* head, int val) {
//Keep calling removeElement until it returns false.
while (removeElement(head, val)) {
}
return head;
}
};
the way do delete something from a linkedlist is this:
iter->prev->next = iter->next;
iter->next->prev = iter->prev;
delete iter;
This requires a doubly linked list though, meaning that each element points to the previous element.
If you don't want (or are not allowed to) add this, you can do something like this:
if(iter->next && iter->next->val == val ){
node* deleteMe = iter->next;
iter->next = iter->next->next;
delete deleteMe;
}
Your removeElement method has a number of issues. For one, if it removes the head, the caller has no way of knowing that it's list pointer has now been deleted.
Functions that manipulate a list like this should take a pointer reference like this... bool removeElement(ListNode*& head, int val). This way if the function changes the value of head the caller gets the new value back.
Next, when iterating across a singly linked list like this you should always maintain a pointer to the previous element...
ListNode* current{head}, prev{nullptr};
while (current) {
// do something interesting
prev = current;
current = current->next;
}
In your case you want to remove nodes matching a given condition...
size_t removeElements(ListNode*& head, int val) {
size_t removed{0};
ListNode* current{ head }, prev{ nullptr };
while (current) {
// Use a nested while loop to check for the condition.
// This simplifies the conditions for the outer loop.
while (current->val == val) {
++removed;
ListNode* oldCurrent = current;
current = current->next;
// If this is the head element, update the head value for the caller
if (oldCurrent == head) {
head = current;
}
// Update the previous element in the list, if any
if (prev) {
prev->next = current;
}
// delete the removed element
delete oldCurrent;
}
prev = current;
current = current->next;
}
// return the number of element removed.
return removed;
}

Recursive way to delete the last element of a singly linked list?

int main(){
IntSLList list1,list2;
list1.addToHead(1);
list1.addToHead(2);
list1.addToHead(3);
list1.printAll();
IntSLLNode *p;
list1.assignvalues(p);
//p....p->next...p->next->next
//p refers to the first node of the linked list
return 0;
}
IntSLList* IntSLList::deletelast(IntSLLNode *p)
{
if(p==NULL || p->next ==NULL)//check this one as my base case
{
return NULL;
}
else
{
p->next = deletelast(p->next);
}
}
void IntSLList::assignvalues(IntSLLNode *p)
{
p=head;
}
Does anybody have any idea what I am doing wrong here? it says that p->next has the wrong data type to be assigned as it is...
Try this:
int main() {
IntSLList list1;
list1.addToHead(1);
list1.addToHead(2);
list1.addToHead(3);
list1.deletelast(list1->head);
list1.printAll();
}
void IntSLList::deletelast(IntSLLNode *p){
if (p->next->next == NULL) {
p->next = NULL;
return;
}
deleteLast(p->next);
}
Some corrections:
You can access the list's head directly with list1->head
The return type of deleteLast should be just void
The base case should be two nodes before NULL. Remember this is a singly list, if you stop at one node before NULL, how can you set the pointer of the previous node to not pointing to the current node? This list has only one direction, once you move forward, you can't go back
You do not actually need a recursion. It has the same time complexity as using loop. Both are O(n) time complexity
Assuming you want to return the abandoned item (the one that is de-listed from the list) from deletelast.
Try this:
IntSLLNode *IntSLList::deletelast(IntSLLNode *p)
{
IntSLLNode *pNextNext = p->next->next;
if(pNextNext == NULL)
{
// Next element is the last element, because
// the element after that does not exist (pNextNext)
p->next = NULL; // make this element the last element
return pNextNext; // we are returning the abandoned element
// so caller can make memory de-allocations
// or whatever with the abandoned last element
}
else
{
p->next = deletelast(p->next);
}
}
And you can call the recursive function like this:
IntSLList *pList;
// populate pList
IntSLLNode *abandonedNode = IntSLList::deletelast(pList->head);
// now you can do whatever you want with abandonedNode. Also, the
// variable pList still points to the list, now reduced by one element.
Solution: to delete last node of linklist using recursive function.
struct node* deletenodeback(struct node*list)
{
if(list==NULL || list->next==NULL) {
return NULL;
}
else {
list->next=deletenodeback(list->next);
return list;
}
}
main(){
struct node *h=NULL;
h=insert(h,2); //insert remaining nodes
h=deletenodeback(h);
}

Deleting a node in a linked list left some data

i've use this function to erase element with a particular value:
void eraseFromTable(ipTable * head,int sock)
{
while(head)
{
if(head->sockNumber == sock)
{
delete head;
break;
}
head = head->next;
}
}
This is the struct:
struct ipTable
{
char iPv4[INET_ADDRSTRLEN];
char iPv6[INET6_ADDRSTRLEN];
int sockNumber;
int ipv4;
int ipv6;
ipTable * next;
};
The problem is that when i use the erase function and then display again all the list
in the place of the node that've erased there's still sockNumber showed.
I've tried also free() function but it's the same.
How can i erase everything,pratically sconnecting that particular node?
You aren't doing two things:
Fixing the broken link from the node previous to the to-be-deleted node leading into it.
Reassigning the head pointer (which must be passed by reference / through a double pointer etc.) in case the node to be deleted is the head of the list.
Here's a fix (untested; also note I'm not really a C++ programmer so this may not be idiomatic - treat it as a general idea):
bool eraseFromTable(ipTable** headPtrPtr, int sock)
{
ipTable* headPtr = *headPtrPtr;
if(headPtr && headPtr->sockNumber == sock)
{
*headPtrPtr = headPtr->next;
delete headPtr;
// I'm assuming there can only be 1 matching entry;
// will need change otherwise.
return true;
}
ipTable* nodePtr = headPtr;
while(nodePtr)
{
ipTable* nextPtr = nodePtr->next;
if(nextPtr && nextPtr->sockNumber == sock)
{
nodePtr->next = nextPtr->next;
delete nextPtr;
// I'm assuming there can only be 1 matching entry;
// will need change otherwise.
return true;
}
nodePtr = nextPtr;
}
return false;
}

adding node at last in Linked List in C++

I have tried to implement Singly Linked List. My addAtLast() function is not getting executed properly. Program crashes while executing this function. Kindly suggest some changes.
class LList
{
public:
int noOfNodes;
Node const *start;/*Header Node*/
LList()
{
start=new Node;
noOfNodes=0;start=0;
}
void addAtFront(Node* n)
{
/*
cout<<endl<<"class"<<n;
cout<<"start"<<start;
cout<<"data in node";n->print();
*/
n->next=const_cast<Node*>(start);
start=n;
// cout<<" next=";start->print();
noOfNodes++;
}
void addAtLast(Node* n)
{
Node *cur=const_cast<Node*>(start);
if (start==NULL)
{
start=n;
return;
}
while(cur->next!=NULL)
{
cur=cur->next;
}
cur->next=n;
noOfNodes++;
}
int getPosition(Node data)
{
int pos=0;
Node *cur=const_cast<Node*>(start);
while(cur!=NULL)
{
pos++;
if(*cur==data)
{
return pos;
}
cur=cur->next;
}
return -1;//not found
}
Node getNode(int pos)
{
if(pos<1)
return -1;// not a valid position
else if(pos>noOfNodes)
return -1; // not a valid position
Node *cur=const_cast<Node*>(start);
int curPos=0;
while(cur!=NULL)
{
if(++curPos==pos)
return *cur;
cur=cur->next;
}
}
void traverse()
{
Node *cur=const_cast<Node*>(start);
while(cur!=NULL)
{
// cout<<"start"<<start;
cur->print();
cur=cur->next;
}
}
~LList()
{
delete start;
}
};
void addAtLast(Node* n) {
Node *cur=const_cast<Node*>(start);
if(start==NULL) {
start=n;
n->next = NULL;
noOfNodes++;
return;
}
while(cur->next!=NULL) {
cur=cur->next;
}
cur->next=n;
n->next = NULL; // Added
noOfNodes++;
}
I mentioned this in-comment, but will address it here as an answer. The caller of this function must ensure two things:
That the passed-in node list (and it is a list, even if only one element long) must be properly terminated with an end-next-pointer set to NULL. The caller must ensure this, as this code cannot assume it and blindly set node->next = NULL;
Make absolutely sure the caller is aware that once this executes, this list now owns the passed-in node and any list it potentially starts and the caller, therefore, must NOT free it, or anything it points to, on the caller side.
Apart from the node-count management issue, there is nothing wrong with the addAtLast() function, though I would have implemented it a little differently:
void addAtLast(Node* n)
{
// no nulls allowed
if (n == NULL)
return;
// set start if first in list
if (start == NULL)
{
start = n;
noOfNodes = 1;
}
// else walk list to find end
else
{
Node *cur = const_cast<Node*>(start);
while(cur->next != NULL)
cur = cur->next;
cur->next = n;
++noOfNodes;
}
// adjust count to contain any nodes from 'n'
while (n->next != NULL)
{
++noOfnodes;
n = n->next;
}
}
From the beginning..
start=new Node;
noOfNodes=0;start=0;
Should this be?
start=new Node;
noOfNodes=0;start->next=NULL;
Within 2 lines you've created memory leak. I have no idea why you would want to set start=0. Don't do that, you've just assigned memory to it!
As for the crash, it's addressed by #liulinhuai's answer. You'll be dereferencing a pointer that is uninitialized attempting to get it's next member.
In your ctor you set start as 0. In your crash function you first check it for NULL:
if (start==NULL)
{
start=n;
//n->next is now points to nowhere
return;
}
Next call to addAtLast iterate until it finds NULL but previous assign didnt set next pointer to NULL so second iteration will cause an access violation:
while(cur->next!=NULL) {
//first time it's ok but second call on cur will crash
cur=cur->next;
}
Solution is - all new Node's must have next pointer setted to NULL

Simple Linked List Implementation in C++

I'm a programming student in my first C++ class, and recently we covered linked lists, and we were given an assignment to implement a simple one. I have coded everything but my pop_back() function, which is supossed to return a pointer to the Node that needs to be deleted in Main(). No Node deletion is to be done in the actual function. So my question is:
Would you be willing to help point me in the right direction for my pop_back() function? Also, if you notice anything else that I'm doing wrong, let me know.
Also, this linked list is just to work with strings. In this case, a grocery list, so one string for the quantity of the item(1,2), and one string for the item type. (Milk, Eggs, etc.)
Below I've included my List & Node class implementations, so you can get an idea of what I've done so far.
Node.cpp
Node::Node(void)
{
descrip = " ";
quantity = " ";
previous = NULL;
next = NULL;
}
Node::Node(string q, string d)
{
descrip = d;
quantity = q;
previous = NULL;
next = NULL;
}
Node* Node::GetNext()
{
return next;
}
Node* Node::GetPrevious()
{
return previous;
}
void Node::SetNext(Node * setter)
{
next = setter;
}
void Node::SetPrevious(Node * setter)
{
previous = setter;
}
List.cpp
List::List(void)
{
first = NULL;
last = NULL;
numNodes = 0;
}
Node* List::GetFirst()
{
return first;
}
Node* List::GetLast()
{
return last;
}
void List::SetFirst(Node* setter)
{
first = setter;
}
void List::SetLast(Node* setter)
{
last = setter;
}
int List::GetNumNodes()
{
return numNodes;
}
void List::push_front(Node* item)
{
if (first == NULL)
{
first = item;
last = item;
}
else
{
Node* pFirst = first;
item->SetNext(pFirst);
first = item;
numNodes++;
}
}
void List::push_back(Node * item)
{
if (last == NULL)
{
first = item;
last = item;
}
else
{
last->SetNext(item);
last = item;
numNodes++;
}
}
Node* List::pop_front()
{
Node* temp = first;
first = first->GetNext();
if (first == NULL)
{
temp = first->GetNext();
first = p;
}
if (first == NULL)
{
last = NULL;
}
if (numNodes > 0)
{
numNodes--;
}
return temp;
}
Node* List::pop_back() // this whole function may be wrong, this is just my attempt at it
{
Node* temp;
temp = first;
while((temp->GetNext()) != NULL)
// im stuck here
}
Some pointers:
0x1243bfa3
0x45afc56e
0xdeadbeef
Some more pointers:
You should prefer to initialize your class members in the initialization list, not in the constructor's body.
In C++, unlike C89, we declare and define a function with no parameters as void f();, not void f(void);.
In C++ we commonly reset pointers with 0, not NULL.
See below for what I mean in code.
Good C++ code will try to take advantage of RAII. This implies avoiding primitive pointers for the most part. In this case plain old std::auto_ptr<> would make a perfectly sufficient substitute for the primitve Node* pointers. However, I do reckon part of the exercise here is pointer arithmetics, and so I just leave this as a side-note.
It would be useful for us if you'd attach the class declarations. I assumes all those accessors and mutators, GetFirst() and SetFirst() etc., are there because they are public. That's a bad idea. First, they expose the private pointers, which defeats the whole point of accessor. Second, they don't do anything special so they're just extra code -- which means extra room for bugs. This brings me to the next point.
Your mutators are incorrect. You blindly assign a new value to the private member pointer, without deleting what you had before. That's a memory leak.
Ever tried to pop_front() when the list is empty?
Finally, 8 being a round number it's time we get to the question at hand. pop_back(). My question to you is, why are you traversing the list all the way to the end if you so meticulously maintain a pointer to the last node of your list? Indeed, if you wouldn't bother with maintaining a pointer to the end of the list then you'd have to traverse all the way to the last node in order to pop it. And for that you were in the right direction. Except that ...
When you access members through pointers, as in first->GetNext(), always make sure first isn't a null pointer -- or else state in the function's documentation comment that you assume the pointer is not null.
These should get you started.
Points 1, 2 and 3 in code:
Node::Node()
: descrip(" "), quantity(" "), previous(0), next(0)
{
}
So if I understand this right you just want to run through your linked list until you get to the last node in the linked list and return the pointer to it?
I'm pretty sure what you have there will do it except
Node* List::pop_back() // this whole function may be wrong, this is just my attempt at it
{
Node* temp;
temp = first;
while(temp->GetNext() != NULL)
{
temp = temp->GetNext();
}
return temp;
}
So if I read it right, there it will continually loop around until it gets to the node with none in the line behind it, then return it.
I like the previous posters answer, but one thing you might want to keep in mind is if you have an empty list. Then your first pointer will equal NULL and you would be trying to call NULL->GetNext() basically and Seg Fault. I think you can edit the above code slightly and still get have it work like this:
Node* List::pop_back()
{
Node* temp;
temp = first;
while(temp != NULL && temp->GetNext() != NULL)
{
temp = temp->GetNext();
}
return temp;
}
This will have the function return NULL if there is nothing in the list and still work properly.
It would definitely have helped me if you also had posted your class declaration. I cannot guarantee that the below is correct but it makes sense to me
Node* List::pop_back()
{
Node *temp = NULL;
if(numNodes == 1)
{
temp = first;
// setting the list pointers to NULL
first = NULL;
// setting the list pointers to NULL
last = NULL;
//You should also probably remove the links from your node
//to the next and previous nodes but since you didn't specify
//this it is up to you
numNodes--;
}
else if(numNodes > 1) //more than one element
{
//the pointer you want to return
temp = last;
//For clarity I am creating another variable here
Node *newLast = temp->GetPrevious();
//Setting the new last node to point at nothing so now temp
//is "disconnected from the list"
newLast->next = NULL;
//the last pointer of the list is now pointing at the new last node
last = newLast;
//You should also probably remove the links from your node
//to the next and previous nodes but since you didn't specify this it is up to you
numNodes--; //decrement the counter
}
return temp;
}