• 树——通用树结点的插入


    1,通用树中的插入操作是以查找操作为基础的;

    2,插入的方式:

           1,插入新结点:

                  1,bool insert(TreeNode<T>* node)

           2,插入数据元素:

                  1,bool insert(const T& value, TreeNode<T>* parent)

                 

    3,如何指定新结点在树中的位置?

     

           1,问题分析:

                  1,树是非线性的,无法采用下标的形式定位数据元素;

                  2,每一个树结点都有唯一的前驱结点(父结点);

                  3,因此,必须先找到前驱结点,才能完成新结点的插入;  

    4,新结点的插入:

     

           1,插入操作不是递归实现的;

           2,插入操作在查找操作帮助下是非常容易实现的;

           3,要插入结点,只用关注父结点中的关于子结点部分(child 链表),至于插入结点的 parent 和 value 不是自己维护的范围,已经被插入者维护好了;

      4,代码实现:

     1    /* 实现从 Tree<T> 中继承而来的纯虚函数没有插入操作的时候,无法构建一棵树插入操作是构建树的唯一操作,非递归*/
     2     bool insert(TreeNode<T>* node)
     3     {
     4         bool ret = true;
     5 
     6         if( node != NULL )  // 不能插入空结点
     7         {
     8             if( this->m_root == NULL )  // 插入的树是空树
     9             {
    10                 node->parent = NULL;  // 新结点是根结点,树中通过插入结点的父对象来唯一标识这个结点
    11                 this->m_root = node;
    12             }
    13             else
    14             {
    15                 GTreeNode<T>* np = find(node->parent);  // 插入结点的父结点是不是在树中
    16                 if( np != NULL )
    17                 {
    18                     GTreeNode<T>* n = dynamic_cast<GTreeNode<T>*>(node);
    19 
    20                     if( np->child.find(n) < 0 )  // 当前要插入的父结点没有需要插入的子结点,返回值小于 0
    21                     {
    22                         np->child.insert(n);  // 插入到父结点的子结点链表里面去
    23                     }
    24                 }
    25                 else
    26                 {
    27                     THROW_EXCEPTION(InvalidOperationException, "Invalid parent tree node ...");
    28                 }
    29             }
    30         }
    31         else
    32         {
    33             THROW_EXCEPTION(InvalidParameterException, "Parameter node cannot be NULL ...");
    34         }
    35         return ret;
    36    }

                 

    5,数据元素插入:

     

           1,只用维护插入结点的 parent 和 value 以及父结点的 parent 就可以了,至于自己的 child 链表,还是个空链表,不用管,而父结点的 child 是要维护的,用新结点插入方法维护;

      2,代码实现:

     1    bool insert(const T& value, TreeNode<T>* parent)
     2     {
     3         bool ret = true;
     4         GTreeNode<T>* node = GTreeNode<T>::NewNode();  // 使用工厂方法
     5 
     6         if( node != NULL )
     7         {
     8             node->value = value;
     9             node->parent = parent;
    10 
    11             insert(node);  // 本文 4.4 中 insert 函数复用
    12         }
    13         else
    14         {
    15             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new tree node ...");
    16         }
    17 
    18         return ret;
    19    }

             

    6,插入新结点的操作中,新结点的 child 都不用管;

    7,小结:

           1,插入操作是构建树的唯一操作;

           2,执行插入操作时必须指明结点间的父子关系;

           3,插入操作必须正确处理指向父结点的指针;

           4,插入数据元素时需要从堆空间中创建结点;

  • 相关阅读:
    linux sysfs (2)
    微软——助您启动云的力量网络虚拟盛会
    Windows Azure入门教学系列 全面更新啦!
    与Advanced Telemetry创始人兼 CTO, Tom Naylor的访谈
    Windows Azure AppFabric概述
    Windows Azure Extra Small Instances Public Beta版本发布
    DataMarket 一月内容更新
    和Steve, Wade 一起学习如何使用Windows Azure Startup Tasks
    现实世界的Windows Azure:与eCraft的 Nicklas Andersson(CTO),Peter Löfgren(项目经理)以及Jörgen Westerling(CCO)的访谈
    正确使用Windows Azure 中的VM Role
  • 原文地址:https://www.cnblogs.com/dishengAndziyu/p/10925241.html
Copyright © 2020-2023  润新知