Sorting Nodes (Linked-list) C++ - c++

I'm trying to sort a linked-list. I have a Node called head and it's pointing to the next node, etc.
But when I try to sort the Nodes by the value they carry, I get the sort working because I see it printing out the stuff in the if-statement, but I'm not getting back the linked-list. Where did I go wrong?
Node* head;
void sortlist(){
Node * runner = head;
Node * runner2;
for(runner = head; runner->next != NULL; runner = runner->next){
for(runner2 = runner->next; runner2->next != NULL; runner2 = runner2->next){
if(runner->freq < runner2->freq){
cout<< runner->freq<< " is LT "<<runner2->freq<< endl;
Node * temp = runner;
runner = runner2;
runner2 = temp;
}
}
}
head = runner;
}
I'm only getting back the first Node.

In order to swap two elements in a linked list, consider what you need to change. For example, to get from
Head -> First -> Second -> (NULL)
to
Head -> Second -> First -> (NULL)
you need to update: Head.next, First.next and Second.next. You don't change any of those things when trying to swap nodes, so it can't possibly do what you expect.
Just swapping the values (ie, swap(runner->freq, runner2->freq)) would be much simpler.

you will stop when runner->next == NULL;, which is supposed to be the last element. And then you set head = runner;, which means the head will always be the last element after this routine. Furthermore, I do not trust this swapping.
It seems you vaguely want to do an insertion sort. If you want to do a simple sorting on linked lists, I suggest you to use selection sort: You create another empty list l2, and each time you remove the minimum element from your first list, and add it as the head of l2. The code for the second list is simple:
void prepend(Node* node, Node** list){
//null checks if you want
node->next = *list;
*list=node->next;
}

Related

Creating a second singly-linked list in reverse order of another list

I need to create a function that takes a normal singly-linked list and creates another list in reverse order of the first list, the first element in the new list will be the last element in the original list and so on.
My function for some reason only ever returns the same number over and over for the entirety of the new list. Therefore, if the last number in my original list is e.g. '50', the new list will be made up entirely of '50's.
This is my code, what am I doing wrong? If anyone wants me to post the whole program for more clarity or context give me a shout.
void invert() {
node *list1=top,*newlist,*temp,*prev;
while (list1->next!=NULL) {
list1=list1->next;
}
newlist=new node;
newlist->num=list1->num;
newlist->next=NULL;
if (top2==NULL) {
top2=newlist;
}
else {
for (temp=top2;temp!=NULL;temp=temp->next) {
prev=temp;
}
prev->next=newlist;
}
list1->next=NULL;
}
Your code cannot be correct as it creates only a single new node and then modifies the next link in existing nodes. From your requirements, you have to create a new list which means cloning all nodes and linking them in the reverse order.
Following the suggestion of #user4581301, I came up with the following:
node* invert(node* list)
{
node* inverted = NULL;
// run through original in order
for (node* p = list; p != NULL; p = p->next)
{
// clone the node
node* newNode = new node();
newNode->num = p->num;
// and link it so that the predecessor in the original list
// (which has been processed in the previous iteration) is
// linked as next node
newNode->next = inverted;
inverted = newNode;
}
return inverted;
}

Indexed singly linked list

I want to create a singly linked list with. I already have an implementation that does not permit indexing on it.
I would like to add this feature but I am not sure how to do that.
So basically the head should have index "1". But I can't figure it out myself what am I supposed to do in If statement to increase the index by 1 each step.
void AddNode (int addData)
{
nodePtr NewNode = new node;
NewNode->next = NULL;
NewNode->data = addData;
if (head != NULL)
{
curr = head;
while(curr->next != NULL)
{
curr = curr->next;
}
curr->next = NewNode;
NewNode->index;
}
else
{
head = NewNode;
NewNode->index = 1;
}
}
You mean for the ability to do something like get a linked list node via a get(index)?
Also, your head should not have index 1, it should be 0. This does not comply with standard practice of zero-based indexing.
A linked list does not technically have indexes nor should it store them. It seems like a linked list might not be the right data structure for what you are doing, however you can treat it like so with a loop like this (excuse if my c++ syntax is rusty)
int get(int index) {
Node current = head;
for (int x = 0; x < index; x++) {
if (current->next == null) {
//some sort of error handling for index out of bounds
} else {
current = current->next;
}
}
return current->data
}
get(2) would return the 3rd element of the list.
Graph for the structure
Why do you want to add it to the end of the list? Just simply add the new node to the front.
I don't think it is necessary to follow the order of 1,2,3.... Instead, you can do it reversely
Before you add a new node, you visit the head and find the index(i)of it. When you add the new one, the index of this one will be i+1.
Two advantages:
- It doses not change anything when you loop through this list.
- You know how many you have added into this list.
So what you really want to do is to add the ability to index elements of a linked list.
There is no need to actually store the index anywhere (as you don't really store the index of an array/vector element as the type and the address of the first element of the array is everything you need to retrieve the i-th element).
The only information you want to keep is the length of the list since computing it is costly because you have to traverse the list from head to tail every time you need it. Once you have this information the addNode should only update the size of the list.
As you already know accessing the i-th elements of a linked list is also costly (compared to a vector), but it is easy to code.
Something like the following should work:
void get(Node* head, size_t pos) {
while (head && pos--)
head = head->next;
return pos<=0 ? head : nullptr ;
}
It traverses the list from the head until it either reaches the end (head is nullptr) or pos is <=0.
Once you are out of the loop if pos>0 means that the list is shorter than pos otherwise you can return head (which will point to the pos-th element)

Using an array of pointers-to-pointers to manipulate the pointers it points to (C++)

I've been doing this as an exercise on my own to get better at C++ (messing around with a linked list I wrote). What I want to do is to reverse the list by twisting the pointers around, rather than just 'printing' the data out in reverse (which is relatively straightforward).
I have an array of pointers-to-pointers, each pointing to a node in a linked list. But this is less a question about linked-list dynamics (which I understand), and more about pointer magick.
A node looks like this,
template<class T>
struct node {
T data;
node *next;
node(T value) : data(value), next(nullptr) {}
};
And the code in question,
node<T> **reverseArr[listLength];
node<T> *parser = root;
for (auto i : reverseArr) {
i = &parser;
parser = parser->next;
}
root = *(reverseArr[listLength - 1]);
for (int ppi = listLength - 1; ppi >= 0; --ppi) {
if (ppi == 0) {
(*reverseArr[ppi])->next = nullptr;
//std::cout << "ppi is zero!" << "\t";
}
else {
(*reverseArr[ppi])->next = (*reverseArr[ppi - 1]);
//std::cout << "ppi, 'tis not zero!" << "\t";
}
}
My logic:
The new root is the last element of the list,
Iterate through the array in reverse,
Set the current node's next pointer to the previous one by setting the current node's nextNode to the next node in the loop.
What's happening:
If I leave the debug print statements commented, nothing. The function's called but the linked list remains unchanged (not reversed)
If I uncomment the debug prints, the program seg-faults (which doesn't make a whole lot of sense to me but seems to indicate a flaw in my code)
I suspect there's something I'm missing that a fresh pair of eyes might catch. Am I, perhaps, mishandling the array (not accounting for the decay to a pointer or something)?
You're overthinking the problem. The correct way to reverse a single-linked list is much simpler than you think, and does not involve arrays at all.
All you need to do is walk through the list setting each node's next pointer to the head of the list, then set the head of the list to that node. Essentially, you are unlinking each node and inserting it at the start of the list. Once you reach the end, your list is reversed.
It just requires a bit of care, because the order that you do things is important. Something like this should do it:
template <class T>
node<T> * reverse( node<T> * head )
{
node<T> *current = head;
head = NULL;
while( current != NULL )
{
// store remainder of list
node<T> *remain = current->next;
// re-link current node at the head
current->next = head;
head = current;
// continue iterating remainder of list
current = remain;
}
return head;
}
The operation has a linear time complexity. You would invoke it by passing your list's head node as follows:
root = reverse( root );
It should go without saying that it would be a bad idea to call this function with any node that is not the head of a list, or to pass in a list that contains cycles.

Return a pointer to a sorted list; linked list in C++

i want this function sortPair to take 2 Node pointers and return a pointer to a list of the 2 elements sorted alphabetically. The code below is what I have so far. If someone could let me know where I went wrong, that would be great.
struct Node{
string val;
Node* next;
};
Node* sortPair (Node* p1, Node* p2){
//Assert that neither pointer is null
assert(p1!=NULL);
assert(p2!=NULL);
Node* head=NULL;
Node* current=NULL;
Node* last = NULL;
current = new Node();
if(p1-> val >p2-> val) //If p1->val comes before p2->val in the alphabet
{
current->val = p1->val;
head = current;
last = current;
current = new Node();
current -> val = p2->val;
last = current;
last ->next = NULL;
}
else
{
current->val = p2->val;
head = current;
last = current;
current = new Node();
current -> val = p1->val;
last = current;
last ->next = NULL;
}
return head;
}
A linked list is just a series of nodes that are linked by each element having a pointer to the next one.
From your code, it seems like you do not want to make a list of the two nodes, but rather insert a node into a list that already exists.
If all you want to do is to make a linked list of the two nodes that are there, then set the one with the lower or higher value, depending on how you sort them, to point at the other one. For example, if you are sorting from smallest to biggest, set the smallest node's next pointer to point to the bigger one and return the pointer of the smallest one.
If you want to add one of the nodes into a list of nodes, then you must loop through the list until you find one that is larger or smaller than the node you want to insert. I recommend using a while loop.
If you want to merge two lists, then you must make a new loop that inserts each element of one list into the other list.
There is no need to make a new node for any of this, just use the ones you have and change the next pointers.
Hope this helps.

c++ understanding a circular doubly linked list

I'm having a problem figuring out how to set my ptr's for prev and next when I add a node with at least one existing node. Adding the first node is easy, just setting the ptrs to the front. I need help viewing this mentally, also this program is a queue so each node gets added to the back of the list.
if (Empty())
{
front = new qnode;
front->next=front;
front->prev=front;
front->data = item;
}
else if (front->prev=front)
{
front->prev = new qnode;
front->prev->next= front;
front->next=front->prev;
front->prev->data = item;
}
else
{
}
What i have now still not getting it
else
{
front->prev= new qnode;
front->prev->data= item;
front->prev->next=front;
front->prev=front->prev->prev;
}
I hope this image helps a bit
I have created pictures for 1 item 2 items and 3 items
the pointers just point to the actual object meaning the black rectangle is the whole object if front being blue and prev being brown(those are just there as references)
I really hope this helps linked list can get really tricky and drawing always helps me.
so to add the item at the front of the list you have some code like this:
//ok first I'll define some variables for you
//last === the last node in the list
//head === the first node in the list
//node === the new node you are adding;
qnode node = new qnode;
node.data = data; //whatever data you are holding
node->next = last; //last element in the list since it is circular;
node->prev = head; //you want the new node to point the the first node since it's getting added before that;
head->next = node; //you want the head of the node to point to the new node not the last item
last->prev = node; //last node now should point to the new node you just added not the head;
I am not sure why you need an else if, as I think the case with one element is not different from that with multiple elements. In any case you have a syntax error there - you wanted to write == instead of =.
More to the point, what you want to do is:
Create a new qnode
Set the data of the new node to the item
Set the next of the new node to the front
Set the prev of the new node to front->prev
Set the prev of the front to the new node.
You may check for yourself on a piece of paper how this works.
In a circular doubly linked list, you have 2 pointers, one to the head and one to the tail (last element in the list). If a element has a next, the next element's prev should be the element pointing at it through it's next element.
Your head pointer should never move unless the head element is removed. Your tail will move along always ensuring that the element it points to has head as it's next element.
Hopefully this helps
Since you always add at the end, the case of a queue with a single element is identical with the case of a list with multiple elements. Take a paper and a pen, make some sketches and it will come very easy to you.