I'm testing ADT linked list implementation. It's from my college text from a previous semester and one of my current assignments requires me to use it. and it is derived from a more general linked List Type class. I've been fighting this problem for hours, and cant figure out why it wont link.
this is main:
#include <iostream>
#include <cmath>
#include "unorderedlinkedlist.h"
using namespace std;
int main()
{
unorderedLinkedList<int> newList;
for (int i = 1; i<=10;i++)
newList.insertLast(pow(2,i));
newList.print();
return 0;
}
this is the header for the derived class:
#ifndef UNORDEREDLINKEDLIST_H
#define UNORDEREDLINKEDLIST_H
#include <iostream>
#include "linkedlisttype.h"
using namespace std;
template <class Type>
class unorderedLinkedList : public linkedListType<Type>
{
public:
/// Check to see if item already exists in the list
bool search(const Type& searchItem) const;
/// insert newItem at the beginning of the list
void insertFirst(const Type& newItem);
///function to insert newItem at the end of the list
void insertLast(const Type& newItem);
/// delese deleteItem from the list
void deleteNode(const Type& deleteItem);
protected:
private:
};
template <class Type>
bool unorderedLinkedList<Type>::search(const Type& searchItem) const
{
nodeType<Type> *current;
bool found = false;
current = linkedListType<Type>::first;
while (current != NULL && !found)
if (current->info == searchItem)
found = true;
else current = current->link;
return found;
}
template <class Type>
void unorderedLinkedList<Type>::insertFirst(const Type& newItem)
{
nodeType<Type> *newNode;
newNode = new nodeType<Type>;
newNode->info = newItem;
newNode->link = linkedListType<Type>::first;
linkedListType<Type>::first = newNode;
linkedListType<Type>::count++;
if (linkedListType<Type>::last == NULL)
linkedListType<Type>::last = newNode;
}
template <class Type>
void unorderedLinkedList<Type>::insertLast(const Type& newItem)
{
nodeType<Type> *newNode;
newNode = new nodeType<Type>;
newNode->info = newItem;
newNode->link = NULL;
if (linkedListType<Type>::first == NULL)
{
linkedListType<Type>::first = newNode;
linkedListType<Type>::last = newNode;
linkedListType<Type>::count++;
}
else
{
linkedListType<Type>::last->link = newNode;
linkedListType<Type>::last = newNode;
linkedListType<Type>::count++;
}
}
template <class Type>
void unorderedLinkedList<Type>::deleteNode(const Type& deleteItem)
{
nodeType<Type> *current;
nodeType<Type> *trailCurrent;
bool found;
if (linkedListType<Type>::first == NULL)
cout << "You cannot delete soemthing from an empty list." << endl;
else
{
if (linkedListType<Type>::first ->info == deleteItem)
{
current = linkedListType<Type>::first;
linkedListType<Type>::first = linkedListType<Type>::first->link;
linkedListType<Type>::count--;
if (linkedListType<Type>::first == NULL)
linkedListType<Type>::last = NULL;
delete current;
}
else
{
found = false;
trailCurrent = linkedListType<Type>::first;
current = linkedListType<Type>::first->link;
while (current != NULL && !found)
{
if(current->info != deleteItem)
{
trailCurrent = current;
current = current->link;
}
else
found = true;
}
if(found)
{
trailCurrent->link = current->link;
linkedListType<Type>::count--;
if (linkedListType<Type>::last == current)
linkedListType<Type>::last = trailCurrent;
delete current;
}
else
cout << "the item to be deleted is not in the list." << endl;
}
}
}
#endif // UNORDEREDLINKEDLIST_H
Linker errors:
/tmp/cc9ozgPv.o:
(.rodata._ZTV14linkedListTypeIiE[_ZTV14linkedListTypeIiE]+0x20): undefined reference to linkedListType<int>::search(int const&) const'
/tmp/cc9ozgPv.o:(.rodata._ZTV14linkedListTypeIiE[_ZTV14linkedListTypeIiE]+0x28): undefined reference tolinkedListType::insertFirst(int const&)'
/tmp/cc9ozgPv.o:(.rodata._ZTV14linkedListTypeIiE[_ZTV14linkedListTypeIiE]+0x30): undefined reference to linkedListType<int>::insertLast(int const&)'
/tmp/cc9ozgPv.o:(.rodata._ZTV14linkedListTypeIiE[_ZTV14linkedListTypeIiE]+0x38): undefined reference tolinkedListType::deleteNode(int const&)'
collect2: error: ld returned 1 exit status
Related
I am trying to implement the peek() function of a Stack class and have this issue where I cannot return the top object of the stack, but instead get an error. I have tried removing the & to the peek function and tried to set it to a const, but I still get errors. Would the issue be outside of this function? as I am not sure what else I can try to solve this problem.
Error:
LStack.h:55:28: error: cannot bind non-const lvalue reference of type ‘int&’
to
an rvalue of type ‘int’
return data.get_current();
LStack.h
#include "LinkedList.h"
#include <cstdlib>
#include <iostream>
template <typename T>
class LStack
{
public:
//mutator member functions
LStack(){}
~LStack(){}
void push(const T& obj) //insert obj at the top of the stack
{
data.add_to_head(obj);
numofstacks++;
}
T pop() //remove and return the top object from the stack, error if stack is empty
{
if (is_empty()){
std::cout << "Stack is empty";
}
else{
data.remove_from_head();
numofstacks--;
return data.get_current();
}
}
bool is_empty() const //return a boolean indicating whether the stack is empty
{
return (size() == 0);
}
//query member functions
int size() const //return the number of objects in the stack
{
return numofstacks;
}
//return a reference to the object at the top of the stack, NULL if the stack is empty, (also refered to as top())
T& peek()
{
if (is_empty()){
std::cout << "Stack is empty";
}
else{
//return top of the stack object
return data.get_current();
}
}
private:
LinkedList<T> data;
int used;
int numofstacks;
};
LinkedList.h
#include "Node.h"
#include <cstdlib>
#include <iostream>
template <typename T>
class LinkedList
{
public:
LinkedList() //constructor
{
head = NULL;
tail = NULL;
list_length=0;
}
~LinkedList()//destructor since we're creating the linked list on the heap
{
while (head != NULL)
{
remove_from_head();
}
tail = NULL;//not sure if in or out of while loop
}
LinkedList(T& item)
{
head = new Node<T>();
head->set_data(item);
tail = head;
list_length = 1;
}
void add_to_head(T item)
{
if (list_length == 0){ //if list is empty
head = new Node<T>();
head->set_data(item);
tail = head;
list_length = 1;
}
else //Else if list is not empty.. Insert node at the head
{
Node<T>* head_insert = new Node<T>();
head_insert->set_data(item);
head->set_prev(head_insert);
head_insert->set_next(head);
head = head_insert;
list_length++;
head_insert = NULL;
}
}
void add_to_tail(T item)
{
if (list_length == 0){
head = new Node<T>();
head->set_data(item);
tail = head;
list_length = 1;
}
else //insert node at tail
{
Node<T>* tail_insert = new Node<T>();
tail_insert->set_data(item);
tail->set_next(tail_insert);
tail_insert->set_prev(tail);
tail = tail_insert;
list_length++;
tail_insert = NULL;
}
}
void remove_from_head()
{
if (list_length == 0){
return;
}
else if (list_length == 1){
delete head;
head = NULL;
tail = NULL;
list_length--;
return;
}
else
{
Node<T>* temp_head = head;
head = temp_head->get_next();
delete temp_head;
list_length--;
temp_head = NULL;
}
}
void remove_from_tail()
{
if (list_length == 0){
return;
}
else if (list_length == 1)
{
delete head;
head = NULL;
tail = NULL;
list_length--;
return;
}
else
{
Node<T>* temp_tail = tail;
tail = temp_tail->get_prev();
delete temp_tail;
list_length--;
temp_tail = NULL;
}
}
std::size_t size()
{
return list_length;
}
T get_current() // RESULTS IN SEG ERROR
{
return current->get_data();
}
void forward()
{
current = current->get_next();
}
void back()
{
current = current->get_prev();
}
void move_to_head()
{
current = head;
}
void move_to_tail()
{
current = tail;
}
private: //private members
Node<T>* head; //point to start of list
Node<T>* tail; //point to end of list
Node<T>* current; //optional - used to refer to a node in our list
std::size_t list_length;
};
Would the issue be outside of this function? as I am not sure what else I can try to solve this problem.
I am having an issue with a homework assignment and for the life of me I cannot figure out where I am making the mistake. We are tasked with writing a function that inserts the nodes of binary tree into an ordered linked list. Below are the header files and the main method. Literally any help at this point would greatly appreciated as I am just spinning in circles now.
Error Message: no suitable conversion function from "orderedLinkedList" to "const int" exists
Project: Ch19_Ex9 File: Ch19_Ex9.cpp Line: 33:
Ch19_Ex9.cpp:
//Data
//68 43 10 56 77 82 61 82 33 56 72 66 99 88 12 6 7 21 -999
#include "binarySearchTree.h"
#include "orderedLinkedList.h"
#include "pch.h"
#include <iostream>
using namespace std;
int main()
{
binarySearchTree<int> treeRoot;
orderedLinkedList<int> newList;
int num;
cout << "Enter numbers ending with -999" << endl;
cin >> num;
while (num != -999)
{
treeRoot.insert(num);
cin >> num;
}
cout << endl << "Tree nodes in inorder: ";
treeRoot.inorderTraversal();
cout << endl;
cout << "Tree Height: " << treeRoot.treeHeight()
<< endl;
treeRoot.createList(newList); //HERE IS THE LINE WITH ISSUE
cout << "newList: ";
newList.print();
cout << endl;
system("pause");
return 0;
}
binarySearchTree.h:
//Header File Binary Search Tree
#include <iostream>
#include "binaryTree.h"
using namespace std;
template <class Type>
class binarySearchTree : public binaryTreeType<Type>
{
public:
bool search(const Type& searchItem) const;
//Function to determine if searchItem is in the binary
//search tree.
//Postcondition: Returns true if searchItem is found in
// the binary search tree; otherwise,
// returns false.
void insert(const Type& insertItem);
//Function to insert insertItem in the binary search tree.
//Postcondition: If there is no node in the binary search
// tree that has the same info as
// insertItem, a node with the info
// insertItem is created and inserted in the
// binary search tree.
void deleteNode(const Type& deleteItem);
//Function to delete deleteItem from the binary search tree
//Postcondition: If a node with the same info as deleteItem
// is found, it is deleted from the binary
// search tree.
// If the binary tree is empty or deleteItem
// is not in the binary tree, an appropriate
// message is printed.
void createList(const Type& addItem);
private:
void deleteFromTree(nodeType<Type>* &p);
//Function to delete the node to which p points is
//deleted from the binary search tree.
//Postcondition: The node to which p points is deleted
// from the binary search tree.
};
template <class Type>
bool binarySearchTree<Type>::search
(const Type& searchItem) const
{
nodeType<Type> *current;
bool found = false;
if (root == nullptrptr)
cout << "Cannot search an empty tree." << endl;
else
{
current = root;
while (current != nullptrptr && !found)
{
if (current->info == searchItem)
found = true;
else if (current->info > searchItem)
current = current->lLink;
else
current = current->rLink;
}//end while
}//end else
return found;
}//end search
template <class Type>
void binarySearchTree<Type>::insert
(const Type& insertItem)
{
nodeType<Type> *current; //pointer to traverse the tree
nodeType<Type> *trailCurrent; //pointer behind current
nodeType<Type> *newNode; //pointer to create the node
newNode = new nodeType<Type>;
newNode->info = insertItem;
newNode->lLink = nullptrptr;
newNode->rLink = nullptrptr;
if (root == nullptrptr)
root = newNode;
else
{
current = root;
while (current != nullptrptr)
{
trailCurrent = current;
if (current->info == insertItem)
{
cout << "The item to be inserted is already ";
cout << "in the tree -- duplicates are not "
<< "allowed." << endl;
return;
}
else if (current->info > insertItem)
current = current->lLink;
else
current = current->rLink;
}//end while
if (trailCurrent->info > insertItem)
trailCurrent->lLink = newNode;
else
trailCurrent->rLink = newNode;
}
}//end insert
template <class Type>
void binarySearchTree<Type>::deleteNode
(const Type& deleteItem)
{
nodeType<Type> *current; //pointer to traverse the tree
nodeType<Type> *trailCurrent; //pointer behind current
bool found = false;
if (root == nullptr)
cout << "Cannot delete from an empty tree."
<< endl;
else
{
current = root;
trailCurrent = root;
while (current != nullptr && !found)
{
if (current->info == deleteItem)
found = true;
else
{
trailCurrent = current;
if (current->info > deleteItem)
current = current->lLink;
else
current = current->rLink;
}
}//end while
if (current == nullptr)
cout << "The item to be deleted is not in the tree."
<< endl;
else if (found)
{
if (current == root)
deleteFromTree(root);
else if (trailCurrent->info > deleteItem)
deleteFromTree(trailCurrent->lLink);
else
deleteFromTree(trailCurrent->rLink);
}
else
cout << "The item to be deleted is not in the tree."
<< endl;
}
} //end deleteNode
template <class Type>
void binarySearchTree<Type>::deleteFromTree
(nodeType<Type>* &p)
{
nodeType<Type> *current; //pointer to traverse the tree
nodeType<Type> *trailCurrent; //pointer behind current
nodeType<Type> *temp; //pointer to delete the node
if (p == nullptr)
cout << "Error: The node to be deleted does not exist."
<< endl;
else if (p->lLink == nullptr && p->rLink == nullptr)
{
temp = p;
p = nullptr;
delete temp;
}
else if (p->lLink == nullptr)
{
temp = p;
p = temp->rLink;
delete temp;
}
else if (p->rLink == nullptr)
{
temp = p;
p = temp->lLink;
delete temp;
}
else
{
current = p->lLink;
trailCurrent = nullptr;
while (current->rLink != nullptr)
{
trailCurrent = current;
current = current->rLink;
}//end while
p->info = current->info;
if (trailCurrent == nullptr) //current did not move;
//current == p->lLink; adjust p
p->lLink = current->lLink;
else
trailCurrent->rLink = current->lLink;
delete current;
}//end else
} //end deleteFromTree
template <class Type>
void binarySearchTree<Type>::createList(const Type& addItem)
{
nodeType<Type> *current;
nodeType<Type> *trailCurrent;
nodeType<Type> *newNode;
newNode = new nodeType <Type>;
newNode->info = createItem;
newNode->lLink = nullptr;
newNode->rLink = nullptr;
if (root == nullptr)
{
root = newNode;
}
}
EDIT: adding orderedLinkedList.h:
#include "linkedList.h"
using namespace std;
template <class Type>
class orderedLinkedList : public linkedListType<Type>
{
public:
bool search(const Type& searchItem) const;
void insert(const Type& newItem);
void insertFirst(const Type& newItem);
void insertLast(const Type& deleteItem);
void deleteNode(const Type& deleteItem);
};
template <class Type>
bool orderedLinkedList<Type>::search(const Type& searchItem) const
{
nodeType<Type> *current; //pointer to traverse the list
bool found = false;
current = first; //set current to point to the first
//node in the list
while (current != nullptr && !found) //search the list
if (current->info == searchItem) //searchItem is found
found = true;
else
current = current->link; //make current point to
//the next node
return found;
};
template <class Type>
void orderedLinkedList<Type>::insert(const Type& newItem)
{
};
template <class Type>
void orderedLinkedList<Type>::insertFirst(const Type& newItem)
{
nodeType<Type> *newNode; //pointer to create the new node
newNode = new nodeType<Type>; //create the new node
newNode->info = newItem; //store the new item in the node
newNode->link = first; //insert newNode before first
first = newNode; //make first point to the
//actual first node
count++; //increment count
if (last == nullptr) //if the list was empty, newNode is also
//the last node in the list
last = newNode;
};
template <class Type>
void orderedLinkedList<Type>::insertLast(const Type& deleteItem)
{
nodeType<Type> *newNode; //pointer to create the new node
newNode = new nodeType<Type>; //create the new node
newNode->info = newItem; //store the new item in the node
newNode->link = nullptr; //set the link field of newNode
//to nullptr
if (first == nullptr) //if the list is empty, newNode is
//both the first and last node
{
first = newNode;
last = newNode;
count++; //increment count
}
else //the list is not empty, insert newNode after last
{
last->link = newNode; //insert newNode after last
last = newNode; //make last point to the actual
//last node in the list
count++; //increment count
}
};
template <class Type>
void orderedLinkedList<Type>::deleteNode(const Type& deleteItem)
{
nodeType<Type> *current;
nodeType<Type> *trailCurrent;
bool found;
if (first == nullptr)
{
cout << "Cannot delete from an empty list."
<< endl;
}
else
{
if (first->info == deleteItem)
{
current = first;
first = first->link;
count--;
if (first == nullptr)
{
last = nullptr;
delete current;
}
else
{
found = false;
trailCurrent = first;
current = first->link;
while (current != nullptr && !found)
{
if (current->info != deleteItem)
{
trailCurrent = current;
current = current->link;
}
else
{
found = true;
}
}
if (found)
{
trailCurrent->link = current->link;
count--;
if (last == current)
{
last = trailCurrent;
}
delete current;
}
else
cout << "The item to be deleted is not in "
<< "the list." << endl;
}
}
}
}
My problem is trying to get functions treeLeavesCount() and treeNodeCount() to return a value of leaves and nodes in the tree but, my issue is after providing values through a while loop using an insert() function, the tree seems to stay empty and I know this by using an isEmpty() function before and after inserting values into the tree.
main.cpp
#include <iostream>
#include "binaryTreeType.h"
#include "bSearchTreeType.h"
using namespace std;
int main()
{
int num;
bSearchTreeType<int> *myTree= new bSearchTreeType<int>();
//test if tree is empty
if(myTree->isEmpty())
cout << "yes" << endl;
else
cout << "no" << endl;
cout << "Line 10: Enter numbers ending with -999"<< endl;
cin >> num;
while (num != -999)
{
myTree->insert(num);
cin >> num;
}
myTree->inorderTraversal();
int p;
p=myTree->treeNodeCount();
cout << p << endl;
p=myTree->treeLeavesCount();
cout << p << endl;
//test if tree is empty after data is inserted
if(myTree->isEmpty())
cout << "yes" << endl;
else
cout << "no" << endl;
delete myTree;
return 0;
}
binaryTreeType.h
#ifndef BINARYTREETYPE_H
#define BINARYTREETYPE_H
#include <queue>
template <class elemType>
struct binaryTreeNode
{
elemType info;
binaryTreeNode<elemType> *llink;
binaryTreeNode<elemType> *rlink;
};
template <class elemType>
class binaryTreeType
{
public:
const binaryTreeType<elemType>& operator=(const binaryTreeType<elemType>&);
//Overload the assignment operator.
bool isEmpty() const;
//Returns true if the binary tree is empty;
//otherwise, returns false.
void inorderTraversal() const;
//Function to do an inorder traversal of the binary tree.
void preorderTraversal() const;
//Function to do a preorder traversal of the binary tree.
void postorderTraversal() const;
//Function to do a postorder traversal of the binary tree.
int treeHeight() const;
//Returns the height of the binary tree.
int treeNodeCount() const;
//Returns the number of nodes in the binary tree.
int treeLeavesCount() const;
//Returns the number of leaves in the binary tree.
void destroyTree();
//Deallocates the memory space occupied by the binary tree.
//Postcondition: root = NULL;
binaryTreeType(const binaryTreeType<elemType>& otherTree);
//copy constructor
binaryTreeType();
//default constructor
~binaryTreeType();
//destructor
protected:
binaryTreeNode<elemType> *root;
private:
void copyTree(binaryTreeNode<elemType>* &copiedTreeRoot,binaryTreeNode<elemType>* otherTreeRoot);
//Makes a copy of the binary tree to which
//otherTreeRoot points. The pointer copiedTreeRoot
//points to the root of the copied binary tree.
void destroy(binaryTreeNode<elemType>* &p);
//Function to destroy the binary tree to which p points.
//Postcondition: p = NULL
void inorder(binaryTreeNode<elemType> *p) const;
//Function to do an inorder traversal of the binary
//tree to which p points.
void preorder(binaryTreeNode<elemType> *p) const;
//Function to do a preorder traversal of the binary
//tree to which p points.
void postorder(binaryTreeNode<elemType> *p) const;
//Function to do a postorder traversal of the binary
//tree to which p points.
int height(binaryTreeNode<elemType> *p) const;
//Function to return the height of the binary tree
//to which p points.
int max(int x, int y) const;
//Returns the larger of x and y.
int nodeCount(binaryTreeNode<elemType> *p) const;
//Function to return the number of nodes in the binary
//tree to which p points
int leavesCount(binaryTreeNode<elemType> *p) const;
//Function to return the number of leaves in the binary
//tree to which p points
};
template <class elemType>
bool binaryTreeType<elemType>::isEmpty() const
{
return (root == NULL);
};
template <class elemType>
binaryTreeType<elemType>::binaryTreeType()
{
root = NULL;
}
template <class elemType>
void binaryTreeType<elemType>::inorderTraversal() const
{
inorder(root);
}
template <class elemType>
void binaryTreeType<elemType>::preorderTraversal() const
{
preorder(root);
}
template <class elemType>
void binaryTreeType<elemType>::postorderTraversal() const
{
postorder(root);
}
template <class elemType>
int binaryTreeType<elemType>::treeHeight() const
{
return height(root);
}
template <class elemType>
int binaryTreeType<elemType>::treeNodeCount() const
{
return nodeCount(root);
}
template <class elemType>
int binaryTreeType<elemType>::treeLeavesCount() const
{
return leavesCount(root);
}
template <class elemType>
void binaryTreeType<elemType>::inorder(binaryTreeNode<elemType> *p) const
{
if (p != NULL)
{
inorder(p->llink);
std::cout << p->info << " ";
inorder(p->rlink);
}
}
template <class elemType>
void binaryTreeType<elemType>::preorder(binaryTreeNode<elemType> *p) const
{
if (p != NULL)
{
std::cout << p->info << " ";
preorder(p->llink);
preorder(p->rlink);
}
}
template <class elemType>
void binaryTreeType<elemType>::postorder(binaryTreeNode<elemType> *p) const
{
if (p != NULL)
{
postorder(p->llink);
postorder(p->rlink);
std::cout << p->info << " ";
}
}
template <class elemType>
int binaryTreeType<elemType>::height(binaryTreeNode<elemType> *p) const
{
if (p == NULL)
return 0;
else
return 1 + max(height(p->llink), height(p->rlink));
}
template <class elemType>
int binaryTreeType<elemType>::max(int x, int y) const
{
if (x >= y)
return x;
else
return y;
}
template <class elemType>
void binaryTreeType<elemType>::copyTree(binaryTreeNode<elemType>* &copiedTreeRoot,binaryTreeNode<elemType>* otherTreeRoot)
{
if (otherTreeRoot == NULL)
copiedTreeRoot = NULL;
else
{
copiedTreeRoot = new binaryTreeNode<elemType>;
copiedTreeRoot->info = otherTreeRoot->info;
copyTree(copiedTreeRoot->llink, otherTreeRoot->llink);
copyTree(copiedTreeRoot->rlink, otherTreeRoot->rlink);
}
} //end copyTree
template <class elemType>
void binaryTreeType<elemType>::destroy(binaryTreeNode<elemType>* &p)
{
if (p != NULL)
{
destroy(p->llink);
destroy(p->rlink);
delete p;
p = NULL;
}
}
template <class elemType>
void binaryTreeType<elemType>::destroyTree()
{
destroy(root);
}
template <class elemType>
binaryTreeType<elemType>::binaryTreeType(const binaryTreeType<elemType>& otherTree)
{
if (otherTree.root == NULL) //otherTree is empty
root = NULL;
else
copyTree(root, otherTree.root);
}
template <class elemType>
binaryTreeType<elemType>::~binaryTreeType()
{
destroy(root);
}
template <class elemType>
const binaryTreeType<elemType>& binaryTreeType<elemType>::operator=(const binaryTreeType<elemType>& otherTree)
{
if (this != &otherTree) //avoid self-copy
{
if (root != NULL) //if the binary tree is not empty,
//destroy the binary tree
destroy(root);
if (otherTree.root == NULL) //otherTree is empty
root = NULL;
else
copyTree(root, otherTree.root);
}//end else
return *this;
}
template <class elemType>
int binaryTreeType<elemType>::leavesCount(binaryTreeNode<elemType> *p) const
{
if(p == NULL)
return 0;
if(p->llink == NULL && p->rlink==NULL)
return 1;
else
return leavesCount(p->llink) + leavesCount(p->rlink);
}
template <class elemType>
int binaryTreeType<elemType> ::nodeCount(binaryTreeNode<elemType> *p) const
{
int count = 1;
if ( p == NULL ){
return 0;
}else{
count += nodeCount(p->llink);
count += nodeCount(p->rlink);
}
return count;
}
#endif // BINARYTREETYPE_H
bSearchTreeType.h
#ifndef BSEARCHTREETYPE_H
#define BSEARCHTREETYPE_H
#include "binaryTreeType.h"
#include <iostream>
#include <cassert>
template <class elemType>
class bSearchTreeType : public binaryTreeType<elemType>
{
public:
bool search(const elemType& searchItem) const;
//Function to determine if searchItem is in the binary
//search tree.
//Postcondition: Returns true if searchItem is found in the
// binary search tree; otherwise, returns false.
void insert(const elemType& insertItem);
//Function to insert insertItem in the binary search tree.
//Postcondition: If no node in the binary search tree has the
// same info as insertItem, a node with the info insertItem
// is created and inserted in the binary search tree.
void deleteNode(const elemType& deleteItem);
//Function to delete deleteItem from the binary search tree.
//Postcondition: If a node with the same info as deleteItem
// is found, it is deleted from the binary search tree.
protected:
binaryTreeNode<elemType> *root;
private:
void deleteFromTree(binaryTreeNode<elemType>* &p);
//Function to delete the node to which p points is deleted
//from the binary search tree.
//Postcondition: The node to which p points is deleted from
// the binary search tree.
};
using namespace std;
template <class elemType>
bool bSearchTreeType<elemType>::search(const elemType& searchItem) const
{
binaryTreeNode<elemType> *current;
bool found = false;
if (root == NULL)
cerr << "Cannot search the empty tree." << endl;
else
{
current = root;
while (current != NULL && !found)
{
if (current->info == searchItem)
found = true;
else if (current->info > searchItem)
current = current->llink;
else
current = current->rlink;
}//end while
}//end else
return found;
}//end search
template <class elemType>
void bSearchTreeType<elemType>::insert(const elemType& insertItem)
{
binaryTreeNode<elemType> *current; //pointer to traverse the tree
binaryTreeNode<elemType> *trailCurrent; //pointer behind current
binaryTreeNode<elemType> *newNode; //pointer to create the node
newNode = new binaryTreeNode<elemType>;
assert(newNode != NULL);
newNode->info = insertItem;
newNode->llink = NULL;
newNode->rlink = NULL;
if (root == NULL)
root = newNode;
else
{
current = root;
while (current != NULL)
{
trailCurrent = current;
if (current->info == insertItem)
{
std::cerr << "The insert item is already in the list-";
std::cerr << "duplicates are not allowed." << insertItem << std::endl;
return;
}
else if (current->info > insertItem)
current = current->llink;
else
current = current->rlink;
}//end while
if (trailCurrent->info > insertItem)
trailCurrent->llink = newNode;
else
trailCurrent->rlink = newNode;
}
}//end insert
template <class elemType>
void bSearchTreeType<elemType>::deleteFromTree(binaryTreeNode<elemType>* &p)
{
binaryTreeNode<elemType> *current;//pointer to traverse the tree
binaryTreeNode<elemType> *trailCurrent; //pointer behind current
binaryTreeNode<elemType> *temp; //pointer to delete the node
if (p == NULL)
cerr << "Error: The node to be deleted is NULL." << endl;
else if(p->llink == NULL && p->rlink == NULL)
{
temp = p;
p = NULL;
delete temp;
}
else if(p->llink == NULL)
{
temp = p;
p = temp->rlink;
delete temp;
}
else if(p->rlink == NULL)
{
temp = p;
p = temp->llink;
delete temp;
}
else
{
current = p->llink;
trailCurrent = NULL;
while (current->rlink != NULL)
{
trailCurrent = current;
current = current->rlink;
}//end while
p->info = current->info;
if (trailCurrent == NULL) //current did not move;
//current == p->llink; adjust p
p->llink = current->llink;
else
trailCurrent->rlink = current->llink;
delete current;
}//end else
}//end deleteFromTree
template <class elemType>
void bSearchTreeType<elemType>::deleteNode(const elemType& deleteItem)
{
binaryTreeNode<elemType> *current; //pointer to traverse the tree
binaryTreeNode<elemType> *trailCurrent; //pointer behind current
bool found = false;
if (root == NULL)
std::cout << "Cannot delete from the empty tree." << endl;
else
{
current = root;
trailCurrent = root;
while (current != NULL && !found)
{
if (current->info == deleteItem)
found = true;
else
{
trailCurrent = current;
if (current->info > deleteItem)
current = current->llink;
else
current = current->rlink;
}
}//end while
if (current == NULL)
std::cout << "The delete item is not in the tree." << endl;
else if (found)
{
if (current == root)
deleteFromTree(root);
else if (trailCurrent->info > deleteItem)
deleteFromTree(trailCurrent->llink);
else
deleteFromTree(trailCurrent->rlink);
}//end if
}
}//end deleteNode
#endif // BSEARCHTREETYPE_H
(That's a humongous amount of code. Please remove everything your test case doesn't need next time.)
Cutting your code down to the bare essentials, we get
template <class elemType>
class binaryTreeType
{
public:
bool isEmpty() const;
protected:
binaryTreeNode<elemType> *root;
};
template <class elemType>
bool binaryTreeType<elemType>::isEmpty() const
{
return (root == NULL);
};
template <class elemType>
class bSearchTreeType : public binaryTreeType<elemType>
{
void insert(const elemType& insertItem);
protected:
binaryTreeNode<elemType> *root;
};
template <class elemType>
void bSearchTreeType<elemType>::insert(const elemType& insertItem)
{
// ...
if (root == NULL)
root = newNode;
else
{
current = root;
//...
}
}//end insert
And now we can see that you declare two member variables called "root".
The one in bSearchTreeType hides the one in binaryTreeType - it's not a redeclaration or "override" of the same variable.
This means that your binaryTreeType member functions (such as isEmpty) use the root in binaryTreeType, while the member functions of bSearchTreeType (such as insert) use the root in bSearchTreeType, so after insert has updated one of the roots the other one is still null.
Incidentally, this issue is also difficult to discover with a debugger, where you'll just be staring at a variable whose value changes as if by magic.
You need to do two things:
Remove the root member from bSearchTreeType
Because these are templates, you also need to change root to this->root in the bSearchTreeType member functions. (Finding out why left as an exercise - it's an essay of its own.)
(It seems to work with just these changes, by the way. Well done.)
When I try to compile my code for main, my compiler keeps saying that mergeLists() is undefined. However, I expectedly defined it earlier (in the orderLinkedList class. In addition, I know I defined it as a member and I didn't put a calling object, but when I redefine it as a non-member it throws
/--------------------------------------------
In file included from main.cpp:4:0:
orderedLinkedList.h:204:6: note: candidate: template void mergeLists(orderedLinkedList&, orderedLinkedList&)
void mergeLists(orderedLinkedList & list1, orderedLinkedList & list2) {
^
orderedLinkedList.h:204:6: note: template argument deduction/substitution failed:
main.cpp:43:31: note: 'unorderedLinkedList' is not derived from 'orderedLinkedList'
mergeLists(list, otherList);
/------------------------------------------------
In addition to the other errors. What am I missing?
template <class Type>
void orderedLinkedList<Type>::mergeLists(orderedLinkedList<Type> & list1, orderedLinkedList<Type> & list2) {
if(list2.first != NULL) {
nodeType <Type> * current = list2.first;
nodeType <Type> * trail = NULL;
for(int cntr = 0; cntr <= list2.count; cntr++) {
list1.insert(current->info);
trail = current;
current = current->link;
delete trail;
}
list2.count = 0;
list2.first = list2.last = NULL;
}
}
#ifndef H_orderedListType
#define H_orderedListType
#include "linkedList.h"
using namespace std;
template <class Type>
class orderedLinkedList: public linkedListType<Type>
{
typedef linkedListType<Type> super;
using super::first;
using super::count;
using super::last;
public:
bool search(const Type& searchItem) const;
//Function to determine whether searchItem is in the list.
//Postcondition: Returns true if searchItem is in the list,
// otherwise the value false is returned.
void insert(const Type& newItem);
//Function to insert newItem in the list.
//Postcondition: first points to the new list, newItem
// is inserted at the proper place in the
// list, and count is incremented by 1.
void insertFirst(const Type& newItem);
//Function to insert newItem in the list.
//Because the resulting list must be sorted, newItem is
//inserted at the proper in the list.
//This function uses the function insert to insert newItem.
//Postcondition: first points to the new list, newItem is
// inserted at the proper in the list,
// and count is incremented by 1.
void insertLast(const Type& newItem);
//Function to insert newItem in the list.
//Because the resulting list must be sorted, newItem is
//inserted at the proper in the list.
//This function uses the function insert to insert newItem.
//Postcondition: first points to the new list, newItem is
// inserted at the proper in the list,
// and count is incremented by 1.
void deleteNode(const Type& deleteItem);
//Function to delete deleteItem from the list.
//Postcondition: If found, the node containing
// deleteItem is deleted from the list;
// first points to the first node of the
// new list, and count is decremented by 1.
// If deleteItem is not in the list, an
// appropriate message is printed.
//void mergeLists(orderedLinkedList<Type> & list1, orderedLinkedList<Type> & list2);
};
/*******************************************************************************
********************************************************************************
*******************************************************************************/
template <class Type>
bool orderedLinkedList<Type>::search(const Type& searchItem) const
{
bool found = false;
nodeType<Type> *current; //pointer to traverse the list
current = first; //start the search at the first node
while (current != NULL && !found)
if (current->info >= searchItem)
found = true;
else
current = current->link;
if (found)
found = (current->info == searchItem); //test for equality
return found;
}//end search
template <class Type>
void orderedLinkedList<Type>::insert(const Type& newItem)
{
nodeType<Type> *current; //pointer to traverse the list
nodeType<Type> *trailCurrent; //pointer just before current
nodeType<Type> *newNode; //pointer to create a node
bool found;
newNode = new nodeType<Type>; //create the node
newNode->info = newItem; //store newItem in the node
newNode->link = NULL; //set the link field of the node
//to nullptr
if (first == NULL) //Case 1
{
first = newNode;
last = newNode;
count++;
}
else
{
current = first;
found = false;
while (current != NULL && !found) //search the list
if (current->info >= newItem)
found = true;
else
{
trailCurrent = current;
current = current->link;
}
if (current == first) //Case 2
{
newNode->link = first;
first = newNode;
count++;
}
else //Case 3
{
trailCurrent->link = newNode;
newNode->link = current;
if (current == NULL)
last = newNode;
count++;
}
}//end else
}//end insert
template<class Type>
void orderedLinkedList<Type>::insertFirst(const Type& newItem)
{
insert(newItem);
}//end insertFirst
template<class Type>
void orderedLinkedList<Type>::insertLast(const Type& newItem)
{
insert(newItem);
}//end insertLast
template<class Type>
void orderedLinkedList<Type>::deleteNode(const Type& deleteItem)
{
nodeType<Type> *current; //pointer to traverse the list
nodeType<Type> *trailCurrent; //pointer just before current
bool found;
if (first == NULL) //Case 1
cout << "Cannot delete from an empty list." << endl;
else
{
current = first;
found = false;
while (current != NULL && !found) //search the list
if (current->info >= deleteItem)
found = true;
else
{
trailCurrent = current;
current = current->link;
}
if (current == NULL) //Case 4
cout << "The item to be deleted is not in the "
<< "list." << endl;
else
if (current->info == deleteItem) //the item to be
//deleted is in the list
{
if (first == current) //Case 2
{
first = first->link;
if (first == NULL)
last = NULL;
delete current;
}
else //Case 3
{
trailCurrent->link = current->link;
if (current == last)
last = trailCurrent;
delete current;
}
count--;
}
else //Case 4
cout << "The item to be deleted is not in the "
<< "list." << endl;
}
}//end deleteNode
template <class Type>
void mergeLists(orderedLinkedList<Type> & list1, orderedLinkedList<Type> & list2) {
if(list2.first != NULL) {
nodeType <Type> * current = list2.first;
nodeType <Type> * trail = NULL;
for(int cntr = 0; cntr <= list2.count; cntr++) {
list1.insert(current->info);
trail = current;
current = current->link;
delete trail;
}
list2.count = 0;
list2.first = list2.last = NULL;
}
}
#endif
My calling is such that mergeLists(list,otherlist); where list and other list are lists of type int
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...