Our teacher provided us with the AVL_Tree.h and AVL_Node.h
I am trying to declare a new AVL_Tree of Folder (class that I created). However I keep getting the same error
error C2784: 'bool std::operator <(const std::vector<_Ty,_Ax> &,const
std::vector<_Ty,_Ax> &)' : could not deduce template argument for 'const
std::vector<_Ty,_Ax> &' from 'const AVLNode<Item_Type>'
Here is the AVL_Tree class
#ifndef AVL_TREE_H
#define AVL_TREE_H
#include "AVL_Node.h"
template<typename Item_Type>
class AVL_Tree{
public:
AVL_Tree() : root(NULL){
}
AVL_Tree(const Item_Type& the_data, const AVL_Tree<Item_Type>& left_child = AVL_Tree(),
const AVL_Tree<Item_Type>& right_child = AVL_Tree()) :
root(new AVLNode<Item_Type>(the_data, left_child.root,
right_child.root)) {}
/** Return the left-subtree */
AVL_Tree<Item_Type> get_left_subtree() const {
if (root == NULL) {
throw std::invalid_argument("get_left_subtree on empty tree");
}
return AVL_Tree<Item_Type>(root->left);
}
/** Return the right-subtree */
AVL_Tree<Item_Type> get_right_subtree() const {
if (root == NULL) {
throw std::invalid_argument("get_right_subtree on null tree");
}
return AVL_Tree<Item_Type>(root->right);
}
/** Return the data field of the root
#throws std::invalid_argument if null tree
*/
const Item_Type& AVL_Tree<Item_Type>::get_data() const {
if (root == NULL) {
throw std::invalid_argument("get_data on null tree");
}
return root->data;
}
bool is_null() const {
return root == NULL;
}
/** Indicate that this tree is a leaf. */
bool is_leaf() const {
if (root != NULL) {
return root->left == NULL && root->right == NULL;
}
else
return true;
}
virtual bool insert(const Item_Type& item) {
return insert(this->root, item);
}
bool erase(const Item_Type& item) {
return erase(this->root, item);
}
const Item_Type* find(const Item_Type& item) const {
return find(this->root, item);
}
protected:
AVLNode<Item_Type>* root;
AVL_Tree(AVLNode<Item_Type>* new_root) : root(new_root) {}
const Item_Type* find(AVLNode<Item_Type>* local_root, const Item_Type& target) const {
if (local_root == NULL)
return NULL;
if (target < local_root->data)
return find(local_root->left, target);
else if (local_root->data < target)
return find(local_root->right, target);
else
return &(local_root->data);
}
bool erase(AVLNode<Item_Type>*& local_root, const Item_Type& item) {
if (local_root == NULL) {
return false;
}
else {
if (item < local_root->data){
bool return_value = erase(local_root->left, item);
if (return_value){
adjust_balance(local_root);
rebalance(local_root);
}
return return_value;
}
else if (local_root->data < item){
bool return_value = erase(local_root->right, item);
if (return_value){
adjust_balance(local_root);
rebalance(local_root);
}
return return_value;
}
else {
AVLNode<Item_Type>* old_root = local_root;
if (local_root->left == NULL)
local_root = local_root->right;
else if (local_root->right == NULL)
local_root = local_root->left;
else
replace_parent(old_root, old_root->left);
if (local_root != NULL){
adjust_balance(local_root);
rebalance(local_root);
}
delete old_root;
return true;
}
}
}
void rebalance(AVLNode<Item_Type>*& local_root){
if (local_root->balance() <= -2)
rebalance_left(local_root);
else if (local_root->balance() >= 2)
rebalance_right(local_root);
}
void adjust_balance(AVLNode<Item_Type>*& node){
node->update_left_height();
node->update_right_height();
}
void replace_parent(AVLNode<Item_Type>*& old_root, AVLNode<Item_Type>*& local_root) {
if (local_root->right != NULL) {
replace_parent(old_root, local_root->right);
adjust_balance(local_root);
rebalance(local_root);
}
else {
old_root->data = local_root->data;
old_root = local_root;
if (local_root->left != NULL){
local_root = local_root->left;
adjust_balance(local_root);
}
else
local_root = NULL;
}
}
bool insert(AVLNode<Item_Type>*& local_root, const Item_Type& item) {
if (local_root == NULL) {
local_root = new AVLNode<Item_Type>(item);
return true;
}
else {
if (item < local_root->data) {
bool return_value = insert(local_root->left, item);
if (return_value){ //we have inserted the item
local_root->update_left_height(); //left height might increase by 1
if (local_root->balance() <= -2) // local root is now critically unbalanced
rebalance_left(local_root);
}
return return_value;
}
else if (local_root->data < item) {
bool return_value = insert(local_root->right, item);
if (return_value){
local_root->update_right_height(); //right height might increase by 1
if (local_root->balance() >= 2) // local root is now critically unbalanced
rebalance_right(local_root);
}
return return_value;
}
else
return false; //item already exists
}
}
void rebalance_left(AVLNode<Item_Type>*& local_root) {
if (local_root->left->balance() > 0) // See whether left-right-heavy
rotate_left(local_root->left); // Perform left rotation
// Finally rotate right
rotate_right(local_root);
}
void rebalance_right(AVLNode<Item_Type>*& local_root) {
if (local_root->right->balance() < 0) // See whether right-left-heavy
rotate_right(local_root->right); // Perform left rotation
// Finally rotate right
rotate_left(local_root);
}
void rotate_right(AVLNode<Item_Type>*& local_root) {
AVLNode<Item_Type>* temp = local_root->left;
local_root->left = temp->right;
//adjust the balances
local_root->update_left_height();
temp->right = local_root;
temp->update_right_height();
local_root = temp;
}
void rotate_left(AVLNode<Item_Type>*& local_root) {
AVLNode<Item_Type>* temp = local_root->right;
local_root->right = temp->left;
//adjust the balances
local_root->update_right_height();
temp->left = local_root;
temp->update_left_height();
local_root = temp;
}
};
#endif
This is the AVL_Node class
#ifndef AVLNODE_H_
#define AVLNODE_H_
#include <sstream>
template<typename Item_Type>
struct AVLNode {
// Additional data field
int right_height;
int left_height;
AVLNode<Item_Type>* left;
AVLNode<Item_Type>* right;
Item_Type data;
// Constructor
AVLNode(const Item_Type& the_data, AVLNode<Item_Type>* left = NULL, AVLNode<Item_Type>* right = NULL) : data(the_data), left(left), right(right), right_height(0), left_height(0) {}
// Destructor (to avoid warning message)
virtual ~AVLNode() {}
int balance(){ return right_height - left_height; }
int height(){
return right_height > left_height ? right_height : left_height; }
void update_right_height(){
if (right != NULL)
right_height = 1 + right->height();
else
right_height = 0;
}
void update_left_height(){
if (left != NULL)
left_height = 1 + left->height();
else
left_height = 0;
}
// to_string
virtual std::string to_string() const {
std::ostringstream os;
os << "data : " << this->data;
return os.str();
}
}; // End AVLNode
#endif
Finally, the class I created, the Folder class:
#pragma once
#include <string>
#include "AVL_Tree.h"
using namespace std;
class Folder
{
private:
string name;
int size;
public:
Folder()
{
name = "";
size = 0;
}
Folder(string Name, int Size)
{
name = Name;
size = Size;
}
int getSize()
{
return size;
}
string getName()
{
return name;
}
void setSize(int Size)
{
size = Size;
}
void setName(string Name)
{
name = Name;
}
};
The error only occurs when I try to do
AVL_Tree<Folder> folderTree;
it works for other types, such as string, int, char, etc. Any help would be greatly appreciated. As far as I know, we are not supposed to modify the instructor's code.
Your class Folder should be "comparable", it means the following code should compile Folder a,b; bool result = (a<b);
To achieve this, you can define the comparison operator withing your class
bool operator< (const Folder & other) const
{
return size < other.size || (size == other.size && name < other.name);
}
Alternatively you can define a global comparison operator bool operator< (const Folder & lhs, const Folder & rhs).
Related
I have spent some time recently designing an iterator for the AVL Tree (right now it just has the inserting mechanics though; haven't implemented tree balancing).
I wanted to test out the iterator, so I checked how to make it online and settled on making it by having a stack holding the tree nodes (e.g. in normal iteration stack would contain all nodes left of this->top node).
This is how the iteration is supposed to work:
for (auto it = tree.iterator(); it.hasNext(); it.next())
{
// process
}
However, VS changes (disables) my Iterator(const Iterator& it) and Iterator(Iterator&& it) constructors and then the iteration fails because the stack is always empty.
After setting Iterator() = delete;, I run into the issue of stack having an unusually large size with invisible parameters.
If extra information is needed, feel free to ask. I think that it's best if I just paste the relevant code because I do not understand this behaviour and do not know what details I should say:
avlTree<Key, Info>::iterator:
class Iterator
{
private:
std::vector<Node*> stack;
bool reverse;
Node* ptr;
std::vector<Node*> makeStack(Node* start, long height)
{
std::vector<Node*> newStack;
newStack.reserve(height);
while (start != nullptr)
{
newStack.push_back(start);
if (reverse)
start = start->right;
else
start = start->left;
}
return newStack;
}
Iterator(Node* start, long height, bool reverse = false) : reverse(reverse), ptr(nullptr)
{
stack = makeStack(start, height);
}
friend class avlTree;
public:
Iterator(Iterator&& iterator)
{
stack = move(iterator.stack);
ptr = nullptr;
}
Iterator(const Iterator& iterator)
{
stack = iterator.stack;
ptr = nullptr;
}
//Iterator() = delete;
bool hasNext()
{
return stack.size() > 0;
}
void next()
{
if (!stack.size()) throw "Empty iterator stack";
if (ptr == stack[stack.size() - 1])
{
stack.pop_back();
if (reverse) // fill the stack with the subsequent nodes (reverse or normal direction)
{
Node* start = ptr->left;
while (start != nullptr)
{
stack.push_back(start);
start = start->right;
}
}
else
{
Node* start = ptr->right;
while (start != nullptr)
{
stack.push_back(start);
start = start->left;
}
}
}
if (stack.size() > 0)
ptr = stack[stack.size() - 1];
}
const Key& getKey()
{
if (!ptr) throw "ptr is nullptr";
else return ptr->key;
}
Info& getInfo()
{
if (!ptr) throw "ptr is nullptr";
else return ptr->info;
}
};
main:
avlTree<char, int> tester;
for (char i = 'g'; i <= 'z'; ++i)
tester.insert(i);
for (char i = 'a'; i < 'g'; ++i)
tester.insert(i);
for (auto it = tester.iterator(); it.hasNext(); it.next())
{
std::cout << it.getKey() << " ";
}
Screenshot of the code & message I get while debugging: http://prntscr.com/qi79zd
How do I fix the issue and make the iteration work?
EDIT:
Complete code:
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <fstream>
#include <chrono>
#include <iterator>
#include <functional>
//#include <ctime>
template<typename T>
void swap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
template<typename Key, typename Info>
class avlTree
{
private:
struct Node
{
const Key key;
Info info;
Node* left;
Node* right;
long leftHeight, rightHeight;
Node(const Key& key, Info&& info = Info(), Node* left = nullptr, Node* right = nullptr)
: key(key), info(info), left(left), right(right), leftHeight(1), rightHeight(1) {}
Node& operator()(Node* nleft, Node* nright)
{
left = nleft;
right = nright;
return *this;
}
Node& operator()(long left, long right)
{
leftHeight = left;
rightHeight = right;
}
};
Node* top;
long length;
public:
class Iterator
{
private:
std::vector<Node*> stack;
bool reverse;
Node* ptr;
std::vector<Node*> makeStack(Node* start, long height)
{
std::vector<Node*> newStack;
newStack.reserve(height);
while (start != nullptr)
{
newStack.push_back(start);
if (reverse)
start = start->right;
else
start = start->left;
}
return newStack;
}
Iterator(Node* start, long height, bool reverse = false) : reverse(reverse), ptr(nullptr)
{
stack = makeStack(start, height);
}
friend class avlTree;
public:
Iterator(Iterator&& iterator)
{
stack = move(iterator.stack);
ptr = nullptr;
}
Iterator(const Iterator& iterator)
{
stack = iterator.stack;
ptr = nullptr;
}
bool hasNext()
{
return stack.size() > 0;
}
void next()
{
if (!stack.size()) throw "Empty iterator stack";
//stack.insert(stack.end(), vector.begin(), vector.end());
if (ptr == stack[stack.size() - 1])
{
stack.pop_back();
if (reverse)
{
Node* start = ptr->left;
while (start != nullptr)
{
stack.push_back(start);
start = start->right;
}
}
else
{
Node* start = ptr->right;
while (start != nullptr)
{
stack.push_back(start);
start = start->left;
}
}
}
if (stack.size() > 0)
ptr = stack[stack.size() - 1];
}
const Key& getKey()
{
if (!ptr) throw "ptr is nullptr";
else return ptr->key;
}
Info& getInfo()
{
if (!ptr) throw "ptr is nullptr";
else return ptr->info;
}
};
avlTree()
{
this->top = nullptr;
this->length = 0;
}
~avlTree()
{
recursiveDelete(top);
length = 0;
}
void printAsc()
{
for (auto it = iterator(); it.hasNext(); it.next())
{
std::cout << it.getKey() << " " << it.getInfo() << "\n";
}
}
void printDesc()
{
recDesc(top);
}
void printTop()
{
if (top) // != nullptr
{
std::cout << ".." << top->key << std::endl;
if (top->left)
std::cout << "." << top->left->key << "..";
else std::cout << ".0..";
if (top->right)
std::cout << top->right->key << std::endl;
else std::cout << "0" << std::endl;
}
}
void insert(const Key& key);
long height()
{
return !top ? 0 : top->leftHeight > top->rightHeight ? top->leftHeight : top->rightHeight;
}
private:
void recDesc(Node* parent);
void recursiveDelete(Node* parent);
void insertRecursive(Node* parent, const Key& key, int& depth);
// void rightRotation(Node* top, Node* parent = nullptr);
public:
Iterator iterator()
{
return Iterator(top, height());
}
};
std::vector<std::string> readFile(bool toDarwin = true);
/****************************************************************************/
int main()
{
// auto start = std::chrono::system_clock::now();
avlTree<std::string, int> counter;
avlTree<char, int> tester;
for (char i = 'g'; i <= 'z'; ++i)
tester.insert(i);
for (char i = 'a'; i < 'g'; ++i)
tester.insert(i);
for (auto it = tester.iterator(); it.hasNext(); it.next())
{
std::cout << it.getKey() << " ";
}
return 0;
}
/****************************************************************************/
template<typename Key, typename Info>
void avlTree<Key, Info>::recDesc(Node* parent)
{
if (parent->left != nullptr)
recAsc(parent->left);
std::cout << parent->key;
if (parent->right != nullptr)
recAsc(parent->left);
}
template<typename Key, typename Info>
void avlTree<Key, Info>::recursiveDelete(Node* parent)
{
if (!parent) return;
if (parent->left != nullptr)
recursiveDelete(parent->left);
if (parent->right != nullptr)
recursiveDelete(parent->right);
delete parent;
}
template<typename Key, typename Info>
void avlTree<Key, Info>::insertRecursive(Node* parent, const Key& key, int& depth)
{
if (parent->key == key)
++(parent->info);
else if (parent->key > key)
{
if (parent->left == nullptr)
{
parent->left = new Node(key);
++(parent->left->info);
++length;
depth = 1;
// (* parent->left)(depth, depth)
}
else
{
insertRecursive(parent->left, key, depth);
++depth;
parent->leftHeight = depth;
}
}
else if (parent->key < key)
{
if (parent->right == nullptr)
{
parent->right = new Node(key);
++(parent->right->info);
++length;
depth = 1;
// (* parent->right)(depth, depth)
}
else
{
insertRecursive(parent->right, key, depth);
++depth;
parent->rightHeight = depth;
}
}
}
template<typename Key, typename Info>
void avlTree<Key, Info>::insert(const Key& key)
{
int depth = 0;
if (!top)
{
top = new Node(key);
// (*top)(1, 1)
++length;
++(top->info);
}
else
{
insertRecursive(top, key, depth);
++depth;
top->key > key ? ++(top->leftHeight) : top->key < key ? ++(top->rightHeight) : NULL;
}
}
/* Irrelevant to the problem
std::vector<std::string> readFile(bool toDarwin)
{
// shrink_to_fit()
std::ifstream file;
std::string word;
std::vector<std::string> words;
words.reserve(1000000);
if (toDarwin == 1)
file.open("OnTheOriginOfSpecies.txt");
else
file.open("The_bible.txt");
while (file >> word)
{
words.push_back(word);
}
words.shrink_to_fit();
return words;
}
*/
I believe the problem is that you are not aware of RVO - return value optimization. Most compilers do so and in fact it is mandatory in C++17. What's RVO?
class A;
A func()
{
A a_infunc = {};
return a_infunc;
}
//use
A a_outsidefunc = func();
In this simple example at no point A::A(const A&) or A::A(A&&) is called. a_infunc is exactly the same variable as a_outsidefunc.
So in the for-loop:
for (auto it = tree.iterator(); it.hasNext(); it.next())
{
// process
}
There will be no calls to Iterator(const Iterator& it) or Iterator(Iterator&& it) due to RVO.
So I've been wrestling with this for the last two days. I need to create a LinkedList that's a template class for any . My current issue is that I can't test anything I've written. When I try and run it I get back a build error for the destructor saying:
Undefined symbols for architecture x86_64:
"List342::~List342()", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
This happens even when using the built in ints data type. Here is my code, everything is in the .hpp file. The code isn't complete, I still have a few methods and operators to implement. I just can't seem to get any further right now since I can't test anything. If there's anything you guys can see that I'm just missing from staring at code for too long, I would greatly appreciate it.
** UPDATE I've implemented the functions and copied all the code to a new xCode project. I thought I was no longer getting the linker error, but it turned out I had a typo. Once I fixed the typo linker error returns. Here's the current error message followed by my current code:
Undefined symbols for architecture x86_64:
"operator<<(std::__1::basic_ostream >&, List342 const&)", referenced from:
_main in main.o
"operator<<(std::__1::basic_ostream >&, List342 const&)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
**
//
// List342.hpp
// Program 3 Linked Lists
//
// Created by Chayse Summers on 10/30/16.
// Copyright © 2016 Chayse Summers. All rights reserved.
#ifndef List342_hpp
#define List342_hpp
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
template<class ItemType>
class List342
{
public:
List342();
List342(const List342 &target);
~List342();
bool BuildList(string fileName);
bool Insert(ItemType *obj);
bool Remove(ItemType target, ItemType &result);
bool Peek(ItemType target, ItemType &result) const;
bool isEmpty() const;
void DeleteList();
bool Merge(List342 &input);
//Still need to do op overloaders for +, +=, <<, ==, !=, =.
const List342 operator +(const List342 &item)const;
List342& operator +=(const List342<ItemType> &item);
bool operator ==(const List342 &item) const;
bool operator !=(const List342 &item) const;
List342& operator =(const List342 &item);
friend ostream& operator<<(ostream &outStream, const List342<ItemType> &LL);
private:
virtual void Print (ostream Out) const;
struct Node
{
ItemType *value;
Node *Next;
};
int count;
Node *Head;
};
template <class ItemType>
List342<ItemType>::List342()
{
cout<<"TestConstruct"<<endl;
Head = NULL;
}
template <class ItemType>
List342<ItemType>::List342(const List342 &target)
{
Head = NULL;
*this = target;
}
//**Test BuildList.**
template <class ItemType>
bool List342<ItemType>::BuildList(string fileName)
{
ifstream inFile;
ItemType temp;
inFile.open(fileName);
if(inFile)
{
while(!inFile.eof())
{
inFile>>temp;
Insert(&temp);
}
}
return false;
}
//**Test Insert function.**
template <class ItemType>
bool List342<ItemType>:: Insert(ItemType *obj)
{
Node *insertNode;
ItemType *objValue;
if(obj == NULL)
{
return false;
}
insertNode = new Node;
objValue = obj;
insertNode->value = objValue;
if(Head == NULL)
{
Head = insertNode;
return true;
}
if(objValue < Head->value)
{
insertNode->Next = Head;
Head = insertNode;
return true;
}
Node *pNode = Head;
while((pNode->Next != NULL)&&((pNode->Next)->value< objValue))
{
pNode = pNode->Next;
}
insertNode->Next = pNode->Next;
pNode->Next = insertNode;
count++;
return true;
}
//**Test Remove function.**
template <class ItemType>
bool List342<ItemType>:: Remove(ItemType target, ItemType &result)
{
Node *temp;
if(Head == NULL)
{
return false;
}
if(*(Head->value) == target)
{
temp = Head;
Head = Head->Next;
delete temp;
temp = NULL;
count--;
return true;
}
Node *pNode = Head;
while((pNode->Next != NULL)&&(*(pNode->Next->value) != target))
{
pNode = pNode->Next;
}
if(pNode->Next == NULL)
{
return false;
}
// if(pNode->Next->value == target->value)
// {
// temp = pNode->Next;
// pNode->Next = pNode->Next->Next;
// delete temp;
// temp = NULL;
// return true;
// }
// return true;
else
{
temp = pNode->Next;
pNode->Next = pNode->Next->Next;
delete temp;
temp = NULL;
return true;
}
}
//**Test Peek.**
template <class ItemType>
bool List342<ItemType>:: Peek(ItemType target, ItemType &result) const
{
if (Head != NULL)
{
Node *pNode;
pNode = Head;
while(pNode!=NULL)
{
if(*(pNode->value) != target)
{
pNode = pNode->Next;
}
else
{
result = *(pNode->value);
return true;
}
}
return false;
}
else
{
cout << "Null Pointer" << endl;
return false;
}
}
//**Test isEmpty.**
template <class ItemType>
bool List342<ItemType>:: isEmpty() const
{
if (Head == NULL)
{
return true;
}
else
{
return false;
}
}
//**Implement Merge.**
template <class ItemType>
bool List342<ItemType>:: Merge(List342 &input)
{
Node *Left, *Right;
ItemType *Value;
if(input.Head != NULL)
{
if(Head != NULL)
{
if(this != &input)
{
Right = input.Head;
if (!(*(Right->value) > *(Head->value)))
{
input.Head = input.Head->Next;
if (!(*(Right->value) >= *(Head->value)))
{
Right->Next = Head;
Head = Right;
}
else
{
Value = Right->value;
delete Value;
delete Right;
}
}
Left = Head;
while (input.Head != NULL)
{
Right = input.Head;
if (Left->Next != NULL)
{
if (*(Right->value) > *(Left->Next->value))
{
Left = Left->Next;
}
else
{
input.Head = input.Head->Next;
if (*(Right->value) < *(Left->Next->value))
{
Right->Next = Left->Next;
Left->Next = Right;
}
else
{
Value = Right->value;
delete Value;
delete Right;
}
Left = Left->Next;
}
}
else
{
Left->Next = Right;
input.Head = NULL;
return true;
}
return true;
}
}
else
{
return false;
}
}
else
{
Head = input.Head;
input.Head = NULL;
return true;
}
}
else
{
return true;
}
return false;
}
//**This will be tested along with << overload.**
template<class ItemType>
void List342<ItemType>:: Print (ostream Out) const
{
typename List342<ItemType>::Node *pNode;
pNode = this->Head;
if(pNode!= nullptr)
{
while(pNode->value != NULL)
{
Out << pNode->value;
pNode = pNode->Next;
}
}
}
//**Test and correct if needed.**
template <class ItemType>
ostream& operator<< (ostream &outStream, const List342<ItemType> &LL)
{
typename List342<ItemType>::Node *pNode;
pNode = LL->Head;
if(pNode!= NULL && pNode->Next != NULL)
{
while(pNode != NULL)
{
outStream << *(pNode->value);
pNode = pNode->Next;
}
}
else
{
outStream << "Null Pointer" << endl;
}
//LL.Print(outStream);
return outStream;
}
template <class ItemType>
const List342<ItemType> List342<ItemType>::operator+ (const List342 &item) const
{
List342<ItemType> result = *this;
result += item;
return result;
}
template <class ItemType>
List342<ItemType>& List342<ItemType>:: operator+= (const List342 &input)
{
Node *Left, *Right, *Insert;
ItemType *InsertValue;
if(input.Head != NULL)
{
if(Head == NULL && input.Head != NULL)
{
*this = input;
return *this;
}
Right = input.Head;
if(!(Right->value > Head->value))
{
if(!(Right->value == Head->value))
{
Insert = new Node;
InsertValue = new ItemType;
InsertValue = Right->value;
Insert->value = InsertValue;
Insert->Next = Head;
Head = Insert;
}
Right = Right->Next;
}
Left = Head;
while(Right != NULL)
{
if(Left->Next != NULL)
{
if(!(*(Right->value) > *(Left->Next->value)))
{
if(!(*(Right->value) == *(Left->Next->value)))
{
Insert = new Node;
InsertValue = new ItemType;
*InsertValue = *(Right->value);
Insert->value = InsertValue;
Insert->Next = Left->Next;
Left->Next = Insert;
Left = Left->Next;
}
Right = Right->Next;
}
else
{
Left = Left->Next;
}
}
else
{
Insert = new Node;
InsertValue = new ItemType;
*InsertValue = *(Right->value);
Insert->value = InsertValue;
Insert->Next = Left->Next;
Left->Next = Insert;
Left = Left->Next;
Right = Right->Next;
}
}
return *this;
}
else
{
return *this;
}
}
template<class ItemType>
bool List342<ItemType>:: operator== (const List342 &Input) const
{
Node *Left, *Right;
if(Head != NULL && Input.Head != NULL)
{
Left = Head;
Right = Input.Head;
while(Left != NULL && Right != NULL)
{
if(Left->value != Right->value)
{
return false;
}
else
{
Left = Left->Next;
Right = Right->Next;
}
}
return true;
}
else
{
return false;
}
}
template <class ItemType>
List342<ItemType>& List342<ItemType>:: operator= (const List342 &input)
{
Node *Left, *Right, *Insert;
ItemType *newValue;
if (this != &input || input.Head != NULL)
{
this->DeleteList();
this->Head = NULL;
Head = new Node;
newValue = new ItemType;
newValue = input.Head->value;
Head->value = newValue;
Left = Head;
Right = input.Head->Next;
while(!(Right == NULL))
{
Insert = new Node;
newValue = Right->value;
Insert->value = newValue;
Insert->Next = NULL;
Left->Next = Insert;
Left = Left->Next;
Right = Right->Next;
}
return *this;
}
else
{
return *this;
}
}
template<class ItemType>
bool List342<ItemType>::operator!= (const List342 &item) const
{
return !(*this == item);
}
template <class ItemType>
void List342<ItemType>:: DeleteList()
{
cout << "Deleting list...";
Node *temp;
while(!isEmpty())
{
cout << "...";
temp = Head;
Head = Head->Next;
delete temp;
temp = NULL;
count--;
}
cout << "Done!" << endl;
}
template <typename ItemType>
List342<ItemType>::~List342()
{
cout << "Destructor has run!" << endl;
DeleteList();
}
#endif /* List342_hpp */
I am using Visiual Studio 2013. For some reason, I am getting the following error:
Error 1 error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Word &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#AAVWord###Z) referenced in function "protected: virtual void __thiscall BST<class Word>::visit(class BSTNode<class Word> *)" (?visit#?$BST#VWord####MAEXPAV?$BSTNode#VWord#####Z) C:\Users\Reuben\documents\visual studio 2013\Projects\CS321 Lab4\CS321 Lab4\main.obj CS321 Lab4
The error is due to this particular line:
BST<Word> tree;
If the line were as follows, then it seems to compile just fine:
BST<int> tree;OR BST<string> tree;
So for some reason, it's not liking my implementation of the Word class I defined. Here is the following code.
main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "Word.h"
#include "genBST.h"
using namespace std;
int main()
{
BST<Word> tree;
system("pause");
return 0;
}
Word.h
#include <string>
#include <set>
using namespace std;
class Word{
public:
string* word;
set<int>* lineNums;
void addLineNum(int);
Word(string*, int);
Word();
friend ostream& operator<<(ostream& out, Word& pr);
friend bool operator==(Word, Word);
friend bool operator!=(Word, Word);
friend bool operator<(Word, Word);
friend bool operator<=(Word, Word);
friend bool operator>=(Word, Word);
friend bool operator>(Word, Word);
};
Word::Word(string* myWord, int myLineNum) {
word = myWord;
set<int>* lineNums = new set<int>();
lineNums->insert(myLineNum);
}
Word::Word()
{
word = new string("");
set<int>* lineNums = new set<int>();
lineNums->insert(1);
}
void Word::addLineNum(int line)
{
lineNums->insert(line);
}
//overload comparison operators
//take note that the order of these are important
//since some of the operators are defined in terms of the previously defined ones
bool operator==(Word word1, Word word2)
{
if (*(word1.word) == *(word2.word))
{
return true;
}
return false;
}
bool operator!=(Word word1, Word word2)
{
return !(word1 == word2);
}
bool operator<=(Word word1, Word word2)
{
if (*(word1.word) <= *(word2.word))
{
return true;
}
return false;
}
bool operator<(Word word1, Word word2)
{
if (word1 <= word2 && word1 != word2)
return true;
return false;
}
bool operator>(Word word1, Word word2)
{
return !(word1 <= word2);
}
bool operator>=(Word word1, Word word2)
{
return !(word1 < word2);
}
std::ostream& operator<<(std::ostream& out, const Word& word1)
{
out << *(word1.word);
out << ": ";
set<int>::iterator it;
for (it = word1.lineNums->begin(); it != word1.lineNums->end(); it++)
{
out << *it << " ";
}
return out;
}
The last file is genBST.h. It's a long file, so I'm posting it last. This file was given to me as part of my assignment and we are not allowed to make changes to this file or else we will lose points.
//************************ genBST.h **************************
// generic binary search tree
#include <queue>
#include <stack>
#ifndef BINARY_SEARCH_TREE
#define BINARY_SEARCH_TREE
template<class T>
class Stack : public stack<T> {
public:
T pop() {
T tmp = top();
stack<T>::pop();
return tmp;
}
};
template<class T>
class Queue : public queue<T> {
public:
T dequeue() {
T tmp = front();
queue<T>::pop();
return tmp;
}
void enqueue(const T& el) {
push(el);
}
};
template<class T> class BST;
template<class T>
class BSTNode {
public:
BSTNode() {
left = right = 0;
}
BSTNode(const T& e, BSTNode<T> *l = 0, BSTNode<T> *r = 0) {
el = e; left = l; right = r;
}
T el;
BSTNode<T> *left, *right;
};
template<class T>
class BST {
public:
BST() {
root = 0;
}
~BST() {
clear();
}
void clear() {
clear(root);
root = 0;
}
bool isEmpty() const {
return root == 0;
}
void preorder() {
preorder(root);
}
void inorder() {
inorder(root);
}
void postorder() {
postorder(root);
}
void insert(const T&);
void recursiveInsert(const T& el) {
recursiveInsert(root, el);
}
T* search(const T& el) const {
return search(root, el);
}
T* recursiveSearch(const T& el) const {
return recursiveSearch(root, el);
}
void deleteByCopying(BSTNode<T>*&);
void findAndDeleteByCopying(const T&);
void deleteByMerging(BSTNode<T>*&);
void findAndDeleteByMerging(const T&);
void iterativePreorder();
void iterativeInorder();
void iterativePostorder();
void breadthFirst();
void MorrisPreorder();
void MorrisInorder();
void MorrisPostorder();
void balance(T*, int, int);
protected:
BSTNode<T>* root;
void clear(BSTNode<T>*);
void recursiveInsert(BSTNode<T>*&, const T&);
T* search(BSTNode<T>*, const T&) const;
T* recursiveSearch(BSTNode<T>*, const T&) const;
void preorder(BSTNode<T>*);
void inorder(BSTNode<T>*);
void postorder(BSTNode<T>*);
virtual void visit(BSTNode<T>* p)
{
cout << p->el << ' ';
}
};
template<class T>
void BST<T>::clear(BSTNode<T> *p) {
if (p != 0) {
clear(p->left);
clear(p->right);
delete p;
}
}
template<class T>
void BST<T>::insert(const T& el) {
BSTNode<T> *p = root, *prev = 0;
while (p != 0) { // find a place for inserting new node;
prev = p;
if (el < p->el)
p = p->left;
else p = p->right;
}
if (root == 0) // tree is empty;
root = new BSTNode<T>(el);
else if (el < prev->el)
prev->left = new BSTNode<T>(el);
else prev->right = new BSTNode<T>(el);
}
template<class T>
void BST<T>::recursiveInsert(BSTNode<T>*& p, const T& el) {
if (p == 0)
p = new BSTNode<T>(el);
else if (el < p->el)
recursiveInsert(p->left, el);
else recursiveInsert(p->right, el);
}
template<class T>
T* BST<T>::search(BSTNode<T>* p, const T& el) const {
while (p != 0)
if (el == p->el)
return &p->el;
else if (el < p->el)
p = p->left;
else p = p->right;
return 0;
}
template<class T>
T* BST<T>::recursiveSearch(BSTNode<T>* p, const T& el) const {
if (p != 0)
if (el == p->el)
return &p->el;
else if (el < p->el)
return recursiveSearch(p->left, el);
else return recursiveSearch(p->right, el);
else return 0;
}
template<class T>
void BST<T>::inorder(BSTNode<T> *p) {
if (p != 0) {
inorder(p->left);
visit(p);
inorder(p->right);
}
}
template<class T>
void BST<T>::preorder(BSTNode<T> *p) {
if (p != 0) {
visit(p);
preorder(p->left);
preorder(p->right);
}
}
template<class T>
void BST<T>::postorder(BSTNode<T>* p) {
if (p != 0) {
postorder(p->left);
postorder(p->right);
visit(p);
}
}
template<class T>
void BST<T>::deleteByCopying(BSTNode<T>*& node) {
BSTNode<T> *previous, *tmp = node;
if (node->right == 0) // node has no right child;
node = node->left;
else if (node->left == 0) // node has no left child;
node = node->right;
else {
tmp = node->left // node has both children;
previous = node; // 1.
while (tmp->right != 0) { // 2.
previous = tmp;
tmp = tmp->right;
}
node->el = tmp->el; // 3.
if (previous == node)
previous->left = tmp->left;
else previous->right = tmp->left; // 4.
}
delete tmp; // 5.
}
// findAndDeleteByCopying() searches the tree to locate the node containing
// el. If the node is located, the function DeleteByCopying() is called.
template<class T>
void BST<T>::findAndDeleteByCopying(const T& el) {
BSTNode<T> *p = root, *prev = 0;
while (p != 0 && !(p->el == el)) {
prev = p;
if (el < p->el)
p = p->left;
else p = p->right;
}
if (p != 0 && p->el == el)
if (p == root)
deleteByCopying(root);
else if (prev->left == p)
deleteByCopying(prev->left);
else deleteByCopying(prev->right);
else if (root != 0)
cout << "el " << el << " is not in the tree\n";
else cout << "the tree is empty\n";
}
template<class T>
void BST<T>::deleteByMerging(BSTNode<T>*& node) {
BSTNode<T> *tmp = node;
if (node != 0) {
if (!node->right) // node has no right child: its left
node = node->left; // child (if any) is attached to its parent;
else if (node->left == 0) // node has no left child: its right
node = node->right; // child is attached to its parent;
else { // be ready for merging subtrees;
tmp = node->left; // 1. move left
while (tmp->right != 0)// 2. and then right as far as possible;
tmp = tmp->right;
tmp->right = // 3. establish the link between the
node->right; // the rightmost node of the left
// subtree and the right subtree;
tmp = node; // 4.
node = node->left; // 5.
}
delete tmp; // 6.
}
}
template<class T>
void BST<T>::findAndDeleteByMerging(const T& el) {
BSTNode<T> *node = root, *prev = 0;
while (node != 0) {
if (node->el == el)
break;
prev = node;
if (el < node->el)
node = node->left;
else node = node->right;
}
if (node != 0 && node->el == el)
if (node == root)
deleteByMerging(root);
else if (prev->left == node)
deleteByMerging(prev->left);
else deleteByMerging(prev->right);
else if (root != 0)
cout << "el " << el << " is not in the tree\n";
else cout << "the tree is empty\n";
}
template<class T>
void BST<T>::iterativePreorder() {
Stack<BSTNode<T>*> travStack;
BSTNode<T> *p = root;
if (p != 0) {
travStack.push(p);
while (!travStack.empty()) {
p = travStack.pop();
visit(p);
if (p->right != 0)
travStack.push(p->right);
if (p->left != 0) // left child pushed after right
travStack.push(p->left); // to be on the top of the stack;
}
}
}
template<class T>
void BST<T>::iterativeInorder() {
Stack<BSTNode<T>*> travStack;
BSTNode<T> *p = root;
while (p != 0) {
while (p != 0) { // stack the right child (if any)
if (p->right) // and the node itself when going
travStack.push(p->right); // to the left;
travStack.push(p);
p = p->left;
}
p = travStack.pop(); // pop a node with no left child
while (!travStack.empty() && p->right == 0) { // visit it and all nodes
visit(p); // with no right child;
p = travStack.pop();
}
visit(p); // visit also the first node with
if (!travStack.empty()) // a right child (if any);
p = travStack.pop();
else p = 0;
}
}
template<class T>
void BST<T>::iterativePostorder() {
Stack<BSTNode<T>*> travStack;
BSTNode<T>* p = root, *q = root;
while (p != 0) {
for (; p->left != 0; p = p->left)
travStack.push(p);
while (p->right == 0 || p->right == q) {
visit(p);
q = p;
if (travStack.empty())
return;
p = travStack.pop();
}
travStack.push(p);
p = p->right;
}
}
template<class T>
void BST<T>::breadthFirst() {
Queue<BSTNode<T>*> queue;
BSTNode<T> *p = root;
if (p != 0) {
queue.enqueue(p);
while (!queue.empty()) {
p = queue.dequeue();
visit(p);
if (p->left != 0)
queue.enqueue(p->left);
if (p->right != 0)
queue.enqueue(p->right);
}
}
}
template<class T>
void BST<T>::MorrisInorder() {
BSTNode<T> *p = root, *tmp;
while (p != 0)
if (p->left == 0) {
visit(p);
p = p->right;
}
else {
tmp = p->left;
while (tmp->right != 0 &&// go to the rightmost node of
tmp->right != p) // the left subtree or
tmp = tmp->right; // to the temporary parent of p;
if (tmp->right == 0) { // if 'true' rightmost node was
tmp->right = p; // reached, make it a temporary
p = p->left; // parent of the current root,
}
else { // else a temporary parent has been
visit(p); // found; visit node p and then cut
tmp->right = 0; // the right pointer of the current
p = p->right; // parent, whereby it ceases to be
} // a parent;
}
}
template<class T>
void BST<T>::MorrisPreorder() {
BSTNode<T> *p = root, *tmp;
while (p != 0) {
if (p->left == 0) {
visit(p);
p = p->right;
}
else {
tmp = p->left;
while (tmp->right != 0 &&// go to the rightmost node of
tmp->right != p) // the left subtree or
tmp = tmp->right; // to the temporary parent of p;
if (tmp->right == 0) { // if 'true' rightmost node was
visit(p); // reached, visit the root and
tmp->right = p; // make the rightmost node a temporary
p = p->left; // parent of the current root,
}
else { // else a temporary parent has been
tmp->right = 0; // found; cut the right pointer of
p = p->right; // the current parent, whereby it ceases
} // to be a parent;
}
}
}
template<class T>
void BST<T>::MorrisPostorder() {
BSTNode<T> *p = new BSTNode<T>(), *tmp, *q, *r, *s;
p->left = root;
while (p != 0)
if (p->left == 0)
p = p->right;
else {
tmp = p->left;
while (tmp->right != 0 &&// go to the rightmost node of
tmp->right != p) // the left subtree or
tmp = tmp->right; // to the temporary parent of p;
if (tmp->right == 0) { // if 'true' rightmost node was
tmp->right = p; // reached, make it a temporary
p = p->left; // parent of the current root,
}
else { // else a temporary parent has been found;
// process nodes between p->left (included) and p (excluded)
// extended to the right in modified tree in reverse order;
// the first loop descends this chain of nodes and reverses
// right pointers; the second loop goes back, visits nodes,
// and reverses right pointers again to restore the pointers
// to their original setting;
for (q = p->left, r = q->right, s = r->right;
r != p; q = r, r = s, s = s->right)
r->right = q;
for (s = q->right; q != p->left;
q->right = r, r = q, q = s, s = s->right)
visit(q);
visit(p->left); // visit node p->left and then cut
tmp->right = 0; // the right pointer of the current
p = p->right; // parent, whereby it ceases to be
} // a parent;
}
}
template<class T>
void BST<T>::balance(T data[], int first, int last) {
if (first <= last) {
int middle = (first + last) / 2;
insert(data[middle]);
balance(data, first, middle - 1);
balance(data, middle + 1, last);
}
}
#endif
Any help would be appreciated! I'm still learning the basics of c++, I transferred schools so I'm trying to learn c++ (as opposed to Java which is what I was doing before at my other school). Thanks in advance!
EDIT: Oops, I was being dumb, the following line of code:
friend ostream& operator<<(ostream& out, Word& pr);
Should be (I think):
friend ostream& operator<<(ostream, const Word);
However, after this change, I still get the following error:
Error 1 error C2593: 'operator <<' is ambiguous c:\users\reuben\documents\visual studio 2013\projects\cs321 lab4\cs321 lab4\genbst.h 105 1 CS321 Lab4
Where the line 105 refers is the statement in the function (in the genBST.h file):
virtual void visit(BSTNode<T>* p)
{
cout << p->el << ' ';
}
EDIT v2:
Ok, I've changed the code and it seems to work now. I just placed the implementation of the << operator inside the declaration like so:
class Word{
public:
string* word;
set<int>* lineNums;
void addLineNum(int);
Word(string*, int);
Word();
friend ostream& operator<<(ostream& out, const Word& word1 )
{
out << *(word1.word);
out << ": ";
set<int>::iterator it;
for (it = word1.lineNums->begin(); it != word1.lineNums->end(); it++)
{
out << *it << " ";
}
return out;
};
friend bool operator==(Word, Word);
friend bool operator!=(Word, Word);
friend bool operator<(Word, Word);
friend bool operator<=(Word, Word);
friend bool operator>=(Word, Word);
friend bool operator>(Word, Word);
};
And it seems to work now.
I noticed that in your class definition you have:
class Word{
public:
string* word;
set<int>* lineNums;
void addLineNum(int);
Word(string*, int);
Word();
friend ostream& operator<<(ostream& out, Word& pr);
there is no const before Word & pr
however later in your code you have:
std::ostream& operator<<(std::ostream& out, const Word& word1)
see , there is a const here before Word& word1
should make them same( both have const), I think
I tried your code on my Visual Stdio 2010 ( I do not have 2013).
Before I adding the keyword const (before Word & pr) I got same error as you.
However, after I added the const, it was built successfully.
What is the error you got after you add the keyword const ? Post in detail here.
I only use function insert, remove and midorder.
#include<iostream>
template<class Elem>
class BinNode
{
public:
virtual Elem& getVal() = 0;
};
template<class Elem>
class BinNodePtr:public BinNode<Elem>
{
public:
Elem val;
BinNodePtr* lc;
BinNodePtr* rc;
BinNodePtr()
{
lc = rc = NULL;
}
~BinNodePtr()
{
delete lc;
delete rc;
}
Elem& getVal()
{
return this->val;
}
};
template<class Elem>
class BST
{
public:
BinNodePtr<Elem> *root;
int nodenum;
void midorder(BinNodePtr<Elem>* start);
public:
BST()
{
root = NULL;
nodenum = 0;
}
bool insert(BinNodePtr<Elem>*&ptr,const Elem &e);//
void remove(BinNodePtr<Elem>*&start,const Elem &e);//
BinNodePtr<Elem>* getRoot(){return root;}
};
template<class Elem>
void BST<Elem>::midorder(BinNodePtr<Elem> *start)
{
if(start == NULL) return;
midorder(start->lc);
printf("%d ",start->getVal());
midorder(start->rc);
}
template<class Elem>
bool BST<Elem>::insert(BinNodePtr<Elem>*&ptr,const Elem &e)
{
if(ptr == NULL)
{
ptr = new BinNodePtr<Elem>;
ptr->lc = NULL;
ptr->rc = NULL;
ptr->val = e;
return true;
}
else
{
if(ptr->val < e || ptr->val == e)
{
insert(ptr->rc,e);
}
else
{
insert(ptr->lc,e);
}
}
return false;
}
template<class Elem>
void BST<Elem>::remove(BinNodePtr<Elem>*&start,const Elem &e)
{
if(start == NULL)
return ;
if(start->val < e)
remove(start->rc,e);
else if(start->val > e)
remove(start->lc,e);
else
{
if(start->lc == NULL && start->rc == NULL)
{
delete start;
}
else if(start->lc == NULL)
{
BinNodePtr<Elem> *temp = start;
start = start->rc;
delete (temp);
}
else if(start->rc == NULL)
{
BinNodePtr<Elem> *temp = start;
start = start->lc;
delete temp;
}
else
{
BinNodePtr<Elem>* temp = start->rc;
while(temp->lc!= NULL)
{
temp = temp->lc;
}
start->val = temp->val;
remove(start->rc,temp->val);
}
}
}
int main()
{
BST<int> myBST;
(myBST.insert(myBST.root,10));
(myBST.insert(myBST.root,20));
(myBST.insert(myBST.root,5));
(myBST.insert(myBST.root,30));
myBST.midorder(myBST.getRoot());
myBST.remove(myBST.root,10);
myBST.midorder(myBST.getRoot());
system("pause");
return 0;
}
I have successfully inserted 10, 20, 5, 30 because I can "printf" them out, but the program breaks down when I use function remove. I debugged this and found that there is something wrong in function remove but I don't know how to fix it.
Please read the comments below
Here is the specific error:
Error 2 error LNK2019: unresolved external symbol "void __cdecl totalPolynomial(class LinkedList *,class LinkedList *,class LinkedList *)" (?totalPolynomial##YAXPAV?$LinkedList#VTerm####00#Z) referenced in function _main
Warning 1 warning C4805: '==' : unsafe mix of type 'unsigned int' and type 'bool' in operation 38
I think the problem resides in sumPolynomial in functions.cpp/.h Specifically with it's declaration/implementation.
header.h
#include <iostream>
#include <string>
#include <sstream>
#include <stdlib.h>
using namespace std;
#include "linkedList.h"
#include "term.h"
void loadPolynomial(string expression, LinkedList<Term> *theList);
void totalPolynomial(LinkedList<Term> *x, LinkedList<Term> *y, LinkedList<Term> *sum);
functions.cpp
#include "header.h"
void loadPolynomial(string expression, LinkedList<Term> *theList)
{
Term tempPolynomial;
string varDelimiter = "x";
string posDelimiter = "+";
string negDelimiter = "-";
string token = "";
double coefficient;
double exponent;
/*bool isNeg;*/
bool removedCoefficient = false;
while(expression.length() > 0)
{
/*isNeg = false;*/
coefficient = 1.0;
exponent = 1.0;
removedCoefficient = false;
if(expression.substr(0, 1) == "+")
{
expression.erase(0, 1);
}
/*else if(expression.substr(0, 1) == "-")
{
isNeg = true;
expression.erase(0, 1);
}*/
if( expression.length() > 1 && expression.find(varDelimiter) == true)
{
//Get the coefficient
token = expression.substr(0, expression.find(varDelimiter));
//Remove the coefficient and variable from the string leaving only the exponent
expression.erase(0, expression.find(varDelimiter) + varDelimiter.length());
//Convert and put token's coeficient into a double
coefficient = atof(token.c_str());
/*if(isNeg == true)
{
coefficient = coefficient * -1;
}*/
//Put the coefficient value into the tempPolynomial
tempPolynomial.setCoefficient(coefficient);
removedCoefficient = true;
}
if(expression.find(posDelimiter) > 0 && expression.length() > 0 && removedCoefficient == true)
{
//Get the exponent
token = expression.substr(0, expression.find(posDelimiter));
//Remove the exponent but leave the +
expression.erase(0, expression.find(posDelimiter) + posDelimiter.length());
//Convert and put token's coeficient into a double
exponent = atof(token.c_str());
//Put the exponent value into the tempPolynomial
tempPolynomial.setExponent(exponent);
}
if(removedCoefficient == false)
{
//Get the trailing number
token = expression.substr(0);
coefficient = atof(token.c_str());
//Set it as the coefficient
tempPolynomial.setCoefficient(coefficient);
//Set the exponent as 0 so we know it doesn't include a variable
tempPolynomial.setExponent(0.0);
//Remove it from the string
expression.erase(0, token.length());
}
//Intert the first term into the linked list
theList->insert(tempPolynomial);
}
}
void sumPolynomial(LinkedList<Term> *x, LinkedList<Term> *y, LinkedList<Term> *sum)
{
LinkedList<Term> *tempNodeX;
LinkedList<Term> *tempNodeY;
Term tempTermX;
Term tempTermY;
Term newTerm;
tempNodeX = x->getNext();
tempNodeY = y->getNext();
while(tempNodeX != NULL)
{
tempTermX = tempNodeX->getData();
while(tempNodeY !=NULL)
{
tempTermY = tempNodeY->getData();
if(tempTermX.getExponent() == tempTermY.getExponent())
{
newTerm.setCoefficient(tempTermX.getCoefficient() + tempTermY.getCoefficient());
newTerm.setExponent(tempTermY.getExponent());
sum->insert(newTerm);
}
tempNodeX = tempNodeY->getNext();
}
tempNodeX = tempNodeX->getNext();
}
}
term.h
#ifndef TERM_H
#define TERM_H
#include<iostream>
using namespace std;
class Term
{
private:
double mCoefficient;
double mExponent;
public:
Term();
//Term(double coefficient);
//Term(double exponent);
Term(double coefficient, double exponent);
~Term();
double getCoefficient();
double getExponent();
void setCoefficient(double coefficient);
void setExponent(double exponent);
friend ostream& operator<<(ostream &output, Term object);
bool operator==(Term right);
//friend bool operator==(Term left, Term right);
bool operator!=(Term right);
//friend bool operator!=(Term left, Term right);
bool operator>(Term right);
//friend bool operator>(Term left, Term right);
bool operator<(Term right);
//friend bool operator<(Term left, Term right);
};
#endif
term.cpp
#include "term.h"
Term::Term()
{
mCoefficient = 1;
mExponent = 1;
}
//
//Term::Term(double coefficient)
//{
// mCoefficient = coefficient;
// mExponent = 1.0;
//}
//
//
//Term::Term(double exponent)
//{
// mCoefficient = 1.0;
// mExponent = exponent;
//}
Term::Term(double coefficient, double exponent)
{
mCoefficient = coefficient;
mExponent = exponent;
}
Term::~Term(){}
double Term::getCoefficient()
{
return mCoefficient;
}
double Term::getExponent()
{
return mExponent;
}
void Term::setCoefficient(double coefficient)
{
mCoefficient = coefficient;
}
void Term::setExponent(double exponent)
{
mExponent = exponent;
}
ostream& operator<<(ostream &output, Term object)
{
if(object.mExponent > 0)
{
output << object.mCoefficient << "x" << object.mExponent;
}
else
{
output << object.mCoefficient;
}
return output;
}
bool Term::operator==(Term right)
{
if(mExponent == right.mExponent && mCoefficient == right.mCoefficient)
{
return true;
}
else
{
return false;
}
}
bool Term::operator!=(Term right)
{
if(mExponent != right.mExponent)
{
return true;
}
else if(mCoefficient != right.mCoefficient)
{
return true;
}
else
{
return false;
}
}
bool Term::operator>(Term right)
{
if(mExponent > right.mExponent)
{
return true;
}
else if(mExponent == right.mExponent && mCoefficient > right.mCoefficient)
{
return true;
}
else
{
return false;
}
}
bool Term::operator<(Term right)
{
if(mExponent < right.mExponent)
{
return true;
}
else if(mExponent == right.mExponent && mCoefficient < right.mCoefficient)
{
return true;
}
else
{
return false;
}
}
linkedList.h
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
#include <iostream>
#include <fstream>
using namespace std;
template <class T>
class LinkedList
{
private:
T mData;
LinkedList<T> *mNext;
public:
LinkedList();
LinkedList(T data);
~LinkedList();
T getData();
LinkedList<T> *getNext();
void setData(T data);
void display();
void insert(T data);
bool isExist(T data);
void remove(T data);
friend ostream& operator<<(ostream &output, LinkedList<T> object);
bool operator==(T right);
friend bool operator==(T left, LinkedList<T> right);
bool operator!=(T right);
friend bool operator!=(T left, LinkedList<T> right);
bool operator>(T right);
friend bool operator>(T left, LinkedList<T> right);
bool operator<(T right);
friend bool operator<(T left, LinkedList<T> right);
};
template <class T>
LinkedList<T>::LinkedList()
{
mNext = NULL;
mData = T();
}
template <class T>
LinkedList<T>::LinkedList(T data)
{
mNext = NULL;
mData = data;
}
template <class T>
LinkedList<T>::~LinkedList()
{
LinkedList<T> *tempNode;
tempNode = mNext;
while(tempNode != NULL)
{
mNext = tempNode->mNext;
tempNode->mNext = NULL;
delete tempNode;
tempNode = mNext;
}
}
template <class T>
T LinkedList<T>::getData()
{
return mData;
}
template <class T>
LinkedList<T> *LinkedList<T>::getNext()
{
return mNext;
}
template <class T>
void LinkedList<T>::setData(T data)
{
mData = data;
}
template <class T>
void LinkedList<T>::display()
{
LinkedList<T> *tempNode;
tempNode = mNext;
while(tempNode != NULL)
{
cout << tempNode->mData << endl;
tempNode = tempNode->mNext;
}
}
template <class T>
void LinkedList<T>::insert(T data)
{
LinkedList<T> *previousNode;
LinkedList<T> *tempNode;
LinkedList<T> *newNode;
newNode = new LinkedList(data);
if(mNext == NULL)
{
mNext = newNode;
}
else
{
previousNode = mNext;
tempNode = mNext;
while(tempNode != NULL && tempNode->mData > data)
{
previousNode = tempNode;
tempNode = tempNode->mNext;
}
if(tempNode == mNext)
{
newNode->mNext = mNext;
mNext = newNode;
}
else
{
previousNode->mNext = newNode;
newNode->mNext = tempNode;
}
}
}
template <class T>
bool LinkedList<T>::isExist(T data)
{
LinkedList<T> *tempNode;
bool exist = false;
tempNode = mNext;
while(tempNode != NULL)
{
if(tempNode->mData == data)
{
exist = true;
break;
}
tempNode = tempNode->mNext;
}
return exist;
}
template <class T>
void LinkedList<T>::remove(T data)
{
LinkedList<T> *tempNode;
LinkedList<T> *previousNode;
if(isExist(data) == false)
{
return;
}
tempNode = mNext;
previousNode = mNext;
while(tempNode->mData != data)
{
previousNode = tempNode;
tempNode = tempNode->mNext;
}
if(tempNode == mNext)
{
mNext = tempNode->mNext;
tempNode->mNext = NULL;
}
else
{
if(tempNode->mNext == NULL)
{
previousNode->mNext = NULL;
}
else
{
previousNode->mNext = tempNode->mNext;
tempNode->mNext = NULL;
}
}
delete tempNode;
}
template <class T>
ostream& operator<<(ostream &output, LinkedList<T> object)
{
output << object.mData;
return output;
}
template <class T>
bool LinkedList<T>::operator==(T right)
{
return mData == right;
}
template <class T>
bool operator==(T left, LinkedList<T> right)
{
return left == right.mData;
}
template <class T>
bool LinkedList<T>::operator!=(T right)
{
return mData != right;
}
template <class T>
bool operator!=(T left, LinkedList<T> right)
{
return left != right.mData;
}
template <class T>
bool LinkedList<T>::operator>(T right)
{
return mData > right;
}
template <class T>
bool operator>(T left, LinkedList<T> right)
{
return left > right.mData;
}
template <class T>
bool LinkedList<T>::operator<(T right)
{
return mData < right;
}
template <class T>
bool operator<(T left, LinkedList<T> right)
{
return left < right.mData;
}
#endif
Here is the revised loop that now works:
while(tempNodeX != NULL)
{
tempTermX = tempNodeX->getData();
while(tempNodeY != NULL)
{
tempTermY = tempNodeY->getData();
if(tempTermX.getExponent() == tempTermY.getExponent())
{
newTerm.setCoefficient(tempTermX.getCoefficient() + tempTermY.getCoefficient());
newTerm.setExponent(tempTermY.getExponent());
//cout << tempTermX << " " << tempTermY << " " << newTerm << endl;
sum->insert(newTerm);
tempNodeY = y->getNext();
tempNodeY->remove(tempTermY);
break;
}
tempNodeY = tempNodeY->getNext();
}
tempNodeX = tempNodeX->getNext();
tempNodeY = y->getNext();
}