Priority Queue that Utilizes BST - Funny Ouptut - c++

I wrote a priority queue that utilizes a binary search tree for my data structures class. The out put it produces is correct for some inputs and incorrect for others.
Correct output:
Enter number of elements: 5
Enter number 1 of 5: 1
Enter number 2 of 5: 2
Enter number 3 of 5: 3
Enter number 4 of 5: 4
Enter number 5 of 5: 5
Outputting number 1 of 5: 5
Outputting number 2 of 5: 4
Outputting number 3 of 5: 3
Outputting number 4 of 5: 2
Outputting number 5 of 5: 1
Press any key to continue . . .
Incorrect Output
Enter number of elements: 5
Enter number 1 of 5: -56
Enter number 2 of 5: 4
Enter number 3 of 5: 56
Enter number 4 of 5: 21
Enter number 5 of 5: 32
Outputting number 1 of 5: 56
Outputting number 2 of 5: 4
Outputting number 3 of 5: -56
Outputting number 4 of 5: -56
Outputting number 5 of 5: -56
Press any key to continue . . .
Test.cpp
#include <iostream>
#include "CTree.h"
#include "PriorityQueueBST.h"
using namespace std;
int main()
{
int num, input, output;
cout << "Enter number of elements: ";
cin >> num;
PriorityQueueBST p;
for (int x = 0; x < num; x++)
{
cout << "Enter number " << x + 1
<< " of " << num << ": ";
cin >> input;
p.Enqueue(input);
}
for (int y = 0; y < num; y++)
{
cout << "Outputting number " << y + 1
<< " of " << num << ": ";
if(p.IsEmpty())
{
break; //we are done (this is an error!)
}
output = p.Dequeue();
cout << output << endl;
}
system("pause");
return 0;
//CTree* tr = new CTree();
//
//for (int i = 0; i < 3; i++)
// tr->Add();
//tr->View();
//system("pause");
//return 0;
}
BST Declaration
//#ifndef CTREE_H
//#define CTREE_H
//using namespace std;
struct TreeNode
{
int info;
TreeNode* leftLink;
TreeNode* rightLink;
};
class CTree
{
public:
CTree();
~CTree();
void Add(int);
void View();
bool IsEmpty();
int DeleteLargest(TreeNode*);
TreeNode *tree;
private:
void AddItem( TreeNode*&, TreeNode*);
void DisplayTree(TreeNode*);
void Retrieve(TreeNode*&, TreeNode*,bool&);
void Destroy(TreeNode*&);
};
//#endif
BST Implementation
#include <iostream>
#include <string>
using namespace std;
#include "CTree.h"
CTree::CTree()
{
tree = NULL;
}
CTree::~CTree()
{
Destroy(tree);
}
void CTree::Destroy(TreeNode*& tree)
{
if (tree != NULL)
{
Destroy(tree->leftLink);
Destroy(tree->rightLink);
delete tree;
}
}
bool CTree::IsEmpty()
{
if(tree == NULL)
{
return true;
}
else
{
return false;
}
}
void CTree::Add(int dataToEnter)
{
TreeNode* newPerson = new TreeNode();
/*cout << "Enter the person's name: ";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cin.getline(newPerson->name, 20);*/
//cout << "Enter the person's contribution: ";
//cin >> newPerson->info;
/*bool found = false;*/
newPerson->info = dataToEnter;
newPerson->leftLink = NULL;
newPerson->rightLink = NULL;
/*Retrieve(tree, newPerson, found);
if (found)
cout << "info allready entered\n";
else*/
AddItem(tree, newPerson);
}
void CTree::View()
{
if (IsEmpty())
{
cout<<"The list is empy";
}
else
{
DisplayTree(tree);
}
};
void CTree::AddItem( TreeNode*& ptr, TreeNode* newPer )
{
if (ptr == NULL)
{
ptr = newPer;
}
else if ( newPer->info < ptr->info)
AddItem(ptr->leftLink, newPer);
else
AddItem(ptr->rightLink, newPer);
}
void CTree::DisplayTree(TreeNode* ptr)
{
if (ptr == NULL)
return;
DisplayTree(ptr->rightLink);
cout << ptr->info << endl; //cout<<ptr->name<<" "<<"$"<<ptr->info <<endl;
DisplayTree(ptr->leftLink);
}
void CTree::Retrieve(TreeNode*& ptr, TreeNode* newPer, bool& found)
{
{
if (ptr == NULL)
{
found = false; // item is not found.
}
else if ( newPer->info < ptr->info)
{
Retrieve(ptr->leftLink, newPer, found);
}
// Search left subtree.
else if (newPer->info > ptr->info)
{
Retrieve(ptr->rightLink, newPer, found);// Search right subtree.
}
else
{
//newPer.info = ptr->info; // item is found.
found = true;
}
}
}
int CTree::DeleteLargest(TreeNode* tr)
{
int largest = tr->info;
TreeNode* prev = NULL;
while (tr->rightLink != NULL)
{
prev = tr;
tr = tr->rightLink;
largest = tr->info;
}
if (prev != NULL && prev->rightLink != NULL)
{
delete prev->rightLink;
prev->rightLink = NULL;
}
return largest;
}
//
//int CTree::DeleteLargest(TreeNode* tr)
//{
// int largest = 0;
// TreeNode* prev = NULL;
//
//
// while (tr->rightLink != NULL)
// {
// prev = tr;
// tr = tr->rightLink;
// largest = tr->info;
// }
//
// prev->rightLink = NULL;
//
// return largest;
//}
/*
if (tr == NULL)
{
cout << "The tree is empty"<<endl;
}
else if (tr->rightLink == NULL)
{
largest = tr->info;
prev->rightLink = NULL;
}
else
{
prev = tr;
tr = tr->rightLink;
largest = DeleteLargest(tr);
}
*/
PQ Declaration
//#include <iostream>
//using namespace std;
//#include "SortedLinkedList.h"
#ifndef PRIORITYQUEUESLL__H
#define PRIORITYQUEUESLL__H
class PriorityQueueBST
{
public:
PriorityQueueBST();
~PriorityQueueBST();
void Enqueue(int);
int Dequeue();
bool IsEmpty();
private:
CTree* ourTree;
//sslNode* head;
};
#endif
PQ Implementation
#include <iostream>
using namespace std;
#include "CTree.h"
#include "PriorityQueueBST.h"
PriorityQueueBST::PriorityQueueBST()
{
ourTree = new CTree();
//head = NULL;
}
PriorityQueueBST::~PriorityQueueBST()
{
}
void PriorityQueueBST::Enqueue(int dataToEnter)
{
ourTree->Add(dataToEnter);
}
int PriorityQueueBST::Dequeue()
{
//check for empty??
return ourTree->DeleteLargest(ourTree->tree);
}
bool PriorityQueueBST::IsEmpty()
{
return ourTree->IsEmpty();
}

In DeleteLargest, consider what happens if the tree looks like
4
/ \
/ \
2 7
/ \ /
1 3 5
With
int CTree::DeleteLargest(TreeNode* tr)
{
int largest = tr->info;
TreeNode* prev = NULL;
while (tr->rightLink != NULL)
{
prev = tr;
tr = tr->rightLink;
largest = tr->info;
}
if (prev != NULL && prev->rightLink != NULL)
{
delete prev->rightLink;
prev->rightLink = NULL;
}
return largest;
}
you're finding the 7, but cut the 5 out of the tree, it's lost then. And when the right subtree of the root node has been completely removed, tr->rightLink is NULL from the start, so prev remains NULL and nothing is deleted.
For the first case, you have to graft tr's left child to prev's right before deleting tr. The second case is a bit more complicated. Since you can't change the containing CTree without changing the function's signature, you can't delete the root node that is passed in. You have to¹ fake that by copying the value of its left child, relinking the children of that, and deleting the original left child.
¹ Well, of course there are other methods available, but all I can think of involve copying an info and deleting a different node.

Related

Implementing linked list on manipulating multiple list order with C++

Disclaimer: This is homework and I am pretty much a complete beginner in programming (only took an intro class to C a few years ago). If it matters, this is from a Competitive Programming class. I appreciate all feedback besides on the question itself like good programming practices, naming conventions...etc. I am new to coding, but love it and want to improve.
Consider n lists that are initialized with a single member that corresponds to its list number, i.e.:
#1: 1
#2: 2
#3: 3
...
Input:
First line contains n m where 1 ≤ n ≤ 1000000, 1 ≤ m ≤ 2000000;
Followed by m lines of k a b, where k is either 0 or 1 and denotes the type of manipulation:
k = 0: find member a and move from its position to behind member b
k = 1: move the entire list of #a list and place it behind the #b list
Output:
Print the lists in order after all the commands are executed. The question specifically states no whitespaces at the end of each line.
What I've tried:
#include <iostream>
#include <sstream>
#include <vector>
#include <ctime>
using namespace std;
class List {
private:
struct Node {
int data;
Node *next;
};
Node *head;
public:
List() {
head = NULL;
}
Node *GetHead() {
return head;
}
Node *GetPrevNode(int value) { // Gets the previous node to the node I am trying to move
Node *temp, *peek;
temp = head;
peek = temp->next;
if (head->data == value)
return head;
else {
while (peek != NULL) {
if (peek->data == value) {
return temp;
}
else {
temp = temp->next;
peek = temp->next;
}
}
return NULL;
}
return NULL;
}
Node *GetNode(int value) { // Gets the actual node I'm trying to move
Node *temp;
temp = head;
while (temp != NULL) {
if (temp->data == value) {
return temp;
}
else {
temp = temp->next;
}
}
return NULL;
}
void PushNode(int value) {
Node *temp = new Node;
temp->data = value;
temp->next = NULL;
if (head == NULL) {
head = temp;
}
else {
head->next = temp;
}
}
void MoveNode(Node *prevFrom, int value, Node *dest) { // called on the FROM list
Node *tempDestNext, *from;
tempDestNext = dest->next;
if (prevFrom->data == value) {
from = prevFrom;
}
else {
from = prevFrom->next;
}
//different cases
if (dest->next == from) {
return;
}
else if (from->next == dest) {
from->next = dest->next;
dest->next = from;
if (from == prevFrom) {
head = dest;
}
else {
prevFrom->next = dest;
}
}
else {
Node *tempFromNext;
tempFromNext = from->next;
dest->next = from;
if (from == head) {
head = tempFromNext;
}
else {
prevFrom->next = tempFromNext;
}
from->next = tempDestNext;
}
}
void ConcList(Node *headFrom) { // called on the DESTINATION list
if (head == NULL) {
head = headFrom;
}
else {
Node *temp;
temp = head;
while (temp != NULL) {
if (temp->next == NULL) {
temp->next = headFrom;
break;
}
else {
temp = temp->next;
}
}
}
}
void PrintList() {
Node *temp;
temp = head;
while (temp != NULL) {
cout << " " << temp->data;
temp = temp->next;
}
}
};
struct Move {
int type, from, to;
};
void MarkNodePos(vector<int> &NodePos, int type, int from, int to) { // record on which list a node is
switch (type) {
case 0:
NodePos[from - 1] = NodePos[to - 1];
break;
case 1:
for (int i = 0; i < NodePos.size(); i++) {
if (NodePos[i] == (from - 1)) {
NodePos[i] = (to - 1);
}
}
break;
}
}
int RandomNum(int min, int max) {
int range = max - min + 1;
int num = rand() % range + min;
return num;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); // my teacher told us to include this code for speed optimization
int n, m;
cin >> n >> m;
cin.ignore();
vector<List> line;
for (int i = 0; i < n; i++) {
List temp;
temp.PushNode(i + 1);
line.push_back(temp);
}
vector<int> NodePos;
for (int i = 0; i < n; i++) {
NodePos.push_back(i);
}
string instrc;
Move step;
srand(time(NULL));
for (int i = 0; i < m; i++) {
int mode = 0; // switch between input and testing mode
switch (mode) {
case 0: {
getline(cin, instrc);
stringstream ss(instrc);
ss >> step.type >> step.from >> step.to;
break;
}
case 1:
stringstream ss;
ss << RandomNum(0, 1) << " " << RandomNum(1, n) << " " << RandomNum(1, n);
ss >> step.type >> step.from >> step.to;
cout << step.type << " " << step.from << " " << step.to << endl;
break;
}
if (step.from != step.to) {
switch (step.type) {
case 0:
int from, to;
from = NodePos[step.from - 1];
to = NodePos[step.to - 1];
line[from].MoveNode(line[from].GetPrevNode(step.from), step.from, line[to].GetNode(step.to));
MarkNodePos(NodePos, step.type, step.from, step.to);
break;
case 1:
if (line[step.from - 1].GetHead() != NULL) {
line[step.to - 1].ConcList(line[step.from - 1].GetHead());
List clear;
line[step.from - 1] = clear;
MarkNodePos(NodePos, step.type, step.from, step.to);
}
break;
}
}
}
for (int i = 0; i < n; i++) {
cout << "#" << (i + 1) << ":";
line[i].PrintList();
if (i != (n - 1))
cout << "\n";
}
return 0;
}
An example:
Input:
6 4
0 4 3
0 6 5
1 2 5
1 6 5
Output:
#1: 1
#2:
#3: 3 4
#4:
#5: 5 6 2
#6:
I keep getting wrong answer from the judge but as you can seen, I used a random number generator to test out my program and from my testing it all seems fine. I really have no clue what to look for. What could be causing the error?

A ton of undefined reference errors

I don't know if I'm linking wrong but I'm compiling this on linux and I'm getting a LOT of undefined references for my node functions. I'm writing a binary search tree to searches for telephones for class that is due tonight.
bst.cpp
#include "bst.hpp"
BST::BST(void)
{
count = 0;
root = NULL;
}
void BST::insert(long long x, string y)
{
Node *newnode = new Node(x, y);
Node *temp;
if (count == 0)
{
root = newnode;
count++;
}
else
{
while(temp->getleft() != NULL && temp->getright() != NULL)
{
if(newnode->getnum() < temp->getnum())
{
temp = temp->getleft();
}
else
{
temp = temp->getright();
}
}
if (newnode->getnum() < temp->getnum())
{
temp->setleft(newnode);
}
else
{
temp->setright(newnode);
}
}
}
Node * BST::getroot(void)
{
return root;
}
Node* BST::delete_node(Node *troot, long long key)
{
if (count == 0)
{
return troot;
}
else if(key < troot->getnum())
{
delete_node(troot->getleft(), key);
}
else if (key > troot->getnum())
{
delete_node(troot->getright(), key);
}
else
{
if(troot->getleft() == NULL && troot->getright() == NULL)
{
delete troot;
troot == NULL;
}
else if(troot->getright() == NULL)
{
Node *temp = troot;
troot = troot->getleft();
delete temp;
}
else if(troot->getleft() == NULL)
{
Node *temp = troot;
troot = troot->getright();
delete temp;
}
}
return troot;
}
void BST::preverse(Node* troot)
{
if(root == NULL)
{
cout << "The tree is empty\n";
}
if(troot == NULL)
{
return;
}
cout << troot->getname() << endl;
cout << troot->getnum() << endl;
preverse(troot->getleft());
preverse(troot->getright());
}
void BST::postverse(Node* troot)
{
if(root == NULL)
{
cout << "The tree is empty\n";
}
if(troot == NULL)
{
return;
}
postverse(troot->getleft());
postverse(troot->getright());
cout << troot->getname() << endl;
cout << troot->getnum() << endl;
}
void BST::inverse(Node* troot)
{
if(root == NULL)
{
cout << "The tree is empty\n";
}
if(troot == NULL)
{
return;
}
inverse(troot->getleft());
cout << troot->getname() << endl;
cout << troot->getnum() << endl;
inverse(troot->getright());
}
void BST::search(Node* troot, long long key)
{
if(root == NULL)
{
cout << "The tree is empty\n";
}
if(troot == NULL)
{
return;
}
if(key == troot->getnum())
{
cout << troot->getname();
}
search(troot->getleft(), key);
search(troot->getright(), key);
}
bst.hpp
#include "node.hpp"
#ifndef bst_hpp
#define bst_hpp
class BST
{
Node* root;
long long count;
public:
BST(void);
void insert(long long x, string y);
Node* getroot(void);
Node* delete_node(Node* troot, long long key);
void preverse(Node* troot);
void postverse(Node* troot);
void inverse(Node* troot);
void search(Node* troot, long long key);
};
#endif
node.cpp
#include "node.hpp"
Node::Node(void)
{
number = 0;
name = "no name";
left = NULL;
right = NULL;
}
Node::Node(long long t, string n)
{
number = t;
name = n;
left = NULL;
right = NULL;
}
Node * Node::getleft(void)
{
return left;
}
Node * Node::getright(void)
{
return right;
}
void Node::setleft(Node * ptr)
{
left = ptr;
}
void Node::setright(Node * ptr)
{
right = ptr;
}
long long Node::getnum(void)
{
return number;
}
string Node::getname(void)
{
return name;
}
node.hpp
#ifndef node_hpp
#define node_hpp
#include <string>
#include <iostream>
using namespace std;
class Node
{
long long number;
string name;
Node *left;
Node *right;
public:
Node(void);
Node(long long t, string n);
Node* getleft(void);
Node* getright(void);
void setleft(Node* ptr);
void setright(Node* ptr);
long long getnum(void);
string getname(void);
};
#endif
main.cpp
#include "bst.hpp"
using namespace std;
int main(void)
{
int choice;
long long numin;
string input;
BST phbook;
do
{
cout << "1. Insert a name and number.\n2. Delete using number.\n3. Traverse pre-order\n4. Traverse post-order\n";
cout << "5. Traverse in-order\n6. Search using number.\n6. Exit program\n";
switch(choice)
{
case 1:
cout << "Enter a name\n";
cin.ignore();
getline(cin, input);
cout << "Enter a number\n";
cin >> numin;
phbook.insert(numin, input);
break;
case 2:
cout << "Enter the phone number you'd like to delete.\n";
cin >> numin;
phbook.delete_node(phbook.getroot(), numin);
break;
case 3:
phbook.preverse(phbook.getroot());
break;
case 4:
phbook.postverse(phbook.getroot());
break;
case 5:
phbook.inverse(phbook.getroot());
break;
case 6:
cout << "Enter a phone number to search.\n";
cin >> numin;
phbook.search(phbook.getroot(),numin);
default:
numin=numin;
}
}while(choice >= 1 && choice <= 6);
return 0;
}
To me, nothing looks wrong in linking the files.
Some examples : undefined reference to Node::getnum()
undefined reference to Node::getname()
Check the order of compiled elements:
g++ node.cpp -o node.o bst.cpp -o bst.o main.cpp -o main.o
Result:
./main.o
1. Insert a name and number.
2. Delete using number.
3. Traverse pre-order
4. Traverse post-order
5. Traverse in-order
6. Search using number.
6. Exit program

Level Order Traversal: Deleting a Subtree

#include <iostream>
using namespace std;
struct node {
int item;
node* l;
node* r;
node (int x) {
item = x;
l = 0;
r = 0;
}
node(int x, node* l, node* r) {
item = x;
this->l = l;
this->r = r;
}
};
typedef node* link;
class QUEUE {
private:
link* q;
int N;
int head;
int tail;
public:
QUEUE(int maxN) {
q = new link[maxN + 1];
N = maxN + 1;
head = N;
tail = 0;
}
int empty() const {
return head % N == tail;
}
void put(link item) {
q[tail++] = item;
tail = tail % N;
}
link get() {
head = head % N;
return q[head++];
}
};
link head = 0; // Initial head of the tree
link find(int x) {
if (head == 0) {
cout << "\nEmpty Tree\n";
return 0;
}
link temp = head;
// To find the node with the value x and return its link
QUEUE q(100);
q.put(temp);
while (!q.empty()) {
temp = q.get();
if (temp->item == x) {
return temp;
}
if (temp->l != 0) q.put(temp->l);
if (temp->r != 0) q.put(temp->r);
}
return 0;
}
void print(link temp) {
QUEUE q(100);
q.put(temp);
while (!q.empty()) {
temp = q.get();
cout << temp->item << ", ";
if (temp->l != 0) q.put(temp->l);
if (temp->r != 0) q.put(temp->r);
}
}
void deleteAll(link h) {
// This deletes the entire binary tree
QUEUE q(100);
q.put(h);
while (!q.empty()) {
h = q.get();
if (h->l != 0) q.put(h->l);
if (h->r != 0) q.put(h->r);
delete h;
}
}
int main() {
link temp = 0;
char c;
int n1, n2;
cout << "\n\nPlease enter the input instructions (X to exit program) : \n\n";
do {
cin >> c;
switch (c) {
case 'C': cin >> n1;
if (head == 0) {
head = new node(n1);
cout << "\nRoot node with item " << n1 << " has been created\n\n";
} else {
cout << "\nError: Tree is not empty\n\n";
}
break;
case 'L': cin >> n1 >> n2;
temp = find(n1);
if (temp != 0) {
if (temp->l == 0) {
temp->l = new node(n2);
cout << "\nNode with item " << n2 << " has been added\n\n";
}
else {
cout << "\nError: The specified node already has a left child\n\n";
}
}
else {
cout << "\nError: The specified node doesn't exist\n\n";
}
break;
case 'R': cin >> n1 >> n2;
temp = find(n1);
if (temp != 0) {
if (temp->r == 0) {
temp->r = new node(n2);
cout << "\nNode with item " << n2 << " has been added\n\n";
}
else {
cout << "\nError: The specified node already has a right child\n\n";
}
}
else {
cout << "\nError: The specified node doesn't exist\n\n";
}
break;
case 'P': cin >> n1;
temp = find(n1);
if (head != 0) {
cout << "\nLevel-order traversal of the entire tree: ";
print(temp);
}
else {
cout << "\nError: No elements to print\n\n";
}
break;
case 'D': cin >> n1;
temp = find(n1);
deleteAll(temp);
temp = 0;
break;
case 'X': cout << "\nExiting Program\n\n";
break;
default: cout << "\nInvalid input entered. Try again.\n\n";
}
} while (c != 'X');
system("pause");
return 0;
}
Sample Input:
C 9
L 9 8
R 9 6
L 8 3
R 8 5
R 6 2
L 3 4
L 4 10
L 5 1
R 5 11
L 1 12
R 1 7
It all works fine until I delete a subtree and print when it prints garbage value before crashing. Please help me figure out the bug because I've been trying in vain for hours now.
It all works fine until I delete a subtree and print when it prints garbage value before crashing. Please help me figure out the bug because I've been trying in vain for hours now.
Try the recursive function:
void Delete(link h)
{
if(h)
{
if(h->l) Delete(h->l);
if(h->r) Delete(h->r);
delete(h);
}
}
When you delete a node, you call deleteAll(temp) which deletes temp, but it doesn't remove the pointer value from the l or r of temp's parent node.
This leaves you with a invalid pointer, causing garbage printing and crashing.
Unfortunately, the way your find works currently, you don't know what the current temp node's parent is when you get around to checking its value.
One way to fix it is to have a different type of find (called something like remove) that looks in l and r at each iteration for the value and sets l or r to NULL before returning the pointer. You might have to have a special case for when the value is found in the root.
Edit (sample code added):
I am assuming you are not using recursion for some reason, so my code uses your existing queue based code. I only changed enough to get it working.
findAndUnlink find the node with the value given and "unlinks" it from the tree. It returns the node found, giving you a completely separate tree. Note: it is up to the caller to free up the returned tree, otherwise you will leak memory.
This is a drop in replacement for find in your existing code, as your existing code then calls deleteAll on the returned node.
link findAndUnlink(int x) {
if (head == 0) {
cout << "\nEmpty Tree\n";
return 0;
}
link temp = head;
if (temp->item == x) {
// remove whole tree
head = NULL;
return temp;
}
// To find the node with the value x and remove it from the tree and return its link
QUEUE q(100);
q.put(temp);
while (!q.empty()) {
temp = q.get();
if (temp->l != NULL) {
if (temp->l->item == x) {
link returnLink = temp->l;
temp->l = NULL;
return returnLink;
}
q.put(temp->l);
}
if (temp->r != NULL) {
if (temp->r->item == x) {
link returnLink = temp->r;
temp->r = NULL;
return returnLink;
}
q.put(temp->r);
}
}
return 0;
}

Priority Queue that utilizes BST -- DeleteLargest doesn't work

I am creating a priority queue that utilizes a binary search tree for my Data Structures class. But when I attempt to output the queue I always get 0. I have looked over my DeleteLargest and Dequeue member function but I can't find the mistake
Test.cpp
#include <iostream>
#include "CTree.h"
#include "PriorityQueueBST.h"
using namespace std;
int main()
{
int num, input, output;
cout << "Enter number of elements: ";
cin >> num;
PriorityQueueBST p;
for (int x = 0; x < num; x++)
{
cout << "Enter number " << x + 1
<< " of " << num << ": ";
cin >> input;
p.Enqueue(input);
}
for (int y = 0; y < num; y++)
{
cout << "Outputting number " << y + 1
<< " of " << num << ": ";
if(p.IsEmpty())
{
break; //we are done (this is an error!)
}
output = p.Dequeue();
cout << output << endl;
}
system("pause");
return 0;
//CTree* tr = new CTree();
//
//for (int i = 0; i < 3; i++)
// tr->Add();
//tr->View();
//system("pause");
//return 0;
}
BST Declaration file
//#ifndef CTREE_H
//#define CTREE_H
//using namespace std;
struct TreeNode
{
int info;
TreeNode* leftLink;
TreeNode* rightLink;
};
class CTree
{
private:
void AddItem( TreeNode*&, TreeNode*);
void DisplayTree(TreeNode*);
void Retrieve(TreeNode*&, TreeNode*,bool&);
void Destroy(TreeNode*&);
public:
CTree();
~CTree();
void Add();
void View();
bool IsEmpty();
int DeleteLargest(TreeNode*&);
TreeNode *tree;
};
//#endif
BST Implementation file
#include <iostream>
#include <string>
using namespace std;
#include "CTree.h"
CTree::CTree()
{
tree = NULL;
}
CTree::~CTree()
{
Destroy(tree);
}
void CTree::Destroy(TreeNode*& tree)
{
if (tree != NULL)
{
Destroy(tree->leftLink);
Destroy(tree->rightLink);
delete tree;
}
}
bool CTree::IsEmpty()
{
if(tree == NULL)
{
return true;
}
else
{
return false;
}
}
void CTree::Add()
{
TreeNode* newPerson = new TreeNode();
/*cout << "Enter the person's name: ";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cin.getline(newPerson->name, 20);*/
/* cout << "Enter the person's contribution: ";
cin >> newPerson->info;*/
/*bool found = false;*/
newPerson->leftLink = NULL;
newPerson->rightLink = NULL;
/*Retrieve(tree, newPerson, found);
if (found)
cout << "info allready entered\n";
else*/
AddItem(tree, newPerson);
}
void CTree::View()
{
if (IsEmpty())
{
cout<<"The list is empy";
}
else
{
DisplayTree(tree);
}
};
void CTree::AddItem( TreeNode*& ptr, TreeNode* newPer )
{
if (ptr == NULL)
{
ptr = newPer;
}
else if ( newPer->info < ptr->info)
AddItem(ptr->leftLink, newPer);
else
AddItem(ptr->rightLink, newPer);
}
void CTree::DisplayTree(TreeNode* ptr)
{
if (ptr == NULL)
return;
DisplayTree(ptr->rightLink);
cout << ptr->info << endl; //cout<<ptr->name<<" "<<"$"<<ptr->info <<endl;
DisplayTree(ptr->leftLink);
}
void CTree::Retrieve(TreeNode*& ptr, TreeNode* newPer, bool& found)
{
{
if (ptr == NULL)
{
found = false; // item is not found.
}
else if ( newPer->info < ptr->info)
{
Retrieve(ptr->leftLink, newPer, found);
}
// Search left subtree.
else if (newPer->info > ptr->info)
{
Retrieve(ptr->rightLink, newPer, found);// Search right subtree.
}
else
{
//newPer.info = ptr->info; // item is found.
found = true;
}
}
}
int CTree::DeleteLargest(TreeNode*& tr)
{
int largest = 0;;
TreeNode* prev;
TreeNode* cur;
prev = NULL;
cur = tr;
if (tr == NULL)
{
cout << "The tree is empty"<<endl;
}
else if (tr->rightLink == NULL)
{
largest = tr->info;
}
else
{
prev = tr;
tr = tr->rightLink;
DeleteLargest(tr);
}
return largest;
}
Priority Queue Declaration
//#include <iostream>
//using namespace std;
//#include "SortedLinkedList.h"
#ifndef PRIORITYQUEUESLL__H
#define PRIORITYQUEUESLL__H
class PriorityQueueBST
{
public:
PriorityQueueBST();
~PriorityQueueBST();
void Enqueue(int);
int Dequeue();
bool IsEmpty();
private:
CTree* ourTree;
//sslNode* head;
};
#endif
Priority Queue Implementation
#include <iostream>
using namespace std;
#include "CTree.h"
#include "PriorityQueueBST.h"
PriorityQueueBST::PriorityQueueBST()
{
ourTree = new CTree();
//head = NULL;
}
PriorityQueueBST::~PriorityQueueBST()
{
}
void PriorityQueueBST::Enqueue(int dataToEnter)
{
ourTree->Add();
}
int PriorityQueueBST::Dequeue()
{
//check for empty??
return ourTree->DeleteLargest(ourTree->tree);
}
bool PriorityQueueBST::IsEmpty()
{
return ourTree->IsEmpty();
}
Your output is always 0 because in
int CTree::DeleteLargest(TreeNode*& tr)
{
int largest = 0;;
TreeNode* prev;
TreeNode* cur;
prev = NULL;
cur = tr;
if (tr == NULL)
{
cout << "The tree is empty"<<endl;
}
else if (tr->rightLink == NULL)
{
largest = tr->info;
}
else
{
prev = tr;
tr = tr->rightLink;
DeleteLargest(tr);
}
return largest;
}
you only set largest to something potentially != 0 if tr->rightlink is NULL. Otherwise you recur and set the largest variable local to another invocation of the function. That change is lost when the recursion goes up again, and in the topmost invocation, largest is still 0.
In the last line of the else branch, you should either
largest = DeleteLargest(tr);
or
return DeleteLargest(tr);
Another problem is that, despite its name, deleteLargest doesn't actually delete anything, so with the above, you would still always get the same value.

Priority Queue using Binary Search Tree not producing correct output

I implemented a Priority Queue using a BST. Its output is not correct.
Output:
Enter number of elements: 9
Enter number 1 of 9: 8
Enter number 2 of 9: 10
Enter number 3 of 9: 14
Enter number 4 of 9: 13
Enter number 5 of 9: 3
Enter number 6 of 9: 6
Enter number 7 of 9: 7
Enter number 8 of 9: 4
Enter number 9 of 9: 1
Outputting number 1 of 9: 14
Outputting number 2 of 9: 13
Outputting number 3 of 9: 10
Outputting number 4 of 9: 3
Outputting number 5 of 9: 3
Outputting number 6 of 9: 3
Outputting number 7 of 9: 3
Outputting number 8 of 9: 3
Outputting number 9 of 9: 3
Press any key to continue . . .
Test.cpp
//Arkadiy Vasilkovskiy 832a1
#include <iostream>
#include "CTree.h"
#include "PriorityQueueBST.h"
using namespace std;
int main()
{
int num, input, output;
cout << "Enter number of elements: ";
cin >> num;
PriorityQueueBST p;
for (int x = 0; x < num; x++)
{
cout << "Enter number " << x + 1
<< " of " << num << ": ";
cin >> input;
p.Enqueue(input);
}
for (int y = 0; y < num; y++)
{
cout << "Outputting number " << y + 1
<< " of " << num << ": ";
if(p.IsEmpty())
{
break; //we are done (this is an error!)
}
output = p.Dequeue();
cout << output << endl;
}
system("pause");
return 0;
//CTree* tr = new CTree();
//
//for (int i = 0; i < 3; i++)
// tr->Add();
//tr->View();
//system("pause");
//return 0;
}
BST Declaration File
struct TreeNode
{
int info;
TreeNode* leftLink;
TreeNode* rightLink;
};
class CTree
{
public:
CTree();
~CTree();
void Add(int);
void View();
bool IsEmpty();
int popLargest(TreeNode*);
TreeNode *tree;
private:
void AddItem( TreeNode*&, TreeNode*);
void DisplayTree(TreeNode*);
void Retrieve(TreeNode*&, TreeNode*,bool&);
void Destroy(TreeNode*&);
};
BST Implementation FIle
#include <iostream>
#include <string>
using namespace std;
#include "CTree.h"
CTree::CTree()
{
tree = NULL;
}
CTree::~CTree()
{
Destroy(tree);
}
void CTree::Destroy(TreeNode*& tree)
{
if (tree != NULL)
{
Destroy(tree->leftLink);
Destroy(tree->rightLink);
delete tree;
}
}
bool CTree::IsEmpty()
{
if(tree == NULL)
{
return true;
}
else
{
return false;
}
}
void CTree::Add(int dataToEnter)
{
TreeNode* newPerson = new TreeNode();
/*cout << "Enter the person's name: ";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cin.getline(newPerson->name, 20);*/
//cout << "Enter the person's contribution: ";
//cin >> newPerson->info;
/*bool found = false;*/
newPerson->info = dataToEnter;
newPerson->leftLink = NULL;
newPerson->rightLink = NULL;
/*Retrieve(tree, newPerson, found);
if (found)
cout << "info allready entered\n";
else*/
AddItem(tree, newPerson);
}
void CTree::View()
{
if (IsEmpty())
{
cout<<"The list is empy";
}
else
{
DisplayTree(tree);
}
};
void CTree::AddItem( TreeNode*& ptr, TreeNode* newPer )
{
if (ptr == NULL)
{
ptr = newPer;
}
else if ( newPer->info < ptr->info)
AddItem(ptr->leftLink, newPer);
else
AddItem(ptr->rightLink, newPer);
}
void CTree::DisplayTree(TreeNode* ptr)
{
if (ptr == NULL)
return;
DisplayTree(ptr->rightLink);
cout << ptr->info << endl; //cout<<ptr->name<<" "<<"$"<<ptr->info <<endl;
DisplayTree(ptr->leftLink);
}
void CTree::Retrieve(TreeNode*& ptr, TreeNode* newPer, bool& found)
{
{
if (ptr == NULL)
{
found = false; // item is not found.
}
else if ( newPer->info < ptr->info)
{
Retrieve(ptr->leftLink, newPer, found);
}
// Search left subtree.
else if (newPer->info > ptr->info)
{
Retrieve(ptr->rightLink, newPer, found);// Search right subtree.
}
else
{
//newPer.info = ptr->info; // item is found.
found = true;
}
}
}
int CTree::popLargest(TreeNode* tr)
{
//Failed Attempt at returning one value at a time and deleting that node
int largest; // = tr->info;
TreeNode* prev = NULL;
TreeNode* cur = tr;
if(tr != NULL)
largest = tr->info;
while (cur->rightLink != NULL)
{
prev = cur;
cur = cur->rightLink;
largest = cur->info;
//DeleteAttemptTwo(tr, largest);//DeleteItem(largest);
}
/*if (prev != NULL)
{
prev->rightLink = cur->leftLink;
}*/
if(prev != NULL)
{
if (cur->leftLink != NULL)
{
prev->rightLink = cur->leftLink;
}
else
{
prev->rightLink = NULL;
}
}
else if (cur->leftLink != NULL)
{
largest = cur->leftLink->info;
}
return largest;
}
Priority Queue Declaration File
#ifndef PRIORITYQUEUESLL__H
#define PRIORITYQUEUESLL__H
class PriorityQueueBST
{
public:
PriorityQueueBST();
~PriorityQueueBST();
void Enqueue(int);
int Dequeue();
bool IsEmpty();
private:
CTree* ourTree;
};
#endif
Priority Queue Implementation File
#include <iostream>
using namespace std;
#include "CTree.h"
#include "PriorityQueueBST.h"
PriorityQueueBST::PriorityQueueBST()
{
ourTree = new CTree();
//head = NULL;
}
PriorityQueueBST::~PriorityQueueBST()
{
}
void PriorityQueueBST::Enqueue(int dataToEnter)
{
ourTree->Add(dataToEnter);
}
int PriorityQueueBST::Dequeue()
{
int largest = ourTree->popLargest(ourTree->tree);
return largest;
}
bool PriorityQueueBST::IsEmpty()
{
return ourTree->IsEmpty();
}
I ran your code and looked at what was happening in the debugger. As it turns out your tree is being corrupted when you pop the numbers out of it. I didn't look into exactly how it was happening but basically. Before the first few calls to pop largest your tree looked like:
8
3 10
1 6 14
4 7 13
And after you pop 14, 13, 10 it became:
8
3
1 6
4 7
Now if I understood your code correctly the error in logic is here:
if(prev != NULL)
{
if (cur->leftLink != NULL)
{
prev->rightLink = cur->leftLink;
}
else
{
prev->rightLink = NULL;
}
}
else if (cur->leftLink != NULL)
{
largest = cur->leftLink->info;
}
Now if you notice in the case that the highest number is the root of the tree (meaning prev == NULL), in this case 8, you return the wrong value. You say the highest value is the left link but it isn't it's the root node's value. Wost, you never take it out of the tree, so you're stuck giving the same answer all the time.