I had found this implementation in [github][1], i made some changes like adding a 2nd value to the node, and using each left and right node as a pointer Node the problem with the tree it is and whenever inserting nodes then searching in the nodes in the tree it only iterates through the tree from first to last pointers when using TMapFind which calls the function pointer TMapNodeComparison_F to compare pointers. I wonder what could be causing this bug I suspect it's something in the logic of TMapInsertNode checking if a node is black/red?
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#define ASSERT_NOT_NULL(x) if(x)
#define ASSERT_NULL(x) if(x ==NULL)
#define ASSERT_NULL_(x,y) if(x== NULL && y==NULL)
typedef struct CByte
{
unsigned char* value;
size_t index;
size_t length;
}BYTES;
//struct Data;
struct Node;
struct TMap;
struct Node
{
CByte* value;
size_t index;
struct Node* Left;
struct Node* Right;
struct Node* Parent;
bool color;
};
typedef int (*TMapNodeComparison_F) (struct TMap* map, struct Node* a, struct Node* b);
typedef void (*TMapNode_F) (struct TMap* map, struct Node* node);
struct TMap
{
struct Node* root;
size_t TSize;
TMapNodeComparison_F compareNodeFunction;
};
struct Node* TMapNodeAlloc()
{
return (Node*)malloc(sizeof(Node));
}
struct Node* TMapNodeCalloc()
{
return (Node*)calloc(1,sizeof(Node));
}
struct Node* TMapInitializationNodeTree(struct Node* node,struct CByte* _data)
{
ASSERT_NOT_NULL (node)
{
node->value = _data;
std::string s = reinterpret_cast<char const*>(_data->value);
std::cout << s << std::endl;
node->color = 1;//Initialize as Black
node->Left = node->Right = NULL;
node->index = _data->index;
}
return node;
}
struct Node* TMapInitializationCreateNode(CByte* _data)
{
return TMapInitializationNodeTree(TMapNodeAlloc(), _data);
}
void TMapNodeDeAlloc(struct Node* node)
{
ASSERT_NOT_NULL(node)
free(node);
}
int AreNodesRed(struct Node* nodeA, struct Node* nodeB)
{
return (nodeA && nodeB) ? !nodeA->color && !nodeB->color : 0;
}
static bool TMapIsNodeBlack (struct Node* node)
{
return node ? node->color == 1 : false;
}
static bool TMapIsNodeRed(struct Node* node)
{
return node ? !node->color : false;
}
static bool TMapAreNodesBlack(struct Node* nodeA,struct Node* nodeB)
{
return nodeA && nodeB ? nodeA->color == 1 && nodeB->color ==1 : false;
}
static struct Node* TMapNodeRotateL(struct TMap* map,struct Node* node , int side)
{
struct Node* blackNode = NULL;
ASSERT_NOT_NULL (node)
{
blackNode = !side == 0 ? node->Left : node->Right;
/* blackNode->Left = blackNode->Right = (Node*)calloc(1, sizeof(Node));*/
!side == 0 ? node->Left : node->Right = side == 0 ? blackNode->Left : blackNode->Right;
node->color = 0; //Red
blackNode->color = 1;//Black
side == 0 ? blackNode->Left : blackNode->Right = node;
node->Parent = blackNode;
}
return blackNode;
}
static struct Node* TMapNodeRotateR(TMap* map,struct Node* node,int side)
{
struct Node* rightNode = NULL;
ASSERT_NULL(node)
{
!side ==0 ? node->Left :node->Right = TMapNodeRotateL(map,!side == 0 ? node->Left : node->Right,!side);
rightNode = TMapNodeRotateL(map,node,side);
}
return rightNode;
}
int TMapNodeComparison(struct TMap* map, struct Node* a, struct Node* b)
{
return (a->value > b->value) - (a->value < b->value);
}
void TMapNodeDealloc(struct TMap* map, struct Node* node)
{
ASSERT_NOT_NULL (map)
{
ASSERT_NOT_NULL (node)
{
TMapNodeDeAlloc(node);
}
}
}
struct TMap* TMapAlloc()
{
return (TMap*)malloc(sizeof(TMap));
}
struct TMap* TMapInitialize(struct TMap* map, TMapNodeComparison_F node_cmp_cb)
{
ASSERT_NOT_NULL (map)
{
map->root = NULL;
map->TSize = 0;
map->compareNodeFunction = node_cmp_cb ? node_cmp_cb : TMapNodeComparison;
}
return map;
}
struct TMap* TMapCreate(TMapNodeComparison_F node_cb)
{
return TMapInitialize(TMapAlloc(), node_cb);
}
void TMapDealloc(struct TMap* map, TMapNode_F node_cb)
{
ASSERT_NOT_NULL(map)
{
ASSERT_NOT_NULL(node_cb)
{
struct Node* node = map->root;
struct Node* save = NULL;
while (node)
{
ASSERT_NULL (node->Left)
{
save = node->Right;
node_cb(map, node);
node = NULL;
}
else
{
save = node->Left;
node->Left = save->Right;
save->Right = node;
}
node = save;
}
}
free(map);
}
}
int
rb_tree_test(struct TMap* map, struct Node* root)
{
int lh, rh;
if (root == NULL)
return 1;
else
{
struct Node* ln = root->Left;
struct Node* rn = root->Right;
/* Consecutive red links */
if (TMapIsNodeRed(root))
{
if (AreNodesRed(ln,rn))
{
printf("Red violation");
return 0;
}
}
lh = rb_tree_test(map, ln);
rh = rb_tree_test(map, rn);
/* Invalid binary search tree */
if
((ln != NULL && map->compareNodeFunction(map, ln, root) >= 0)
|| (rn != NULL && map->compareNodeFunction(map, rn, root) <= 0))
{
puts("Binary tree violation");
return 0;
}
/* Black height mismatch */
if (lh != 0 && rh != 0 && lh != rh)
{
puts("Black violation");
return 0;
}
/* Only count black links */
if (lh != 0 && rh != 0)
return TMapIsNodeRed(root) ? lh : lh + 1;
else
return 0;
}
}
void* TMapFind(struct TMap* map, CByte* value)
{
void* result = NULL;
ASSERT_NOT_NULL (map)
{
struct Node node;
node.value = value;
struct Node* it = map->root;
int cmp = 0;
while (it)
{
if ((cmp = map->compareNodeFunction(map, it, &node)))
{
it = cmp < 0 ? it->Right : it->Left;
}
else
break;
}
result = it ? it->value : NULL;
}
return result;
}
#define CompareANullElement(nonNull,Null) ((!Null || !nonNull) ? (0) : nonNull==Null)
int TMapInsertNode(struct TMap* self, struct Node* node)
{
int result = 0;
if (self && node)
{
ASSERT_NULL (self->root)
{
self->root = node;
result = 1;
}
else
{
struct Node head = { NULL };
struct Node* g, * t;
struct Node* p, * q;
int dir = 0, last = 0;
// Set up our helpers
t = &head;
g = p = NULL;
q = t->Right = self->root;
while (1)
{
ASSERT_NULL (q)
{
// Insert node at the first null link.
p->Left = q = node;
}
else if (AreNodesRed(q->Left,q->Right))
{
q->color = 0;//red
q->Left->color = 1;// black
q->Right->color = 1;// black
}
if (AreNodesRed(q,p))
{
int dir2 = CompareANullElement(t->Right,g);
if (CompareANullElement(q,(last == 0 ? p->Left : p->Right)))
{
t->Right = TMapNodeRotateL(self,g,!last);
}
else
{
t->Left = TMapNodeRotateR(self,g,!last);
}
}
// Stop working if we inserted a node. This
// check also disallows duplicates in the tree
if (self->compareNodeFunction(self, q, node) == 0)
{
break;
}
last = dir;
dir = self->compareNodeFunction(self, q, node) < 0;
// Move the helpers down
if (g != NULL)
{
t = g;
}
g = p, p = q;
q = dir ==0 ? q->Left : q->Right;
}
// Update the root (it may be different)
self->root = head.Right;
}
// Make the root black for simplified logic
self->root->color = 1;
++self->TSize;
}
return 1;
}
int TMapInsert(struct TMap* map, CByte* value)
{
return TMapInsertNode(map, TMapInitializationCreateNode(value));
}
int TMapRemoveFrom(struct TMap* map, CByte* value, TMapNode_F node_cb)
{
ASSERT_NOT_NULL (map->root)
{
struct Node head = { 0 };
struct Node node;
node.value = value ;
struct Node* q, * p, * g;
struct Node* f = NULL;
int dir = 1;
q = &head;
g = p = NULL;
q->Right = map->root;
while ((dir == 0 ? q->Left : q->Right) != NULL)
{
int last = dir;
g = p, p = q;
q = dir == 0 ? q->Left : q->Right;
dir = map->compareNodeFunction(map, q, &node) < 0;
if (map->compareNodeFunction(map, q, &node) == 0)
{
f = q;
}
// Push the red node down with rotations and color flips
if (TMapIsNodeBlack(q) && TMapIsNodeBlack(dir == 0 ? q->Left : q->Right))
{
if (TMapIsNodeRed(!dir == 0 ? q->Left : q->Right))
{
p = last == 0 ? p->Left : p->Right = TMapNodeRotateL(map,q,dir);
}
else if (TMapIsNodeBlack(!dir == 0 ? q->Left : q->Right))
{
struct Node* s = !last == 0 ? p->Left : p->Right;
if (s)
{
if (TMapAreNodesBlack(!last == 0 ? s->Left : s->Right,last == 0 ? s->Left : s->Right))
{
// Color flip
p->color = 1;
s->color = 0;
q->color = 0;
}
else
{
int dir2 = g->Right == p;
if (TMapIsNodeRed(last == 0 ? s->Left : s->Right)) //check for red
{
dir2 == 0 ? s->Left : s->Right = TMapNodeRotateR(map,p,last);
}
else if (TMapIsNodeBlack((last != 0 ? s->Left : s->Right)))
{
dir2 == 0 ? g->Left: g->Right = TMapNodeRotateL(map,p,last);
}
// Ensure correct coloring
q->color = dir2 == 0 ? g->Left->color : g->Right->color = 0;
dir2==0 ? g->Left->Left->color : g->Right->Left->color = 1;
dir2 == 0 ? g->Left->Right->color : g->Right->Right->color = 1;
}
}
}
}
}
// Replace and remove the saved node
ASSERT_NOT_NULL (f)
{
CByte* tmp = f->value;
f->value = q->value;
q->value = tmp;
p->Right == q ? p->Right : p->Left = ((q->Left == NULL) ? q->Right: q->Left);
ASSERT_NOT_NULL (node_cb)
{
node_cb(map, q);
}
q = NULL;
}
// Update the root (it may be different)
map->root = head.Right;
// Make the root black for simplified logic
if (map->root != NULL)
{
map->root->color = 1;
}
--map->TSize;
}
return 1;
}
int TMapRemoveTree(struct TMap* map, CByte* value)
{
int result = 0;
ASSERT_NOT_NULL (map)
{
result = TMapRemoveFrom(map, value, TMapNodeDealloc);
}
return result;
}
size_t TMapGetSize(struct TMap* map)
{
size_t result = 0;
ASSERT_NOT_NULL(map)
{
result = map->TSize;
}
return result;
}
int my_cmp_cb(struct TMap* self, struct Node* node_a, struct Node* node_b)
{
BYTES* a = (BYTES*) node_a->value;
BYTES* b = (BYTES*) node_b->value;
return (a->value > b->value) - (a->value < b->value);
}
int main()
{
int t = true;
int d,c = 1;
(t ? d : c) = 2;
struct TMap* tree = TMapCreate(my_cmp_cb);
std::cout << sizeof(*tree) << std::endl;
ASSERT_NOT_NULL (tree)
{
BYTES* bytes = (BYTES*)calloc(1000,sizeof(BYTES));
std::stringstream ss;
// Use the tree here...
for (int i = 0; i < 1000; i++)
{
// Default insert, which allocates internal rb_nodes for you.
ss << i;
auto message = std::string("Hello " + ss.str());
unsigned char* val = new unsigned char[message.length() + 1];
strcpy((char*)val, message.c_str());
bytes[i].value = val;
bytes[i].index = i;
bytes[i].length = sizeof(message) / sizeof(unsigned char*);
TMapInsert(tree, &bytes[i]);
ss.str("");
ss.clear();
}
std::string str ="Hello 2";
BYTES b { (unsigned char*)str.c_str(), 2, 8 };
// To f
BYTES* f = (BYTES*)TMapFind(tree, &b);
if (f)
{
fprintf(stdout, "found BYTES(value = %s, index = %ull, length = %ull )\n", f->value,f->index,f->length);
}
else {
printf("not found\n");
}
TMapDealloc(tree, NULL);
}
}
[1]: https://github.com/mirek/rb_tree/blob/master/rb_tree.c
Related
So I'm making a binary max heap for my c++ class and I keep encountering this exception saying that I'm returning a nullptr in my class methods. I'm having trouble finding where it could be at in my code so any help would be greatly appreciated. The exception that keeps getting thrown is as follows:
Unhandled exception thrown: read access violation.
**std::_String_alloc<std::_String_base_types<char,std::allocator<char> > ::_Get_data**(...) returned nullptr. occurred
Here's my header file for the tree:
#ifndef HEAP_H
#define HEAP_H
#include <iostream>
#include "THeapNode.h"
class TreeHeap {
private:
THeapNode *root; // the top node of the heap
int next_loc; // the next valid location to place a node
void bubble_up(THeapNode *node); //performs the bubble up operation on the given node
void bubble_down(THeapNode *node); //performs the bubble down operation on the given node
void clear_heap(THeapNode *node); // removes all elements from the heap
public:
TreeHeap(); // the constructor
~TreeHeap(); // the destructor
THeapNode* find_node(const int position); // finds the node in the position given and returns a pointer to it
void insert(const string &item); // creates a node with the string given as the value and places it in the next location
bool Delete(); // removes the root of the heap and returns false if the tree is empty
};
#endif
Here's my Node's .h file:
#ifndef NODE_H
#define NODE_H
#include<string>
using std::string;
struct THeapNode {
string data; // stores a data string
THeapNode *parent; // a pointer to the parent node
THeapNode *rightChild; // a pointer to the right child node
THeapNode *leftChild; // a pointer to the left child node
THeapNode( const string &str );
};
#endif
And here's my .cpp file:
#include "stdafx.h"
#include <cmath>
#include "TreeHeap.h"
#include "THeapNode.h"
TreeHeap::TreeHeap() {
root = NULL;
next_loc = 1;
};
TreeHeap::~TreeHeap() {
THeapNode *current = root;
THeapNode *deleteNode = NULL;
int d = floor(log2(next_loc - 1));
int j = next_loc;
for ( int i = 1; i <= j-1; i++ ) {
while (1) {
int d = floor(log2(next_loc - i));
int power = std::pow(2, d - 1);
if (next_loc == 1) {
deleteNode = current;
j -= 1;
}
else if (next_loc < (std::pow(2, d - 1) * 3)) {
current = current->leftChild;
}
else {
current = current->rightChild;
}
// Update location and depth to reflect traversal
next_loc = std::pow(2, d - 1) + next_loc % power;
d = d - 1;
}
clear_heap(deleteNode);
}
}
void TreeHeap::clear_heap(THeapNode *node) {
if (node == NULL) {
return;
}
node->data = "";
node->leftChild = NULL;
node->rightChild = NULL;
node->parent = NULL;
}
void TreeHeap::insert( const string &value ) {
THeapNode newNode = THeapNode(value);
int loc = next_loc;
if (loc == 1) {
*root = newNode;
}
THeapNode *current = root;
while (1) {
int d = floor(log2(loc));
int power = std::pow(2, d - 1);
if (loc < (power * 3)) {
if (current->leftChild = nullptr) {
*current->leftChild = newNode;
newNode.parent = current;
next_loc += 1;
break;
}
else {
current = current->leftChild;
}
}
else {
if (current->rightChild = nullptr) {
*current->rightChild = newNode;
newNode.parent = current;
next_loc = +1;
break;
}
else {
current = current->rightChild;
}
}
// Update location and depth to reflect traversal
loc = std::pow(2, d - 1) + loc % power;
d = d - 1;
}
std::cout << current->data << "\n";
system("PAUSE");
}
void TreeHeap::bubble_up( THeapNode *node ) {
if (node == NULL) {
return;
}
THeapNode *parent = node->parent;
while ( parent->data < node->data ) {
parent = node->parent;
string temp = parent->data;
parent->data = node->data;
node->data = temp;
}
}
void TreeHeap::bubble_down( THeapNode *node ) {
if (node == NULL) {
return;
}
while( node->data < node->rightChild->data || node->data < node->leftChild->data ){
if (node->rightChild->data > node->leftChild->data) {
THeapNode *right = node->rightChild;
string temp = right->data;
right->data = node->data;
node->data = temp;
}
else if (node->rightChild->data < node->leftChild->data) {
THeapNode *left = node->leftChild;
string temp = left->data;
left->data = node->data;
node->data = temp;
}
}
}
THeapNode* TreeHeap::find_node( const int position ){
int loc = position;
int d = floor(log2(position));
int power = std::pow(2, d - 1);
THeapNode *returnValue = root;
while (returnValue != NULL && 1 < position && position < (next_loc - 1)) {
if (loc == 1) {
return returnValue;
}
else if (loc < ( std::pow( 2, d-1 ) * 3)) {
returnValue = returnValue->leftChild;
}
else {
returnValue = returnValue->rightChild;
}
// Update location and depth to reflect traversal
loc = std::pow(2, d - 1) + loc % power;
d = d - 1;
}
std::cout << returnValue->data<<"\n";
return returnValue;
}
bool TreeHeap::Delete() {
if (next_loc = 1) {
return false;
}
int d = floor(log2(next_loc - 1));
THeapNode *current = root;
THeapNode *usedNode = NULL;
int loc = next_loc - 1;
while ( 1 ) {
int d = floor(log2(loc));
int power = std::pow(2, d - 1);
if (loc == 1) {
usedNode = current;
break;
}
else if (loc < (std::pow(2, d - 1) * 3)) {
current = current->leftChild;
}
else {
current = current->rightChild;
}
// Update location and depth to reflect traversal
loc = std::pow(2, d - 1) + loc % power;
d = d - 1;
}
THeapNode *temp = root;
clear_heap(root);
root = usedNode;
delete temp;
bubble_down(root);
return true;
}
Thanks in advance for any help you've got.
Quick inspection reveals errors in your bubble_up and bubble_down functions.
In bubble_up, you have the following:
THeapNode *parent = node->parent;
while ( parent->data < node->data ) {
parent = node->parent;
string temp = parent->data;
parent->data = node->data;
node->data = temp;
}
This is going to fail when a node bubbles all the way to the top, because it doesn't check for the node being at the root. You need to write:
while (parent != NULL && parent->data < node->data)
In bubble_down, you have this code:
while( node->data < node->rightChild->data || node->data < node->leftChild->data ){
if (node->rightChild->data > node->leftChild->data) {
You don't check to see if the rightChild or leftChild are NULL.
More importantly, that looks like an infinite loop to me because you never change the value of node.
Those are just the errors I saw on a quick read through your code. There might be more.
I am working on an exercise in processing an AVL tree. The debugger shows no errors. I ran the program and it is supposed to output an output text file. However the program crashes every time.
#include <stdio.h>
#include <assert.h>
#include <algorithm>
#include <vector>
using namespace std;
struct node
{
int key;
int height;
node *left, *right;
node(int k)
{
key = k;
height = 1;
left = right = 0;
}
};
void pre_order(node* root)
{
if(root == 0) return;
printf("%d", root->key);
printf(" ");
pre_order(root->left);
pre_order(root->right);
}
void in_order(node* root)
{
in_order(root->left);
printf("%d", root->key);
printf(" ");
in_order(root->right);
}
int height(node* r)
{
return r ? r->height : 0;
}
void update_height(node* root)
{
if(root == 0) return;
int hl = height(root->left), hr = height(root->right);
root->height = std::max(hl, hr) + 1;
}
node* right_rotate(node* ref_root)
{
assert(ref_root && ref_root->left);
node *a = ref_root, *b = ref_root->left;
a->left = b->right;
b->right = a;
update_height(a);
update_height(b);
return b;
}
node* left_rotate(node* ref_root)
{
assert(ref_root && ref_root->right);
node *c = ref_root, *d = ref_root->right;
c->right = d->left;
d->left = c;
update_height(c);
update_height(d);
return d;
}
node* maintain(node* ref_root)
{
if(ref_root == 0) return ref_root;
update_height(ref_root);
node* ret = ref_root;
if(height(ref_root->left) > height(ref_root->right) + 1)
{
node* p = ref_root->left;
if( height(p->left) < height(p->right) )
ref_root->left = left_rotate(p);
ret = right_rotate(ref_root);
}
else if(height(ref_root->right) > height(ref_root->left) + 1)
{
node* p = ref_root->right;
if(height(p->right) < height(p->left)){
ref_root->right = right_rotate(p);
}
ret = left_rotate(ref_root);
}
return ret;
}
node* insert_key(int key, node* ref_root)
{
if(ref_root == 0)
{
return ref_root = new node(key);
}
if(key < ref_root->key){
node* child = insert_key(key, ref_root->left);
ref_root->left = child;
}
else if(key > ref_root->key){
node* child = insert_key(key, ref_root->right);
ref_root->right = child;
}
else
assert(0);
return maintain(ref_root);
}
vector<node*> minimum(node* T) {
vector<node*> x;
node* y = T;
while (y->left != NULL) {
x.push_back(y->left);
}
return x;
}
node* delete_key(int key, node* ref_root)
{
if(key < ref_root->key){
node* child = delete_key(key, ref_root->left);
ref_root->left = child;
}
else if(key > ref_root->key){
node* child = delete_key(key, ref_root->right);
ref_root->right = child;
}
else
{
if(ref_root->left && ref_root->right)
{
vector <node*> y = minimum(ref_root->right);
node* successor = y.back();
node* sParent = y[y.size()-2];
ref_root->key = successor->key;
sParent->left = successor->right;
}
else
{
if(ref_root->left != NULL){
ref_root = ref_root->left;
}
else if(ref_root->right != NULL){
ref_root = ref_root->right;
}
}
}
return maintain(ref_root);
}
int main()
{
node *root = 0;
char op[10] = "";
int k;
while(true)
{
scanf("%s", op);
if(op[0] == 'E') break;
switch(op[0])
{
case 'A': scanf("%d", &k); root = insert_key(k, root); break; //Insert
case 'D': scanf("%d", &k); root = delete_key(k, root); break;//Delete
case 'P': pre_order(root); printf("\n"); break;//preorder
case 'I': in_order(root); printf("\n"); break;//inorder
default: assert(0);
}
}
return 0;
}
There is no check in the in_order function that root is not NULL.
I'm writing a function that counts the leaf nodes of a height balanced tree using struct and pointers. The function takes 3 arguments: the tree, pointer to an array and the maximum depth of the tree. The length of the array is the maximum depth. When function is called the array is initialized to zero. The function recursively follows the tree structure,
keeping track of the depth, and increments the right counter whenever it reaches a leaf. The function does not follow any pointer deeper than maxdepth. The function returns 0 if there was no leaf at depth greater than maxdepth, and 1 if there was some pointer togreater depth. What is wrong with my code. Thanks.
typedef int object;
typedef int key;
typedef struct tree_struct { key key;
struct tree_struct *left;
struct tree_struct *right;
int height;
} tree_n;
int count_d (tree_n *tr, int *count, int mdepth)
{
tree_n *tmp;
int i;
if (*(count + 0) == NULL){
for (i =0; i<mdepth; i++){
*(count + i) = 0;
}
}
while (medepth != 0)
{
if (tr == NULL) return;
else if ( tree-> left == NULL || tree->right == NULL){
return (0);
}
else {
tmp = tr;
*(count + 0) = 1;
int c = 1;
while(tmp->left != NULL && tmp->right != NULL){
if(tmp-> left){
*(count + c) = 2*c;
tmp = tmp->left;
return count_d(tmp, count , mdepth);
}
else if(tmp->right){
*(count + c + 1) = 2*c + 1;
tmp = tmp->right;
return count_d(tmp,count, mdepth);
}
c++;
mpth--;
}
}
}
What is wrong with my code
One thing I noticed is that you are missing return in the recursive calls.
return count_d(tmp, count , mdepth);
// ^^^ Missing
There are two such calls. Make sure to add return to both of them.
Disclaimer: Fixing this may not fix all your problems.
Correct Function To Insert,Count All Nodes and Count Leaf Nodes
#pragma once
typedef int itemtype;
#include<iostream>
typedef int itemtype;
#include<iostream>
#include<conio.h>
#include<string>
using namespace std;
class Node
{
public:
Node* left;
Node* right;
itemtype data;
};
class BT
{
private:
int count = 0;
Node* root;
void insert(itemtype d, Node* temp);//Override Function
public:
BT();//Constructor
bool isEmpty();
Node* newNode(itemtype d);
Node* getroot();
void insert(itemtype d);//Function to call in main
int countLeafNodes(Node * temp);
int countAllNodes();//to count all nodes
}
BT::BT()//constructor
{
root = NULL;
}
bool BT::isEmpty()
{
if (root == NULL)
return true;
else
return false;
}
Node* BT::newNode(itemtype d)
{
Node* n = new Node;
n->left = NULL;
n->data = d;
n->right = NULL;
return n;
}
void BT::insert(itemtype d)//Function to call in main
{
if (isEmpty())
{
Node* temp = newNode(d);
root = temp;
}
else
{
Node* temp = root;
insert(d, temp);
}
count++;//to count number of inserted nodes
}
void BT::insert(itemtype d, Node* temp)//Private Function which is overrided
{
if (d <= temp->data)
{
if (temp->left == NULL)
{
Node* n = newNode(d);
temp->left = n;
}
else
{
temp = temp->left;
insert(d, temp);
}
}
else
{
if (temp->right == NULL)
{
temp->right = newNode(d);
}
else
{
temp = temp->right;
insert(d, temp);
}
}
}
int BT::countAllNodes()
{ return count; }
int BT::countLeafNodes(Node* temp)
{
int leaf = 0;
if (temp == NULL)
return leaf;
if (temp->left == NULL && temp->right == NULL)
return ++leaf;
else
{
leaf = countLeafNodes(temp->left) + countLeafNodes(temp->right);
return leaf;
}
}
void main()
{
BT t;
t.insert(7);
t.insert(2);
t.insert(3);
t.insert(15);
t.insert(11);
t.insert(17);
t.insert(18);
cout<<"Total Number Of Nodes:" <<t.countAllNodes() <<endl;
cout << "Leaf Nodes:" << t.countLeafNodes(t.getroot()) << endl;
_getch();
}
Output:
Ouput
I'm trying to implement a program for finding a starting node of circular linked list. My code is-
struct node
{
char data;
struct node *link;
} ;
char FindStartNode(struct node **q)
{
struct node *r,*t;
r = *q;
t = *q;
while(t->link != NULL)
{
r = r->link;
t = t->link->link;
if(r == t)
{
break;
}
}
if(t == NULL )
return NULL;
r = *q;
while(r != t)
{
t = t->link;
r = r->link;
}
return t->data;
}
int main()
{
struct node *p;
p = NULL;
char num;
Append(&p,'A');
Append(&p,'B');
Append(&p,'C');
Append(&p,'D');
Append(&p,'E');
Append(&p,'C');
Display(p);
num = FindStartNode(&p);
printf("\nStarting node of the cycle linked list is:- %c",num);
_getch();
return 0;
}
int Append(struct node **q, char data)
{
struct node *r,*t;
r = (struct node *)malloc(sizeof(struct node));
r->data = data;
r->link = NULL;
if(*q == NULL)
*q = r;
else
{
t = *q;
while(t->link != NULL)
{
t = t->link;
}
t->link = r;
}
return 0;
}
int Display(struct node *q)
{
while(q != NULL)
{
printf("%c\t",q->data);
q = q->link;
}
return 0;
}
ths is my code. I'm not getting any value in return t->data part or I'm unable to find the start node of cycle ink list.Any help?
t = t->link->link; // t->link can be null
//so t = t->link->link can be a crash or illegal reference
Change the loop to:
while(t != NULL)
{
r = r->link;
t = t->link;
if(t == NULL)
break; // or return no circle
else t = t->link;
if(r == t)
{
break;
}
}
I have gone through your code. Comparing with the algorithm discussion here it seems to be OK. But you are returning a char why dont you return a pointer so that you can check if it is NULL or not. In case it is not null then issue pt->tada. This makes more sense.
I checked you code it seems you are not implementing circular linked list correctly in Append(). I am providing you with a working implementation below. See how I modified Append()
#include <stdio.h>
#include <stdlib.h>
struct node
{
char data;
struct node *link;
} ;
char FindStartNode(struct node **q)
{
struct node *r,*t;
r = *q;
t = *q;
while(t->link != NULL)
{
r = r->link;
t = t->link->link;
if(r == t)
{
break;
}
}
if(t == NULL )
return NULL;
r = *q;
while(r != t)
{
t = t->link;
r = r->link;
}
return t->data;
}
int Append(struct node **q, char data);
int main()
{
struct node *p;
p = NULL;
char num;
Append(&p,'A');
Append(&p,'B');
Append(&p,'C');
Append(&p,'D');
Append(&p,'E');
Append(&p,'C');
//Display(p);
num = FindStartNode(&p);
printf("\nStarting node of the cycle linked list is:- %c\n",num);
//_getch();
return 0;
}
int Append(struct node **q, char data)
{
struct node *r,*t, *startOfcycle=NULL;
r = (struct node *)malloc(sizeof(struct node));
r->data = data;
r->link = NULL;
if(*q == NULL)
*q = r;
else
{
t = *q;
while(t->link != NULL)
{
if(t->data == data)
startOfcycle = t;
t = t->link;
}
if(startOfcycle == NULL)
t->link = r;
else {// there is a cycle point to the start of cycle
t->link = startOfcycle;
free(r);
}
}
return 0;
}
int Display(struct node *q)
{
while(q != NULL)
{
printf("%c\t",q->data);
q = q->link;
}
Please note that Display function is also wrong as runs an infinite loop of the linked list is circular. I have not modified it since it is not relevant to you question. Thanks.
...
p = NULL;
char num;
Append(&p,'A');
...
You are trying to assign to NULL, which Append handles, but you are doing it repeatedly, which means you won't make a list, just a bunch of dangling nodes.
You need to make one node to start, outside of append, as your seed node, and pass that in.
I have searched through the other questions and none of them seem to apply
exactly.
I am writing a program that finds a route through a maze,
the only real thing im having a problem with is this one compiler error.
It has to do with the one function I have the returns a Node ( struct).
Header file: (I cut the define stuff off)
#include <iostream>
#include <string>
using namespace std;
class Graph {
private:
struct Node {
int id; //int id
Node * north; //north path node
Node * south; //south path node
Node * east; //east path node
Node * west; //went path node
bool visited; // visited bool
};
//this struct holds the path that is found.
struct Elem {
int id; //The id of the node
string last; //the door that it passed through
Elem * back; //back one path
Elem * next; //forward one path
};
//This is a graph with a very smart struct
//This is the main node that makes up the graph.
Node * start;
Node ** initArr;
int arrLen;
Elem * head;
Elem * tail;
int path;
public:
Graph();
//Constructs empty graph
Graph(const Graph &v);
//copy constructor
~Graph();
//destructor
Graph & operator = (const Graph &v);
//assignment operator
void output(ostream & s) const;
//Prints the graph
void input(istream & s);
//input and creates the graph
Node * find(int id);
//finds the node in the graph
void makePath();
//makes a path through the maze
bool findPath(Node* cur, string room);
//worker function for recursion
void pathOut(ostream & s) const;
//Outputs the found path
void removeTail();
//Removes the last element
void addTail(Node* n, string door);
//Adds the element to the tail
//Mutators
void setId(Node* n ,int x);
void setVisited(Node* n, bool v);
//Elem Mutator
void seteId(Elem* e, int x);
//Elem Accessor
int geteId(Elem* e);
//Accessors
int getId(Node* n);
bool getVisited(Node* n);
};
And my actual code file.
#include <iostream>
#include "graph.h"
using namespace std;
//Constructs empty graph
Graph::Graph()
{
start = 0;
head = tail = 0;
path = 0;
}
//copy constructor
Graph::Graph(const Graph &v)
{
//not implemented
}
//destructor
Graph::~Graph()
{
for(int i = 0; i < arrLen + 1; i++)
{
delete initArr[i];
}
while(head != 0)
{
Elem* p = head;
head = head->next;
delete p;
}
delete[] initArr;
}
//assignment operator
Graph & Graph::operator = (const Graph &v)
{
//not implemented
}
//Prints the graph
void Graph::output(ostream & s) const
{
s<<"Node"<<'\t'<<"North"<<'\t'<<"East"<<'\t'<<"South"<<'\t'<<"West"<<'\n';
for(int i = 1; i < arrLen + 1; i++)
{
Node* temp = initArr[i];
s<<temp->id<<'\t';
if(temp->north != 0)
s<<temp->north->id<<'\t';
else
s<<"--"<<'\n';
if(temp->east != 0)
s<<temp->east->id<<'\t';
else
s<<"--"<<'\n';
if(temp->south != 0)
s<<temp->south->id<<'\t';
else
s<<"--"<<'\n';
if(temp->west != 0)
s<<temp->west->id<<'\t';
else
s<<"--"<<'\n';
s<<'\n';
}
}
//input and creates the graph
void Graph::input(istream & s)
{
int length = 0;
s>>length;
arrLen = length;
if(s)
{
//define array
initArr = new Node*[length + 1];
int temp = 0;
for(int i = 1; i < length + 1; i++)
{
//Create node
s>>temp;
Node* n = new Node;
n->id = temp;
n->visited = false;
//Add to array
initArr[i] = n;
}
//Make Exit Node
Node *x = new Node;
x->id = 0;
x->visited = false;
initArr[0] = x;
//Loop through all of the node input
int tn = 0;
for(int f = 0; f < length; f++)
{
//Set Pointers
s>>tn;
Node* curNode = find(tn);
int n = 0;
int e = 0;
int st = 0;
int w = 0;
s>>n>>e>>st>>w;
curNode->north = find( n );
curNode->east = find( e );
curNode->south = find( st );
curNode->west = find( w );
}
//set Entry point to graph
int last = 0;
s>>last;
start = find(last);
}
}
//finds the node in the array
Node* Graph::find(int id)
{
if( id == 0)
{
return initArr[0];
}
if(id == -1)
{
return 0;
}
else
{
for(int i = 1; i < arrLen + 1; i++)
{
if(initArr[i]->id == id)
{
return initArr[i];
}
}
cerr<<"NOT FOUND IN GRAPH";
return 0;
}
}
//makes a path through the maze
void Graph::makePath()
{
if(findPath(start->north, "north") == true)
{
path = 1;
return;
}
else if( findPath(start->east, "east") == true)
{
path = 1;
return;
}
else if( findPath(start->south, "south") == true)
{
path = 1;
return;
}
else if( findPath(start->west, "west") == true)
{
path = 1;
return;
}
return;
}
//finds a path to the outside
bool Graph::findPath(Node* cur, string room)
{
addTail(cur, room);
if(cur = initArr[0])
{
return true;
}
if(cur->north != 0 && cur->north->visited == false)
{
cur->visited = true;
findPath(cur->north, "north");
}
else if(cur->east != 0 && cur->east->visited == false)
{
cur->visited = true;
findPath(cur->north, "east");
}
else if(cur->south !=0 && cur->south->visited == false)
{
cur->visited = true;
findPath(cur->north, "south");
}
else if(cur->west != 0 && cur->west->visited == false)
{
cur->visited = true;
findPath(cur->north, "west");
}
else
{
cur->visited = false;
removeTail();
}
}
//Outputs the found path
void Graph::pathOut(ostream & s) const
{
if(path == 1)
{
Elem *p;
p = head->next;
while(p != 0)
{
s<<p->id<<"--> "<<p->last;
p= p->next;
}
}
else if(path == 0)
{
}
}
//Removes the last element in the chain
void Graph::removeTail()
{
Elem* temp = 0;
temp = tail;
tail = tail->back;
delete temp;
}
//Adds the element to the tail
void Graph::addTail(Node* n, string door)
{
if(head != 0)
{
Elem* temp = new Elem;
temp->id = n->id;
tail->next = temp;
tail->last = door;
temp->back = tail;
temp->next = 0;
tail = 0;
}
else
{
Elem *p = new Elem;
p->last = "";
p->back = 0;
p->next = 0;
head = p;
tail = p;
}
}
//Mutators
void Graph::setId(Node *n ,int x)
{
n->id = x;
}
void Graph::setVisited(Node *n, bool v)
{
n->visited = v;
}
//Elem Mutator
void Graph::seteId(Elem *e, int x)
{
e->id = x;
}
//Elem Accessor
int Graph::geteId(Elem *e)
{
return e->id;
}
//Accessors
int Graph::getId(Node *n)
{
return n-> id;
}
bool Graph::getVisited(Node *n)
{
return n->visited;
}
/*
//This is a graph with a very smart struct
//This is the main node that makes up the graph.
struct Node {
int id; //int id
Node *north; //north path node
Node *south; //south path node
Node *east; //east path node
Node *west; //went path node
bool visited; // visited bool
};
//this struct holds the path that is found.
struct Elem {
int id; //The id of the node
string last; //the door that it passed through
Elem* back; //back one path
Elem* next; //forward one path
};
Node* Start;
Node ** initArr;
Elem* head;
Elem* tail;
*/
//outputs using named operation
ostream & operator << (ostream &s, const Graph & v)
{
v.output(s);
return s;
}
The error is occurring on the find function.
In the cpp file, Node is not in global scope. It's nested inside Graph as such, you need to qualify it in a return type:
Graph::Node* Graph::find(int id){
// ...
}
Inside the function, you're in the scope of Graph again, as such you do not need to qualify it.
You have both Node and Element defined as structs inside the class Graph. It would be better to define them outside the class Graph. You can define a separate Node class and store the element struct as its private members. The error happens because Node is a private member of Graph, which can be accessed as Graph::Node. E.g. Graph::Node* find(...).