AVL树C 的Ostream操作员

Ostream Operator for AVL Trees C++

本文关键字:Ostream 操作员 AVL      更新时间:2023-10-16

议程是使用Ostream Operator打印AVL树的内容。内容必须以特定格式打印。

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

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

Ostream Operator

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, }

所需的输出为

{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}

"不应该打印,如何检测树的最后一个元素?我不了解情况。这很简单,但我看不到它。

考虑此问题的另一种方法是打印逗号 first ,而不是最后。这样,您将永远不会得到尾随的逗号,因为它将是第一个打印的物品。

可以通过在辅助功能中引入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跟踪是否是第一次打印。如果是这种情况,则不会打印逗号,否则打印了逗号。

我可以看到的两种方法:

1。

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

2。

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

我将使用选项ONE,因为现在更容易实现。另外,AVL树不应该知道其中有多少个物品。同样,您的树越大,打印速度越慢,因为语句和count增量会增加更多。这两个操作很少,但是如果您收到数千或数百万的项目,则会加起来。

引入一个简单的if语句条件:

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

用内部逻辑替换条件

我想您需要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);
        }
    }

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

真的很难检测到树上的最后一个节点,因为树的左侧和右侧都有无效的结尾。因此,打印整棵树并删除额外的字符确实做得很好。

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);
        }
}

,然后使用root节点作为参数和Ostream对象的Ostream Operator。

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

还有另一种选择,将它们推入堆栈并弹出最后一个字符并完全打印堆栈,这非常接近我所需的内容,但由于树上有接近15,000个节点,因此非常效率。/p>