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
Related
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");
}
}
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);
}
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;
}
I'm trying to find a way of deleting a linked list without recursion, because a stack overflow isn't really something nice.
I have a struct as follows:
typedef struct _my_Item
{
_my_Item(const std::string& name)
{
m_name = name;
}
~my_Item()
{
delete next; // this recursively deletes the "tail" of the list
next = NULL;
}
struct _my_Item *next;
std::string m_name;
// ... More members here...
}
In some piece of code (not relevant here) I'm constructing a list from a data file using the above structure. I keep the pointer to the head of the list in a variable and can work with it. All fine.
When I finally call the destructor on the head of the list, the destructor gets called and the delete next; causes a recursion to delete the "tail" of the list (which is the entire list without the first element). Now since the list is quite long, I see a stack overflow sometimes.
Is there a nice way to get around this problem?
~my_Item()
{
while (next)
{
_my_Item* item = next;
next = item->next;
item->next = NULL; // this prevents the recursion
delete item;
}
}
Create a class representing the list itself that will encapsulate nodes deletion in its destructor via a for/while loop. Doing it the way you do leaves the possibility to delete part of the list and leave dangling pointer.
One suggestion would be to remove the delete code from the destructor and use a pointer to delete the list.
struct _my_Item * nodeToDelete = NULL;
while(firstNode != NULL)
{
nodeToDelete = firstNode;
firstNode = firstNode->next;
delete nodeToDelete;
}
// I wrote this java code to delete a node from BST
// I only used one recursion call to remove successor
public Boolean delete(int data){
if(isEmpty() || !search(data))
return false;
return delete(null,root,data);
}
public Boolean delete(Node parent,Node temp,int data) {
while(true){
if(data == temp.getData()) {
break;
} else if(data < temp.getData()) {
parent = temp;
temp = temp.getLeft();
} else {
parent = temp;
temp = temp.getRight();
}
}
if(parent == null && (temp.getLeft() == null || temp.getRight() == null)){
if(temp.getLeft() == null)
root = temp.getRight();
else
root = temp.getLeft();
} else if(temp.getLeft() == null || temp.getRight() == null) {
if (parent.getLeft() == temp) {
if (temp.getLeft() == null)
parent.setLeft(temp.getRight());
else
parent.setLeft(temp.getLeft());
} else if (parent.getRight() == temp) {
if (temp.getLeft() == null)
parent.setRight(temp.getRight());
else
parent.setRight(temp.getLeft());
}
}else{
int min = findMin(temp.getRight());
temp.setData(min);
delete(temp,temp.getRight(),min);
}
return true;
}
I've checked the boards and could not find any help with this. I find it easy to implement recursive functions given base and general cases, but this doesn't work the way I do it. I'm supposed to iterate down a list until I reach the tail of a linked list. If the next node is NULL, then I have to store the value at the last node, remove that node, and return the value. So it's similar to a dequeue method, except it's performed recursively. What am I doing wrong?
int LinkedList::removeTailRec(Node *n)
{
// check for the base case(s)
if(n->next == NULL)
{
Node *tmp = new Node();
tmp = n;
int val = n->value;
tmp = NULL;
return val;
}
else
return removeTailRec(n->next);
// else call the recursive method
}
First, I recommend you use nullptr instead of NULL.
Then, onto your code. You're actually not removing anything from your list.
if(n->next == NULL)
{
Node *tmp = new Node();
^^^^^^^^^^
//Useless, and dangerous. This memory is never free'd
tmp = n;
int val = n->value;
tmp = NULL;
^^^^^^^^^^
//You just set a local variable to NULL, you're not deleting anything
return val;
}
If you want to remove the node, you'll have to keep a reference to the previous node (e.g. having a doubly linked list, that is, having a pointer to the next element and a pointer to the previous element in each node, or working on the previous node directly).
Set this previous node's next to nullptr, store the node's value and then delete the Node pointer.
One way to do this is to work with the pointer to the next node :
int LinkedList::removeTailRec(Node *n)
{
//EDIT: Adding a check for n validity
if(!n){
//Here, you should have a way of detecting
//a call to your method with a null pointer
return 0;
}
Node* nextNode = n->next;
// check for the base case(s)
if(nextNode->next == nullptr)
{
//Get the next node value
int val = nextNode->value;
//Set the current node next member to nullptr
n->next = nullptr;
//Free the last node
delete nextNode;
return val;
}
else{
return removeTailRec(n->next);
}
// else call the recursive method
}
You are storing the result but not deleting it from linked list. You can return result in another variable (pointer : result).
Node* getTail(Node *n,int *result){
//u can even free the memory
if(!n->next)
{
result=n->value;
return NULL;
}
n->next=getTail(n->next,result);
}
or you can do it other way
int getTail(Node *n)
{
if(!n) return 0;
if(n->next)
{
if(!n->next->next)
{
Node *frnode=n->next;
int result=n->next->value;
n->next=NULL;
delete frnode;
return result;
}
getTail(n->next);
}
You are not removing last node in your code, and you leak another (temporary) node here.
To remove last node you have to zero the link in the previous node.
Your code should look like
...
if (n == NULL || n->next == NULL)
throw std::out_of_range("node");
if(n->next->next == NULL)
{
int val = n->next->value;
delete n->next;
n->next = NULL;
return val;
}
else ...
Be aware of the fact that c++ is not a functional language and has no optimizations for tail recursion, so in real application as your lists grow big enough you'll eventually have failure with stack overflow =) use Haskell or Erlang for this style of programming, in c++ use for or while.
You should set the Node n's previous Node's next field to NULL when n is the tail Node.