数据结构(12)_树的概念及通用树的实现

发布时间:2020-08-21 10:43:00 作者:三九感冒灵
来源:网络 阅读:4728

1.树的定义与操作

1.1.树的相关定义

1.树的定义

树是一种非线性的数据结构,右n(n>=0)个结点组成的有限集合,如果n=0,称为空树,如果n>0,则:

3.3.树中结点的清除操作

3.3.1.清除操作

清除操作的定义:void clear() //将树中的所有节点清除(释放堆中的节点)
数据结构(12)_树的概念及通用树的实现
清除操作功能函数定义:
free(node) //清除node为根结点的树,释放树中的每一个结点
数据结构(12)_树的概念及通用树的实现
问题:树中的结点可能来源于不同的存储空间,如何判断堆空间中的结点并释放?
1.单凭内存地址很难准确判断具体的存储区域;
2.只有堆空间的内存才需要主动释放(delete)
3.清除操作时只需要对堆中的结点进行释放

3.3.2.工厂模式

1.在GTreeNode中增加保护成员m_flag;
2.将GTreeNode中的operator new重载为保护成员函数;
3.提供工厂方法GTreeNode<T>* NewNode()
4.在工厂方法中new新结点并将m_flage设置为true;
树结点的工厂模式示例:

template <typename T>
  class GTreeNode:public TreeNode<T>
  {
  protected:
    bool m_flag;//堆空间标识
    //重载new操作符,声明为保护
    void* operator new(unsigned int size)throw()
    {
      return Object::operator new(size);
    }

  public:
    LinkedList<GTreeNode<T>*> m_children;
    GTreeNode()
    {
      //栈上分配的空间标识为false
      m_flag = false;
    }
    //工厂方法,创建堆空间的结点
    static GTreeNode<T>* NewNode()
    {
      GTreeNode<T>* ret = new GTreeNode<T>();
      if(ret != NULL)
      {
          //堆空间的结点标识为true
          ret->m_flag = true;
      }
      return ret;
    }
    //堆空间结点标识访问函数
    bool flag()const
    {
      return m_flag;
    }
  };
//结点的释放:
    void free(GTreeNode<T>* node)
    {
      if(node != NULL)
      {
          for(node->m_children.move(0); !node->m_children.end(); node->m_children.next())
          {
              free(node->m_children.current());
          }
          //如果结点存储在堆空间
          if(node->flag())
             delete node;//释放
      }
    }
//清空树:
    void clear()
    {
        free(root());
        this->m_root = NULL;
    }

总结:
1.清除操作用于销毁树中的每个结点,需要释放对应的内存空间;
2.工厂模式可用于“定制”堆空间中的结点,只有销毁定制结点的时候需要进行释放

3.4树中结点的删除操作

删除的方式:

int count(GTreeNode<T>* node) const
    {
      int ret = 0;
      if(node != NULL)
      {
          ret = 1;//根结点
          //遍历根节点的子结点
          for(node->m_children.move(0); !node->m_children.end(); node->m_children.next())
          {
              ret += count(node->m_children.current());
          }
      }
      return ret;
    }
    //树的结点数目访问函数
    int count()const
    {
        count(root());
    }

3.5.2.树的高度

功能定义:height(node),获取node为根结点的树的高度。
递归实现:树的高度 = 子树结点高度的最大值 + 1(根结点)。
数据结构(12)_树的概念及通用树的实现
数据结构(12)_树的概念及通用树的实现

int degree(GTreeNode<T>* node) const
    {
      int ret = 0;
      if(node != NULL)
      {
          //结点的子结点的数量
          ret = node->m_children.length();
          //遍历子结点
          for(node->m_children.move(0); !node->m_children.end(); node->m_children.next())
          {
              int d = degree(node->m_children.current());
              if(ret < d)
              {
                  ret = d;
              }
          }
      }
      return ret;
    }

    //树的度访问函数
    int degree()const
    {
        return degree(root());
    }

3.5.3.树的度数

功能定义:degree(node),获取node为结点的树的度数。
递归实现:树的度数 = 子树的最大度数 + 1(根结点)
数据结构(12)_树的概念及通用树的实现
数据结构(12)_树的概念及通用树的实现

int height(GTreeNode<T>* node)const
    {
      int ret = 0;
      if(node != NULL)
      {
          //遍历子结点
          for(node->m_children.move(0); !node->m_children.end(); node->m_children.next())
          {
              //当前结点的高度
              int h = height(node->m_children.current());
              if(ret < h)
              {
                  ret = h;
              }
          }
          ret = ret + 1;
      }
      return ret;
    }
    //树的高度访问函数
    int height()const
    {
        height(root());
    }

3.6.树形结构的层次遍历

问题:如何按照层次遍历通用树结构中的每一个数据元素?
当前的事实:- 树是一种非线性的数据结构,树的节点没有固定的编号方式;
新的需求:- 为通用树结构提供新的方法,快速遍历每一个节点
设计思路:
在树中定义一个新游标(GTreeNode<T>*),遍历开始将游标指向根结点(root()),获取游标指向的数据元素,通过结点中的child成员移动游标;
提供一组遍历相关的函数,按层次访问树中的数据元素。
数据结构(12)_树的概念及通用树的实现
层次遍历算法:
原料:class LinkQueue<T>; 游标:LinkQueue<T>::front();
思想:

4.2. GTreeNode的实现

template < typename T >
class GTreeNode : public TreeNode<T>
{
protected:
    //堆空间标识,如果在堆空间中创建了结点,则置为true,以便后续释放结点时判断结点是否创建自堆空间
    bool m_flag;

    GTreeNode(const GTreeNode<T>&);
    GTreeNode<T>& operator =(const GTreeNode<T>&);  //容器的内容不能复制

    //重载new操作符,声明为保护成员
    void* operator new(unsigned int size)throw()
    {
      return Object::operator new(size);
    }
public:
    LinkList<GTreeNode<T>*> child;

    GTreeNode()
    {
        m_flag = false;
    }

    static GTreeNode<T>* NewNode()
    {
        GTreeNode<T>* ret = new GTreeNode<T>();

        if(ret != NULL)
        {
            ret->m_flag = true;  //在堆空间中申请了结点,则将该标识置为true
        }

        return ret;
    }

    //堆空间结点标识访问函数
    bool flag()const
    {
     return m_flag;
    }

    ~GTreeNode(){}
};
推荐阅读:
  1. 数据结构--树
  2. 数据结构(十三)——树

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

数据结构 通用树 工厂模式

上一篇:php使用替换字符串函数的方法

下一篇:php设置关闭网页错误提示的方法

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》