Why am I getting a Redefinition of a C++ class error? - c++

Using the following code below I am getting a "Redefinition of SortedLL" error.
So I removed "class SortedLL" from the header file below. But when I remove SortedLL from the header file then I can't declare a SortedLL in the main.cpp file.
So I am stuck. What am I missing?
Sorted Linked List header file
#ifndef SortedLinkedList_SortedLL_h
#define SortedLinkedList_SortedLL_h
struct Node {
int data;
struct Node * next;
};
class SortedLL {
public:
int find(int data);
bool remove(int data);
int size();
bool removeOdd();
bool add(int data);
private:
struct Node * pHead;
int length;
};
#endif
Sorted Linked List CPP file
#include <iostream>
#include "SortedLL.h"
class SortedLL {
private:
// searches the linked list linearly
int findLinear(int data, struct Node ** pPrev, struct Node ** pCurr){
// start at head of list
*pCurr = pHead;
*pPrev = NULL;
int index = 0;
while (*pCurr != NULL){
if ((*pCurr)->data == data){
// found
return index;
}
else {
*pPrev = *pCurr;
*pCurr = (*pCurr)->next;
index++;
}
}
return -1;
}
bool findInsertPointLinear(struct Node ** pPrev, struct Node ** pCurr, int data){
while (*pCurr != NULL){
// if current data is less then new data
if ((*pCurr)->data < data){
// store previous node
*pPrev = *pCurr;
// advance to next position
*pCurr = (*pCurr)->next;
}
// current value is >= new val
else {
// we found insertion point
break;
}
}
return true;
}
// returns the value at the index or NULL if no value exists
bool get(int index, int * val) {
// check if out of bounds
if (index < 0 || index > (length-1)) {
// out of bounds
return false;
}
struct Node * pCurr = pHead;
for (int i=0;i<=index;i++){
pCurr = pCurr->next;
}
if (val != NULL) {
*val = pCurr->data;
}
return true;
}
public:
bool add (int data) {
struct Node * pCurr = pHead;
struct Node * pPrev = NULL;
bool returnVal = true;
// if the list is empty
if (pHead == NULL){
// add the new node
pHead = (struct Node *)malloc(sizeof(struct Node));
pHead->data = data;
pHead->next = NULL;
// return success
length++;
return returnVal;
}
// the list is not empty, so find insertion point
if (findInsertPointLinear(&pPrev, &pCurr, data)){
// if inserting at the begininng of list
if (pPrev == NULL){
pPrev = (struct Node *)malloc(sizeof(struct Node));
if (pPrev != NULL) {
pPrev->data = data;
pPrev->next = pCurr;
// keep track of head pointer
pHead = pPrev;
}
else {
// failed to allocate memory
returnVal = false;
}
}
// if inserting at end of list
else if (pCurr == NULL && pPrev !=NULL) {
pCurr = (struct Node *)malloc(sizeof(struct Node));
if (pCurr != NULL){
pCurr->data = data;
pPrev->next = pCurr;
pCurr->next = NULL;
}
else {
// failure to allocate memory
returnVal = false;
}
}
// if inserting in the middle of list
else {
pPrev->next = (struct Node *) malloc (sizeof(struct Node));
if (pPrev->next != NULL){
pPrev->next->data = data;
pPrev->next->next = pCurr;
}
else {
// failure to allocate memory
returnVal = false;
}
}
}
// increment size of list by 1
if (returnVal == true)
length++;
return returnVal;
}
// returns index of first occurrence of data or -1 if not found
int find(int data){
struct Node * pPrev = NULL;
struct Node * pCurr = NULL;
return findLinear(data, &pPrev, &pCurr);
}
bool remove(int data) {
// try to find data
struct Node * pPrev = NULL;
struct Node * pCurr = NULL;
int removeIndex = findLinear(data, &pPrev, &pCurr);
bool returnVal = false;
// if found
if (removeIndex != -1){
// remove node
return false;
}
// if removing at the head
if (removeIndex == 0){
if (pCurr != NULL){
pHead = pCurr->next;
free(pCurr);
pCurr = NULL;
returnVal = true;
}
else {
printf("trying to remove an element that does not exist\n");
}
}
// if removing at the end
else if (removeIndex == (length-1)){
if (pCurr != NULL) {
free(pCurr);
pCurr = NULL;
if (pPrev != NULL){
pPrev->next = NULL;
}
returnVal = true;
}
else {
printf("trying to remove an element that does not exist\n");
}
}
// removing somewhere in the middle
else {
if (pPrev != NULL && pCurr != NULL){
struct Node * temp = pCurr->next;
free(pCurr);
pCurr = NULL;
pPrev->next = temp;
returnVal = true;
}
// something is wrong
else {
printf("attempting to remove an element from middle but either previous or curr element is NULL\n");
}
}
return returnVal;
}
int size(){
return length;
}
bool removeOdd(){
struct Node * pCurr = pHead;
struct Node * pPrev = NULL;
// iterate over list
while (pCurr != NULL){
// if current data element is odd
if (pCurr->data %2 != 0){
// remove it
// removing at head
if (pCurr == pHead){
pHead = pHead->next;
free(pCurr);
pCurr = pHead;
}
// if removing at the end
else if (pCurr->next == NULL){
free(pCurr);
pCurr = NULL;
pPrev->next = NULL;
}
// removing somewhere in the middle
else {
struct Node * temp = pCurr->next;
free(pCurr);
pPrev->next = temp;
// advance pCurr to next node
pCurr = temp;
}
}
// if current data element even
else {
pPrev = pCurr;
pCurr = pCurr->next;
}
}
return true;
}
}SortedLL;

As # PaulMcKenzie points out, you've defined the class SortedLL in both your header and your .cpp file. What you want in the .cpp is just the method definitions. Something like:
int SortedLL ::findLinear(int data, struct Node ** pPrev, struct Node ** pCurr) {
...
}

Related

Inserting a node before a specific node in a singly linked list

I have implemented a method to insert a new node before a specific node.
#ifndef FORWARD_SINGLY_LINKED_LIST_H
#define FORWARD_SINGLY_LINKED_LIST_H
#include <cstdlib>
#include <string.h>
#include <iostream>
namespace forward_singly_linked_list {
typedef struct Node {
std::string data;
struct Node *nextPointer;
} Node;
typedef Node *NodeP;
class LinkedList {
private:
int elementsCount;
Node *head;
public:
LinkedList() {
head = NULL;
elementsCount = 0;
}
int get_length() const
{
return elementsCount;
}
// ... ... ...
void add_before(std::string value, std::string before)
{
// empty an area in the memory, and
// save the address of the empty area in 'newNode'
Node *newNode = new Node();
// assign 'value' to the 'data' section of the
// area pointed by 'newNode'
newNode->data = value;
Node * copyOfHead = head;
if (copyOfHead == nullptr)
{
// the list is empty.
// there is no possibility to find 'before'.
// so, return.
return;
}
else
{
bool found = false;
Node * previousNode = nullptr;
while (copyOfHead != nullptr)
{
if (copyOfHead->data == before)
{
found = true;
break;
}
else
{
previousNode = copyOfHead;
copyOfHead = copyOfHead->nextPointer;
}
}
if (!found)
{
return;
}
if (previousNode != nullptr)
{
newNode->nextPointer = previousNode->nextPointer;
previousNode->nextPointer = newNode;
}
else
{
newNode->nextPointer = head;
head = newNode;
}
}
elementsCount++;
}
// ... ... ...
void print() {
Node *copyOfHead = head;
while (copyOfHead != NULL) {
std::cout << copyOfHead->data;
copyOfHead = copyOfHead->nextPointer;
}
std::cout<<"\n\n";
}
public:
static int Test() {
forward_singly_linked_list::LinkedList list;
list.print();
// list.add_at_tail("A");
// list.add_at_tail("B");
// list.add_at_tail("C");
list.print();
list.add_at("-XXX-", 1);
list.print();
return 0;
}
};
}
#endif
Personally, I don't like it because it uses an extra pointer previousNode. I have a feeling that it could be improved.
How can I improve the implementation?
The idea is about link the previous node to input/target node, then link the target/input node to current node.
Here is my code using simple loop index(i) instead of using extra pointer
void Sll::add_at_index( int ind , int value ){
Node *target = new Node( value ) ;
if( ind == 1){
target->next = head ;
head = target ;
}else if( ind == length){
tail->next = target ;
tail = target ;
tail->next = nullptr ;
}else{
Node *curr =head ;
for( int i = 1 ; i < length ; i++ ){
if( i+1 == ind){
Node *Mynext = curr->next ;
curr->next = target ;
target->next = Mynext ;
break ;
}
curr = curr->next ;
}
}
length++ ;
}
Become a two-star programmer:
void add_before(std::string value, std::string_view before) {
auto p = &head;
while (*p && (*p)->data != before)
p = &(*p)->nextPointer;
if (!*p)
return;
*p = new Node {
.data = std::move(value),
.nextPointer = *p,
};
++elementsCount;
}

Exception thrown: read access violation this->pCurr was 0xDDDDDDDD

I am a beginner and am working on linked list. I am trying to make a method that removes the current link of a list. I am getting an exception : read access violation this->pCurr was 0xDDDDDDDD.
This is what my code looks like (I removed some methods, such as adding links and left only those related to removal)
template <class T>
struct TNode {
T val;
TNode<T> *pNext;
};
template <class T>
class TList {
protected:
TNode <T> *pFirst, *pLast, *pCurr, *pPrev, *pStop;
int len; //lenght
int pos;//where pCurr shows
public:
//constructor
TList() {
pFirst = NULL;
pLast = NULL;
pCurr = NULL;
pPrev = NULL;
pStop = NULL;
len = 0;
pos = 0;
}
//destructor
~TList() {
TNode<T> *tmp = pFirst;
//if (tmp == pStop)
//delete tmp;
while (pFirst != pStop) {
pFirst = pFirst->pNext;
delete tmp;
tmp = pFirst;
}
}
//delete first link
void DelFirst() {
T res = pFirst->val;
TNode<T> *tmp;
tmp = pFirst;
pFirst = pFirst->pNext;
delete tmp;
len--;
}
//delete current link
void DelCurr() {
if (pCurr == pFirst)
DelFirst();
else {
TNode<T> *tmp = pCurr;
pPrev->pNext = pCurr->pNext; // an exception is thrown on this line
pCurr = pCurr->pNext;
delete tmp;
len--;
}
}
//set pCurr to the beginning
void Reset() {
pCurr = pFirst;
pPrev = pStop;
pos = 0;
}
//go to the next link
void GoNext() {
//if (IsEnd()) throw - 1;
//else {
pPrev = pCurr;
pCurr = pCurr->pNext;
pos++;
//}
}
//end check
bool IsEnd() {
return (pCurr == pStop);
}
//delete the whole list
void DelList() {
for (Reset(); !IsEnd(); GoNext()) {
DelCurr();
}
DelCurr();
}
};
Please tell me what this exception is related to and how to fix it.
Check for null pointers everywhere
And in DelFirst() function, set the pCurr to the next, when it points on pFirst
void DelFirst()
{
if (pFirst == NULL)
{
return;
}
if (pCurr == pFirst)
{
pCurr = pFirst->pNext;
}
T res = pFirst->val;
TNode<T>* tmp;
tmp = pFirst;
pFirst = pFirst->pNext;
delete tmp;
len--;
}

Doubly Linked List fails to add or delete valid entries

I've run it many times. I tried fixing my deleteNode() and addNode(), but it did not work. The output showed me that it failed to add some valid entries in my list, which resulted in failing to delete these valid entries. Someone please help me find the errors... I think either my isEmpty() is wrong or the addNode got messed up.
// Add nodes and makes it work in any cases: backward/forward
bool LinkedList::addNode(int id, string str) {
bool result = false;
if (id >= 0 && !(idExists(id))) {
Node *current = head;
Node *temp = new Node;
temp->data.data = str;
temp->data.id = id;
temp->forward = NULL;
temp->back = NULL;
// Kinds of adding cases
if(head == NULL) { // Check if list is empty
addHead(temp, current);
result = true;
} else {
while(temp->data.id > current->data.id && current->forward != NULL) {
current = current->forward;
}
// Backward
if(current->back == NULL) {
if(temp->data.id > current->data.id) {
if(current->forward == NULL) {
addTail(temp, current);
} else {
addMiddle(temp, current);
}
} else {
addHead(temp, current);
}
result = true;
// Forward
}else if(current->forward == NULL) {
if (temp->data.id > current->data.id) {
addTail(temp, current);
} else {
addMiddle(temp, current);
}
result = true;
}else {
if(temp->data.id > current->data.id) {
addMiddle(temp, current);
result = true;
}
}
}
}
return result;
}
void LinkedList::addHead(Node *temp, Node *current) {
if (head != NULL){
temp->forward = current;
current->back = temp;
head = temp;
} else {
head = temp;
}
}
void LinkedList::addMiddle(Node *temp, Node *current) {
temp->forward = current;
temp->back = current->back;
current->back->forward = temp;
current->back = temp;
}
void LinkedList::addTail(Node *temp, Node *current) {
current->forward = temp;
temp->back = current;
}
// Delete list
bool LinkedList::deleteNode(int id){
bool result = false;
if (idExists(id)) {
Node *current = head;
while (current->forward != NULL && current->data.id != id) {
current = current->forward;
}
if (current->data.id == id && current->forward == NULL) {
if (current->back == NULL) { // Delete head
delete current;
head = NULL;
} else { // delete tail
deleteTail(current);
}
result = true;
} else if (current->data.id == id) {
if (current->back == NULL)
deleteHead(current);
else // delete middle
deleteMiddle(current);
result = true;
}
}
return result;
}
// Helper delete functions
void LinkedList::deleteHead(Node *current) {
head = current->forward;
head->back = NULL;
delete current;
}
void LinkedList::deleteMiddle(Node *current) {
current->back->forward = current->forward;
current->forward->back = current->back;
delete current;
}
void LinkedList::deleteTail(Node *current) {
current->back->forward = NULL;
delete current;
}
bool LinkedList::getNode(int id, Data *data) {
bool didGetNode = false;
if (idExists(id)) {
Node *current = head;
while (current->forward != NULL && current->data.id != id) {
current = current->forward;
}
data->id = current->data.id;
data->data = current->data.data;
didGetNode = true;
}
return didGetNode;
}
// Check whether or not the id exists
bool LinkedList::idExists(int id){
bool exists = false;
if (head != NULL){
Node *current = head;
while (current->forward != NULL && current->data.id != id) {
current = current->forward;
}
if (current->data.id == id) {
exists = true;
}
}
return exists;
}
You probably want to be passing a pointer to a pointer (**) or a pointer to a reference (*&) in functions where you are wanting to make a change to what the address of the node is containing. I hope that this helps you visualize it.
For example:
struct Node { };
void setNull1(Node* temp)
{
temp = nullptr;
}
void setNull2(Node** temp)
{
(*temp) = nullptr;
}
void setNull3(Node*& temp)
{
temp = nullptr;
}
int main()
{
Node* tmp = new Node;
setNull1(tmp);
if (tmp == nullptr)
{
cout << "NULLPTR";
} // tmp is not nullptr
Node* tmp1 = new Node;
setNull2(&tmp1);
if (tmp1 == nullptr)
{
cout << "NULLPTR";
} // tmp1 is nullptr
Node* tmp2 = new Node;
setNull3(tmp2);
if (tmp2 == nullptr)
{
cout << "NULLPTR";
} // tmp2 is nullptr
}
You should also consider writing nullptr instead of NULL.

C++ Linked List list_copy_front function confusion

I've been struggling with this last function (list_copy_front). The function is for a linked list, it is supposed to return the value of the head pointer for a new list that contains copies of the first n nodes that the source pointer points to. Also if there is less than n nodes in the source then just copy all. Currently, when I run it as is I get a nasty Segmentation Fault SIGSEGV error. The debugger says the error happens at "Node *cursor = source_ptr-> link; Any help would be greatly appreciated, thank you.
Here is some relevant info,
struct Node
{
typedef int Item;
Item data;
Node *link;
};
void list_tail_attach(Node*& head_ptr, const Node::Item& entry);
Node* list_copy_front(Node* source_ptr, size_t n);
void list_tail_attach(Node*& head_ptr, const Node::Item& entry)
{
Node *last = new Node;
last->data = entry;
last->link = NULL;
if(head_ptr == NULL)
{
head_ptr = last;
}
else
{
Node *temp = new Node;
temp = head_ptr;
while(temp->link != NULL)
{
temp = temp->link;
}
temp->link = last;
}
}
Node* list_copy_front(Node* source_ptr, size_t n)
{
Node *new_head_ptr = new Node;
Node *cursor = source_ptr->link;
size_t i = 0;
for(i = 0; i < n; i++)
{
list_tail_attach(new_head_ptr, cursor->data);
cursor = cursor->link;
}
return new_head_ptr;
}
Here's the Main test for the function
int test4()
{
Node* list = NULL; // an empty list
Node* copy = NULL;
copy = list_copy_front(list, 3);
if(copy != NULL)
{
cout << "list_copy_front function doesn't work for copying empty list\n";
return 0;
}
for(int i = 1; i <= 4; i++)
list_tail_attach(list, i);
// list contains 1, 2, 3, 4
copy = list_copy_front(list, 3);
if(list_length(copy) != 3 || copy->data != 1 || copy->link->data != 2 || copy->link->link->data != 3 )
{
cout << "list_copy_front function doesn't work\n";
return 0;
}
copy->link->data = 100;
if(list->link->data == 100)
{
cout << "list_copy_front function doesn't work.\n";
return 0;
}
list_clear(copy);
copy = list_copy_front(list, 6);
if(list_length(copy) != 4)
{
cout << "list_copy_front function doesn't work\n";
return 0;
}
cout << "list_copy_front passes the test\n";
list_clear(list);
for(int i = 1; i <= 3; i++)
list_head_insert(list, i);
// list contains 3, 2, 1
list_copy(list, copy);
if(list_length(copy) != 3 || copy->data != 3 || copy->link->data != 2 || copy->link->link->data != 1 )
{
cout << "list_copy function doesn't work\n";
return 0;
}
cout << "list_copy function passes the test\n";
return 2;
}
Edit 3
So far here's what I'm working with I appreciate the comments so far it's just not quite working out. Which is probably my fault for not explaining better.
void list_tail_attach(Node*& head_ptr, const Node::Item& entry)
{
Node *last = new Node; // Creates new Node
last->data = entry; // Points last to data
last->link = NULL;
if(last == NULL)
{
return;
}
if(head_ptr == NULL)
{
head_ptr = last;
}
else
{
Node *temp = head_ptr;
while(temp->link != NULL)
{
temp = temp->link;
}
temp->link = last;
}
}
Node* list_copy_front(Node* source_ptr, size_t n)
{
if(source_ptr == NULL)
{
return NULL;
}
Node *new_head_ptr = new Node;
Node *cursor = source_ptr;
size_t i = 0;
while(cursor!= NULL && i < n)
{
list_tail_attach(new_head_ptr, cursor->data);
cursor = cursor->link;
i++;
}
return new_head_ptr;
}
I am not allowed to change the way the function takes it's input so, that's why I left Node *last.
I left list_tail_attach(new_head_ptr, cursor->data) because without it I get an invalid conversion error. However when I run the above code I still receive an SIGSEGV error for while(temp->link != NULL) in list_tail_attach and on list_tail_attach(new_head_ptr, cursor->data); in list_copy_front.
Thank you if you are able to comment further
The first test case
Node* list = NULL; // an empty list
Node* copy = NULL;
copy = list_copy_front(list, 3);
gives Node* source_ptr == NULL and expects your function to handle it gracefully.
The function code soon tries to dereference NULL
Node *cursor = source_ptr->link;
The result is a segfault.
First is list_tail_attach, this function I assumed to be attaching an existing Node into a linked list. If the linked list is null then the Node become the head
void list_tail_attach(Node *& head_ptr, Node *& entry)
{
if (entry == NULL) {
return;
}
if (head_ptr == NULL)
{
head_ptr = entry;
}
else
{
Node *temp = head_ptr;
while (temp->link != NULL)
{
temp = temp->link;
}
temp->link = entry;
}
}
I changed the entry into a reference to a pointer to made it easier.
Ok, now move on to the list_copy_front
Node * list_copy_front(Node* source_ptr, size_t n)
{
if (source_ptr == NULL) {
return NULL;
}
Node * new_head_ptr = new Node;
Node * cursor = source_ptr;
size_t i = 0;
while(cursor != NULL && i < n){
list_tail_attach(new_head_ptr, cursor);
cursor = cursor->link;
i++;
}
return new_head_ptr;
}
You have to guard the source_ptr in case it is null.
To attach a new Node
for (int x = 0; x < 5; x++) {
Node * tmp = new Node();
tmp->data = x;
tmp->link = NULL;
list_tail_attach(list, tmp);
}
My professor helped me out with the correct solution. For anyone who views this in the future...
Node* list_copy_front(Node* source_ptr, size_t n)
{
if(source_ptr == NULL) // Takes care of NULL case
{
return NULL;
}
Node *new_head_ptr = NULL; // Creates new head and ensures NULL
Node *cursor = source_ptr; // Sets temp Node = to source
size_t i = 0; // Initializes temp variable
while(cursor!= NULL && i < n) // Loop that continues while n is bigger than i and it is not NULL
{
list_tail_attach(new_head_ptr, cursor->data);
cursor = cursor->link; // Attaches to new list
i++; // Increases count
}
return new_head_ptr;
}
The line that needed to be changed was
Node * new_head_ptr = new Node;
to
Node * new_head_ptr = NULL;

Reversing a Doubly Linked List with member function

I am trying to reverse a doubly linked list. According to other questions on stack overflow and the web this is the proper method to reverse a doubly linked list; swapping the next and back pointers of every node. For some reason it's not working for me and I can't debug it because XCode 6 has the entire debug menu grayed out. The reverse function is at the bottom of dll.cpp. Heres my code:
dll.h:
#ifndef dll_h
#define dll_h
#include <iostream>
using namespace std;
template <class ItemType>
struct NodeType
{
ItemType info;
NodeType* next;
NodeType* back;
};
template <class ItemType>
class DoublyLinkedList
{
public:
DoublyLinkedList(); // Class constructor.
~DoublyLinkedList(); // Class destructor.
////////// implement these functions //////////
DoublyLinkedList(DoublyLinkedList<ItemType>& );
void InsertItem(ItemType item);
void DeleteItem(ItemType item);
void reverseDoublyLinkedList();
void FindItem(NodeType<ItemType>* listData, ItemType item, NodeType<ItemType>*& location, bool& found);
int LengthIs() const;
void MakeEmpty();
void RetrieveItem(ItemType& item, bool& found);
void ResetList();
void GetNextItem(ItemType& item);
private:
NodeType<ItemType>* listData;
int length;
NodeType<ItemType>* currentPos;
};
#endif
dll.cpp:
#include "DLL.h"
template<class ItemType>
DoublyLinkedList<ItemType>::DoublyLinkedList()
{
listData = NULL;
length =0;
currentPos = NULL;
}
template<class ItemType>
void DoublyLinkedList<ItemType>::FindItem(NodeType<ItemType>* listData, ItemType item,
NodeType<ItemType>*& location, bool& found)
// Assumption: ItemType is a type for which the operators "<" and
// "==" are defined-either an appropriate built-in type or a
// class that overloads these operations.
// Pre: List is not empty.
// Post: If there is an element someItem whose key matches item's
// key, then found = true; otherwise, found = false.
// If found, location contains the address of someItem;
// otherwise, location contains the address of the logical
// successor of item.
{
bool moreToSearch = true;
location = listData;
found = false;
while (moreToSearch && !found)
{
if (item < location->info)
moreToSearch = false;
else if (item == location->info)
found = true;
else
{
location = location->next;
moreToSearch = (location != NULL);
}
}
}
template <class ItemType>
int DoublyLinkedList<ItemType>::LengthIs() const
{
return length;
}
template <class ItemType>
void DoublyLinkedList<ItemType>::MakeEmpty()
// Post: List is empty; all items have been deallocated.
{
NodeType<ItemType>* tempPtr;
while (listData != NULL)
{
tempPtr = listData;
listData = listData->next;
delete tempPtr;
}
length = 0;
}
template <class ItemType>
void DoublyLinkedList<ItemType>::ResetList()
{
currentPos = NULL;
}
template <class ItemType>
void DoublyLinkedList<ItemType>::GetNextItem(ItemType& item)
{
if (currentPos == NULL)
currentPos = listData;
else
currentPos = currentPos->next;
item = currentPos->info;
}
template <class ItemType>
void DoublyLinkedList<ItemType>::RetrieveItem(ItemType& item,
bool& found)
{
bool moreToSearch;
NodeType<ItemType>* location;
location = listData;
found = false;
moreToSearch = (location != NULL);
while (moreToSearch && !found)
{
if (location->info < item)
{
location = location->next;
moreToSearch = (location != NULL);
}
else if (item == location->info)
{
found = true;
item = location->info;
}
else
moreToSearch = false;
}
}
template <class ItemType>
DoublyLinkedList<ItemType>:: ~DoublyLinkedList() // Class destructor.
{
MakeEmpty();
}
template <class ItemType>
void DoublyLinkedList<ItemType>::InsertItem(ItemType item)
{
NodeType<ItemType>* node = new NodeType<ItemType>;
node->info = item;
if(!length)
{
listData = node;
node->next = NULL;
node->back = NULL;
length++;
return;
}
NodeType<ItemType>* temp =listData;
if(temp->next == NULL)
{
if(temp->info < item)
{
node->next = NULL;
node->back = temp;
temp->next = node;
}
else
{
node->next = temp;
node->back = NULL;
temp->back = node;
}
length++;
return;
}
while(1)
{
if(temp->info > item)
{
node->next = temp;
node->back = temp->back;
if(temp->back != NULL)
{
node->back->next = node;
}
if(temp->back == NULL)
listData = node;
node->back = temp->back;
length++;
return;
}
else if(temp->next == NULL)
{
node->next = NULL;
node->back = temp;
temp->next = node;
length++;
return;
}
temp = temp->next;
}
}
template <class ItemType>
void DoublyLinkedList<ItemType>::DeleteItem(ItemType item)
{
NodeType<ItemType>* node = listData;
if(node == NULL)
return;
while(node != NULL && node->info != item)
node = node->next;
if(node == NULL)
return;
if(node->back != NULL)
node->back->next = node->next;
if(node->next != NULL)
node->next->back = node->back;
delete node;
length--;
}
template <class ItemType>
DoublyLinkedList<ItemType>::DoublyLinkedList(DoublyLinkedList<ItemType>& original)
{
length = 0;
currentPos = NULL;
listData = NULL;
NodeType<ItemType>* copy = original.listData;
while(copy != NULL)
{
InsertItem(copy->info);
copy = copy->next;
}
}
template<class ItemType>
void DoublyLinkedList<ItemType>::reverseDoublyLinkedList()
{
if(listData == NULL || listData->next == NULL)
return;
NodeType<ItemType>* node = listData;
while(node!=NULL)
{
swap(node->next, node->back);
listData = node;
node = node->back;
}
currentPos = NULL;
}
main.cpp:
#include <iostream>
#include "dll.h"
#include "dll.cpp"
int main()
{
DoublyLinkedList<int> s;
s.InsertItem(3);
s.InsertItem(4);
s.InsertItem(1);
s.DeleteItem(2);
s.DeleteItem(4);
cout<<"Length of s: "<<s.LengthIs()<<endl;
DoublyLinkedList<int> t = s;
cout<<"Length of t: "<<t.LengthIs()<<endl;
t.InsertItem(5);
t.InsertItem(13);
t.InsertItem(10);
t.InsertItem(-3);
int a;
t.ResetList();
for(int i=0;i<t.LengthIs();i++)
{
t.GetNextItem(a);
cout<<"Item #"<<i<<": "<<a<<endl;
}
cout<<endl;
t.reverseDoublyLinkedList();
t.ResetList();
for(int i=0;i<t.LengthIs();i++)
{
t.GetNextItem(a);
cout<<"Item #"<<i<<": "<<a<<endl;
}
cout<<endl;
}
Unrelated but if anyone could tell me why XCode 6.1 wont let me debug on my new Macbook Pro that would be helpful too.
EDIT:
Output:
Length of s: 2
Length of t: 2
Item #0: -3
Item #1: 1
Item #2: 3
Item #3: 5
Item #4: 10
Item #5: 13
Item #0: 13
Item #1: 5
Item #2: 3
Item #3: 1
Program ended with exit code: 9
At the end it crashes on member function GetNextItem() on line item = currentPos->info;.
The issue has to do with your InsertItem. Right now, it is overly complicated.
You are attempting to insert an item in increasing order. So the easiest thing to do is take a pair of nodes, and see if the item goes in-between the pair. Here is an easier implementation:
template <class ItemType>
void DoublyLinkedList<ItemType>::InsertItem(ItemType item)
{
NodeType<ItemType>* node = new NodeType<ItemType>;
node->info = item;
if (!length)
{
listData = node;
node->next = NULL;
node->back = NULL;
length++;
return;
}
NodeType<ItemType>* temp = listData;
while (temp)
{
// get the next node
NodeType<ItemType>* nextNode = temp->next;
// make sure we have a pair of nodes
if (nextNode)
{
// test for inbetween
if (item >= temp->info && item <= nextNode->info)
{
// set the pointers and return
// make sure we set the node in-between the temp and nextNode
temp->next = node;
nextNode->back = node;
// now set node to point to temp (back), and nextNode (next)
// for the in-between to link correctly
node->next = nextNode;
node->back = temp;
// increase the length and get out
++length;
return;
}
}
else
{
// we're at the last node, so only place for this is at the back
// set the pointers and return
temp->next = node;
node->back = temp;
// last node, so make sure it points to NULL as next
node->next = NULL;
// increase length and get out
++length;
return;
}
// go to next node and get next pair
temp = nextNode;
}
}
Now, this works. Can it be better? Probably, but the point is that it is easy to understand what is going on.
If you drew on paper what is needed to be done, the above is probably closest to what you would draw on paper, i.e. get two nodes, see if the item goes in-between the two nodes, if not, get the next pair of nodes, etc...