Cevapi Man69
Cevapi Man69

Reputation: 11

Segmentation fault for inserting into an BST

So for this class here, I have to write out functions, including a recursive find function, an insert function, and a operator[] function, which overall helps insert into a BST

#include <compare>
#include <cstddef>
#include <format>
#include <iostream>
#include <string>
#include <utility>


template<typename Key, typename Value>
struct BST
{
  using KeyValue_Pair = std::pair<Key const, Value>;

  struct Node
  {
    Node() = default;
    Node( KeyValue_Pair const & pair ) : _pair{ pair } {}

    KeyValue_Pair _pair = { Key{}, Value{} };

    Node * _left   = nullptr;
    Node * _right  = nullptr;
    Node * _parent = nullptr;
  };

  Node *      _root = nullptr;
  std::size_t _size = 0;


Node * find( Key const & key )
 {
   return find(key, _root);  // Delegate the call to the private helper function
 }

Node* find(Key const& key, Node* current) {
    // Base Case: Node not found
    if (current == nullptr) {
        return nullptr;
    }

    // Visit: Node found
    if (key == current->_pair.first) {
        return current;
    }

    // Recurse: Search left or right subtree
    if (key < current->_pair.first) {
        return find(key, current->_left);
    } else {
        return find(key, current->_right);
    }
}

Node * insert( KeyValue_Pair const & pair ) {
     Node * newNode = new Node( pair );
     if(_root == nullptr){
      _root = newNode;
      ++_size;
      return newNode;
    }
    Node * current = _root;
    Node * parent  = nullptr;

    while(current != nullptr){
      parent = current;
      auto comp   = std::compare_weak_order_fallback( pair.first, current->_pair.first );
      if( comp == 0 ) return current;
      else if(comp < 0 ) current = current->_left;
      current = current->_right;
    }
    auto comp = std::compare_weak_order_fallback( pair.first, current->_pair.first );
    if( comp < 0 ) parent->_left = newNode;
    else parent->_right = newNode;

    newNode->_parent = parent;
    ++_size;
    return newNode;
}

Value & operator[]( Key const & key )
{
  return insert( { key, Value{} } )->_pair.second;
}   

//everything under this comment already came with the code
void print()
{
  auto count = 0uz;
  print( _root, count );
}

void print( Node * current, std::size_t & count )  // in-order traversal
{
  // Base case
  if( current == nullptr ) return;

  // Recurse left
  print( current->_left, count );

  // Visit
  auto && [key, value] = current->_pair;
  std::cout << std::format( "{:3}:  {{{}, {}}}\n", ++count, key, value );

  // Recurse right
  print( current->_right, count );
}

~BST() noexcept
{ clear(); }
};

int main()
{
  BST<unsigned int, std::string> myTree;

  std::cout << "Test Case 1:\n";                     //          50         //
  myTree[50] = "indeed";                             //        /   \        //
  myTree.insert( { 40, "Structures" } );             //       40    60      //
  myTree.insert( { 60, "very" } );                   //      / \   / \      //
  myTree.insert( { 30, "Lego" } );                   //     30 45 55  70    //
  myTree.insert( { 45, "are" } );
  myTree[55] = "truly";
  myTree[70] = "entertaining";
  myTree.print();
  std::cout << "------------------------------\n";
}

yet, I get a segmentation fault (core dumped) error message for test case 1. I'm not sure if the error is in the recursive find or insert function. I would greatly appreciate some feedback, please and thank you. I also apologize if the code is too long, I wanted to include the test case 1 from main but I wasn't sure if I should include the void print functions or not.

Upvotes: 0

Views: 67

Answers (1)

Joseph Larson
Joseph Larson

Reputation: 9068

Your while loop either exits when it finds a match or when it runs out of the bottom -- at which point current is null. The very next statement dereferences current. You maybe mean parent. Is this the output you expect:

  1:  {30, Lego}
  2:  {40, Structures}
  3:  {45, are}
  4:  {50, indeed}
  5:  {55, truly}
  6:  {60, very}
  7:  {70, entertaining}

That's what I got when I made two changes:

cout << "while....\n";
    while(current != nullptr){
      parent = current;
      auto comp   = std::compare_weak_order_fallback( pair.first, current->_pair.first );
      if( comp == 0 ) return current;
      else if(comp < 0 ) current = current->_left;
      else current = current->_right;
    }
cout << "while done\n";
    auto comp = std::compare_weak_order_fallback( pair.first, parent->_pair.first );

See the else-clause at the end of the while loop (you were just setting it) and the dereference of parent instead of current.

Upvotes: 0

Related Questions