AVL Trees C ++的Ostream运算符

时间:2017-12-28 14:29:51

标签: c++ templates recursion avl-tree ostream

议程是使用ostream运算符打印AVL树的内容。内容必须以特定格式打印。

树是使用模板实现的。 一个简单的主要实现。

document

Ostream Operator

AVLTree<int, float> tree;
for(int i = 0; i < 10; i++)
   tree.insert(i, i+0.1);
cout << tree;

我有两个帮助函数可供打印。

我得到的输出是

friend ostream&  operator<<(ostream& out, const AVLTree& v)
{   
    out << "{";
    v.print(out, v.root);
    out << "}";
    return out;
}


void print(AVLnode<KEY,INFO>* curr)const
    {
        if(curr)
        {
            print(curr->left);
            print(curr->right);
        }
    }

void print(ostream& out, AVLnode<KEY, INFO>* curr)const
    {
        if(curr)
        {
            print(out, curr->left);
            out << curr->Key_ << ": " << curr->Info_<<", ";
            print(out, curr->right);
        }
    }

所需的输出是

{1:1.1, 2:2.1. 3:3.1, 4:4.1, 5:5.1, 6:6.1, 7:7.1, 8:8.1, 9:9.1, }

不应该打印“,”,如何检测树的最后一个元素?我无法理解这种情况。这很简单,但我没有看到它。

5 个答案:

答案 0 :(得分:0)

介绍一个简单的if statement条件:

out << curr->Key_ << ": " << curr->Info_;
if (some_condition_of_yours) {
    out << ", ";
} 
else {
    out << " ";
}

用您的内部逻辑替换条件

答案 1 :(得分:0)

我可以通过两种方式来实现这一目标:

1

生成字符串,存储在变量中,然后删除最后2或3个字符(取决于间距),然后附加}以关闭格式,然后输出到ostream

2

进入第一个打印功能时,将计数器设置为0,并在每次处理节点时递增。这将为您提供打印的项目总数。然后,您可以将其与AVL树中的项目总数进行比较。您还必须跟踪某处的项目总数。

我会使用选项一,因为它现在更容易实现。此外,AVL树不应该知道其中有多少项。此外,树越大,打印速度越慢,因为将有更多if语句和count增量。这两项操作很少,但如果你得到数以千计的项目,它就会加起来。

答案 2 :(得分:0)

我想您需要print()中的其他参数来了解右侧是否有内容。

通过示例(警告:未经测试)

friend ostream&  operator<<(ostream& out, const AVLTree& v)
{   
    out << "{";
    v.print(out, v.root, false);
    out << "}";
    return out;
}


void print (ostream & out, AVLnode<KEY, INFO> * curr, bool proComma) const
    {
        if (curr)
        {
            bool proC2 = proComma || (NULL != curr->right);

            print(out, curr->left, proC2);

            out << curr->Key_ << ": " << curr->Info_;

            if ( proC2 )
               out << ", ";

            print(out, proComma);
        }
    }

答案 3 :(得分:0)

另一种思考此问题的方法是先打印逗号 ,而不是最后一次。这样你永远不会得到一个尾随的逗号,因为它将是第一个打印的项目。

这可以通过在辅助函数中引入bool引用变量(未测试)来实现:

friend ostream&  operator<<(ostream& out, const AVLTree& v)
{   
    bool firstTime = true;
    out << "{";
    v.print(out, v.root, firstTime);
    out << "}";
    return out;
}


void print(ostream& out, AVLnode<KEY, INFO>* curr, bool& firstTime) const
{
    if (curr)
    {
       print(out, curr->left, firstTime);
       out << (firstTime?"":", ") << curr->Key_ << ": " << curr->Info_;
       firstTime = false;
       print(out, curr->right, firstTime);
    }
}

firstTime跟踪是否是第一次打印。如果是这种情况,则不会打印逗号,否则会打印逗号。

答案 4 :(得分:0)

所以过了一会儿我弄清楚问题是什么,并且能够提出一个简单的解决方案,所以我决定在忘记这样做之前发布答案。

由于树的左侧和右侧都有一个NULL结尾,因此很难检测到树中的最后一个节点。因此,打印整个树并删除多余的字符就可以很好地完成这个任务。

template<typename KEY, typename INFO>
void AVLTree<KEY, INFO>:: print(ostream& out, AVLnode<KEY,INFO>* curr) const{
        //sstream operator to calc the output and delete (n-1) of the output.        
        out << "{";
        std::stringstream ss;
        printHelp(ss, curr);
        std::string output = ss.str();
        if (output.length() > 1)
            output.erase(output.end()-2, output.end());

        out << output;
        out << "}";
}

template<typename KEY, typename INFO>
void AVLTree<KEY, INFO>::printHelp(std::stringstream& ss, AVLnode<KEY, INFO>* curr) const{
    if(curr){
            printHelp(ss, curr->left);  
            ss << curr->Key_<< ": " << curr->Info_ << ", ";
            printHelp(ss, curr->right);
        }
}

然后使用带有根节点作为参数的打印函数和ostream对象的ostream运算符。

friend ostream& operator<<(ostream& out, const AVLTree& v){
        v.print(out, v.root);
        return out;
    }

还有另一种方法可以将它们推入堆栈并弹出最后一个字符并完全打印堆栈,这非常接近我所需要的但是效率非常低,因为树上有接近15,000个节点。 / p>