# include/net/tree.hpp

# Namespaces

Name
net

# Classes

Name
struct net::tree
树,每个节点包含一个值
struct net::Tree_combine
对树的操作:两个树生成一个新的树
struct net::Tree_act
对树的操作:根节点的值进行改变

# Source code

#ifndef NET_TREE_HPP
#define NET_TREE_HPP
#include "gviz_themes.hpp"
#include <memory>

namespace net {

   template <typename Data>
   struct tree {
      using DataType=Data;

      Data val;

      std::shared_ptr<tree<Data>> left_child;
      std::shared_ptr<tree<Data>> right_child;

      tree() = default;
      tree(const Data & D) : val(D){};
      tree(const Data & D, std::shared_ptr<tree<Data>> Tree1, std::shared_ptr<tree<Data>> Tree2) : val(D), left_child(Tree1), right_child(Tree2){};
      tree(const tree<Data> &) = default;
      ~tree() = default;

      std::string gviz() const;
#ifdef NET_GRAPH_VIZ
      void draw();
#endif
   };

   template <typename contract_type>
   struct Tree_combine {
      template <typename Data, typename NoUse>
      std::shared_ptr<tree<Data>> operator()(std::shared_ptr<tree<Data>> const & a, std::shared_ptr<tree<Data>> const & b, const NoUse & c) const {
         return std::make_shared<tree<Data>>(contract_type::contract(a->val, b->val), a, b);
      }
   };

   template <typename absorb_type>
   struct Tree_act {
      template <typename Data, typename Data2, typename NoUse>
      std::shared_ptr<tree<Data>> operator()(std::shared_ptr<tree<Data>> const & a, const Data2 & b, const NoUse & c) const {
         a->val = absorb_type::absorb(a->val, b);
         return a;
      }
   };

   template <typename Data>
   void gviz_nodes(const tree<Data> & node, std::ostream & dot_content, const std::string & nodename) {
      std::string nodelable = node.val.show();
      if (node.left_child && node.right_child){
         nodelable += "\nN ";
         for (auto & s : node.val.node_set) {
            nodelable += s;
         }
      }
      dot_content << "  " << nodename << " [ color=" << gviz_theme["node_strokecolor"] << ", label = \"" << nodelable
                  << "\", fontcolor=" << gviz_theme["node_fontcolor"] << ", fontname=" << gviz_theme["node_fontname"] << "];\n";

      if (node.left_child) {
         dot_content << "  " << nodename << " -> " << nodename << "l"
                     << " [fontcolor=" << gviz_theme["edge_fontcolor"] << ", fontname=" << gviz_theme["edge_fontname"]
                     << ", color=" << gviz_theme["edge_strokecolor"] << "];\n";
         gviz_nodes<Data>(*(node.left_child), dot_content, nodename + 'l');
      }
      if (node.right_child) {
         dot_content << "  " << nodename << " -> " << nodename << "r"
                     << " [fontcolor=" << gviz_theme["edge_fontcolor"] << ", fontname=" << gviz_theme["edge_fontname"]
                     << ", color=" << gviz_theme["edge_strokecolor"] << "];\n";
         gviz_nodes<Data>(*(node.right_child), dot_content, nodename + 'r');
      }
   }

   template <typename Data>
   std::string tree<Data>::gviz() const {
      std::stringstream dot_content;
      std::string grp;

      dot_content << "digraph G {\n";
      dot_content << "  scale=0.6\n";
      dot_content << "  dpi=160\n";
      dot_content << "  bgcolor=" << gviz_theme["global_bgcolor"] << "\n";
      dot_content << "  fontcolor=" << gviz_theme["global_fontcolor"] << "\n";
      dot_content << "  fontname=" << gviz_theme["global_fontname"] << "\n";
      dot_content << "  label = \"figure of tree\"\n";

      std::string nodename = "t";

      gviz_nodes<Data>(*this, dot_content, nodename);

      dot_content << "}\n";

      // std::cout<<dot_content.str();
      return dot_content.str();
   }
#ifdef NET_GRAPH_VIZ
   std::string render(std::string dot_content, const std::string & engine);
   void show_fig(const std::string & fig_content, bool tmux, bool st);

   template <typename Data>
   void tree<Data>::draw() {
      show_fig(render(gviz(), "dot"), true, true);
   }
#endif

} // namespace net
#endif

Updated on 15 June 2022 at 16:04:19 CST