C++数据结构第55课、树中结点的清除操作

1、 清除操作的定义:将树中的所有结点清除(释放堆中的结点)

void clear()
  • 树中数据元素的清除
    在这里插入图片描述
  • 清除操作功能的定义
    — free(node):清除 node 为根结点的树,释放树中的每一个结点
    在这里插入图片描述
void free(GTreeNode<T>* node)
{
    if(node != nullptr)
    {
        for(node->child.move(0); !node->child.end(); node->child.next())
        {
            free(node->child.current());
        }
        delete node;
    }
}

void clear()
{
    free(root());
    this->m_root = nullptr;
}
#include <iostream>
#include "GTree.h"

using namespace std;
using namespace XiebsLib;

int main()
{
    GTree<char> t;
    GTreeNode<char>* node = nullptr;

    GTreeNode<char> root;
    root.value = 'A';
    root.parent = nullptr;
    t.insert(&root);

//    t.insert('A', nullptr);
    node = t.find('A');

    t.insert('B', node);
    t.insert('C', node);
    t.insert('D', node);

    node = t.find('B');
    t.insert('E', node);
    t.insert('F', node);

    node = t.find('E');
    t.insert('K', node);
    t.insert('L', node);

    node = t.find('C');
    t.insert('G', node);

    node = t.find('G');
    t.insert('N', node);

    node = t.find('D');
    t.insert('H', node);
    t.insert('I', node);
    t.insert('J', node);

    node = t.find('H');
    t.insert('M', node);

    t.clear();
    const char* s = "KLFNMIJ";
    for(int i = 0; i < 7; i++)
    {
        TreeNode<char>* node = t.find(s[i]);

        while( node != nullptr )
        {
            cout << node->value << " ";

            node = node->parent;
        }

        cout << endl;
    }
    return 0;
}

在这里插入图片描述
如果我们把根结点定义在栈上,程序的运行没有问题,但是在调用 clear()函数时,我们会把根结点给 delete 掉,这样做是不对的,你不知道什么时候程序会崩溃掉。

在这里插入图片描述

  • 问题分析:
    1、单凭内存地址很难准确判断具体的存储区域
    2、只有堆空间的内存需要主动释放(delete)
    3、清除操作时只需要对堆中的结点进行释放

解决方案:工厂模式

1、在 GTreeNode 中增加保护成员变量 m_flag
2、将 GTreeNode 中的 operator new 重载为保护成员函数(防止在外部定义堆对象,我们统一把堆对象的生成放在内部)
3、提供工厂方法 GTreeNode<T>* NewNode()
4、在工厂方法中 new 新结点并将 m_flag 设置为 true

在这里插入图片描述
GTreeNode.h

#ifndef GTREENODE_H
#define GTREENODE_H

#include "LinkList.h"
#include "TreeNode.h"

namespace XiebsLib
{

template <typename T>
class GTreeNode : public TreeNode<T>
{
protected:
    bool m_flag;

    void* operator new(unsigned int size)throw()
    {
        return Object::operator new(size);
    }
public:
    LinkList<GTreeNode<T>*> child;

    GTreeNode()
    {
        m_flag = false;
    }

    bool flag()
    {
        return m_flag;
    }

    static GTreeNode<T>* NewNode()
    {
        GTreeNode<T>* ret = new GTreeNode<T>;
        if(ret != nullptr)
        {
            ret->m_flag = true;
        }
        return ret;
    }

};
}
#endif // GTREENODE_H

void free(GTreeNode<T>* node)
{
    if(node != nullptr)
    {
        for(node->child.move(0); !node->child.end(); node->child.next())
        {
            free(node->child.current());
        }
        if(node->flag())
        {
            delete node;
        }
        else
        {
            cout << node->value << endl;
        }

    }
}

bool insert(const T& value, TreeNode<T>* parent)
{
    bool ret = true;
    GTreeNode<T>* node = GTreeNode<T>::NewNode();
    if(node != nullptr)
    {
        node->value = value;
        node->parent = parent;

        insert(node);
    }
    else
    {
        THROW_EXCEPTION(NoEnoughMemoryException, "no memory to create new tree node");
    }
    return ret;
}
  • 小结
    1、清除操作 用于销毁树中的每个结点
    2、销毁结点时需要决定是否释放对应的内存空间
    3、工厂模式可用于定制堆空间中的结点
    4、只有销毁定制结点的时候需要进行释放
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值