如何为二叉搜索树设计通用节点?

时间:2017-05-09 13:27:31

标签: java design-patterns

我的设计问题是我试图编写一个适合几种可能的子类型的通用类。具体来说,我试图为二叉搜索树编写一个Node类,它适合搜索树的几种实现(Avl Tree,2-3 Tree,Red-Black tree等)我的问题是:不同的树在Node类中需要不同的变量以保持效率。 AvlTree需要一个高度变量,RedBlackTree需要一个颜色变量(AvlTree没有用),依此类推。什么是最好的设计解决方案:

  1. 在Node中声明了很多变量(颜色,高度,平衡因子......),只给出了很多构造函数?
  2. 在Node中有一个Object类型的变量,称为元数据,每个实现都会用它来包含元数据吗?
  3. 别的什么?

2 个答案:

答案 0 :(得分:1)

如何为二叉搜索树设计通用节点?

好的,你问过......

首先,这是一个很好的链接。肯定会曝光 问题的广度,严格遵守数据结构。

Abstract_Hierarchies让一切变得更加轻松。 至少你在思考正确的方向。正如我在这里看到的那些,至少在表面上,最好的方法(语言不可知)在OOP中始终是相同的。

顺便说一下,Java是一种很好的语言,可以开始练习OOP原则。事实上,我刚刚删除了该段......

IFace,IFaces,FullInterface 。建立任何良好的抽象层次结构的秘诀是“骨干”。实现。 (我不会在这里实现泛型,但Java只为此提供了强大的支持。 java.util.collection 这是集合层次结构的根目录)。

但是,泛型几乎内置于您的语言中。一切都是Java中的对象。你去......你能想象的任何类型的最抽象的表现形式。

根据您的具体要求:伪...或伪伪 这是我所能掌握的全部。伪伪(无论如何)。

INode 必须至少包含:

  1. 一个私有DATA成员键。

  2. 至少提到参考,但此时不超过2。 孩子 INode s(这里有一点小小的不便.java没有 让用户通过指针直接访问内存,比如 C / C ++ )显然,这正好是2,但是至少是“#C ++”。是一个 在思考进步时非常重要的方法论 实现。只是绝对的本质,不再是。

  3. 私有DATA的公共访问者和mutator。

  4. 经理职能声明。(简短列表,我不记得了 是否支持运算符重载在java中是否支持) 考虑到这种情况,无法想象如何处理操作等于......嗯......

  5. 由于 INode 除了数据之外没用(不是fullley) 结构,这是我将设置私人访问密钥的地方。 (Java特定)这也意味着,参考了 上面的管理员功能 INode 不会声明 公共CTOR。 java的C ++朋友类版本(ITree) 在你的情况下。(查找类访问键/ Java)。这也是 展示Singleton模式的属性。 ---停在这里这个虽然看起来很不完整,但却是 第一阶段实现抽象 INode 层次结构。

  6. 这对于二叉树数据结构来说已经足够了 (扩展或实现) INode 接口 具体的二叉树节点类。到目前为止这么简单。

    接下来,我们正在寻找满足的设计规定 BST 节点类。可以想象,虽然既不方便也不方便 正确的,将我们当前的 INode 接口实现为 二进制搜索树节点类。(不......不......不...修改!!)它是什么
    它是...'关闭修改和&&开放扩展;

    我们将从新界面扩展 INode ...我想我会称之为 IOrderedNode 接口应始终具有超级描述性 命名约定。 (我知道,发生了什么事)。实际上,它 确实反映了二叉树和a之间的主要区别 二进制搜索树二进制搜索树只是一个有序的 二叉树。有与此相关的含义,显然是 琐碎,差异。主要是,所有的实用性都有一个 串行数据结构。这意味着,我们应该回到 INode
    评估(NOT CHANGE !!)私有数据成员。       --------

    希望在考虑抽象可扩展性时我们很周到 该数据成员。如果我没记错的话,java中的泛型已经成为了 增加了多功能性......我会把它留给你。借用一个概念
    从C ++开始,我会使用通用的指针来键入模板Arg 。或
    更好的是 无效指针 不能在那里使用星号'因为它格式化我的文字)不会#n;得到比这更抽象! void )(明星),我的意思是;

    暂时忘记你正在使用java,因为java中的所有类型都是
    整数类型,通过从Object类继承的哈希码来实现的 ToString()方法。用户定义类型(UDT)应该经过深思熟虑 在这里,因为跨数据结构的不同实现 将实施一系列IFace扩展。 (指针,java中的 refs:)始终是基本级别的最佳初始类型。他们可以是 适应指向甚至是最复杂的UDT的参考。

    好的,回到我们即将利用的那些Serial属性 遍历 :: 预购 按顺序 < em>订购后 广度优先 。由于我们只是在探索 INode 层次结构, 我们应该开始考虑将在实施中实施的算法 关联的数据结构,并尝试识别任何下属
    需要出现在 IOrderedNode

    中的依赖项
    //I think from here on out I will just write the code...
    //20 min later...this stupid @$$ message box is the worst
    //dev environment I have EVER! worked in...
    //......(granted it isn't that)
    //40 min later in Visual Studio. Tired of working without
    //a net...no KB short cts...NO TAB! no auto formatting...?
    
    template<class T>
    class IcanOnlyBeaBT;//fwd _decl 
                    //or a doubley linked list, an Adapter, a...
                    //keep thinking as you go...
    template<class T>
    class INode
    {   
        friend class IcanOnlyBeaBT<T>;//this takes care of access
    public:
    
    //  At this level we have protected
    //  access for derived classes--
    //  EXCEPT! with TEMPLATED classes!
    //  in C++ this is NOT an issue WHEN.
    //  1. data members are 'captured' by
    //     template instantiation
    //  2. and 3. are the exact same answer
    //     as 1. only I would be forced to
    //     elaborate on two specific instances
    //     with the only advantage being a 
    //     sufficing ward on those nit-pickers
    //     who love to leave comments like
    //
    //          "Weellll...NOT exactly"
    //
    //          I dont care. I would rather
    //          write my explaination for not 
    //          explaining further...
    
            /************************************/
            // (no worries here in java - C#)
            // implement now to enforce the
            // design on higher level abstractions;
            // protected access may become 
            // private in remote derived classes
            // we never want to come back here!!!
            // push dependencies up! up! up!
    
    
         INode() : whatever_Data_I_want_Ha_Ha(nullptr) {}
         virtual void SetWhatEverDataIWant(T*) = 0;
         virtual T* GetWhateverDataIWant() = 0;
         virtual T* GetWhateverDataIWant() const = 0;
     protected:
         virtual ~INode() = 0;
         T* whatever_Data_I_want_Ha_Ha;
         INode<T>*left_child;
         INode<T>*right_child;
     };
    
     template<class T>
     INode<T>::~INode() {} // don't worry about this it's cool
                          //...notice that   
                      // the member is protected...and pure virtual...
                      // it's just a boomerang--    
    
        // Notice how adaptable this Interface has become
        // after only one extension and implementation is refined. 
    
        // This is BOTTOM UP because we are BUILDING... 
        // ...this should be TOP DOWN as we DESIGN...
        // THINK--TOP DOWN...BUILD BOTTOM UP...
    
        // Push ALL negotiable DEPENDENCIES UP AS YOU BUILD.
        // Ideally, these were identified during design.
        // It rarely ever goes that way cleanly...
        // at least not for me, but try...try
    
        // As incremental implementation progresses, You
        // may start to identify some of these negotiable
        // dependencies...these two interfaces are still
        // super lean..and rather boring, but continue towards
        // the AVL, Red Black, Other Data structurs they will show.
    
        // Nodes are, for the most part, like a drawer full
        // of silverware. They CAN'T do anything unless
        // they are being used.
    
        // GO UP now!!!...BUT always JUST enough!!
        // No more; GOAL...to have a DESIGN SPECIFIC
        // hierarchy, that IS extensible in a MODULAR 
        // fasion, like LEGOS. ADAPTABLE to ANY COMPATIBLE
        // Data Structure, Not just TREES. Even from here...
        // there are other suitablilities coming to mind,
        // such as Graphs, Doubley Linked Lists, circular queues.
        // Nodes are common place in Data Structures...on...on...
    
        // Principle Attribute: ICanBe_A_BST Data Struct now.
    
        // fwd _decl: 
      template<class T>     
      class ICanBe_A_BST; //The BT Node was FIRST Abstraction, 
                    // BST is SECOND.
                    // OR a Composite Object Structure! for the  
                    // Composite Design Pattern...or...or...or
                    // BECAUSE, this IOrderedNode is more QUALIFIED 
                    // and adaptable. LOOK HERE! Don't throw away
                    // the specific sutibility of lower abstractions
                    // This should be extended to fulfil design reqs
                    // IOrderedNode is not intended to be a BT, 
                    // IT 'IS A' BT by extension, BUT, it is a BST Node.
    
                    // This abstract hierarchy, UPON DESIGN COMPLETION  
                    // Will have pervasive extensibility @ unique levels.  
                    // think {OPEN-CLOSED} open for EXTENSION, and
                    // CLOSED for MODIFICATION...GOAL...DON'T...come
                    // BACK inside this BLACK BOX once it is CLOSED..!  
    
    template<class T>
    class IOrderedNode : public INode<T>
    { 
                  // RIGHT HERE! ALL previous implementation
                  // Is abstracted AWAY. Look how clean it all is..
                  // in java you would be Extending INode Interface HERE!.
                  // Extending IN JAVA IS inheritance.
                  // ALL public and protected members.
                  // Closed for MOD. open for EXTENSION
    public:                                
        IOrderedNode() : height(0) { }
    
    protected:
    //NOTICE!(I Can Be A BST Node IF!)my data is INTEGRAL & comparable.
    //FOR instance a bool is unqualified--how can you order a tree
    //when the only value is a 1 or a 0;
    //UDT is dependent upon guess...
    //THE USER who defind it(integral && comparable);
    
    // Question: is there anything missing from this level 
    // that would disqualify concrete instantiations from adequately
    // filling the intended role? .....Seriously...
    // I have been awake for two days now. This may need editing. 
    // Regardless the process is the 
    // same all the way to Red Black and beyond...
    
    int height; //new data member; height of the tree at that node...
                //this comes in handy when computing the balance factor
                //on balanced trees...AVL, R&B,
    };
    
    
    
    /***********************NOTE:***********************
    *
    *   There are several considerations that have to be made 
    *   when you are "leaving" data and and implementation "behind". 
    *   We know we don't EVER want to come back here...
        (not a super realistic GOAL...)
    *   Is the implementation specific to the level of bstraction.?...
    *   YES? then leave it here. 
    
        IS...the DATA specific to the implementation ????
    *   this deserves 4 Q-marks because, IF at all POSSIBLE PUSH
    *   these IMPLEMENTATION DEPENDENCIES..UP This RESULTS in IoC
    *   Inversion of Control Inversion of CONTROL INVERSION! of Control...
    *   Implementation dependencies should come from higher level abs
    *   to lower level Implementation...repeats you are seeing all over
        this now TLDR, are Cardinal principles of Object
    *   Oriented Design. Not because I love commenting code...
        but since YOU asked...I won't leave out the 'life blood'.
    
    *   Incidentally, there is a requisite 
        'AHAAH moment' that either comes
    *       or it doesn't.
    *
    ****************************   PERSONAL NOTE:*********************
    *
    *   I picked up java in the late 90's, and was like.
    *   "...what the hell is an OBJECT..?" Two years of programming from a
    *   procedural paradigm, in an OOP language-LATER! It hit me......
    *   (I know...slow learner)...but I remember saying out loud....
    *   'THAT...IS...THE...COOLEST...THING...I HAVE EVER...tripped over...
    *   Consensually, OOP is considered to be in its INFANCY. 
    *   Theories (opinions) are often the cause of some rather heated
    *   contest. In fact, one of the most intense and persistant 
        "cival-war" I have ever encountered, nearly dominated an entire 
        forum. I didn't really know enough to have an opinion
    *   one way or the other on the matter, but I remember thinking, 
        how absurd...and laughing alot.
    *   The theoretical epicenter was localized on the issue of...
            wait for it...
    *
    *                   INHERITANCE v.s. COMPOSITION/AGGRAGATION
    *
    *       Hmm....Everybody knows that programming to interfaces, 
        adhereing to common sense, established design principles, 
        and proven patterns, can all be accomplished without inheriting
        from a single archtype...
    *        "Not that there's anything wrong with that..." 
        I'm pretty sure, that was the vein of the row on that
             forum...Super entertaining though...
    *
    *******************************************/
    

答案 1 :(得分:0)

我遇到了同样的问题,因此决定采用这种简单的解决方案。

abstract class BSTnode<K, M> {
    K key;
    M meta; 
    BSTnode<K> left;
    BSTnode<K> right;
    BSTnode<K> parent;
}

这只是解决了您的元数据问题。