C++ Ordered Linked List Search Function Algorithm logic - c++

I'm new to C++ and I'm trying to write an algorithm to search a linked list, but I'm having a little trouble with my logic. The ??? question marks in bold are the parts I'm having trouble with. I appreciate any help with this.
ListNode *MyLinkedList::Search(int key)
{
ListNode *temp = head; // Assume ListNode is a structure and contains the variable int key;
// Search for the key
while((temp != NULL) && (key != temp->key))
{
temp = temp -> next; // Advance to next node
{
if(**???**) // Make sure node is found
{
return **???**; // If found, return appropriate value
}
else
{
return NULL; // return NULL when not found
}
}

If the key was found key == temp->key will be true and temp != NULL will be false, so:
if(key == temp->key) // Make sure node is found
{
return temp; // If found, return appropriate value
}
OR:
if (temp != NULL) // Make sure node is found
{
return temp; // If found, return appropriate value
}

Try this code:
ListNode *MyLinkedList::Search(int key, ListNode *head)
{
ListNode *temp = head; // Assume ListNode is a structure and contains the variable int key;
// Search for the key
while(temp != NULL)
{
if (key == temp->key)
return temp;
temp = temp -> next; // Advance to next node
}
return NULL; // return NULL when not found
}
EDIT
You should use the list from stl and the find algorithm, if you aren't required to write your own container; They are tested and safe:
http://en.cppreference.com/w/cpp/container/list
http://en.cppreference.com/w/cpp/algorithm/find

You don't need an if. Just return temp. If the correct key is present in the list, temp would be pointing to it, otherwise it's NULL.

This will work for you
if(temp != NULL) // Make sure node is found
{
return temp; // Make sure node is found
}

You could do this:
if(temp != NULL) // Make sure node is found
{
return temp; // If found, return appropriate value
}
But much simpler is just
return temp;
since if temp is null, you want to return null anyway.

Related

How to delete a linked list without recursion?

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;
}

Writing an Insert Algorithm for an Ordered Linked List C++

I'm writing an insert algorithm for an ordered linked list. I've got most of the algorithm completed, but the one while loop condition is throwing me off. I think the rest of it I have correct, but any help with it would be appreciated, thanks!
bool MyLinkedList::Insert(ListNode *newNode)
{
// Assume ListNode is a structure and contains the variable int key;
// Assume the function returns true if it successfully inserts the node
ListNode *back = NULL, *temp = head;
if(head == NULL) // Check for inserting first node into an empty list
{
head = newNode;
return true;
}
else
{ // Search for insert location
while((**???**) && (**???**))
{
back = temp; // Advance to next node
temp = temp -> next;
{
// Check for inserting at head of the list
if(back == NULL)
{
newNode -> next = head; // Insert at head of list
head = newNode;
return true;
}
else // Insert elsewhere in the list
{
newNode -> next = temp;
back -> next = newNode;
return true;
}
}
return false; // Should never get here
}
I am assuming you have the following structure for ListNode (based on your prior comment).
struct ListNode {
int Key;
double dataValue;
ListNode *next;
}
On the assumption that the list is ordered based on the key values, the while loop condition should look like this:
while((temp != NULL) && (temp->Key < newNode->Key))
The rest of the code seems to agree with it.
The second argument would need change if the comparison methodology for ordering the sorted list is different than simple key comparison.
while((**???**) && (**???**))
You need to insert your comparisons here. Whatever kind of data is inside the ListNode, you should have some way of comparing two of them. I suspect you have an overloaded operator if it isn't a primitive type.

C++ - OOP implementation of linked list, I not sure why adding to end is not working for me, please advise

I am refreshing my knowledge of C++ OOP but not sure why I can get this traversal and adding to end of list up and running. Any advice on this context would be highly appreciated.
#include "stdafx.h"
#include "LinkedList.h"
LinkedList::LinkedList(void)
{
}
LinkedList::~LinkedList(void)
{
}
void LinkedList::add(Node* node)
{
Node* root = this->getRoot();
if(root !=NULL)
{
//with two nodes the commented code worked
//while(root->getNextNode() != NULL){}
//root->setNextNode(node);
//this part is culprit
Node* newNode = root->getNextNode();
while(newNode!=NULL)
{
newNode = newNode->getNextNode();
}
//I was thinking I am reaching to last node using this traversal
newNode = new Node(node->getData(),node->getNextNode());
}else
{
this->setRoot(node);
}
};
void LinkedList::traverseNodes()
{
Node* node = this->getRoot();
printf("\ntraversing the nodes:");
while(node != NULL){
printf("%d", node->getData());
node = node->getNextNode();
}
}
The problem with your code is that once you set the pointer newNode to NULL, pointing it to a new node won't change the previous last node.
Try this:
Node* root = this->getRoot();
if (root != NULL) {
Node* parent = root;
while(true) {
// two variables mean you have access to the previous node,
// which is needed to add the next one.
Node* child = parent->getNextNode();
if (child != NULL) {
parent = child;
} else {
parent->setNextNode(/* new node */);
break; // EDIT
}
}
} else //...
That fault is because you did not append at end, actually, you can fix the code by something like following
Node* previouseNode = this->getRoot();
while(previouseNode->getNextNode() != NULL)
{
previouseNode = previouseNode->getNextNode();
}
//Next node of previouseNode is null so you can assign to it
Node * newNode = new Node(node->getData(), previouseNode); // Maybe your list is bi-directional!
previouseNode->setNextNode(newNode);
When you have reached NULL it is too late, you need to keep track of the node before.
void LinkedList::add(Node* node) {
Node* current = this->getRoot();
if (current != NULL) {
while(current->getNextNode() != NULL) {
current = current->getNextNode();
}
current->setNextNode(node);
} else {
this->setRoot(node);
}
};

Binary Search Tree Insertion C++

Maybe asked million times before but I simply cannot understand what's wrong with this. I didn't want to use any code on the internet so I've just tried to program what's on my mind. Either this or my print function is wrong. Is there anything wrong with the code below?
void addNode(int value)
{
Node* newNode=new Node;
newNode->data=value;
if(root==NULL)
root=newNode;
else {
Node* temp=root,*parent;
while(temp!=NULL)
{
parent=temp;
if(temp->data == value)
return;
else if(temp->data < value)
temp=temp->left;
else
temp=temp->right;
}
temp=newNode;
}
}
temp=newNode;
This assigns the pointer to a local variable, which is discarded when the function returns, losing the new node. Instead, you want to assign it to a pointer within the tree; perhaps something like:
if (temp->data < value) { // If the new node should be to the left
if (temp->left) { // If there is a left subtree
temp = temp->left; // Move into the left subtree
} else { // Otherwise
temp->left = newNode; // Insert the new node there
return; // Done.
}
}
and likewise for temp->right if value < temp->data.
Also:
if (temp->data == value)
return;
You have a memory leak there; you should delete newNode before returning.

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;
}
}