I am trying to build a basic Binary search tree in C++ and running into some problems, specifically when I try to insert a node via function and read, it gives me segmentation fault. But the same node struct works perfectly fine when I manually insert it.
The code for BST insert is as follows, and is most likely the culprit:
void BST::insert(Node* temproot,int val){
// std::cout << root->value <<std::endl;
if(!temproot){
Node* newNode = new Node;
newNode->value = val;
temproot = newNode;
std::cout << "Added Node with Value: " << val << std::endl;
return;
}
if(val<(temproot->value)){
std::cout << "LEFT" << std::endl;
insert(temproot->left, val);
}else{
std::cout << "RIGHT" << std::endl;
insert(temproot->right, val);
}
}
The node structure looks like this:
struct Node{
int value;
Node* left = nullptr, *right = nullptr;
};
And the BST class looks something like below:
class BST{
public:
Node* root= new Node;
BST(int val){
root->value = val;
}
void insert(Node*,int val);
void insertStart(int vasl){
Node* temproot = root;
insert(temproot, vasl);
}
void print(Node*);
void _print(){
print(root);
}
};
When I try to print it as follow, it gives me segmentation fault:
void BST::print(Node* temp){
std::cout << temp->value << std::endl;
temp = temp->left;
std::cout << (temp->value) << std::endl;
}
I am a bit new to C++ and am having struggle pin pointing it for couple of days. Can someone help me figure out what I am doing wrong here?
The function deals with a copy of the passed to it pointer to node. So changing a copy does not influence on the original pointer.
You have to pass a pointer to node to the function by reference.
The function declaration can look the following way
void insert(Node* &temproot,int val);
and call it like
void insertStart(int vasl){
insert( root, vasl );
}
without an intermediate pointer.
And you should declare this function as a provate static function of the class.
And initialize the data member root by nullptr.
For example
class BST{
public:
Node* root = nullptr;
BST(int val){
insert( root, val );
}
void insertStart(int vasl){
insert( root, vasl);
}
void print(Node*);
void _print(){
print(root);
}
private:
static void insert(Node* &,int val);
};
Basically, SEGFAULT comes from print function which should look like this:
void BST::print(Node* temp){
if (nullptr == temp) {
return;
}
print(temp->left);
std::cout << temp->value << std::endl;
print(temp->right);
}
And your insert function should look like this:
void BST::insert(Node *&temproot,int val){
if(nullptr == temproot){
Node* newNode = new Node;
newNode->value = val;
temproot = newNode;
return;
}
if(val < (temproot->value)){
insert(temproot->left, val);
}else{
insert(temproot->right, val);
}
}
Check it out live
Related
please don't dig into me too hard, I am still steadily learning and ran into an issue when trying to construct an AVL tree. When iterating through the tree on insert, I go until I reach a nullptr, create a new node, and assign that ptr to the nullptr. The value is never accepted though. Can someone find the error and explain it to me? ty!
#ifndef AVLTree_hpp
#define AVLTree_hpp
#include <stdio.h>
#include <stack>
template<typename T>
class AVLTree{
private:
struct Node{
T val;
Node* left;
Node* right;
int height;
Node(T V)
:left{nullptr},right{nullptr}
{
val = V;
}
~Node(){
}
};
Node* head;
void rightRotate(Node*& node);
void leftRotate(Node*& node);
void leftRight(Node*& node);
void rightLeft(Node*& node);
public:
AVLTree();
~AVLTree();
AVLTree(const AVLTree &c);
AVLTree(AVLTree &&c);
AVLTree &operator=(const AVLTree &c);
AVLTree &operator=(AVLTree &&c);
void add(T value);
int getHeight(Node* n);
};
template <typename T>
AVLTree<T>::AVLTree()
:head{nullptr}{
}
template <typename T>
AVLTree<T>::~AVLTree(){
}
template <typename T>
void AVLTree<T>::rightRotate(Node*& node){
Node* temp = node;
node = node->left;
Node* leftLL = node->right;
temp->left = leftLL;
node->right = temp;
}
template <typename T>
void AVLTree<T>::leftRotate(Node*& node) {
Node* temp = node;
node = node->right;
Node* yL = node->left;
temp->right = yL;
node->left = temp;
}
//left right condition
template <typename T>
void AVLTree<T>::leftRight(Node*& node) {
leftRotate(node->left);
rightRotate(node);
}
//right left condition
template <typename T>
void AVLTree<T>::rightLeft(Node*& node){
rightRotate(node->right);
leftRotate(node);
}
template <typename T>
void AVLTree<T>::add(T value){
if(head==nullptr){
head = new Node(value);
return;
}
std::stack<Node*> st;
Node* it = head;
while(it!=nullptr){
st.push(it);
if(value <= it->val){
it = it->left;
}else{
it=it->right;
}
}
//here is where the it is not assigned to the new node pointer.
//I have tested it and the node is created, "it" just does not hold the value at any point.
it = new Node(value);
int count = 0;
while(!st.empty()){
int balance = getHeight(st.top()->left) - getHeight(st.top()->right);
if(balance > 1){
if(st.top()->left!= nullptr&&st.top()->left!=nullptr){
leftRotate(st.top());
}else{
leftRight(st.top());
}
}else if(balance<-1){
if(st.top()->right!=nullptr&&st.top()->right!=nullptr){
rightRotate(st.top());
}else{
rightLeft(st.top());
}
}
st.pop();
if(++count==4){
break;
}
}
}
template <typename T>
int AVLTree<T>::getHeight(Node* n){
int max =0;
if(n!=nullptr){
max = std::max(getHeight(n->left),getHeight(n->right))+1;
}
return max;
}
#endif /* AVLTree_hpp */
It is a copy of the pointer and updating it has no effect on the original pointer. You need to do something like this instead:
Node* it = head;
bool left = true;
while(it!=nullptr){
st.push(it);
left = value <= it->val;
if(left){
it = it->left;
}else{
it=it->right;
}
}
it = new Node(value);
if (left){
stack.top()->left = it;
} else {
stack.top()->right = it;
}
Consider this simplified version of your code:
#include <iostream>
struct Linked {
Linked* next;
};
int main(int argc, char** argv) {
Linked l0 {nullptr};
// Case 1: Does not work
std::cout << "case 1" << std::endl;
Linked* node = l0.next;
node = new Linked {nullptr};
std::cout << "node=" << std::hex << node << std::endl;
std::cout << "l0.next=" << std::hex << l0.next << std::endl;
free(node);
std::cout << std::endl;
// Case 2: Works
std::cout << "case 2" << std::endl;
l0.next = new Linked {nullptr};
std::cout << "l0.next=" << std::hex << l0.next << std::endl;
free(l0.next);
l0.next = nullptr;
std::cout << std::endl;
// Case 3: Works
std::cout << "case 3" << std::endl;
Linked** nodeP = &(l0.next);
*nodeP = new Linked {nullptr};
std::cout << "*nodeP=" << std::hex << *nodeP << std::endl;
std::cout << "l0.next=" << std::hex << l0.next << std::endl;
free(l0.next);
l0.next = nullptr;
}
Which outputs:
$ ./main
case 1
node=0x7fba0d400620
l0.next=0x0
case 2
l0.next=0x7fba0d400620
case 3
*nodeP=0x7fba0d400620
l0.next=0x7fba0d400620
Case 1: does not work because the new Node is assigned to a copy of the left/right child pointer (i.e. not the actual child node from the parent node)
Case 2: works as expected because the new node is assigned directly to one of the parent's child node.
Case 3: also works because instead of assigning the new node to a copy of the child pointer, you assign it to a pointer referencing the pointer to child itself. In this respect, case 2 and 3 are equivalent.
I am trying to execute linked list with the below code.But I am unable to figure out the mistake in it.
I got the concept of it but I am failing to implement the same.
Any help is highly appreciated.
#include <iostream>
using namespace std;
struct Node {
int data;
Node *next;
Node(int j) : data(j), next(nullptr) {}
friend ostream &operator<<(ostream &os, const Node &n) {
cout << "Node\n"
<< "\tdata: " << n.data << "\n";
return os;
}
};
void addElement(Node **head, int data){
Node *temp = nullptr;
temp->data = data;
temp->next=nullptr;
Node *cur = *head;
while(cur) {
if(cur->next == nullptr) {
cur->next = temp;
return;
}
cur = cur->next;
}
};
void printList(const Node *head){
const Node *list = head;
while(list) {
cout << list;
list = list->next;
}
cout << endl;
cout << endl;
};
void deleteList(Node *head){
Node *delNode =nullptr;
while(head) {
delNode = head;
head = delNode->next;
delete delNode;
}};
int main() {
Node *list = nullptr;
addElement(&list, 1);
addElement(&list, 2);
printList(list);
deleteList(list);
return 0;
}
after compiling I am getting no error and no output.So I am unable to figure what is going wrong or else my implementation of which is not right!
Here an error straightaway
void addElement(Node **head, int data){
Node *temp = nullptr;
temp->data = data;
temp is null, but you dereference it. It's an error to dereference a null pointer.
I guess you meant this
void addElement(Node **head, int data) {
Node *temp = new Node(data);
which allocates a new Node, initialises it with data and makes temp point to the newly allocated Node.
I'm writing a program in c++ that reverse a linked list in c++.
And I have seen a lot of questions about it but my answer is not on them so please don't mark this as a duplicate!
I want to reverse a linked list using recursion and this is my full program and on Function reverse recursion() there is something wrong with it those programs ends and don't print.
I have tried to Get this function out of my class but it doesn't work and I have tried to make the head global too.
class LinkedList{
public:
Node* Head;
int Length;
LinkedList(Node* head,int c){
Head=head;
Length=c;
}
void ReverseRecursion(Node* temp,Node** Heading){
if(temp->next==0){
*Heading = temp;
cout << "This is the head item==>" << temp->value << " And this
is the Heading now " << *Heading << endl;
return;
}
ReverseRecursion(temp,Heading);
temp->next->next = temp;
temp->next = 0;
}
}
I have insert and delete and print functions in this class But i have test them and they are correct.
And on my main, I save the head element in a local variable on main and every time I pass it to the LinkedList.
And I call this function like this on main :
MyLinked.ReverseRecursion(head,&head);
When calling the recursion function you must pass a different parameter, otherwise you will have an infinite recursion until you get out of memory.
Try this version, where each time you call the function with the next element in the list, until you find the end of the list:
class LinkedList{
public:
Node* Head;
int Length;
LinkedList(Node* head,int c){
Head=head;
Length=c;
}
void ReverseRecursion(Node* temp,Node** Heading){
if(temp->next==0){
*Heading = temp;
cout << "This is the head item==>" << temp->value << " And this
is the Heading now " << *Heading << endl;
return;
}
ReverseRecursion(temp->next,Heading);
temp->next->next = temp;
temp->next = 0;
}
}
EDIT:
I show a complete testing of how my solution works. I intended to do the minimum change necessary to the original code to make it work, and the minimum is changing only one word:
#include <iostream>
using namespace std;
class Node {
public:
int value;
Node * next;
Node(int v, Node * n) : value(v), next(n) {}
};
class LinkedList{
public:
Node* Head;
int Length;
LinkedList(Node* head,int c){
Head=head;
Length=c;
}
void ReverseRecursion(Node* temp,Node** Heading){
if(temp->next==0){
*Heading = temp;
//cout << "This is the head item==>" << temp->value << " And this
//is the Heading now " << *Heading << endl;
return;
}
ReverseRecursion(temp->next,Heading);
temp->next->next = temp;
temp->next = 0;
}
void print() const;
};
void LinkedList::print() const {
cout << '{';
for (Node* node = Head; node != 0; node = node->next)
cout << ' ' << node->value; // value is public ?
cout << " }" << endl;
}
int main()
{
Node n3(3, 0);
Node n2(2, &n3);
Node n1(1, &n2);
LinkedList ll(&n1, 3);
Node *heading;
ll.print();
ll.ReverseRecursion(&n1, &heading);
ll.Head = heading;
ll.print();
return 0;
}
Output:
{ 1 2 3 }
{ 3 2 1 }
I followed a guide on youtube by Paul Programming to create this linked list. Now I want to expand on it. I am trying to learn how to do recursive functions.
The error I am getting is that head isn't declared in main.cpp. I was wondering if anyone could shed some light on the issue I am having.
Code:
main.cpp:
#include <cstdlib>
#include <iostream>
#include "linkedlist.h"
using namespace std;
int main(int argc, char** argv)
{
List list;
list.addNode(1);
list.addNode(2);
list.addNode(3);
list.addNode(4);
list.addNode(5);
cout << "Printing list" << endl;
list.printList();
cout << "Printing list recursively" << endl;
list.printListRecur(head);
return 0;
}
linkedlist.h:
#ifndef _LINKEDLISTHEADER_
#define _LINKEDLISTHEADER_
class List{
private:
typedef struct node{
int data;
node* next;
}* nodePtr;
nodePtr head;
nodePtr curr;
nodePtr temp;
public:
List();
void addNode(int addData);
void deleteNode(int delData);
void printList();
void printListRecur(nodePtr head);
};
#endif
linkedlist.cpp:
#include <iostream>
#include <cstdlib>
#include "linkedlist.h"
using namespace std;
List::List()
{
head = NULL;
curr = NULL;
temp = NULL;
}
void List::addNode(int addData)
{
nodePtr n = new node;
n->next = NULL;
n->data = addData;
if(head != NULL)
{
curr = head;
while(curr->next != NULL)
{
curr = curr->next;
}
curr->next = n;
}
else
{
head = n;
}
}
void List::deleteNode(int delData)
{
nodePtr delPtr = NULL;
temp = head;
curr = head;
while(curr != NULL && curr->data != delData)
{
temp = curr;
curr = curr->next;
}
if(curr == NULL)
{
cout << delData << " was not in the list." << endl;
delete delPtr;
}
else
{
delPtr = curr;
curr = curr->next;
temp->next = curr;
if(delPtr == head)
{
head = head->next;
temp = NULL;
}
delete delPtr;
cout << "The value " << delData << " was deleted" << endl;
}
}
void List::printList()
{
curr = head;
while(curr != NULL)
{
cout << curr->data << endl;
curr = curr->next;
}
}
void List::printListRecur(nodePtr head)
{
if(head == NULL)
{
return;
}
cout << head->data <<endl;
printListRecur(head->next);
}
To use recursion, you need to have the passed and returned data to be the same type, i.e, the function should consume a Node and then return a Node, recursion call will not be formed if function consumes a List but return a Node.
From my understanding, List can be a wrapper class for Node. To give you a very simple example:
class List {
struct Node {
int data;
Node *next;
void print();
...
};
Node *head;
public:
void print();
...
};
void List::Node::print() {
std::cout << data << endl;
if (next) next->print();
}
void List::print() {
if (head) head->print();
}
List will have all the interface methods that a client might need, but the actual work is done by the methods of Node, if you want to go with the recursion way (iteration is more frequently used since recursion consumes much more memory space).
head is a (private) member of the List class. There is no variable named head in main(), that is why the compiler is complaining.
I would suggest either:
adding a method to List to return the head node, then you can pass it to printListRecur():
class List {
...
public:
...
nodePtr getHead() { return head; }
...
void printListRecur(nodePtr node);
...
};
list.printListRecur(list.getHead());
remove the input parameter from printListRecur(), and then define a private method for printListRecur() to call recursively, passing it the head node:
class List {
private:
...
void internalPrintListRecur(nodePtr node);
...
public:
...
void printListRecur();
...
};
void List::internalPrintListRecur(nodePtr node)
{
if (node)
{
cout << node->data <<endl;
internalPrintListRecur(node->next);
}
}
void List::printListRecur()
{
internalPrintListRecur(head);
}
But, as others stated in comments, iterating through the list recursively is not usually desired due to the fact that data may have to be pushed onto the call stack on each iteration. Using recursion to iterate a large list is subject to a stack overflow error, unless the code is written in a way that allows the compiler to apply tail call optimization to avoid the stack error.
In this example, it is better to just use a simple iterative loop instead, like your printList() is already using. Don't use recursion.
I'm trying to code a binary tree search/insert/print(BFS) functions.
It compiles fine, but I keep getting segment faults when I try to insert new nodes. Consequently, I could not test the print function neither. Any suggestions, lads?
I did code the functions in a separate Binarytree.cpp file, by the way.
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include <iostream>
#include <vector>
using namespace std;
typedef struct Node{
int key;
struct Node* leftNode;
struct Node* rightNode;
//C++에서는 struct의 constructor 가능
Node(int _key){key = _key;};
} Node;
class BinaryTree
{
private:
static Node* rootNode;
public:
static Node* search(int searchkey){
Node* curNode = rootNode;
while (curNode){
if (searchkey == curNode->key){
break;
} else if (searchkey < curNode->key){
curNode = curNode->leftNode;
} else {
curNode = curNode->rightNode;
}
}
return curNode;
}
static bool insert(int insertkey){
Node* curNode = search(insertkey);
if (insertkey == search(insertkey)->key){
cout << "Key already exits" << endl;
return false;
}
if (!rootNode){
rootNode = new Node(insertkey);
return true;
} else {
Node* newNode = new Node(insertkey);
newNode = search(insertkey);
return true;
}
}
static void print(){
//Node* rootNode = getRoot();
vector<Node*> v;
if (rootNode == NULL){
cout << "Binary tree is empty." << endl;
return;
} else {
v.push_back(rootNode);
cout << rootNode->key << endl;
}
while (!v.empty()){
Node* temp = v.front();
v.erase(v.begin());
if (temp->leftNode){
v.push_back(temp->leftNode);
cout << temp->leftNode->key << endl;
}
if (temp->rightNode){
v.push_back(temp->rightNode);
cout << temp->rightNode->key << endl;
}
}
}
};
Node* BinaryTree::rootNode = NULL;
#endif
Here in insert:
Node* curNode = search(insertkey);
When you call insert the first time, curNode will be NULL. In the following condition:
if (insertkey == search(insertkey)->key){
cout << "Key already exits" << endl;
return false;
}
you are trying to deference a NULL pointer by doing search(insertkey)->key. This causes the seg fault.
Here is the output from backtrace in gdb on my machine:
Program received signal SIGSEGV, Segmentation fault.
0x00000000004009a3 in BinaryTree::insert (insertkey=1) at binarytree.h:38
38 if (insertkey == search(insertkey)->key){
(gdb) backtrace
#0 0x00000000004009a3 in BinaryTree::insert (insertkey=1) at binarytree.h:38
A quick way you can fix this is check if the return from search is NULL first, then move on to other cases.