我正在进行这个项目的兴趣,并继续回到它...
我尝试创建的是一种枚举Fibonacci值二叉树值的算法:
我用来打印这棵树的排列的算法:
每个集合应该加起来为root的值。我认为我尝试描述算法中每个步骤的方法可能并不完全清楚 - 在编写算法步骤的最佳实践方面的任何帮助对我都有用。
我在这里期待的结果,列举上面的树将是:
([root 0] 5),([left 1] 3,[right 1] 2),([left 1] 3,[left 3] 1,[right 3] 1),([left 2] 2,[右2] 1,[右1] 2),([左2] 2,[右2] 1,[左3] 1,[右3] 1)
我想采用递归方法,并将作为一种方法合并到我创建的构建树的二进制结构类中。所以这不是关于构建树结构,而是按照上面的方法遍历它,或者产生相同结果的方法。
有人可以帮助我吗?任何帮助将不胜感激。
class FibTree {
public:
class Node {
public:
int data;
Node const* left;
Node const* right;
Node const* parent;
int n;
int level;
int index;
Node (void);
};
Node const* root; // 'root' pointer to constant Node
FibTree (int);
Node const* getRoot(void);
void startWriteSets(Node const* root); // Write all sets of tree
private:
static Node* buildTree( int n, int level = 0, int i = 1, Node* parent = NULL );
// Used by startWriteSets
void writeSets(std::vector<Node const*> &setsList, Node const* cur);
// FibTree Constructor
FibTree::FibTree(int n) {
this->root = buildTree( n );
};
// Getters
FibTree::Node const* FibTree::getRoot(void) {
return this->root;
}
// Write sets of tree
void FibTree::startWriteSets(Node const* root) {
std::vector<Node const*> setsList;
std::cout << root->data;
writeSets(setsList, root);
}
// Private FibTree methods
FibTree::Node* FibTree::buildTree( int n, int level, int i, Node* parent ) { // Build Tree structure
Node* thisNode = new Node();
thisNode->n = n;
thisNode->level = level;
thisNode->index = i;
thisNode->parent = parent;
if (n < 2) {
thisNode->left = NULL;
thisNode->right = NULL;
thisNode->data = n;
return thisNode;
} else {
thisNode->left = buildTree( n - 1 , level + 1, i*2, thisNode );
thisNode->right = buildTree( n - 2, level + 1, i*2+1, thisNode );
thisNode->data = thisNode->left->data + thisNode->right->data;
return thisNode;
}
}
void FibTree::writeSets(std::vector<Node const*> &setsList, Node const* cur) {
std::vector<Node const*>::iterator nodeIterator;
// Displays all preceding left values
for (nodeIterator = setsList.begin();
nodeIterator != setsList.end(); nodeIterator++) {
std::cout << *nodeIterator->data;
}
std::cout << cur->left->data;
std::cout << cur->right->data;
setsList.push_back(cur->left);
writeSets(setsList,cur->right);
setsList.pop_back();
}
// FibTree Node constructor
FibTree::Node::Node()
: data( 0 ),
left( NULL ),
right( NULL ),
parent( NULL ),
n( 0 ),
level( 0 ),
index( 0 )
{
};
我在std::cout << *nodeIterator->data;
报告中void FibTree::writeSets
收到编译错误:
_error:请求成员&#39;数据& #39;在&#39; * nodeIterator中。 __gnu_cxx :: __ normal_iterator&lt; _Iterator,_Container&gt; :: operator-&gt;使用_Iterator = const FibTree :: Node **, Container = std :: vector&gt;&#39;,这是非类型的&#c; const FibTree :: Node *&#39;
非常感谢任何追踪此错误的帮助!
答案 0 :(得分:1)
任何树都可以被视为指向头节点的指针。节点构造函数:
Node(int val,Node* left,Node* right)
树构造函数:
Node* Tree(int n){
return new Node(fib(n),Tree(n-1),Tree(n-2));
}
这会有效,但会有指数时复杂度,我建议您使用动态编程来保存以前的树。
现在按照你的说法设置它们必须总结为root,例如5 = 3 + 2.在其他集合中,你只能找到将3和2写成集合的方法。为了找到将3作为一组写入的方法,你可以递归调用你调用5的相同函数。
vector < vector <int> > SetOfSets(Node * root){
vector < vector <int> > leftSets = SetOfSets(root.left);
vector < vector <int> > rightSets = SetOfSets(root.right);
vector < vector <int> > ans;
for(int i=0;i<leftSets.size();i++){
for(int j=0;i<rightSets.size();j++){
ans.push_back(leftSets[i].insert(leftSet[i].end(),rightSet[j].begin(),rightSet[j].end()));
}
}
return ans;
}
为最终案例添加代码(root.val == 1),您就完成了。
答案 1 :(得分:1)
你遇到的问题不是你需要遍历B树。这是相当直接的。你遇到的问题是你需要跟踪方程的另一半的状态。 Aka,当你进入右链的第二层时,你仍然需要知道[left 1] = 3.
对此的可能解决方案是跟踪向量(或其他构造)中的左节点。那就是......
void start(void) {
vector<NODE*> list;
cout << head->val;
visit(list, head);
}
void visit(vector<NODE*> &list, NODE *cur) {
// Displays all preceding left values.
for (vector<NODE*> it = list.begin(); it != list.end(); it++) {
cout << *it->val;
}
cout << cur->left->val;
cout << cur->right->val;
list.push_back(cur->left);
visit(list, cur->right);
list.pop_back();
}
这会在正确的方向上为您提供所需的信息。您需要添加适当的安全检查和其他方向,但它应该让您前进。
答案 2 :(得分:0)
考虑节点的结构是:
struct SNode
{
int m_iValue;
SNode* m_psLeft;
SNode* m_psRight;
};
我认为最接近你想要的是:
//returns true if there are still not visited children
bool Traverse(SNode* psNode, int iDepth)
{
if(iDepth > 0)
{
bool bLeftRes;
if(psNode->m_sLeft != NULL)
{
bLeftResult = Traverse(psNode->m_psLeft, iDepth - 1);
}
else
{
bLeftResult = false;
}
bool bRightRes;
if(psNode->m_sLeft != NULL)
{
bRightRes = Traverse(psNode->m_psRight, iDepth - 1);
}
else
{
bRightRes = false;
}
return bLeftRes || bRightRes;
}
else
{
printf("%d ", psNode->m_iValue);
return psNode->m_psLeft || psNode->m_psRight;
}
}
所以遍历调用看起来像:
int i = 0;
printf("(");
while(Traverse(psRoot, i))
{
printf(")\n(");
++i;
}
printf(")");
输出将与您的树: (5) (3 2) (2 1 1 1)