Changing a line in linked list reversal causes error - c++

This question is probably one of the most popular questions around and while searching for a solution, I've found many but the code below was the most suitable for me.
What it actually does is that it creates another list and iterates through the old list and add the element always to the head of the new list.
Node *reverseList(Node *oldList)
{
Node* newList=NULL;
while(oldList!=NULL)
{
Node *temp=oldList;
oldList=oldList->next;
temp->next=newList;
newList=temp;
}
return newList;
}
However when I decided to re-implement this idea without looking at this code I've changed place of the oldList=oldList->next; and put it after the newList=temp.
My question is does it really make a difference? I couldn't comprehend the reason because after all you are iterating through the oldList. Why would it require to be done immediately after the *temp declaration?

After doing
Node *temp = oldList;
both pointers point at the same place. Since
temp->next = newList;
will overwrite the next pointer of oldList (because it points to the same thing as temp at this stage), you need to update oldList from its next pointer first.

Related

How to add a linked list to itself?

Considering that this is my function:
void addtoSameList(const List &another){
for (Node *temp = new Node(*head); temp != nullptr; temp = temp -> next){
Node *ptr = other.head;
Node *temp2 = new Node;
temp2->value = temp->value;
while (ptr -> next != nullptr) {
ptr = ptr -> next;
}
ptr->next = temp2;
temp2->next = nullptr;
}
return;
}
where my goal is to append a linkedlist to itself, I do not know exactly what goes wrong.
If, for example, I have a linkedlist called n in the main function, where I then declare:
n.addtoSameList(n);
meaning that &other is going to be pointing at the same node as n, I figured that I would make a new node and deep copy the contents of n.
However, my two outputs are either that I end up in an infinite loop, or that some node ends up getting skipped.
How do I fix this issue?
This code has numerous issues. First, the interface doesn't suggest that the only use is to append a linked list to itself. Nor does it suggest that a deep copy is necessary in any other case.
So, lets adjust the requirements...
You want a member function that will append a copy of a linked list to the existing one. Then the case of self-appending naturally falls out of the problem description.
The approach here would be to step through the linked list that is passed in, carefully copying each node, then re-adjusting the pointers on the main linked list to point at your new node and the pointer in the new node to be set to appear to be the end of the list. This maintains a list invariant as the list is stepped through.
There is a pitfall here though. If you are self appending, you risk creating an infinite loop. So you should find the end node of the passed in list before you start this process and consistently use it to find out if you've gotten to the end of the list. If you maintain a tail pointer, this is trivial. If you don't, it means a list traversal.
Another way would be to simply create a copy first, carefully maintaining the pointer to the first node of the copy. Then just adjust the tail node's next pointer to point at the new list, and then adjust the tail node (if you maintain that pointer in the LinkedList data structure) to point at the tail node of the copy. And that's probably the way you should go. It's cleaner and more efficient. The main drawback is cleanup when doing exception handling. But, at your level, you shouldn't be concerned with that right now.
Here's an alternate approach. Create three pointers: ptrBegin, ptrEnd and ptrNew. ptrBegin points to the beginning of the linked list and traverse the linked list so that ptrEnd and ptrNew point to the last element of the linked list. Then increment ptrBegin until ptrBegin != ptrEnd at the same time copying the data at ptrBegin to a new node at ptrNew->next and increment ptrNew.

Deleting the last node in the linked list

Please can you explain to me how this function deletes the last node in a single linked list
void deleend()
{
Node *q;
Node *p;
for (q = head; q != NULL; q = q->next)
{
p=q;
p->next=NULL;
}
delete q;
}
The deletion of the last item of a list is a pretty simple algorithm.
You need to loop throught the whole list until you reach a node with the next pointer equals to NULL. This is your last element, the element you want to delete.
So you need to free the memory allocated by this object and set the next pointer for your previous item to NULL. This is the most important thing since it avoids to get segfaults.
Now, about the code you posted, I see you are doing something pretty bad.. you're declaring *q and *p, then looping throught your list (pointed by a global Node* head, I suppose).
The issue is that with the code in your loop you're unlinking the first item from the linked list and then the loop ends because You're copying the pointer q in p and then setting it's next pointer tu Null which leads to setting q->next to NULL. The first iterations goes ""fine"" leading you to have the first element with next set to Null the second iteration finds the next set to Null and thus it stops.
NOTE: Before posting the code solution I'd like to know if you have pretty clear in mind what the algorithm purpose is, try make an attempt to fix your code, if you can't do it again I'll post the correct algorithm :)

How to change my Linked-List insert function from O(N) to O(1)

I implemented my linkedList function which inserts at the end, but I used the brute force method going through until the end and then adding it. I would like to change it to O(1). If you guys have any tips that would be great.
The only way to make this O(1) is to maintain a reference to the last Object in your List object. Whenever a new object is inserted at the end of the List, the pointer is updated to point to it.
Your actual problem has already been answered: Store an additional tail pointer at which you can insert without looping over the entire list.
But also take a look at your code:
for (node; node->getNext() != NULL && node->getNext()->getElement() != data;)
node= node->getNext();
node->setNext(insertNode);
The second condition in the for loop looks kind of weird to me. In case you would want to append a new element with element == data, your loop would stop at any existing element with that value and you would attach your newly allocated element just before it ... and lose all old elements starting with the existing node with element == data. Looks like a bug go me.
As other people have said, you need to add a tail node to your list, and then you can use this implementation for insertAtEnd():
template <class Object>
void List<Object>::insertAtEnd(const Object& o)
{
ListNode<Object>* insertNode = new ListNode<Object>(o, nullptr);
if (!head) head = insertNode;
if (tail) tail->setNext(insertNode);
tail = insertNode;
}

Just trying to insert a node and set the pointer in it to the next node C++

I feel really silly asking this, as it seems really simple, but I just can't figure it out. All I want to do is set the node pointer to the next node in the list. The function is from a teacher, I wrote the body, so I don't want to mess with the head of the function.
void LList::insert(int num, int at)
{
node* n = new node(num);
if (!n) throw runtime_error("Can't allocate node!");
if(!root || at == 0){
// if empty list - new node is root…
if (!root) root = n;
}
if(root){
node* nextNode = new node(num);
int numF = 0;
for (node* t = root; t != NULL ; t = t->next){
numF++;
if(numF == at){
n->next=t->next;
t->next=n;
}
}
}
}
Since it seems you are using n for the new node to be inserted into the linked list (I'm inferring that it's a singly linked list from the existing code and class name), there are a few things you have to do off the top of my head:
Identify the existing member of the list after which the new node will be inserted. You are making an attempt to do this already with that for loop, but in my opinion you may want to rewrite that as a while loop since you probably don't want it to keep iterating after the insertion position has been identified. Alternately, you could short-circuit out of the for loop with a break once you've found the right place for insertion, but I don't like that for stylistic reasons. :)
Set the newly inserted node's next pointer to the same location to which the next pointer of the node identified in #1.
Set the next pointer of the node identified in #1 to point at the new node, thus re-establishing the integrity of the chain.
Your code looks like it is attempting to do #2 and #3 out of order, which won't work. You're obliterating the value of t->next before you've had a chance to point n->next at it.
Finally, you may need to define some behavior to which you can fall back in case you are adding to a position not already defined in the list (i.e. inserting into the fourth position of a linked list that currently has three elements). You may need to re-jigger your loop to terminate when t->next is null rather than when t itself is null - otherwise you lose the hook to be able to connect the (currently) last element of the list to your new node.

How to make a linked list in using structs?

I've seen a few topics about linked lists, and I've read enough to glean how to do it generally, but I want to make sure I'm not wrongly interpreting the information I've gathered.
Let's say I have:
struct element
{
int val;
element *next;
};
The element *next is a pointer to an element, which will be used to connect the elements together in order to form the linked list.
I've also gathered that you need to have some kind of "tie off" so you don't lose your list. My professor describes it as a trail of balloons, and if you dont have a "tie off" your list can get lost.
So I start off with creating the "tie off" pointer:
element first;
first -> *next = 0; // or null
This is where I get lost... How do I add to the head of a linked list? Ordering it isn't important at this point, I just need to start with an unordered list, I'll get more complicated later.
Something like this?
element addMe;
addMe -> val = 100;
first -> next = *addMe;
Is that right?
What would I do to add something to a non-empty list?
Thanks for the time!
Edit: This is not homework. We have gone over linked lists, and have done an assignment with them. I did not get a very good grade on the assignment, so I am trying to strengthen my understanding before the next assignment. We will use linked lists again.
Edit2: Thanks!
I do not know if this would be considered "homework" or not. I personally do not think it is, considering I will not be using the code I posted here.
With singly-linked lists, the efficient way to add new elements is putting them at the beginning of the list. For your design, this would be:
element newHead;
newHead.next = &list;
You'll notice that newHead is now the first element, and list no longer represents the whole list. This leads to a more functional programming style, where you are creating new lists all the time (see: the cons function in Lisp).
Procedural languages like C++ generally use some wrapper structure like this:
struct list
{
element * first;
void prepend(element * elt)
{
elt->next = first;
first = elt;
}
}
so list prepends are expressed as changing an existing list instead of creating a new one.
With such an auxiliary structure, it is also trival to keep track of the list size, and keep a pointer to the last element for fast appends. These both come at the cost of a few extra instructions for every list operation.
You generally store a pointer to the first node:
element* first = &first_node; // this "ties" it off
first->val = 5; // set first node value to 5
first->next; // pointer to next node
If your list is empty then first should be set to NULL.
Also, the last node in your list should have next be set to NULL.
you got to have a first pointer or head pointer or whatever you may call it. its the pointer that is NULL when your linked list is empty. But when you add first element to the linked list add that elements node address to the hear/first pointer too. and from the 2nd node onwards append the new nodes address to end of the list (node whose next pointer is NULL) or at the star by changing head/first and then adding the current head to new head's next.
I don't know if such theory has helped. Just follow examples or write your own code. and if you encounter errors post it on SO. i guess linked list , queue, stack , etc are available on all c or c++ books.
or search for linked list in SO.
this might do for a start: Simple C++ Linked List
If you want to add to the head of the list
struct element *el = (element *) malloc(sizeof(struct element));
el->val = 100;
el->next = first;
Now el is the first element, and first is the second.
In your example, you where overwriting the first element next element with a new one. You where cutting the list and inserting your new element as the second element. Everything after first is now off the list (which is also a list, but you can't access it, since you overwrote the pointer to this 3rd element).
To add to the end of the list, iterate
struct element *e;
e = first;
while (e->next !=0)
e = e->next;
// here e is the last element. Allocate a new one and point e->next to it. And set this new one next to 0.