I'm trying to write a simple linked-list and am trying to throw an out_of_range exception when the user wants a node index that is out-of-bounds. However, when I compile the source file, I get an error "'out_of_range' is not a member of 'std'".
It was my understanding that 'out_of_range' IS a member of std::, so I assume I am doing something wrong that I am unaware of.
Here is where the error occurs:
T getValueAtIndex (int index)
{
// If the index is less than 0 or greater than/equal to
// the length, throw index out-of-bounds exception.
if (index < 0 || index >= length)
{
throw std::out_of_range ("Index out of bounds.");
}
else
{
// Start at index 0.
int i = 0;
// Start with the first node in the list (headNode).
Node * currentNode = headNode;
// While we have not yet reached the index we want...
while (i < index)
{
currentNode = currentNode->getNextNode();
i++;
}
return currentNode->getValue();
}
}
And here is the entire file so far (not completed yet):
#include <iostream>
template <typename T>
class LinkedList
{
// Private variables/information.
private:
// Struct 'Node' which holds the data and a pointer to the next
// node in the linked-list.
struct Node {
T value;
Node * nextNode;
// Node constructor, sets nextNode to NULL.
Node()
{
nextNode = NULL;
}
// Sets the value of this node to the value passed to it.
void setValue (T Value)
{
value = Value;
}
void setNextNode (Node * newNode)
{
nextNode = newNode;
}
// Returns the value of this node.
T getValue()
{
return value;
}
// Returns a pointer to the next node in the list.
Node * getNextNode()
{
return nextNode;
}
};
// The head or 'first' node in the list.
Node * headNode;
// The tail or 'last' node in the list.
Node * tailNode;
// Length of the list. Useful for making sure we
// do not search for a node index that is out of bounds.
int length;
// Public methods.
public:
// Default constructor for the linked list.
// Initializes the two nodes to NULL.
LinkedList()
{
headNode = NULL;
tailNode = NULL;
length = 0;
}
// Adds a value to the linked-list as a node.
void add (T Value)
{
// Create a new node on the heap.
Node newNode = new Node();
// Set the value of this new node to the value specified.
newNode.setValue(Value);
// If there is no node in the list yet...
if (headNode == NULL)
{
// Point headNode and tailNode to the address of newNode.
headNode = &newNode;
tailNode = &newNode;
}
// Else if there is already a node in the list.
else
{
// Link the new node to the last current node.
tailNode->setNextNode(&newNode);
// Set the last node to the new node.
tailNode = &newNode;
}
// Increase the length of the list by one.
length++;
}
// Returns the value of the node at the given index.
// Starts at index 0 like a normal array.
T getValueAtIndex (int index)
{
// If the index is less than 0 or greater than/equal to
// the length, throw index out-of-bounds exception.
if (index < 0 || index >= length)
{
throw std::out_of_range ("Index out of bounds.");
}
else
{
// Start at index 0.
int i = 0;
// Start with the first node in the list (headNode).
Node * currentNode = headNode;
// While we have not yet reached the index we want...
while (i < index)
{
currentNode = currentNode->getNextNode();
i++;
}
return currentNode->getValue();
}
}
};
int main()
{
return 0;
}
What am I doing incorrectly when throwing the exception? I tried without 'std::', including , and with 'new' in front.
Looks like you just forgot to #include <stdexcept>
Related
After randomly filling a linked list with a deck of 52 cards. When I try to print it, it will print the head node 52 times. Is there something wrong with my 'traverse through linked list logic' or something wrong with my insertion logic?
These are the Node helper methods (a bagNode has a CardOfBag and a next)
card *bagNode::getCard() // retreives card in the bagnode as pointer
{
return this->cardOfBag;
}
bagNode *bagNode::getNext() // retreives the next bagnode as pointer
{
return this->next;
}
void bagNode::setCard(card *card) // sets card of bagnode
{
this->cardOfBag = card;
}
void bagNode::setNext(bagNode *setNode) // sets next bagnode
{
setNode->next = this->next;
this->next = setNode;
}
These are the methods for the linked list (called bag):
it has a header, tail, and current bagNode* pointers.
void bag::add(bagNode *node) // adds node to random position
{
int i, place, size;
place = randomPosition();
size = getCurrentSize();
if (size == 0) // for initial insertion into empty linked list
{
setHead(node);
setTail(node);
alterSize(1);
} else {
if ((size - 1) == place) // if the insertion is at the last node
{
this->tail->setNext(node);
setTail(node);
alterSize(1);
} else {
if (place == 0) // if insertion is at head node
{
node->setNext(this->head);
setHead(node);
alterSize(1);
} else {
setCurrent(place); // for any insertion in between first and last nodes
node->setNext(current->getNext());
current->setNext(node);
alterSize(1);
}
}
}
}
int bag::getCurrentSize() // returns size of bag (linked list)
{
return this->size;
}
void bag::alterSize(int num) // changes the size int of bag by num
{
this->size = this->size + num;
}
int bag::randomPosition() // generates random number from 0 to size exclusive
{
int size = getCurrentSize();
if (size != 0)
return (rand() % size);
}
void bag::setCurrent(int desiredPosition) // this traverses the current pointer
// by desiredPosition steps from the head node
{
int i;
this->current = this->head;
for (i = 0; i < desiredPosition; i++) {
this->current->setNext(this->current->getNext());
}
}
bagNode *bag::getCurrentNode() // returns node of current pointer
{
return this->current;
}
bagNode::setNext() is supposed to make next point to the node provided; leave the other node alone:
void bagNode::setNext(bagNode* setNode) //sets next bagnode
{
this->next = setNode;
}
Your bag::setCurrent() doesn't work. You're supposed to make this->current keep going "next" until you hit the desiredPosition, instead you're only changing its next pointer to... the same value it previously had.
Do something like this instead:
void bag::setCurrent(int desiredPosition)
{
int i;
this->current = this->head;
for(i = 0; i < desiredPosition; i++)
{
this->current = this->current->getNext();
}
}
That should work better now.
in your function
void bag::setCurrent(int desiredPosition)
You are not changing this->current at all. Basically you did nothing in that function.
I am writing a simple app that gets a list and saves the objects as nodes in a singly linked list and we can add(), remove(), copy(), etc. each node depending on the given data set. each node has a char value which is our data and an int count which counts the occurrence of the related char.
e.g. for a list like
a, a, b, b, c, a
there would be three nodes (since there are three different characters) which are:
[a,3,*next] -> [b,2,*next] -> [c,1,*next] -> nullptr
bool isAvailable() checks if the data is already in the list or not.
Q: When inserting a data there are two options:
The data has not been entered: so we have to create a newNodewith the given data, count=1and *next=NULL.
The data is already entered: so we have to count++ the node that has the same data.
I know if the given data is available or not, but how can I point to the node with same data?
Here's the code:
#include "stdafx.h"
#include<iostream>
using namespace std;
class Snode
{
public:
char data;
int count;
Snode *next;
Snode(char d, int c)
{
data = d;
count = c;
next = NULL;
}
};
class set
{
private:
Snode *head;
public:
set()
{
head = NULL;
tail = NULL;
}
~set();
void insert(char value);
bool isAvailable(char value);
};
set::~set()
{
Snode *t = head;
while (t != NULL)
{
head = head->next;
delete t;
}
}
bool set::isAvailable(char value)
{
Snode *floatingNode = new Snode(char d, int c);
while(floatingNode != NULL)
{
return (value == floatingNode);
floatingNode->next = floatingNode;
}
}
void set::insert(char value)
{
Snode *newNode = new Snode(char d, int c);
data = value;
if (head == NULL)
{
newNode->next = NULL;
head = newNode;
newNode->count++;
}
else
{
if(isAvailable)
{
//IDK what should i do here +_+
}
else
{
tail->next= newNode;
newNode->next = NULL;
tail = newNode;
}
}
}
I know if the given data is available or not, but how can I point to the node with same data?
You'll need to start at the head of the list and iterate along the list by following the next pointers until you find the node with the same data value. Once you've done that, you have your pointer to the node with the same data.
Some other notes for you:
bool set::isAvailable(char value)
{
Snode *floatingNode = new Snode(char d, int c);
while(floatingNode != NULL)
{
return (value == floatingNode);
floatingNode->next = floatingNode;
}
}
Why is this function allocating a new Snode? There's no reason for it to do that, just initialize the floatingNode pointer to point to head instead.
This function always returns after looking at only the first node in the linked list -- which is not the behavior you want. Instead, it should return true only if (value == floatingNode); otherwise it should stay inside the while-loop so that it can go on to look at the subsequent nodes as well. Only after it drops out of the while-loop (because floatingNode finally becomes NULL) should it return false.
If you were to modify isAvailable() slightly so that instead of returning true or false, it returned either floatingPointer or NULL, you'd have your mechanism for finding a pointer to the node with the matching data.
e.g.:
// Should return either a pointer to the Snode with data==value,
// or NULL if no such Snode is present in the list
Snode * set::getNodeWithValueOrNullIfNotFound(char value) const
{
[...]
}
void set::insert(char value)
{
Snode * theNode = getNodeWithValueOrNullIfNotFound(value);
if (theNode != NULL)
{
theNode->count++;
}
else
{
[create a new Snode and insert it]
}
}
You had a lot of problems in your code, lets see what are they:
First of all, Snode doesn't need to be a class, rather you can go with a simple strcut; since we need everything public.(not a mistake, but good practice)
You could simple initialize count = 1 and next = nullptr, so that no need of initializing them throw constructor. The only element that need to be initialized through constructor is Snod's data.
Since c++11 you can use keyword nullptr instead of NULL, which denotes the pointer literal.
Member function bool set::isAvailable(char value) will not work as you think. Here you have unnecessarily created a new Snode and cheacking whether it points to nullptr which doesn't allow you to even enter the loop. BTW what you have written in the loop also wrong. What do you mean by return (value == floatingNode); ? floatingNode is a Snode by type; not a char.
Hear is the correct implementation. Since we don't wanna overwrite the head, will create a Node* pointer and assign head to it. Then iterate through list until you find a match. If not found, we will reach the end of the isAvailable() and return false.
inline bool isAvailable(const char& value)
{
Node *findPos = head;
while(findPos != nullptr)
{
if(findPos -> data == value) return true;
else findPos = findPos->next_node;
}
return false;
}
In void set::insert(char value), your logic is correct, but implementation is wrong. Following is the correct implementation.(Hope the comments will help you to understand.
void insert(const char& value)
{
if(head == nullptr) // first case
{
Node *newNode = new Node(value);
newNode->next_node = head;
head = newNode;
}
else if(isAvailable(value)) // if node available
{
Node *temp = head;
while(temp->data != value) // find the node
temp = temp->next_node;
temp->count += 1; // and count it by 1
}
else // all new nodes
{
Node *temp = head;
while(temp->next_node != nullptr) // to find the null point (end of list)
temp = temp->next_node;
temp = temp->next_node = new Node(value); // create a node and assign there
}
}
Your destructor will not delete all what you created. It will be UB, since your are deleting newly created Snode t ( i.e, Snode *t = head;). The correct implementation is as bellow.(un-comment the debugging msg to understand.)
~set()
{
Node* temp = head;
while( temp != nullptr )
{
Node* next = temp->next_node;
//std::cout << "deleting \t" << temp->data << std::endl;
delete temp;
temp = next;
}
head = nullptr;
}
Last but not least, the naming (set) what you have here and what the code exactly doing are both different. This looks more like a simple linked list with no duplicates. This is however okay, in order to play around with pointers and list.
To make the code or iteration more efficient, you could do something like follows. In the isAvailable(), in case of value match/ if you found a node, you could simply increment its count as well. Then in insert(), you can think of, if node is not available part.
Hope this was helpful. See a DEMO
#include <iostream>
// since you wanna have all of Node in public, declare as struct
struct Node
{
char data;
int count = 1;
Node* next_node = nullptr;
Node(const char& a) // create a constrcor which will initilize data
: data(a) {} // at the time of Node creation
};
class set
{
private:
Node *head; // need only head, if it's a simple list
public:
set() :head(nullptr) {} // constructor set it to nullptr
~set()
{
Node* temp = head;
while( temp != nullptr )
{
Node* next = temp->next_node;
//std::cout << "deleting \t" << temp->data << std::endl;
delete temp;
temp = next;
}
head = nullptr;
}
inline bool isAvailable(const char& value)
{
Node *findPos = head;
while(findPos != nullptr)
{
if(findPos -> data == value) return true;
else findPos = findPos->next_node;
}
return false;
}
void insert(const char& value)
{
if(head == nullptr) // first case
{
Node *newNode = new Node(value);
newNode->next_node = head;
head = newNode;
}
else if(isAvailable(value)) // if node available
{
Node *temp = head;
while(temp->data != value) // find the node
temp = temp->next_node;
temp->count += 1; // and count it by 1
}
else // all new nodes
{
Node *temp = head;
while(temp->next_node != nullptr) // to find the null point (end of list)
temp = temp->next_node;
temp = temp->next_node = new Node(value);
}
}
void print() const // just to print
{
Node *temp = head;
while(temp != nullptr)
{
std::cout << temp->data << " " << temp->count << "\n";
temp = temp->next_node;
}
}
};
int main()
{
::set mySet;
mySet.insert('a');
mySet.insert('a');
mySet.insert('b');
mySet.insert('b');
mySet.insert('c');
mySet.insert('a');
mySet.print();
return 0;
}
I am working on unsorted linked list check full currently, below is my specification and implementation.
Specification:
#ifndef UNSORTEDLIST_H
#define UNSORTEDLIST_H
#include <iostream>
using namespace std;
struct Node {
float element;
Node* next;
};
class UnsortedList
{
public:
UnsortedList();
bool IsEmpty();
bool IsFull();
void ResetList();
void MakeEmpty();
int LengthIs();
bool IsInTheList(float item);
void InsertItem(float item);
void DeleteItem(float item);
float GetNextItem();
private:
Node* data;
Node* currentPos;
int length;
};
#endif
And implemetation:
UnsortedList::UnsortedList()
{
length = 0;
data = NULL;
currentPos = NULL;
}
bool UnsortedList:: IsEmpty(){
if(length == 0)
{
return true;
}
else
{
return false;
}
}
bool UnsortedList::IsFull(){
Node* ptr = new Node();
if(ptr == NULL)
return true;
else
{
delete ptr;
return false;
}
}
void UnsortedList::ResetList(){
currentPos = NULL;
}
void UnsortedList::MakeEmpty()
{
Node* tempPtr = new Node();
while(data != NULL)
{
tempPtr = data;
data = data->next;
delete tempPtr;
}
length = 0;
}
int UnsortedList::LengthIs(){
return length;
}
bool UnsortedList:: IsInTheList(float item){
Node* location = new Node();
location = data;
bool found = false;
while(location != NULL && !found)
{
if(item == location->element)
found = true;
else
location = location->next;
}
return found;
}
void UnsortedList:: InsertItem(float item){
Node* location = new Node();
location->element = item;
location->next=data;
data = location;
length++;
}
void UnsortedList:: DeleteItem(float item){
Node* location = data;
Node* tempPtr;
if(item == data->element){
tempPtr = location;
data = data->next;
}
else{
while(!(item == (location->next) ->element) )
location = location->next;
tempPtr = location->next;
location->next = (location->next)->next;
}
delete tempPtr;
length--;
}
float UnsortedList::GetNextItem(){
if(currentPos == NULL)
currentPos = data;
else
currentPos = currentPos->next;
return currentPos->element;
}
1.In the constructor, why don't assign currentPos as null?
2.In the IsInTheList function, Why points to pointer "next" ? Isn't next is a null pointer since it has been declared in struct as Node* next?
The pointer value is not set to NULL value by default, you should set to to null explicitly. Also instead of using NULL, choose using nullptr.
This code is rather incomplete, so it is difficult to answer your questions.
This does not contain the code to insert an item in the list, which is where I would expect both the next and currentPos pointers to be set. However, that's based on a number of assumptions.
However, I don't see where next is used in the "check full function" at all, so that question is a bit confusing.
I'll also point out that this code has a glaring memory leak. The first line in IsInTheList allocates memory for a new Node, which is immediately lost with location = data.
Pointers (like any other basic type) need to be initialized before use. A value of NULL is still a value.
The code you provided seems to be very incomplete. Is data supposed to be the head of your list? I am not sure how you define "fullness". If you want to test if the list is empty, you can see if your "head" of the list is null:
bool UnsortedList::IsEmpty() {
if (data == NULL) {return true;} // if there is no first element, empty
else {return false;} // if there is ANY element, not empty
}
Or more compactly:
bool UnsortedList::Empty() {
return (data == NULL);
}
When a node is added to a linked list, we usually add the node as a whole and modify the element that came before it. For example, we might create a new node and add it using code like the following:
// implementation file
void UnsortedList::InsertItem(const float& item) {
if (data == NULL) { // no elements in list, so new node becomes the head
data = new Node; // allocate memory for new node
data->element = item; // fill with requested data
data->next = NULL; // there is no element after the tail
}
else {
new_node = new Node; // allocate memory
new_node->element = item // set data
new_node->next = NULL; // new end of the list, so it points to nothing
tail->next = new_node; // have the OLD end node point to the NEW end
tail = new_node; // have the tail member variable move up
}
}
// driver file
int main() {
UnsortedList my_list;
float pie = 3.14159;
my_list.AddNode(pie);
return 0;
}
Please note that I made use of a Node* member variable called tail. It is a good idea to keep track of both where the list begins and ends.
In your IsFull function, it will always return false since it can always create a new Node*. Except perhaps if you run out of memory, which is probably more problematic.
Your functions are rather confusing and your pointer work leaves many memory leaks. You might want to review the STL list object design here.
If I have a queue implemented as a series of nodes (value, pointer to next node), what would be the best way to transverse that queue and check for a specific value, and edit the queue such that all nodes containing that value would be removed. But the order of the queue would otherwise remain.
Ok here is the header describing all the functions
class queue
{
public:
queue(); // constructor - constructs a new empty queue.
void enqueue( int item ); // enqueues item.
int dequeue(); // dequeues the front item.
int front(); // returns the front item without dequeuing it.
bool empty(); // true iff the queue contains no items.
int size(); // the current number of items in the queue.
int remove(int item); // removes all occurrances of item
// from the queue, returning the number removed.
private:
class node // node type for the linked list
{
public:
node(int new_data, node * next_node ){
data = new_data ;
next = next_node ;
}
int data ;
node * next ;
};
node* front_p ;
node* back_p ;
int current_size ; // current number of elements in the queue.
};
and here is the queue.cpp
#include "queue.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
queue::queue()
{
front_p = NULL;
back_p = NULL;
current_size = 0;
}
void queue::enqueue(int item)
{
node* newnode = new node(item, NULL);
if (front_p == NULL) //queue is empty
front_p = newnode;
else
back_p->next = newnode;
back_p = newnode;
current_size ++;
}
int queue::dequeue()
{
//if there is only one node
int value = front_p->data;
if (front_p == back_p)
{
front_p = NULL;
back_p = NULL;
}
//if there are two or more
else
{
node* temp = front_p;
front_p = temp->next;
delete temp;
}
current_size --;
return value;
}
int queue::front()
{
if (front_p != NULL)
return front_p->data;
}
bool queue::empty()
{
if (front_p == NULL && back_p == NULL)
return true;
else
return false;
}
int queue::size()
{
return current_size;
}
int queue::remove(int item)
{
//?????
}
You need to traverse the list, checking the values of each node. If you see a sequence A -> B -> C, where B is the value that you want to remove, you need to change the link from A to point to C instead of B.
To facilitate this, you'll need to keep a reference to the last node you saw as well as the current one. If the current node's value is equal to the one to remove, change the last node's next pointer to the current node's next pointer. Make sure to free the current node's memory before continuing on.
If your queue exposes standard iterators, the best way would be to use a standard algorithm:
queue.erase(std::remove(queue.begin(), queue.end(), value_to_remove), queue.end());
I am working on a linked list implementation in C++. I am making progress but am having trouble getting the insertion functionality and deletion functionality to work correctly. Below is list object in the C++ header file:
#ifndef linkList_H
#define linkList_h
//
// Create an object to represent a Node in the linked list object
// (For now, the objects to be put in the list will be integers)
//
struct Node
{
Node() : sentinel(0) {}
int number;
Node* next;
Node* prev;
Node* sentinel;
};
//
// Create an object to keep track of all parts in the list
//
class List
{
public:
//
// Contstructor intializes all member data
//
List() : m_listSize(0), m_listHead(0) {}
//
// methods to return size of list and list head
//
Node* getListHead() const { return m_listHead; }
unsigned getListSize() const { return m_listSize; }
//
// method for adding and inserting a new node to the linked list,
// retrieving and deleting a specified node in the list
//
void addNode(int num);
void insertNode(Node* current);
void deleteNode(Node* current);
Node* retrieveNode(unsigned position);
private:
//
// member data consists of an unsigned integer representing
// the list size and a pointer to a Node object representing head
//
Node* m_listHead;
unsigned m_listSize;
};
#endif
And here is the implementation (.cpp) file:
#include "linkList.h"
#include <iostream>
using namespace std;
//
// Adds a new node to the linked list
//
void List::addNode(int num)
{
Node *newNode = new Node;
newNode->number = num;
newNode->next = m_listHead;
m_listHead = newNode;
++m_listSize;
}
//
// NOTWORKING: Inserts a node which has already been set to front
// of the list
//
void List::insertNode(Node* current)
{
// check to see if current node already at
// head of list
if(current == m_listHead)
return;
current->next = m_listHead;
if(m_listHead != 0)
m_listHead->prev = current;
m_listHead = current;
current->prev = 0;
}
//
// NOTWORKING: Deletes a node from a specified position in linked list
//
void List::deleteNode(Node* current)
{
current->prev->next = current->next;
current->next->prev = current->prev;
}
//
// Retrieves a specified node from the list
//
Node* List::retrieveNode(unsigned position)
{
if(position > (m_listSize-1) || position < 0)
{
cout << "Can't access node; out of list bounds";
cout << endl;
cout << endl;
exit(EXIT_FAILURE);
}
Node* current = m_listHead;
unsigned pos = 0;
while(current != 0 && pos != position)
{
current = current->next;
++pos;
}
return current;
}
After running a brief test program in the client C++ code, here is the resulting output:
Number of nodes: 10
Elements in each node:
9 8 7 6 5 4 3 2 1 0
Insertion of node 5 at the list head:
4 9 8 7 6 5 4 9 8 7
Deletion of node 5 from the linked list
As you can see, the insertion is not simply moving node 5 to head of list, but is overwriting other nodes beginning at the third position. The pseudo code I tried to implement came from the MIT algorithms book:
LIST-INSERT(L, x)
next[x] <- head[L]
if head[L] != NIL
then prev[head[L]] <- x
head[L] <- x
prev[x] <- NIL
Also the deletion implementation is just crashing when the method is called. Not sure why; but here is the corresponding pseudo-code:
LIST-DELET'
next[prev[x]] <- next[x]
prev[next[x]] <- prev[x]
To be honest, I am not sure how the previous, next and sentinel pointers are actually working in memory. I know what they should be doing in a practical sense, but looking at the debugger it appears these pointers are not pointing to anything in the case of deletion:
(*current).prev 0xcdcdcdcd {number=??? next=??? prev=??? ...} Node *
number CXX0030: Error: expression cannot be evaluated
next CXX0030: Error: expression cannot be evaluated
prev CXX0030: Error: expression cannot be evaluated
sentinel CXX0030: Error: expression cannot be evaluated
Any help would be greatly appreciated!!
You have got an error in addNode(). Until you fix that, you can't expect insertNode to work.
Also, I think your design is quite silly. For example a method named "insertNode" should insert a new item at arbitrary position, but your method insertNode does a pretty different thing, so you should rename it. Also addNode should be renamed. Also as glowcoder wrote, why are there so many sentinels? I am affraid your class design is bad as a whole.
The actual error is that you forgot to set prev attribute of the old head. It should point to the new head.
void List::addNode(int num)
{
Node *newNode = new Node;
newNode->number = num;
newNode->next = m_listHead;
if(m_listHead) m_listHead->prev = newNode;
m_listHead = newNode;
++m_listSize;
}
Similarly, you have got another error in deleteNode(). It doesn't work when deleting last item from list.
void List::deleteNode(Node* current)
{
m_listSize--;
if(current == m_listHead) m_listHead = current->next;
if(current->prev) current->prev->next = current->next;
if(current->next) current->next->prev = current->prev;
}
Now you can fix your so-called insertNode:
void List::insertNode(Node* current)
{
int value = current->number;
deleteNode(current);
addNode(value);
}
Please note that I wrote everything here without compiling and testing in C++ compiler. Maybe there are some bugs, but still I hope it helps you at least a little bit.
In deleteNode, you are not handling the cases where current->next and/or current->prev is null. Also, you are not updating the list head if current happens to be the head.
You should do something like this:
node* next=current->next;
node* prev=current->prev;
if (next!=null) next->prev=prev;
if (prev!=null) prev->next=next;
if (m_listhead==current) m_list_head=next;
(Warning: I have not actually tested the code above - but I think it illustrates my idea well enough)
I am not sure what exactly your InsertNode method does, so I can't offer any help there.
OK.
As #Al Kepp points out, your "add node" is buggy. Look at Al's code and fix that.
The "insert" that you are doing does not appear to be a normal list insert. Rather it seems to be a "move to the front" operation.
Notwithstanding that, you need to delete the node from its current place in the list before you add it to the beginning of the list.
Update
I think you have misunderstood how insert should work. It should insert a new node, not one that is already in the list.
See below for a bare-bones example.
#include <iostream>
// List Node Object
//
struct Node
{
Node(int n=0);
int nData;
Node* pPrev;
Node* pNext;
};
Node::Node(int n)
: nData(n)
, pPrev(NULL)
, pNext(NULL)
{
}
//
// List object
//
class CList
{
public:
//
// Contstructor
//
CList();
//
// methods to inspect list
//
Node* Head() const;
unsigned Size() const;
Node* Get(unsigned nPos) const;
void Print(std::ostream &os=std::cout) const;
//
// methods to modify list
//
void Insert(int nData);
void Insert(Node *pNew);
void Delete(unsigned nPos);
void Delete(Node *pDel);
private:
//
// Internal data
//
Node* m_pHead;
unsigned m_nSize;
};
/////////////////////////////////////////////////////////////////////////////////
CList::CList()
: m_pHead(NULL)
, m_nSize(0)
{
}
Node *CList::Head() const
{
return m_pHead;
}
unsigned CList::Size() const
{
return m_nSize;
}
void CList::Insert(int nData)
{
Insert(new Node(nData));
}
void CList::Insert(Node *pNew)
{
pNew->pNext = m_pHead;
if (m_pHead)
m_pHead->pPrev = pNew;
pNew->pPrev = NULL;
m_pHead = pNew;
++m_nSize;
}
void CList::Delete(unsigned nPos)
{
Delete(Get(nPos));
}
void CList::Delete(Node *pDel)
{
if (pDel == m_pHead)
{
// delete first
m_pHead = pDel->pNext;
if (m_pHead)
m_pHead->pPrev = NULL;
}
else
{
// delete subsequent
pDel->pPrev->pNext = pDel->pNext;
if (pDel->pNext)
pDel->pNext->pPrev = pDel->pPrev;
}
delete pDel;
--m_nSize;
}
Node* CList::Get(unsigned nPos) const
{
unsigned nCount(0);
for (Node *p=m_pHead; p; p = p->pNext)
if (nCount++ == nPos)
return p;
throw std::out_of_range("No such node");
}
void CList::Print(std::ostream &os) const
{
const char szArrow[] = " --> ";
os << szArrow;
for (Node *p=m_pHead; p; p = p->pNext)
os << p->nData << szArrow;
os << "NIL\n";
}
int main()
{
CList l;
l.Print();
for (int i=0; i<10; i++)
l.Insert((i+1)*10);
l.Print();
l.Delete(3);
l.Delete(7);
l.Print();
try
{
l.Delete(33);
}
catch(std::exception &e)
{
std::cerr << "Failed to delete 33: " << e.what() << '\n';
}
l.Print();
return 0;
}