【发布时间】:2022-01-12 01:25:50
【问题描述】:
我有一个任务是将后缀表达式从 txt 文档转换为二叉树,然后计算表达式。基类是为我完成的,所以我不会将它包含在我的代码 sn-ps 中。我正在使用和 getline() 逐行读取文件并将每个分配给一个字符串变量,然后传递给我的派生类。然而,我正在努力的部分是将字符串转换为 char 数组(因为分配需要我们这样做),然后使用该数组来确定在树上添加每个索引值的位置。我认为问题在于文本文档使用的数字大于 9(例如:35),我不知道如何在我的代码中解释这一点,所以我不断收到分段错误错误。无论如何,我将在下面发布一些代码,非常感谢任何帮助、解释或参考。
主要功能:
int main()
{
ifstream inFile;
ofstream outFile;
string pfx;
binaryExpressionTree tree;
inFile.open("RpnData.txt");
outFile.open("RpnDataOut.txt");
do
{
tree.destroyTree();
getline(inFile, pfx);
tree.buildExpressionTree(pfx);
outFile << tree.evaluateExpressionTree() << endl;
}
while (inFile);
}
我的班级的头文件:
#ifndef EXPRESSIONTREE_H
#define EXPRESSIONTREE_H
#include "binaryTree.h"
class binaryExpressionTree : public binaryTreeType<string>
{
public:
void buildExpressionTree(string);
//Function to build the binary expression tree using a postfix string as a parameter
//Precondition: Must read a string as a parameter
//Postcondition: Will convert the string to a binary tree
double evaluateExpressionTree();
//Function to evaluate the expression tree
//Postcondition: Recursively calls the private function to evaluate the expression tree
bool search(const string&) const;
//Function to search for a string in the tree
//Precondition: Must have the address of a string to search for
//Postcondition: Returns true if string is found in the tree and false otherwise
void insert(const string&);
//Function to insert a string at the end of a branch on the tree
//Precondition: Must have the address of a string to insert
//Postcondition: Inserts the string at the end of a branch
void deleteNode(const string&);
//Function to delete one node (containing the string provided as a parameter) of the tree
//Precondition: Must have the address of a string to delete
//Postcondition: Deletes the string from the tree
private:
double evaluateExpressionTree(nodeType<string>*);
//Private function to evaluate the expression tree
//Precondition: Must have a pointer to a nodeType on the tree
//Postcondition: Returns the value of the postfix expression
};
#endif
产生问题的代码:
void binaryExpressionTree::buildExpressionTree(string pfxExpression)
{
stack<nodeType<string>*> *tree;
char* expression = new char[pfxExpression.length() +1];
strcpy(expression, pfxExpression.c_str());
for (int i = 0; i < pfxExpression.length(); i++)
{
if ((expression[i] >= 'a' && expression[i] <= 'z') || (expression[i] >= 'A' && expression[i] <= 'Z') || (expression[i] >= '0' && expression[i] <= '9'))
{
nodeType<string> *newNode;
newNode = new nodeType<string>; //Create new node
newNode->info = string(expression[i], expression[i+1]); //Set string of i to i+1 character in array to the info field
newNode->lLink = nullptr; //Make pointers for each branch nullptr
newNode->rLink = nullptr;
tree->push(newNode); //Push node onto the stack
//Through the use of cout statements, I have found that the error lies on the line above
}//end if
以下是文本文件中的表达式:
35 27 + 3 *
23 30 15 * /
34 24 12 7 / * + 23 -
3 7 + 14 *
以下内容来自赋值方向本身作为 buildExpressionTree() 成员函数的算法。如果格式已关闭,我深表歉意,我试图使其尽可能可读。
Here is the algorithm for building the expression tree:
Initialize a stack of pointers to binary tree nodes
Get a postfix expression (this will be an input to the evaluateExpressionTree function)
// This line did not really make sense to me since evaluate() takes no parameters
Convert the string to a character array (include <cstring>)
// This is the wording that led me to believe we are supposed to convert it
//to a char array
For each token in the expression:
If token is a number:
Create a node
Convert the token from a character array to a string
Store the string in the info field
Push the new node onto the stack
else if token is an operator:
Create a node and store the operator in the info field
If stack is not empty:
Use top() to get a reference to the node at the top of the stack
Store the reference in the rLink field of the new node.
Use pop() to remove the node from the stack
If stack is not empty:
Use top() to get a reference to the node at the top of the stack
Store the reference in the lLink field of the new node
Use pop() to remove the node from the stack
Push the new node back onto the stack
else:
Error – Stack is empty
else:
Error – Stack is empty
else:
Error – unsupported token
Get the next token
//This ends the for loop
if stack is not empty:
Pop the expression tree from the stack and store in root
If stack is not empty:
There was an error, set root back to null
最后,我将包含基类。挖的比较多,我的教授没有把头文件和实现文件分开。
//Header File Binary Search Tree
#ifndef H_binaryTree
#define H_binaryTree
#include <iostream>
using namespace std;
//Definition of the Node
template <class elemType>
struct nodeType
{
elemType info;
nodeType<elemType> *lLink;
nodeType<elemType> *rLink;
};
//Definition of the class
template <class elemType>
class binaryTreeType
{
protected:
nodeType<elemType> *root;
public:
const binaryTreeType<elemType>& operator=
(const binaryTreeType<elemType>&);
//Overload the assignment operator.
bool isEmpty() const;
//Function to determine whether the binary tree is empty.
//Postcondition: Returns true if the binary tree is empty;
// otherwise, returns false.
void inorderTraversal() const;
//Function to do an inorder traversal of the binary tree.
//Postcondition: Nodes are printed in inorder sequence.
void preorderTraversal() const;
//Function to do a preorder traversal of the binary tree.
//Postcondition: Nodes are printed in preorder sequence.
void postorderTraversal() const;
//Function to do a postorder traversal of the binary tree.
//Postcondition: Nodes are printed in postorder sequence.
int treeHeight() const;
//Function to determine the height of a binary tree.
//Postcondition: Returns the height of the binary tree.
int treeNodeCount() const;
//Function to determine the number of nodes in a
//binary tree.
//Postcondition: Returns the number of nodes in the
// binary tree.
int treeLeavesCount() const;
//Function to determine the number of leaves in a
//binary tree.
//Postcondition: Returns the number of leaves in the
// binary tree.
void destroyTree();
//Function to destroy the binary tree.
//Postcondition: Memory space occupied by each node
// is deallocated.
// root = NULL;
virtual bool search(const elemType& searchItem) const = 0;
//Function to determine if searchItem is in the binary
//tree.
//Postcondition: Returns true if searchItem is found in
// the binary tree; otherwise, returns
// false.
virtual void insert(const elemType& insertItem) = 0;
//Function to insert insertItem in the binary tree.
//Postcondition: If there is no node in the binary tree
// that has the same info as insertItem, a
// node with the info insertItem is created
// and inserted in the binary search tree.
virtual void deleteNode(const elemType& deleteItem) = 0;
//Function to delete deleteItem from the binary tree
//Postcondition: If a node with the same info as
// deleteItem is found, it is deleted from
// the binary tree.
// If the binary tree is empty or
// deleteItem is not in the binary tree,
// an appropriate message is printed.
binaryTreeType(const binaryTreeType<elemType>& otherTree);
//Copy constructor
binaryTreeType();
//Default constructor
~binaryTreeType();
//Destructor
private:
void copyTree(nodeType<elemType>* &copiedTreeRoot,
nodeType<elemType>* otherTreeRoot);
//Makes a copy of the binary tree to which
//otherTreeRoot points.
//Postcondition: The pointer copiedTreeRoot points to
// the root of the copied binary tree.
void destroy(nodeType<elemType>* &p);
//Function to destroy the binary tree to which p points.
//Postcondition: Memory space occupied by each node, in
// the binary tree to which p points, is
// deallocated.
// p = NULL;
void inorder(nodeType<elemType> *p) const;
//Function to do an inorder traversal of the binary
//tree to which p points.
//Postcondition: Nodes of the binary tree, to which p
// points, are printed in inorder sequence.
void preorder(nodeType<elemType> *p) const;
//Function to do a preorder traversal of the binary
//tree to which p points.
//Postcondition: Nodes of the binary tree, to which p
// points, are printed in preorder
// sequence.
void postorder(nodeType<elemType> *p) const;
//Function to do a postorder traversal of the binary
//tree to which p points.
//Postcondition: Nodes of the binary tree, to which p
// points, are printed in postorder
// sequence.
int height(nodeType<elemType> *p) const;
//Function to determine the height of the binary tree
//to which p points.
//Postcondition: Height of the binary tree to which
// p points is returned.
int max(int x, int y) const;
//Function to determine the larger of x and y.
//Postcondition: Returns the larger of x and y.
int nodeCount(nodeType<elemType> *p) const;
//Function to determine the number of nodes in
//the binary tree to which p points.
//Postcondition: The number of nodes in the binary
// tree to which p points is returned.
int leavesCount(nodeType<elemType> *p) const;
//Function to determine the number of leaves in
//the binary tree to which p points
//Postcondition: The number of leaves in the binary
// tree to which p points is returned.
};
//Definition of member functions
template <class elemType>
binaryTreeType<elemType>::binaryTreeType()
{
root = NULL;
}
template <class elemType>
bool binaryTreeType<elemType>::isEmpty() const
{
return (root == NULL);
}
template <class elemType>
void binaryTreeType<elemType>::inorderTraversal() const
{
inorder(root);
}
template <class elemType>
void binaryTreeType<elemType>::preorderTraversal() const
{
preorder(root);
}
template <class elemType>
void binaryTreeType<elemType>::postorderTraversal() const
{
postorder(root);
}
template <class elemType>
int binaryTreeType<elemType>::treeHeight() const
{
return height(root);
}
template <class elemType>
int binaryTreeType<elemType>::treeNodeCount() const
{
return nodeCount(root);
}
template <class elemType>
int binaryTreeType<elemType>::treeLeavesCount() const
{
return leavesCount(root);
}
template <class elemType>
void binaryTreeType<elemType>::copyTree
(nodeType<elemType>* &copiedTreeRoot,
nodeType<elemType>* otherTreeRoot)
{
if (otherTreeRoot == NULL)
copiedTreeRoot = NULL;
else
{
copiedTreeRoot = new nodeType<elemType>;
copiedTreeRoot->info = otherTreeRoot->info;
copyTree(copiedTreeRoot->lLink, otherTreeRoot->lLink);
copyTree(copiedTreeRoot->rLink, otherTreeRoot->rLink);
}
} //end copyTree
template <class elemType>
void binaryTreeType<elemType>::inorder
(nodeType<elemType> *p) const
{
if (p != NULL)
{
inorder(p->lLink);
cout << p->info << " ";
inorder(p->rLink);
}
}
template <class elemType>
void binaryTreeType<elemType>::preorder
(nodeType<elemType> *p) const
{
if (p != NULL)
{
cout << p->info << " ";
preorder(p->lLink);
preorder(p->rLink);
}
}
template <class elemType>
void binaryTreeType<elemType>::postorder
(nodeType<elemType> *p) const
{
if (p != NULL)
{
postorder(p->lLink);
postorder(p->rLink);
cout << p->info << " ";
}
}
//Overload the assignment operator
template <class elemType>
const binaryTreeType<elemType>& binaryTreeType<elemType>::
operator=(const binaryTreeType<elemType>& otherTree)
{
if (this != &otherTree) //avoid self-copy
{
if (root != NULL) //if the binary tree is not empty,
//destroy the binary tree
destroy(root);
if (otherTree.root == NULL) //otherTree is empty
root = NULL;
else
copyTree(root, otherTree.root);
}//end else
return *this;
}
template <class elemType>
void binaryTreeType<elemType>::destroy(nodeType<elemType>* &p)
{
if (p != NULL)
{
destroy(p->lLink);
destroy(p->rLink);
delete p;
p = NULL;
}
}
template <class elemType>
void binaryTreeType<elemType>::destroyTree()
{
destroy(root);
}
//copy constructor
template <class elemType>
binaryTreeType<elemType>::binaryTreeType
(const binaryTreeType<elemType>& otherTree)
{
if (otherTree.root == NULL) //otherTree is empty
root = NULL;
else
copyTree(root, otherTree.root);
}
//Destructor
template <class elemType>
binaryTreeType<elemType>::~binaryTreeType()
{
destroy(root);
}
template<class elemType>
int binaryTreeType<elemType>::height
(nodeType<elemType> *p) const
{
if (p == NULL)
return 0;
else
return 1 + max(height(p->lLink), height(p->rLink));
}
template <class elemType>
int binaryTreeType<elemType>::max(int x, int y) const
{
if (x >= y)
return x;
else
return y;
}
template <class elemType>
int binaryTreeType<elemType>::nodeCount(nodeType<elemType> *p) const
{
if (p == nullptr)
return 0;
else
return 1 + nodeCount(p->lLink) + nodeCount(p->rLink);
}
template <class elemType>
int binaryTreeType<elemType>::leavesCount(nodeType<elemType> *p) const
{
if (p->lLink != nullptr && p->rLink != nullptr)
return 0 + leavesCount(p->lLink) + leavesCount(p->rLink);
else
return 1;
}
#endif
【问题讨论】:
-
基类是为我完成的,所以我不会将它包含在我的代码 sn-ps 中。 糟糕的计划。请记住,我们现在在这里,将来的提问者将无法访问此基类,这可能会使您的问题无用。
-
strcpy(expression, pfxExpression.c_str());-- 解释你为什么不在这里使用std::string以及整个代码集。为什么要使用 char 数组/缓冲区,并以未经检查的方式写入它们?我会删除所有使用C风格的字符串函数(例如strcpy)的迹象,使用std::string执行所有操作,并且仅当函数需要char 指针时,我才会在已经存在的@ 上发出c_str()调用987654333@. -
getline(inFile, pfx);可能会失败,并且在使用数据之前不会执行对有效数据的检查。请改用while (getline(inFile, pfx)) { \\do stuff with pfx }。它读取并且仅在数据确实被读取时才进入。 -
因为任务要求我们这样做 绝对肯定你需要这样做,因为这是一件非常愚蠢的事情。这种要求使年轻程序员成为更差的程序员而不是更好的程序员。
-
@darcamo 我明白你在说什么,我认为这实际上是这里的问题。但是,当我尝试将根节点分配给树指针时,出现错误。
标签: c++ arrays stack binary-tree