I am working on a project in C++ in which I have to create a binary search tree that inserts items from an array. I have to use the following insert algorithm:
tree-insert(T, z)
y = NIL
x = T.root
while x != NIL
y = x
if z.key < x.key
x = x.left
else x = x.right
z.p = y
if y == NIL
T.root = z
else if z.key < y.key
y.left = z
else y.right = z
Here is what I have so far:
#include <iostream>
using namespace std;
struct node
{
int key;
node* left;
node* right;
node* p;
node* root;
};
void insert(node*, node*);
void printinorder(node*);
int main()
{
node *root;
node* tree = new node;
node* z = new node;
int array [10] = {30, 10, 45, 38, 20, 50, 25, 33, 8, 12};
for (int i = 0; i < 10; i++)
{
z->key = array[i];
insert(tree, z);
}
printinorder(tree);
return 0;
}
void insert(node *T, node *z)
{
node *y = nullptr;
node* x = new node;
x = T->root;
while (x != NULL)
{
y = x;
if (z->key < x->key)
x = x->left;
else
x = x->right;
}
z->p = y;
if (y == NULL)
T->root = z;
else if (z->key < y->key)
y->left = z;
else
y->right = z;
}
void printinorder(node *x)
{
if (x != NULL)
{
printinorder(x->left);
cout << x->key << endl;
printinorder(x->right);
}
}
This code compiles however when I run it, it seg faults. I believe the problem has something to do with the nodes I am creating or my function calls.
Thanks for your help.
Besides the issues noted in the comments, the biggest bug in this code is a lack of a constructor that initializes all pointers in a new node to NULL.
As such, every node you create will have its pointers containing random garbage. You code initializes some of them, but most are not. Trying to use uninitialized pointers will result in an immediate crash.
You need to fix all the problems that have been noted in the comments, and have a proper constructor for your node class.
Related
Segmentation faults when trying to delete a node with 2 children
So i've recently started studying algorithms and have been working a bit on binary search trees, basing my C++ code on the pseudo code taken from the book Introduction to Algorithms. I'm however having large issues with it's delete function for it's binary search tree. The code for the delete function is:
void bstDelete(BSTtree &bst, int key)
{
treeNode *z = findNode(bst, key);
if (z != nullptr)
{
treeNode *y = z;
treeNode *x;
if (z->left == bst.NIL)
{
x = z->right;
transplant(bst, z, z->right);
}
else if (z->right == bst.NIL)
{
x = z->left;
transplant(bst, z, z->left);
}
else
{
y = treeMin(z->right);
x = y->right;
if (y->parent == z)
{
x->parent = y;
}
else
{
transplant(bst, y, y->right);
y->right = z->right;
y->right->parent = y;
}
transplant(bst, z, y);
y->left = z->left;
y->left->parent = y;
}
}
}
Transplant function:
void transplant(BSTtree &bst, treeNode *u, treeNode *v)
{
if (u->parent == bst.NIL)
{
v->right = u->right;
v->left = u->left;
v->right->parent = v;
v->left->parent = v;
bst.root = v;
}
else if (u == u->parent->left)
{
u->parent->left = v;
}
else
{
u->parent->right = v;
}
v->parent = u->parent;
}
I'm not expecting someone to debug my code, I've just sat pretty much for multiple days trying to figure it out, looking at other people's versions of the delete function trying to understand why mine doesn't work. There's also the issue of why the book's own delete function doesn't do it's job, or if it's just me who's at fault. I would really appreciate if someone could take a look at this. I've been looking around quite a lot and still haven't found anyone having issues with this.
Edit
Added other parts related to the code
treeNode *findNode(RBtree bst, int key)
{
treeNode *z = nullptr;
treeNode *x = bst.root;
treeNode *y = bst.NIL;
while (x != nullptr && x != bst.NIL)
{
y = x;
if (key < x->value)
{
x = x->left;
}
else
{
x = x->right;
}
if (y->value == key)
{
break;
}
}
if (y->value == key)
{
z = y;
}
return z;
}
treeNode *treeMin(treeNode *root)
{
treeNode *treeNode = root;
while (treeNode->left != nullptr)
{
treeNode = treeNode->left;
}
return treeNode;
}
struct treeNode
{
treeNode *left;
treeNode *right;
treeNode *parent;
std::string color;
int value;
treeNode() : left(nullptr), right(nullptr), parent(nullptr) {}
treeNode(int paramValue) : left(nullptr), right(nullptr), parent(nullptr), value(paramValue) {}
treeNode(int paramValue, treeNode *parent) : value(paramValue), parent(parent) {}
};
struct BSTtree
{
treeNode *root;
treeNode *NIL;
BSTtree()
{
NIL = new treeNode();
root = nullptr;
}
};
Reason i have with NIL is so that i can easier make this into an RB tree later on. The smallest scale needed to cause a crash is a 3 node tree, where you have a root, and it has a right and left child. That way you push the delete function into case three, where it has to find a successor and transplant it. It's in this part of the delete-function which it crashes and gives me a segmentation-fault.
Edit 2
Code which causes a crash:
int main()
{
BSTtree bst;
bstInsert(bst, 5);
bstInsert(bst, 7);
bstInsert(bst, 2);
bstDelete(bst, 5);
}
Insert function
void bstInsert(BSTtree &bst, int key)
{
treeNode *z = new treeNode(key);
treeNode *y = bst.NIL;
treeNode *x = bst.root;
while (x != nullptr && x != bst.NIL)
{
y = x;
if (z->value < x->value)
{
x = x->left;
}
else
{
x = x->right;
}
}
z->parent = y;
if (y == bst.NIL)
{
bst.root = z;
z->parent = bst.NIL;
}
else if (z->value < y->value)
{
y->left = z;
}
else
{
y->right = z;
}
z->left = bst.NIL;
z->right = bst.NIL;
}
The nullptr is not a problem here as it's resolved in the insert function, as you can see if it's root, root is given bst.NIL as it's parent. I agree it's error prone to have this construction, it's only there to be able to be used for red and black trees which uses a specific NIL node instead of nullptr.
I've resolved the issues, firstly the treeMin() function is faulty. It should take in an additional parameter which is BSTtree bst and instead of while (treeNode->left != nullptr) it should be while (treeNode->left != bst.NIL), outside of this one of the constructors in treeNode is faulty, this one being treeNode(int paramValue, treeNode *parent) : value(paramValue), parent(parent) {}, it should instead be changed into:
treeNode(int paramValue, treeNode *paramParent) {
value = paramValue;
parent = paramParent;
}
Struggling to understand why newLL is remaining as a null pointer in the following code (Line 30: Char 16: runtime error: member access within null pointer of type 'struct ListNode' (solution.cpp)) while temp0 is behaving as expected. Thank you for the help.
Problem:
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *temp0 = NULL;
ListNode *temp1 = l1;
ListNode *temp2 = l2;
//keep track of head
ListNode *newLL = temp0;
int x, y, z, f;
//sum val's and create new nodes on newLL, until l1 or l2 hits a null
while(temp1 != NULL && temp2 != NULL){
x = temp1->val;
y = temp2->val;
z = x + y;
temp0 = new ListNode(z);
cout << temp0->val << endl; //no error
cout << newLL->val << endl; //error
temp0 = temp0->next;
temp1 = temp1->next;
temp2 = temp2->next;
//concatenate the rest of l1 or l2 onto newLL
if (temp1 == NULL){
while (temp2 != NULL){
y = temp2->val;
temp0 = new ListNode(y);
temp0 = temp0->next;
temp2 = temp2->next;
}
}
if (temp2 == NULL){
while (temp1 != NULL){
x = temp1->val;
temp0 = new ListNode(x);
temp0 = temp0->next;
temp1 = temp1->next;
}
}
}
//loop through and for all numbers > 9, carry the digit
temp0 = newLL;
int r,d;
while (temp0 != NULL) {
if (temp0->val > 9){
d = temp0->val / 10;
r = temp0->val % 10;
temp0->val = d;
temp0 = temp0->next;
temp0->val += r;
} else {
temp0 = temp0->next;
}
}
//return newLL
return newLL;
}
};
I am trying to convert an ordered array into a binary search tree with minimal height. I am getting an runtime error. Been at it for hours but couldn't figure out the error. Please help.
#include <iostream>
struct node
{
int value;
node* left;
node* right;
};
node* minimalheight(int* array,int start,int end)
{
node* x = new node;
if(start == end)
{
x->value = array[start];
x->left = NULL;
x->right = NULL;
}
else
{
int midpoint = (start+end+1)/2;
x->value = array[midpoint];
x->left = minimalheight(array,start, midpoint);
x -> right = minimalheight(array, midpoint,end);
}
std::cout << x->value<<std::endl;
return x;
}
int main() {
int foo [5] = { 2,16,40, 77, 12071 };
node* head= minimalheight(foo, 0, (sizeof(foo)/sizeof(foo[0]))-1);
}
If start is 0 and end is 1, midpoint gets calculated to 1, and it recurses infinitely at this line:
x->left = minimalheight(array,start, midpoint);
The runtime error you are getting is probably when memory runs out from creating too many new node objects.
I am trying to finish a C++ project where I have to insert an array of integers into a binary search tree. I have to use a particular insertion algorithm:
insert(T, z)
1 y = NIL
2 x = T.root
3 while x != NIL
4 y = x
5 if z.key < x.key
6 x = x.left
7 else x = x.right
8 z.p = y
9 if y == NIL
10 T.root = z
11 else if z.key < y.key
12 y.left = z
13 else y.right = z
Here is my code so far:
main.cpp
#include <iostream>
#include "binarytree.h"
using namespace std;
int main()
{
BinaryTree tree;
int array [10] = {30, 10, 45, 38, 20, 50, 25, 33, 8, 12};
for (int i = 0; i < 10; i++)
{
tree.add(array[i]);
}
tree.inordertreewalk();
return 0;
}
void BinaryTree::insert(node *&T, node *&z)
{
node *y = nullptr;
y = new node;
y->key = 0;
y->left = y->right = y->parent = nullptr;
node *x = T;
while (x != nullptr)
{
y = x;
if (z->key < x->key)
x = x->left;
else
x = x->right;
}
z->parent = y;
if (y == nullptr)
T = z;
else if (z->key < y->key)
y->left = z;
else
y->right = z;
}
void BinaryTree::add(int num)
{
node *newNode = nullptr;
newNode = new node;
newNode->left = newNode->right = newNode->parent = nullptr;
newNode->key=num;
insert(root, newNode);
}
void BinaryTree::inordertreewalk(node *x) const
{
if (x)
{
inordertreewalk(x->left);
cout << x->key << endl;
inordertreewalk(x->right);
}
}
void BinaryTree::destroysubtree(node *newNode)
{
if (newNode)
{
if (newNode->left)
destroysubtree(newNode->left);
if (newNode->right)
destroysubtree(newNode->right);
delete newNode;
}
}
binarytree.h
#ifndef BINARYTREE_H_
#define BINARYTREE_H_
#include <iostream>
using namespace std;
class BinaryTree
{
private:
struct node
{
int key;
node* left;
node* right;
node* parent;
};
node *root;
void insert(node *&, node *&);
void inordertreewalk(node *) const;
void destroysubtree(node *);
public:
BinaryTree()
{ root = nullptr; }
~BinaryTree()
{ destroysubtree(root); }
void add(int);
void inordertreewalk() const
{ inordertreewalk(root); }
};
#endif
This program compiles, however it is not displaying the tree. I know that the problem is with my implementation of the insertion algorithm because I used a different algorithm I found in a textbook and kept the rest of the code the same and the tree was displayed in order. I know that T is a pointer to the root, but I'm not sure if the numbers are being correctly stored in the tree.
Thanks for your help.
Why the search and successor and predecessor returns -1?
// BST.cpp : main project file.
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#define SIZE 10
using namespace std;
struct Node {
int value;
Node *left;
Node *right;
Node *parent;
};
struct BST {
Node *root;
};
void insert(int value, BST *tree) {
Node *x = tree->root;
Node *y = NULL;
Node *z = (Node *) malloc(sizeof(Node));
z->left = NULL;
z->right = NULL;
z->value = value;
// Add your code here
while (x!=NULL){
y=x;
if (z->value < x->value)
x= x->left;
else x = x->right;
}
z->parent=y;
if (y==NULL)
tree->root=z;
else if (z->value <y->value)
y->left =z;
else y->right =z;
}
Node *search(int key, Node *n) {
if (n== NULL || key == n->value)
return n;
if (key < n->value)
search(key, n->left);
else
search(key, n->right);
}
Node *min(Node *n) {
if (n == NULL || n->left == NULL)
return n;
else
return min(n->left);
}
Node *max(Node *n) {
if (n == NULL || n->right == NULL)
return n;
else
return max(n->right);
}
Node *successor(int value, Node *n) {
Node *y = NULL;
Node *x = search(value, n);
if (x == NULL)
return NULL;
if (x->right != NULL)
return min(x->right);
y = x->parent;
while (y != NULL && x == y->right) {
x = y;
y = y->parent;
}
return y;
}
Node *predecessor(int value, Node *n) {
Node *x = search(value, n);
Node *y = NULL;
if (x == NULL)
return NULL;
if (x->left != NULL)
return max(x->left);
y = x->parent;
while (y != NULL && x == y->left) {
x = y;
y = y->parent;
}
return y;
}
Node *remove(int value, BST *tree) {
Node *z = search(value, tree->root);
Node *y = NULL, *x = NULL;
if (z == NULL) return NULL;
if (z->left == NULL || z->right == NULL)
y = z;
else
y = successor(value, z);
if (y->left != NULL)
x = y->left;
else
x = y->right;
if (x != NULL)
x->parent = y->parent;
if (y->parent == NULL)
tree->root = x;
else if (y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
if (y != z) {
int tmp = z->value;
z->value = y->value;
y->value = tmp;
}
return y;
}
// ascending sort function
void sortAsc(Node *node) {
//Add your code here
//inorder
if (node->left!=NULL)
sortAsc(node->left);
cout<<node->value<<" ";
if (node->right!=NULL)
sortAsc(node->right);
}
// descending sort function
void sortDes(Node *node) {
// Add your code here
//inorder
if (node->right!=NULL)
sortDes(node->right);
cout<<node->value<<" ";
if (node->left!=NULL)
sortDes(node->left);
}
void clear(BST *tree) {
Node *n = NULL;
while (tree->root != NULL) {
n = remove(tree->root->value, tree);
free(n);
}
}
int main() {
int A[] = {3, 5, 10, 4, 8, 9, 1, 4, 7, 6};
Node *node = NULL;
BST *tree = (BST *) malloc(sizeof(BST));
tree->root = NULL;
// build BST tree
cout << "Input data:\n\t";
for (int i=0; i<SIZE; i++) {
cout << A[i] << " "; // by the way, print it to the console
insert(A[i], tree); // You need to complete TASK 1, so that it can work
}
// sort values in ascending order
cout << "\n\nAscending order:\n\t";
sortAsc(tree->root); // You need to complete TASK 2. Otherwise you see nothing in the console
// sort values in descending order
cout << "\n\nDescending order:\n\t";
sortDes(tree->root); // TASK 2 also!
// Find minimum value
if (tree->root != NULL)
cout << "\n\nMin: " << min(tree->root)->value;
// Find maximum value
if (tree->root != NULL)
cout << "\n\nMax: " << max(tree->root)->value;
// delete 4
cout << "\n\nDelete 4 and add 2";
//free(remove(4, tree)); // You need to complete TASK 3, so that remove(int, BST *) function works properly
// we also need to release the resource!!!
// insert 2
insert(2, tree); // It belongs to TASK 1 too.
cout << "\n\nAscending order:\n\t";
sortAsc(tree->root); // TASK 2!!
// Find the successor of 5, -1 means no successor
node = search(5, tree->root);
cout << "\n\nSearch of 5 is: " << (node != NULL?node->value:-1);
// Find the successor of 5, -1 means no successor
node = successor(5, tree->root);
cout << "\n\nSuccessor of 5 is: " << (node != NULL?node->value:-1);
// Find the predecessor of 5. -1 means no predecessor
node = predecessor(5, tree->root);
cout << "\n\nPredecessor of 5 is: " << (node != NULL?node->value:-1);
cout << "\n\n";
// clear all elements
clear(tree); // delete all nodes and release resource
free(tree); // delte the tree too
system("Pause");
}
Well there is a bug in your recursive search for starters you need to have all paths return values like this:
Node *search(int key, Node *n) {
if (n== NULL || key == n->value)
return n;
if (key < n->value)
return search(key, n->left);
else
return search(key, n->right);
}
Apart from that I'm inclined to say try debugging your own code first and giving more details about what you've found rather than just posting code and asking what's wrong with it. You're liable to get some real smart ass answers here otherwise ;)