c ++ binarysearchtree insert

时间:2010-11-12 03:41:03

标签: c++ binary-tree

我正在开发一个项目,我必须创建一个存储字符串并考虑双打的二叉搜索树。虽然我已经解决了具体问题,但我不能为我的生活让这个该死的插入功能起作用。它似乎只存储根节点,留下它的“子”NULL,即使它实际上似乎确实将左和右指针分配给新节点。但是,当我尝试输出它时,只存在主父(根)节点。我想这些变化不会因为某种原因而被保存。

这是头文件:

#ifndef BST_H
#define BST_H

#include <string>
#include <vector>
#include <iostream>
using namespace std; 

typedef string ItemType; 

class Node
{
 public:
 Node(); // constructor 
 ItemType data; // contains item
 Node* left; // points to left child
 Node* right;// points to right child
 int dataCount; // keeps track of repeats
 vector<int> lineNumber; // keeps track of line numbers 
};

class Tree
{
 public:
 Tree(); // constructor
// ~Tree(); // destructor. not working.
 bool isEmpty(); // tests for empty tree
 Node* find(Node* root, ItemType item); // finds an item
 void insert(Node* root, ItemType item, int lineN, Tree tree); // inserts an item
 void outputTree(Node* root); // lists all items in tree 
 void treeStats(Tree tree); // outputs tree stats 
 void clearTree(); // erases the tree (restart)
 Node* getRoot(); // returns the root
 void setRoot(Node*& root); 
// void getHeight(Tree *root); // gets height of tree

 private:
 Node* root; // root of tree
 int nodeCount; // number of nodes
};

#endif

cpp:

#include "BST.h"

bool setRootQ = true;

/** Node constructor- creates a node, sets children 
 *  to NULL and ups the count. */
Node::Node()
{
 left = right = NULL; 
 dataCount = 1;
}

/** Tree constructor- creates instance of tree
 *  and sets parameters to NULL */  
Tree::Tree()
{
 root = NULL; 
 nodeCount = 0; 
}

/** Destructor- deallocates tree/node data;
 *  avoids heap leaks. SOMETHING WRONG. CAUSES SEGFAULT
Tree::~Tree()
{
 if(this->root->left) // if a left child is present
 {
  delete this->root->left; //recursive call to destructor ("~Tree(->left)")
  this->root->left = NULL; 
 }
 if(this->root->right) // if a right child is present
 {
  delete this->root->right; //recursive call to destructor 
  this->root->right = NULL; 
 }
} */

/** Returns true if tree is empty. 
 *  Otherwise returns false (DUH). */
bool Tree::isEmpty()
{
 return root == NULL; 
}

/** Searches tree for item; returns the node if found
 * @param root- tree node.
 *   item- data to look for. */
Node* Tree::find(Node* root, ItemType item)
{
 if(root == NULL) // if empty node
 {
  return NULL;
 }
 else if(item == root->data) // if found
 {
  return root; 
 }
 else if(item < root->data) // if item is less than node 
 {
  find(root->left, item); 
 }
 else if(item > root->data) // if item is more than node
 {
  find(root->right, item); 
 }

 return NULL;
}

/** Adds a new node to the tree. If duplicate, increases count. 
 * @param item- data to insert.
 *   root- tree node/ */
void Tree::insert(Node* root, ItemType item, int lineN, Tree tree)
{
 Node* temp = find(tree.getRoot(), item);
 if(temp != NULL) // if item already exists
 {
  temp->dataCount += 1;
  temp->lineNumber.push_back(lineN);
  return;
 }

 if(root == NULL) // if there is an empty space
 {
  root = new Node;   // insert new node  
  root->data = item; // w/ data value
  root->lineNumber.push_back(lineN);
  nodeCount++; 

  if(setRootQ)
  { 
   setRoot(root);
   setRootQ = false;
  } 
  return; 
 }

 if(item < root->data)
 {
  insert(root->left, item, lineN, tree);
 }
 if(item > root->data)
 {
  insert(root->right, item, lineN, tree);
 }
}

/** Outputs tree to console in inorder.
 * @param root- tree root. */
void Tree::outputTree(Node* root)
{
 if(isEmpty()) // if empty tree
 {
  cout << "Error: No items in tree" << endl; // error message
 }
 else
 { 
  if(root->left != NULL)
  {
   outputTree(root->left);
  }

  cout << "- " << root->data << " (" << root->dataCount << ") line#s: ";
  for(unsigned int i = 0; i < root->lineNumber.size(); i++)
  {
   cout << root->lineNumber[i] << ", ";
  }
  cout << endl;

  if(root->right != NULL)
  {
   outputTree(root->right);
  }
 }
}

/** Displays tree stats including number of nodes,
 *  tree height, and more frequent item.
 * @param tree- tree instance. */
void Tree::treeStats(Tree tree) 
{
 cout << "Number of entries: " << nodeCount << endl;
 // unfinished
}

/** Clears tree. 
void Tree::clearTree()
{
 this->~Tree();
} */

/** Returns the root of the tree. */
Node* Tree::getRoot()
{
 return root;
}

void Tree::setRoot(Node*& rootS)
{
 root = rootS;
}

我意识到我的析构函数不起作用,但我稍后会解决这个问题。我一直在拉着头发试图找出我失踪的东西,但无济于事。如果有人能给我任何帮助并指出我的解决方案,我将非常感激。

我认为可能

有关
void Tree::insert(Node* root, ItemType item, int lineN, Tree tree)

而应该像

void Tree::insert(Node* &root, ItemType item, int lineN, Tree tree)

但是当我尝试获得“无匹配功能”错误时。 :/

2 个答案:

答案 0 :(得分:0)

似乎有很多指针比较发生但指针成员变量没有被初始化。确保正确初始化指针成员变量,以便它们在if语句中正确评估。

更改自:

class Node
{
 public:
 Node(); // constructor 
...  
};  

to   

class Node
{
 public:
 Node() : left(0), right(0) {}
...
};

答案 1 :(得分:0)

您自己建议的解决方案(insert()使用Node *& root)将起作用。您必须对.h文件进行相应的更改,并且还要更改getRoot()以在.h和.cc文件中返回Node *&

这会奏效。但是你的代码还有其他问题。例如,就我所知,setRootsetRootQ没有做任何有用的事情。 insert()的第四个参数只会混淆事物而无法检测重复项。它应该删除。要检测重复项,只需在if (item == root->data)方法中执行if (item < root->data)之前执行insert()(即它与find()更相似)。

此外,如果您以外的任何人都使用您的代码,则不应要求getRoot()传递给find()insert()等方法。相反,创建私有帮助器方法,如find_helper(Node*, Item)insert_helper(Node*&,Item),并让公共方法以根节点作为第一个参数调用它们。 E.g:

Node *find(Item item) { return find_helper(root, item); }

这也会使getRoot()的奇怪返回类型变得不必要,您可以将其更改为返回普通Node*,或者完全删除该访问者。