Adding nodes to linked list alphabetically in c++ - c++

I'm trying to make a linked list that gets words from the user until the input is blank, and every word is added so the list stays in alphabetical order. However, only the first node is printed. Is there something I'm doing wrong? Here's what I have (minus the header and declarations):
//put in additional nodes until the input is blank
while(in != " "){
cin >> in;
newPtr->data = in;
prevPtr->data = "";
prevPtr->next = NULL;
nextPtr = list;
//shift the prevPtr and nextPtr until newPtr is alphabetically between them
while(!(prevPtr->data<=in && nextPtr->data>in)){
prevPtr = nextPtr;
nextPtr = prevPtr->next;
}
//make newPtr point to the next node
if(nextPtr != NULL){
newPtr->next = nextPtr;
}
//make newPtr the "next" pointer of the previous node, if any
if(prevPtr != NULL){
prevPtr->next = newPtr;
}
//if there's nothing before newPtr, make it the first node
else{
list = newPtr;
}
printList(list);
};
}

I would post this as a comment, because I am afraid I might be missing something, but I can't yet do this, so here goes a non-answer:
What keeps you from using the std::list? You can insert a word, check if it is non-empty, immediately apply a the standard sorting algorithm (It relies on the comparison operators of the sorted objects) and print it. It is fast, your code is short and readable and you don't spend your time reinventing the wheel.
PS: If you want to test for an empty string it should be "", not " " , I think.

I think there is a number of issues here.
For one in the initial iteration what is prevPtr->data pointing at? If it's pointing at nothing or hasn't been allocated to any memory you shouldn't be setting this to anything yet.
Plus you need to allocate memory for newPtr on every iteration, otherwise you are just writing over the memory location of where it is pointing to last from the in the list.
Second lets assume that prevPtr is pointing to something, on the second iteration (or more) of this while loop prevPtr has been moved farther down the list (prevPtr = nextPtr) which would cause prevPtr->data = " " to erase any data in that element. So you could be printing the first node plus a bunch of spaces afterwards.
Third you should check if list is NULL first in your loop, because if loop is NULL, nextPtr->data would be pointing at junk which is not good. This NULL check on list could be your corner case of the first element.
Try something like this, I didn't have time to test it but it should get going in the right direction:
Node *list = NULL;
while(in != " "){
cin >> in;
Node *newPtr = new Node();
newPtr->data = in;
newPtr->next = NULL;
prevPtr = list;
nextPtr = list;
// Do we have an empty list
if(list != NULL)
{
// Corner Case: First on the list
if(newPtr->data <= prevPtr->data)
{
list = newPtr;
newPtr->next = prevPtr;
}
else
{
// CASE: Somewhere between the first and the list
while(nextPtr->next != NULL)
{
nextPtr = nextPtr->next;
if(newPtr->data >= prevPtr->data && newPtr->data <= nextPtr->data)
{
prevPtr->next = newPtr;
newPtr->next = nextPtr;
break;
}
prevPtr = prevPtr->next;
}
// Corner Case: end of list
if(nextPtr->next == NULL)
{
nextPtr->next = newPtr;
}
}
}
else
{
// Corner Case: We had an empty list
list = newPtr;
}
printList(list);

Related

Creating a hash map with sorted linked list in each slot

I have successfully made a hash map with chaining and singly linked list in each slot. When I use insert it sends the new node to the back of each linked list, however I need to have each slot be sorted when I insert a new node. How can I edit the following insert function so that instead of having to sort each slot afterwards it will insert it in the correct spot to begin with?
void hashInsert(int key){
int hashLoc = h(key);
HashNode* prev = NULL;
HashNode* entry = hTable[hashLoc];
while(entry != NULL){
prev = entry;
entry = entry->next;
}
if(entry == NULL){
entry = new HashNode(key);
if(prev == NULL){
hTable[hashLoc] = entry;
}
else{
prev->next = entry;
}
}
else{
entry->value = key;
}
}
The main trick for keeping each slot sorted is to insert in the correct location, which in this case would be right before the first larger value.
In your code, you enforce inserting at the end of the list with the following while loop.
while(entry != NULL){
prev = entry;
entry = entry->next;
}
Instead, we want to modify this condition so that instead of simply looking for the end of the list (entry == NULL), we also look for a larger value.
while(entry != NULL && entry->value < value_to_insert){
prev = entry;
entry = entry->next;
}
This modified for loop correctly pinpoints the correct place to put your new entry, right between prev and entry.
Another issue in this case is that your insertion logic has a couple of bugs in it.
This is your insertion logic:
if(entry == NULL){
entry = new HashNode(key);
if(prev == NULL){
hTable[hashLoc] = entry;
}
else{
prev->next = entry;
}
}
else{
entry->value = key;
}
The main issue is that the logic is invalid for the else branch of the if(entry==NULL) if statement.
In that case, you need to create a new entry, fix the prev pointers and also fix the next pointers.
It would actually be simpler to rewrite this to the following:
new_entry = new HashNode(key);
new_entry->value = value_to_insert;
if(prev == NULL){
hTable[hashLoc] = new_entry;
}
else{
prev->next = new_entry;
}
new_entry->next = entry;

Deleting the only node in a list issues

I am having issues with deleting nodes in my doubly linked list, it crashes when I try to delete a node when there is only 1 node in the list. It works well otherwise. Its been driving me crazy because everything I have tried seems to make it worse not better. Here is my delete functions before I started changing them to try and get it to work better.
void doublyLinked::DeleteLast(int value) {
if (first == NULL)
cout <<" ERROR: You cannot delete what is not there. Please Try again! "
<< endl <<endl;
else {
Node* toDelete = last;
last = toDelete -> previous;
last->next = NULL;
delete toDelete;
}// end else
}// end function Delete Last
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void doublyLinked::DeleteFirst(int value) {
if (last == NULL)
cout <<" ERROR: You cannot delete what is not there. Please Try again! "
<< endl <<endl;// end if
else {
Node* toDelete = first;
first->next->previous = NULL;
first = toDelete->next;
delete toDelete;
}//end else
}
If there is only one entry, then first == last. Thus:
last = toDelete -> previous;
last->next = NULL;
is bad because after the first line last is NULL ;
Same with:
first->next->previous = NULL;
in the DeleteFirst()
Assume any next or previous pointer might be NULL and only use it after you've checked. Example:
if ( first->next && first->next->previous ) { first->next->previous= NULL ; }
Also note, your DeteleLast would need to modify first when deleting the last item.
I'd add test, if first == last. If so, delete it, and set both to NULL. Example:
if( first == last ) {
delete first;
first = last = NULL;
return;
}

Bubble sorting for linked list

I am trying to sort a singly linked list using bubble sort. If there is a simple mistake then please pardon. Please tell me where I am going wrong. Program stops unexpectedly when I try to do this.
void sortBubble()
{
Node *i=start,*j=start;Node *temp;Node* prev=start;Node* agla;
while(i->next!=NULL)
{
cout<<"\nhello 1";
j=i;
agla=j->next;
while(agla!=NULL)
{
temp=NULL;temp->next=NULL;
cout<<"\nhello2";
if(*(j) > *(agla))
{
temp=agla->next;
agla->next=j;
prev->next=agla;
prev=agla;
agla=j->next;
j->next=temp;
}
else{
prev=j;
j=agla;
agla=j->next;}
}
prev=i;
i=i->next;
}
}
}
Your first obvious mistake that absolutely leads to program crash is:
while(agla!=NULL)
{
temp=NULL;temp->next=NULL;
You are setting a variable to NULL, then setting its fields. A null pointer points to nowhere, so you cannot edit its contents.
Remove temp->next=NULL;
Edit:
Your program logic is not correct. You ruin the list after a few iterations of the loop and the program sticks in an infinite loop with mixed up pointers.
In bubble sort, we iterate through the items several times. In each iteration, the largest item is bubbled up to the end of the list. After first iteration, we are sure that the largest element is at the end of the list. After second iteration, we are sure that the second largest element is before the last element of the list, and so on.
You repeat this process until all the items are on their places:
int getListSize(Node* start)
{
int count = 0;
while(start != NULL)
{
count++;
start = start->next;
}
return count;
}
void bubbleSort(Node *&start) // <-- Pass a reference to pointer, because we may need to modify the start pointer.
{
int size = getListSize(start);
int i = 0;
while(size--)
{
Node
*current = start,
*prev = NULL; // We are at the beginnig, so there is no previous node.
while(current->next != NULL) // We have at least one node (size > 0) so `current` itself is not NULL.
{
Node *after = current->next;
if((*current) > (*after))
{
//swap the items
current->next = after->next;
after->next = current;
if (prev == NULL) // we are at the beginning
start = after;
else
prev->next = after;
prev = after;
}
else
{
prev = current;
current = current->next;
}
}
}
}
We repeat the "bubbling up" process size times. This is not the most efficient way, since we even compare the items that are already sorted. A more efficient way is to sort until no new swapping occurs:
void bubbleSort(Node *&start) // <-- Pass a reference to pointer, because we may need to modify the start pointer.
{
int size = getListSize(start);
int i = 0;
Node *lastSwapped = NULL;
while(size--)
{
Node
*current = start,
*prev = NULL, // We are at the beginnig, so there is no previous node.
*currentSwapped = NULL;
while(current->next != lastSwapped) // We have at least one node (size > 0) so `current` itself is not NULL.
{
Node *after = current->next;
if((*current) > (*after))
{
//swap the items
current->next = after->next;
after->next = current;
if (prev == NULL) // we are at the beginning
start = after;
else
prev->next = after;
prev = after;
currentSwapped = current;
}
else
{
prev = current;
current = current->next;
}
}
if (currentSwapped == NULL)
break; // No swapping occured. The items are sorted.
else
lastSwapped = currentSwapped;
}
}
This is the complete working program
You are comparing the elements by simply doing *(j) > *(agla), I'm not sure how that builds since both j and agla are pointers to structures. Structures cannot be compared directly.

How do I delete a node from linked list?

How can I delete a node (between two nodes) from a single linked list without passing any parameters to the class function?
For example, I have a list of 6 nodes with one head node and I want to delete two of them (without prior knowledge of their address or position) from a class function, how would I do that?
void WordList::deleteNode(){
Node *temp;
temp=head;
if(temp->count<=10)
{
//delete this node... not sure how though
}
else
temp=temp->next;
}
where WordList is my class, Node is my struct which holds a word, a count, and a pointer.
I want to delete any node that has a counter of 10 or less.
Your edit has prior information, the bit that states "counter <= 10" :-)
Pseudo-code for deleting elements meeting that criteria in a singly-linked list:
def delLessThanTen:
# Delete heads meeting criteria, stop when list empty.
while head != NULL and head->count <= 10:
temp = head->next
free head
head = temp
if head == NULL:
return
# Head exists, with count > 10, process starting there (we check
# NEXT element for criteria then delete if met).
ptr = head
while ptr->next != NULL:
# If next in list meets criteria, delete it, otherwise advance.
if ptr->next->count <= 10:
temp = ptr->next->next
free ptr->next
ptr->next = temp
else:
ptr = ptr->next
return
I find the question too confusing.
Deletion of a node from the list is always based on some criteria e.g. the content of the element, the position of the element etc (unless you are deleting all the elements in the list)
something like this:
void WordList::deleteNode(){
Node *prev=NULL;
temp=head;
bool done=false;
while (!done)
{
if (temp->count<=10)
{
if (prev == NULL)
{
head = temp->next;
} else
{
prev->next = temp->next;
}
// delete data in temp, and the node if necessary
temp = temp->next;
done = (temp==NULL) || // some other condition, like deleted 2
} else
{
prev=temp;
temp = temp->next;
done = (temp==NULL);
}
}
Have a previous variable initialized to null. If you delete a node, change previous's next to the element's next, unless previous is null (you are at the start of the list) when you leave previous null and change root to the deleted element's next. If you don't delete the element, change previous to the element.
Here previous will always point to the previous element or be null if you're at the start of the list.
void WordList::deleteNode() {
Node *temp = head;
Node *previous = null;
while (temp != null) {
if(temp->count <= 10) {
// delete node
if (previous == null) {
// there is no previous node, so point head of list past the current node
head = temp->next;
} else {
// there is a previous node, so just point it past the current node
previous->next = temp->next;
}
} else {
// not deleting, so set previous to temp
previous = temp;
}
temp = temp->next;
}
}

Delete a node from the middle of a C++ queue

I have a linked list with a c-style ctor and dtor.
I just got too frustrated when this if statement decided not to test true, putting me in
an infinite loop. I dont understand why it will never test true.
I am trying to delete a node (the address of a class object) from my LinkedList.
Maybe someone could help me out?
Node *Current = first_; // I want this to be my only Node Ptr Varaible Declaration.
if ( NULL == first_ )
std::cout << "Cannot delete from an empty list: \n";
while ( Current != NULL )
{
if ( first_->data_ == node->data_ )
{
//check to see if we are deleteing the head.
first_ = first_->next_;
--listLen_;
delete Current;
std::cout << "Head Deleted!\n";
}
if ( Current->data_ == node->data_ ) // FOR SOME REASON this is never true?
{
--listLen_;
node->data_ = NULL;
Current = Current->next_;
node->data_ = Current;
}
else // we must not of found it. // else should match previous i
{
Current->prev_ = Current;// since we are not deleting the first node we are OK here.
Current = first_->next_;
if ( Current->next_ == NULL ) // see if we are at the end of the list.
{
first_ = NULL;
last_ = Current->prev_;
}
}
}
return;
This should really be rewritten, since it has too many problems...also why not use a STL container? I assume this is a homework question.
The answer to the infinite loop is the else case that increments to the next node:
Current = first_->next_;
This will make you loop forever if the data is not found in in the first two nodes...since you will set the next test to the first's next node always and it will never set the current to NULL provided there are more than 2 nodes in the list.
Keep your loops small, it easier to figure out what went wrong. Assuming your data compare makes sense, look at this the following:
curr = first_;
while( curr && (curr->data_ != node->data_) ) {
curr = curr->next_;
}
if (!curr) return // didnt find it, nothing to remove
if ( curr == first_ )
first_ = curr->next_
else
curr->prev_->next_ = curr->next_
curr->next_->prev_ = curr->prev_ // always fix next's prev
delete curr
I'm not entirely sure what you're trying to accomplish, but I'm certain you're doing it wrong. If you're merely trying to remove an element from a doubly-linked list that matches node->data_, it's as easy as this:
Node *Current = first_;
while (Current != NULL)
{
if (Current->data_ == node->_data)
{
//If Current isn't the head of the list, set prev to next
if (Current != first_)
Current->prev_->next_ = Current->next_
else
{
first_ = Current->next_;
if (first_ != NULL)
first_->prev_ = NULL;
}
//If Current isn't the tail of the list, set next to prev
if (Current->next_ != NULL)
Current->next_->prev_ = Current->prev_
else if (Current->prev_ != NULL)
Current->prev_->next_ = NULL;
delete Current;
Current = NULL;
}
else
{
Current = Current->next_;
}
}
return;
You don't show where node comes from or how data_ is defined, but if it is a pointer type, you probably need to compare the contents, not the addresses.
Assuming that data_ is a pointer to something and what it points to has operator== defined or is a built in type and it has the value you are looking for then you can do this instead:
if ( *Current->data_ == *node->data_ )
if first_->data_ == node->data_ ever evaluates to true then the second if statement will always evaluates to true then the second if condition will always evaluate to false Current->data_ == node->data_ because on the first iteration first_ == Current and you delete Current without ever updating it
To delete a node from a linked list you seem to be doing way too much work.
Not really an answer here for the actual question but a suggestion.I would never iterate through a linked list to delete an entry in the list. Each entry should have a valid next and previous pointer and when you go to delete an entry from the list you just make the previous record point to the next one and vice versa to remove yourself from the list. An empty list should have a head record and a tail record that just point to each other and all valid entries are inserted in between.
Delete a node with value passed.
void deleteBegin()
{
Node* temp =Head;
if(temp==NULL)
return;
Head=Head->next;
free(temp);
}
void deleteMiddle(int _data)
{
Node* curr = Head;
Node* prev = Head;
if(curr==NULL)
return;
if(curr->next==NULL)
{
deleteBegin();
return;
}
while(curr->next!=NULL && curr->data!=_data)
{
prev=curr;
curr=curr->next;
}
if(curr->data == _data)
{
if(prev==curr)
{
deleteBegin();
return;
}
prev->next = curr->next;
free(curr);
}
else
{
cout<<"Element Not Found\n";
return;
}
}