So I am trying to sort nodes according to their location (an integer) and then by the date (year and month). When I use my overloaded operator to print my linked list, it shows that the list is only inserting one of the wanted nodes meaning that my insert function is not correct. It is not giving any errors, it is just not running as expected. My insert function is below. Does anyone have any ideas as to what is wrong?
void LinkedList::insert(int location, int year, int month, double temperature) {
// Implement this function
Node* newNode = new Node();
newNode->loc = location;
newNode->yr = year;
newNode->mo = month;
newNode->temp = temperature;
Node* tempNode = head;
Node* previousNode = nullptr;
if(tail == nullptr & head == nullptr){
head = newNode;
}
while(tempNode != nullptr){
if((tempNode->loc == newNode->loc) && (tempNode->yr == newNode->yr)){
if(tempNode->mo > newNode->mo){
newNode->next = tempNode->next;
tempNode->next = newNode;
}
if(tempNode->mo < newNode->mo){
newNode->next = tempNode;
}
}
if(tempNode->loc > newNode->loc){
newNode->next = tempNode->next;
tempNode->next = newNode;
}
if(tempNode->loc < newNode->loc){
newNode->next = tempNode->next;
tempNode->next = newNode;
}
tempNode = tempNode->next;
}
}
The reason you are not getting the linkedlist properly is because you are making a mistake in pointer manipulation. When you assign cur->next=data->next;
you are basically breaking the list since data->next doesnot point to next node in the list.
Also, note that since this is a single linked list [meaning it has only one pointer forward] you can only insert nodes ahead of the current node.
Try something like this:
if (cur->loc > data->loc) {
data->next = cur->next; // This will insert data in middle of
cur->next = data; // cur and cur->next
}
There are multiple checks you will need to do if you want to insert in a increasing or decreasing order.
Make different cases for when you insert the first element of the list, insert at head, insert at tail and insert in the middle of linkedlist.
Also, at tail node make sure that its next is always set to null.
Related
I am making a code for double linked list in C++. But, i have a problem, I dont know how add node before other node.
I have these.
template<class T>
void LinkedListD<T>::addNodeBeforeTo(Node<T> *before, T info) {
Node<T>* newNode = new Node<T>( info );
if ( isEmpty() ){
head = newNode;
last = newNode;
} else{
if ( before == head ){
newNode->next = head;
head = newNode;
} if ( before == last ){
newNode->previous = last;
last = newNode;
}
else{
Node<T>* act = head;
Node<T>* past = last;
while ( act->next != before && past->previous != before){
act = act->next;
past = past->previous;
}
newNode->previous = past->previous;
newNode->next = act->next;
act->next = newNode;
past->previous = newNode;
}
}
}
The example is 10, 15, 20, 12
Add node before to 20: 30
Finish Output 10, 15, 30, 20, 12
Thks
You have to realize how to approach the solution, methodically (n is the object you want to insert the new_item object before it):
if (head != nullptr) // i.e. if list is not empty
{
}
if (new_item.P == nullptr) // i.e. if new_item is first
head = new_item;
You don't need the while loop at all. Each node knows the nodes on both sides of it, that is all you need to update the list properly. Given the input node before, all you have to do is:
set newNode->previous to point at the before->previous node
set newNode->next to point at the before node
if before->previous is not null, set before->previous->next to point at the newNode node
set before->previous to point at the newNode node
if before is pointing at the head node, set head to point at the newNode node.
Done.
Also, you have some other logic errors in this code. When inserting before the head node, you are not updating head->previous to point at the newNode node before updating head itself. And since your function inserts before a given node, you should not be trying to insert after the last node at all, that job should be handled by a separate addNodeAfterTo() method instead.
Try something more like this:
template<class T>
Node<T>* LinkedListD<T>::addNodeBeforeTo(Node<T> *before, const T &info) {
if ( !before ) return nullptr;
Node<T>* newNode = new Node<T>( info );
newNode->previous = before->previous;
newNode->next = before;
if ( before->previous )
before->previous->next = newNode;
before->previous = newNode;
if ( before == head )
head = newNode;
return newNode;
}
Demo
would help me to solve this problem
i am trying to insert the node at ith location in linked list using recursion
here is the code please help me to imporve the code
i ma specifically facing problem at the end when i have to return the head i am not getting how to return
Node* insertNodeRecursively(Node*head, int n, int data)
{
if(head == nullptr)
{
return head;
}
else if(n==0)
{
Node* newNode= new Node(data);
newNode->next = head->next;
head->next = newNode;
return head;
}
Node * x = insertNodeRecursively(head->next,n-1,data);
}
So I guess you want the function insertNodeRecursively to return the new head, right? Anything else would not work without considering the special case of inserting at position 0 in the caller function.
You could do the following:
if (n == 0) {
Node *newNode = new Node(data);
newNode->next = head;
return newNode;
}
if (head == nullptr) {
return nullptr;
}
Node *node = insertNodeRecursively(head->next, n - 1, data);
head->next = node;
return head;
The idea is that when this is not the position to insert to, we need to assume the next recursive call might give us a new head (from that position on), so we need that head->next = node; assignment. To call the node passed as first argument head might confuse as it is not always the head of the list (Only at the start of the recursion)! It is rather the node in front of which you want to insert in case n is 0. The problem with what you wrote in the n == 0 case is that you always return the old head, even though you should return newNode. The head node should be what follows after newNode.
I am trying to make a sorted doubly linked list that doesn't insert duplicates, but I am having trouble finding a way to do this. I looked at posts on how to remove duplicates, but no posts on preventing duplicate insertions.
Here is the code I have to insert and sort without rejecting duplicates. The parameter, dataIn takes values from a predefined Student object list in main (Student s = {{gpa, name}, ..., {gpa, name}}:
void StudentList::insertNode(Student dataIn)
{
ListNode *newNode; // A new node pointer
ListNode *pCur; // To traverse the list
// Allocate a new node and store num there.
newNode = new ListNode;
newNode->stu = dataIn;
newNode->forw = NULL;
newNode->back = NULL;
//Check if there is node in list
if(head ->forw == NULL && head->back == NULL){
head->forw = newNode;
newNode->back = head;
newNode->forw = head;
head->back = newNode;
}
else{
// Initialize pointers
pCur = head->forw;
// Find location: skip all nodes whose name is less than dataIn's name
while (pCur != head && pCur->stu.name < dataIn.name)
{
pCur = pCur->forw;
}
// Insert the new node between pPre and pCur
ListNode *pPre = pCur->back; // The previous node
newNode->back = pPre;
newNode->forw = pCur;
pCur->back = newNode;
pPre->forw = newNode;
}
// Update the counter
count++;
}
Does anyone know a way for rejecting duplicates without deleting? Thanks everyone!
What is the best way to reject duplicates in a sorted doubly linked list?
I suggest delaying the creation of the new ListNode until you know that the new node isn't a duplicate.
Assuming that the ListNode looks like this
struct ListNode {
Student stu;
ListNode *back;
ListNode *forw;
};
and that you have a head and tail ListNode* that is set to nullptr when the StudentList is empty, then the insertNode function could look like this:
bool StudentList::insertNode(const Student& dataIn) { // return true if node is inserted
ListNode* prev = nullptr;
ListNode* pCur = head;
// search for a good insertion spot
for(; pCur; prev = pCur, pCur = pCur->forw) {
if(dataIn.name == pCur->stu.name) return false; // equal, reject
if(dataIn.name < pCur->stu.name) break; // found a good spot before pCur
}
// delayed creation until here:
ListNode* newNode = new ListNode{dataIn, prev, pCur};
// linking
if(prev) prev->forw = newNode;
else head = newNode;
if(pCur) pCur->back = newNode;
else tail = newNode; // comment this line out if you don't have a "tail"
++count;
return true; // node inserted
}
I have to write a method that's going to delete the last node from the List. Do you guys have any ideas on how I should approach this?
If you have a single-linked list, you have no choice but to iterate through the entire list to the last node, maintaining a pointer to the previous node so you can reset its next field when freeing the last node:
if (head)
{
node *curNode = head;
node *prevNode = NULL;
while (curNode->next)
{
prevNode = curNode;
curNode = curNode->next;
}
if (prevNode) prevNode->next = NULL;
delete curNode;
}
If you were using a double-linked list instead, this would be easier, as you can keep a pointer to the last node in the list and just operate on it directly:
if (head == tail)
{
delete head;
head = tail = NULL;
}
else if (tail)
{
node *curNode = tail;
tail = curNode->previous;
tail->next = NULL;
delete curNode;
}
Of course, if you are really using C++ then you should be using the STL's std::list (double-linked) or std::forward_list (single-linked) containers instead, which handle these details for you.
To delete the last element on a list all you need to do is maintain two separate nodes. Initially one should point to the head of the list and the other should point to the second element on the list. You should do something like the following :
if(head == NULL)
return 0;
else if(head->next == NULL){
Node *temp = head;
delete temp;
head = NULL;
}
else{
Node *one = head;
Node *two = head->next;
while(two->next != NULL){
two = two->next;
one = one->next;
}
one->next = NULL;
delete two;
}
Hi I have a linked list using structs. Right now I got it to add every element at the end. However I'd like to add each element in sorted order based on the ID. The struct has two elements: string name, and long ID.
node* temp = new node;
temp->name = nameRead;
temp->id = idRead;
//check if first item, if so add as head
if(head == NULL)
{
head = temp;
}
else
{
node* temp2 = head;
while(temp2->next != NULL)
{
temp2 = temp2->next;
}
temp2->next = temp;
}
node* temp = new node;
temp->name = nameRead;
temp->id = idRead;
node* temp2 = head;
node** temp3 = &head;
while(temp2 != null && temp2->id < temp->id)
{
temp3 = &temp2->next;
temp2 = temp2->next;
}
*temp3 = temp;
temp->next = temp2;
EDIT: Explanation: The 'temp3' pointer points to where 'temp' would need to go. Initialize temp2 to head, and keep looping until we reach the end of the list, or until temp2's id is >= than temp's id. In each iteration of the loop, advance both temp3 and temp2.
At the end of the loop, 'temp3' will hold the address of the pointer where temp should be. So assign *temp3 to point to temp, and assign temp->next to point to temp2 (which at this point would either be null, or would point to the item that has larger id than temp->id).
Taken from my student notebook:
void addSorted(node * head, int id){
node* newNode = new node;
newNode->number = n;
newNode->next = NULL;
if(head == NULL || head->number >= id ){
newNode->next = head;
head = newNode;
return;
}else if(head->next != NULL && head->next->id >= id){
node * nextNode = head->next;
newNode->next = nextNode;
head->next = newNode;
return;
}else{
node * left;
node * right = head;
while(right != NULL && right->next->id <= id){
left = right;
right = right->next;
}
left->next=newNode;
newNode->next = right;
}
}
Most of the modification to the code is pretty trivial -- just add a comparison based on the ID so you only walk through the list until you get to a node with an ID larger then the new one you need to insert (or reach the end of the list).
This is where things get slightly tricky: before you "realize" you've reached the right spot in the list, you've already gone one node too far (and in a singly linked list, there's no way to go back). The trick to fix that is pretty simple: allocate a new (empty) node and insert it after the too-large node you found. Copy that too-large node's contents into the new one you just inserted, and then copy the data for the new node into the spot it just vacated.
I should add, however, that all of this is mostly a moot point. If you want a sorted collection of items, a linked list is usually a really lousy choice. Unless you're doing something like homework where you have no choice but to do whatever brain-dead crap you've been assigned, look up std::set [Edit: or std::multiset, if duplicates are allowed -- or possibly std::map or std::multimap, if you want to be able to find a node based on an ID] and forget about implementing it yourself.