C++ Function returns wrong return value? - c++

I made a simple command line application based on Kaiji Ep. 16 that mimics the game Emperor Card (for our midterms in basic programming). I got stuck on what I think is a simple problem, but I can't seem to solve it on my own. I have this function "winChecker(List *root, Node *head)," that checks what cards are drawn and who wins over who.
And it seems that it returns a wrong return value whenever I draw Citizen and the opponent draws Citizen as well. It should just loop, since Citizen vs Citizen is draw, according to my code.
Can you help me understand what I'm doing wrong here. Also if you see some other mistakes, feel free to point them out. I'm open to learn.
PS: I only used struct for Node and List since we aren't allowed to use Class for our midterms yet. I got 1 header file for each of those.
Source.cpp
#include "Node.h"
#include "List.h"
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
Node *createKaijiDeck(int round);
Node *selectKaijiCard(Node *head, int index);
Node *deleteSelectedKaijiCard(Node *head, int index);
List* createTonegawaDeck(int round);
List *selectTonegawaCard(List *root, int indexT);
List *deleteSelectedTonegawaCard(List *root, int indexT);
bool betCheck(int betLength, int remainingLength);
int prizeCheck(int betLength, int round);
void printDeck(Node * head);
int winCheck(List *root, Node *head, int cardIndex, int randTonegawa);
void gameOver(int cash, int round, int input, int remaining);
int main() {
// Seed the RNG
srand((unsigned int)time(0));
// Initilizing variables
int input, cardIndex, randTonegawa, countTonegawa = 0, cash = 0, remaining = 30;
// Round loop
for (int round = 1; round < 12; round++) {
cout << "===============================================" << endl;
cout << " ROUND " << round << endl;
cout << "===============================================" << endl;
cout << "How much would you like to bet, in milimeters?" << endl;
cout << "(You still have " << remaining << " milimeters left.)" << endl;
cin >> input;
betCheck(input, remaining);
// Match loop
if (betCheck(input, remaining) == true) {
cout << "You can win " << prizeCheck(input, round) << " Yen." << endl << endl;
cout << "Cash currently at hand: " << cash << endl;
Node* head = createKaijiDeck(round);
List* root = createTonegawaDeck(round);
do {
printDeck(head);
cout << "Select a card to play [1 - 5]: ";
cin >> cardIndex;
randTonegawa = (rand() % (5 - countTonegawa));
Node* selectKaijiCardAtIndex = selectKaijiCard(head, cardIndex);
cout << "You chose the card: " << selectKaijiCardAtIndex->cards << endl;
List* selectTonegawaCardAtIndex = selectTonegawaCard(root, randTonegawa);
cout << "Tonegawa chose the card: " << selectTonegawaCardAtIndex->card << endl;
cout << endl;
countTonegawa++;
} while (winCheck(root, head, cardIndex, randTonegawa) == 0);
// Match up checker (Emperor > Citizen > Slave > Emperor)
if (winCheck(root, head, cardIndex, randTonegawa) == 1) {
cash = cash + prizeCheck(input, round);
cout << "Round " << round << " winner is Kaiji." << endl;
cout << "You won " << prizeCheck(input, round) << " Yen!" << endl;
}
else if (winCheck(root, head, cardIndex, randTonegawa) == 2) {
remaining = remaining - input;
cout << "Round " << round << " winner is Tonegawa." << endl;
cout << "The pin moved by " << input << " milimeters!" << endl;
}
}
else if (betCheck(input, remaining) == false)
{
cout << "You lose! You already lost your ear!" << endl;
system("pause");
exit(0);
}
}
return 0;
}
Node *createKaijiDeck(int round) {
Node* head = NULL;
Node* curr = NULL;
Node* prev = NULL;
if (round == 1 || round == 2 || round == 3 || round == 7 || round == 8 || round == 9) {
curr = new Node;
curr->cards = "Emperor";
prev = curr;
head = curr;
for (int i = 0; i < 3; i++) {
curr = new Node;
curr->cards = "Citizen";
prev->next = curr;
prev = curr;
}
curr = new Node;
curr->cards = "Citizen";
prev->next = curr;
}
if (round == 4 || round == 5 || round == 6 || round == 10 || round == 11 || round == 12) {
curr = new Node;
curr->cards = "Slave";
prev = curr;
head = curr;
for (int i = 0; i < 3; i++) {
curr = new Node;
curr->cards = "Citizen";
prev->next = curr;
prev = curr;
}
curr = new Node;
curr->cards = "Citizen";
prev->next = curr;
}
return head;
}
Node *selectKaijiCard(Node *head, int indexK) {
for (int i = 0; i < indexK - 1; i++) {
head = head->next;
}
return head;
}
Node *deleteSelectedKaijiCard(Node *head, int indexK) {
Node *curr = NULL;
if (indexK == 1)
{
curr = head;
head = head->next;
delete curr;
return head;
}
Node *deleteCard = head;
for (int i = 0; i < indexK - 1; i++) {
curr = deleteCard;
deleteCard = deleteCard->next;
}
curr->next = deleteCard->next;
delete deleteCard;
return head;
}
List *createTonegawaDeck(int round) {
List *root = NULL;
List *front = NULL;
List *tail = NULL;
if (round == 1 || round == 2 || round == 3 || round == 7 || round == 8 || round == 9) {
front = new List;
front->card = "Slave";
tail = front;
root = front;
for (int i = 0; i < 3; i++) {
front = new List;
front->card = "Citizen";
tail->next = front;
tail = front;
}
front = new List;
front->card = "Citizen";
tail->next = front;
}
if (round == 4 || round == 5 || round == 6 || round == 10 || round == 11 || round == 12) {
front = new List;
front->card = "Emperor";
tail = front;
root = front;
for (int i = 0; i < 3; i++) {
front = new List;
front->card = "Citizen";
tail->next = front;
tail = front;
}
front = new List;
front->card = "Citizen";
tail->next = front;
front->next = root;
}
return root;
}
List *selectTonegawaCard(List *root, int indexT) {
for (int i = 0; i < indexT; i++) {
root = root->next;
}
return root;
}
List *deleteSelectedTonegawaCard(List *root, int indexT) {
List *front = NULL;
if (indexT == 0)
{
front = root;
root = root->next;
delete front;
return root;
}
List *deleteTonegawaCard = root;
for (int i = 0; i < indexT; i++) {
front = deleteTonegawaCard;
deleteTonegawaCard = deleteTonegawaCard->next;
}
front->next = deleteTonegawaCard->next;
delete deleteTonegawaCard;
return root;
}
bool betCheck(int betLength, int remainingLength) {
bool flag;
if (betLength <= remainingLength) {
flag = true;
}
else if (betLength > remainingLength) {
flag = false;
}
return flag;
}
int prizeCheck(int betLength, int round) {
int yen;
if (round == 1 || round == 2 || round == 3 || round == 7 || round == 8 || round == 9) {
yen = betLength * 100000;
}
if (round == 4 || round == 5 || round == 6 || round == 10 || round == 11 || round == 12) {
yen = betLength * 500000;
}
return yen;
}
void printDeck(Node * head) {
int count = 1;
cout << "===============" << endl;
cout << "Kaiji's cards" << endl;
cout << "===============" << endl << endl;
while (head != NULL) {
cout << count << ". " << head->cards << endl;
head = head->next;
count++;
}
cout << endl;
}
int winCheck(List *root, Node *head, int cardIndex, int randTonegawa) {
int result = 0;
if ((head->cards == "Citizen") && (root->card == "Citizen")) {
result = 0;
}
else if ((head->cards == "Emperor") && (root->card == "Citizen") || (head->cards == "Slave") && (root->card == "Emeperor") || (head->cards == "Citizen") && (root->card == "Slave")) {
result = 1;
}
else if ((root->card == "Emperor") && (head->cards == "Citizen") || root->card == "Slave" && head->cards == "Emperor" || root->card == "Citizen" && head->cards == "Slave") {
result = 2;
}
head = deleteSelectedKaijiCard(head, cardIndex);
root = deleteSelectedTonegawaCard(root, randTonegawa);
return result;
}
void gameOver(int cash, int round, int input, int remaining) {
if (round <= 12 && cash == 20000000 && betCheck(input, remaining) == true) {
cout << "You did not entirely win! You only got " << cash << " Yen in 12 rounds!" << endl;
system("pause");
exit(0);
}
else if (round == 12 && cash < 20000000 && betCheck(input, remaining) == false) {
cout << "You won! You got" << cash << " Yen at Round " << round << endl;
}
}
List.h
#pragma once
#include <string>
using namespace std;
struct List {
string card;
List* next = NULL;
};
Node.h
#pragma once
#include <string>
using namespace std;
struct Node {
string cards;
Node* next = NULL;
Node* prev = NULL;
};

It looks like when you select a card to play, you then delete that card from the deck, then compare the first card of the two decks. That doesn't seem right, surely you want to compare the cards you just selected?
If so, you should be calling winCheck with selectKaijiCardAtIndex and selectTonegawaCardAtIndex. You also want to do this before you delete the cards from the deck as the deleteSelectedKaijiCard function actually deletes the card so you can't use it after that.
This probably mean rearranging your code a bit and not call wincheck in so many places.

Related

Doubly linked list not printing values properly

When I call the methods to print the data stored in the nodes of my doubly linked list, nothing prints except for empty strings and 0's
#include <iostream>
#include <string>
using namespace std;
struct node {
int weight;
string name;
node *nextname, *nextweight;
};
node *namehead = NULL, *weighthead = NULL;
bool isEmpty()
{
if (namehead == NULL && weighthead == NULL)
return true;
else
return false;
}
void addperson(int w, string n)
{
node* newNode = new node;
node *prev, *curr = newNode;
if (isEmpty()) {
namehead = newNode;
weighthead = newNode;
}
else {
curr = prev = namehead;
if (curr->name > n) {
namehead = newNode;
newNode->nextname = curr;
}
else {
do {
if (curr->name <= n) {
prev = curr;
curr = curr->nextname;
}
else
break;
} while (curr != NULL);
prev->nextname = newNode;
newNode->nextname = curr;
}
curr = prev = weighthead;
if (curr->weight > w) {
weighthead = newNode;
newNode->nextweight = curr;
}
else {
do {
if (curr->weight <= w) {
prev = curr;
curr = curr->nextweight;
}
else
break;
} while (curr != NULL);
prev->nextweight = newNode;
newNode->nextweight = curr;
}
}
}
void printname()
{
node* curr = namehead;
do {
cout << curr->name << " - " << curr->weight << endl;
curr = curr->nextname;
} while (curr != NULL);
cout << endl;
}
void printweight()
{
node* curr = weighthead;
do {
cout << curr->name << " - " << curr->weight << endl;
curr = curr->nextweight;
} while (curr != NULL);
cout << endl;
}
int main()
{
int w = 0;
string n;
for (int i = 0; i < 15; i++) {
cout << "Enter weight: ";
cin >> w;
if (w == -1)
break;
cout << "Enter name: ";
cin >> n;
addperson(w, n);
}
printname();
printweight();
return 0;
}
Expected output (By name):
John - 220
Steven - 190
Tyler - 150
Expected output (By weight):
Tyler - 150
Steven - 190
John - 220
CURRENT OUTPUT(Both ways):
" " - 0
" " - 0
" " - 0
EDIT
By taking the suggestions in the comments about actually assigning the values w (weight) and n (name) to the temporary node in the add method, the problem has been fixed. Thank you for the help.
curr->weight=w;
curr->name=n;
Assign passed values into weight and name members into placeholder node in the add method:
curr->weight=w;
curr->name=n;

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?

Sorting Names in Linked List

(This is a Homework Question)I am having trouble implementing a name sort for a linked list. I have the weight(int) sort working now i just want to sort names in ascending order.
#include<stdio.h>
#include<conio.h>
#include<iostream>
using namespace std;
int c = 0;
struct node
{
char name[20];
int weight;
node *next;
node *prev;
};
node*head = NULL;
node *tail = NULL;
node *start_ptr = NULL;
Here I create the node and insert into the list in sorted position. I want to do the same for names. A name is assigned a weight(For example a persons weight). It has to be in sorted position so when the print function is called it prints the list in sorted order.
void create(int x,char name)
{
node*p = NULL;
node*r = NULL;
node*np = NULL;
np = new node;
np->weight = x;
np->next = NULL;
np->prev = NULL;
if (c == 0)
{
tail = np;
head = np;
p = head;
p->next = NULL;
p->prev = NULL;
c++;
}
else
{
p = head;
r = p;
if (np->weight < p->weight)
{
np->next = p;
p->prev = np;
np->prev = NULL;
head = np;
p = head;
do
{
p = p->next;
} while (p->next != NULL);
tail = p;
}
else if (np->weight > p->weight)
{
while (p != NULL && np->weight > p->weight)
{
r = p;
p = p->next;
if (p == NULL)
{
r->next = np;
np->prev = r;
np->next = NULL;
tail = np;
break;
}
else if (np->weight < p->weight)
{
r->next = np;
np->prev = r;
np->next = p;
p->prev = np;
if (p->next != NULL)
{
do
{
p = p->next;
} while (p->next != NULL);
}
tail = p;
break;
}
}
}
}
}
void traverse_head()
{
node *t = head;
while (t != NULL)
{
cout << t->weight << "\t";
t = t->next;
}
cout << endl;
}
void print_node()
{
node *temp;
temp = start_ptr;
if (temp == NULL) cout << "Empty List!" << endl;
while (temp != NULL)
{
if (temp == NULL) cout << "Empty List!" << endl;
cout << "Names & weights sorted(ascending) by name. :\n";
cout << "Name : " << temp->name << endl;
cout << "Weight : " << temp->weight << endl;
cout << "Names & weights sorted(ascending) by weight. : \n";
cout << endl;
temp = temp->next;
}
}
int main()
{
int i = 0, n, x;
char names[20];
cout << "Enter the number of people: \n";
cin >> n;
A loop that reads in the weight and the name of that person
while (i < n)
{
cout << "\nEnter Weights: \n";
cin >> x;
cout<<"Enter a Name"<<endl;
cin>>names;
create(x,*names);
i++;
}
cout << "Output: \n";
traverse_head();
system("pause");
return 0;
}

Bidirectional list

The following code calculates the sum of the elements of the unidirectional list items greater than 3 and smaller than 8 and the result of the sum is changed the beginning of the list.
#include <iostream>
using namespace std;
struct List
{
int num;
List* nItem;
};
int Input()
{
int number;
cout << "Enter the number: "; cin >> number;
return number;
}
void MakeList(List **head, int n)
{
if (n > 0) {
*head = new List;
(*head)->num = Input();
(*head)->nItem = NULL;
MakeList(&(*head)->nItem, n - 1);
}
}
void Print(List* head)
{
if (head != NULL) {
cout << head->num << " ";
Print(head->nItem);
}
}
List* Add_start(List* head, int index, int elm)
{
List* p = new List;
p->num = elm;
p->nItem = NULL;
if (head == NULL) {
head = p;
}
else {
List* current = head;
for (int i = 0; (i < index - 1) && (current->nItem != NULL); i++)
{
current = current->nItem;
}
if (index == 0)
{
p->nItem = head;
head = p;
}
else {
if (current->nItem != NULL) {
p->nItem = current->nItem;
}
current->nItem = p;
}
}
return head;
}
int Sum(List* head)
{
int sum = 0;
List* p = head;
while(p) {
if ((p->num > 3) && (p->num < 8))
sum += p->num;
p = p->nItem;
}
return sum;
}
void DeleteList(List* head)
{
if (head != NULL) {
DeleteList(head->nItem);
delete head;
}
}
int main()
{
int n = 10;
List* head = NULL;
cout << "Enter 10 number to the list\n" << endl;
MakeList(&head, n);
int sum = Sum(head);
head = Add_start(head, 0, sum);
cout << "\nList: ";
Print(head);
cout << endl;
DeleteList(head);
system("pause");
return 0;
}
How can I do the same operation with a bidirectional list?
Notes:
A bidirectional (or double linked) list, also has a member pointing to the previous node: this is the whole difference between the 2 list types (as a consequence the first element - or the one at the left of the list, will have this member pointing to NULL). So, when such a node is created/inserted into a list, this new member should be set as well (I commented in the code places where this happens), for the new node and for the one following it (if any).
I modified the way of how a list is created - MakeList replaced by _MakeList2 + MakeList2; the underscore(_) in _MakeList2 specifies that it's somehow private (convention borrowed from Python) - it's not very nice, but I thought it's easier this way
I don't have Visual Studio on this computer, so I used gcc. It complained about system function so I had to add #include <stdlib.h>
I renamed some of the identifiers (List -> Node, Add_start -> AddNode, nItem -> nNode) either because the new names make more sense, or their names are consistent
I tried to keep the changes to a minimum (so the solution is as close as possible to your original post)
I enhanced (by adding an additional argument: toRight (default value: 1)) the Print func, so it can iterate the list both ways - I am iterating right to left (for testing purposes) before deleting the list
I corrected some (minor) coding style issues
Here's the modified code:
#include <iostream>
#include <stdlib.h>
using namespace std;
struct Node {
int num;
Node *pNode, *nNode; // Add a new pointer to the previous node.
};
int Input() {
int number;
cout << "Enter the number: "; cin >> number;
return number;
}
Node *_MakeList2(int n, Node *last=NULL) {
if (n > 0) {
Node *node = new Node;
node->num = Input();
node->pNode = last;
node->nNode = _MakeList2(n - 1, node);
return node;
}
return NULL;
}
Node *MakeList2(int n) {
return _MakeList2(n);
}
void Print(Node *head, int toRight=1) {
if (head != NULL) {
cout << head->num << " ";
if (toRight)
Print(head->nNode, 1);
else
Print(head->pNode, 0);
}
}
Node* AddNode(Node *head, int index, int elm) {
Node *p = new Node;
p->num = elm;
p->pNode = NULL; // Make the link between this node and the previous one.
p->nNode = NULL;
if (head == NULL) {
head = p;
} else {
Node *current = head;
for (int i = 0; (i < index - 1) && (current->nNode != NULL); i++) {
current = current->nNode;
}
if (index == 0) {
p->nNode = head;
head->pNode = p; // Make link between next node's previous node and the current one.
head = p;
} else {
if (current->nNode != NULL) {
p->nNode = current->nNode;
}
p->pNode = current; // Make the link between this node and the previous one.
current->nNode = p;
}
}
return head;
}
int Sum(Node* head) {
int sum = 0;
Node *p = head;
while(p) {
if ((p->num > 3) && (p->num < 8))
sum += p->num;
p = p->nNode;
}
return sum;
}
void DeleteList(Node *head) {
if (head != NULL) {
DeleteList(head->nNode);
delete head;
}
}
int main() {
int n = 10;
Node *head = NULL, *tail = NULL;
cout << "Enter " << n << " number(s) to the list" << endl << endl;
head = MakeList2(n);
int sum = Sum(head);
head = AddNode(head, 0, sum);
cout << endl << "List: ";
Print(head);
cout << endl;
tail = head;
if (tail) {
while (tail->nNode != NULL)
tail = tail->nNode;
cout << endl << "List reversed: ";
Print(tail, 0);
cout << endl;
}
DeleteList(head);
system("pause");
return 0;
}

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;
}