-
插入的方式应分为两种:
— 插入新结点:bool insert(TreeNode<T>* node)
— 插入数据元素:bool insert(const T& value, TreeNode<T>* parent)
-
如何在树中指定新结点的位置?
— 树是非线性的,无法采用下标的形式定位数据元素
— 每一个树结点都有唯一的前驱结点(父结点)
— 因此,必须先找到前驱节点,才能完成新结点的插入
插入新结点的流程:
插入数据元素流程:
GTreeNode.h
#ifndef GTREENODE_H
#define GTREENODE_H
#include "LinkList.h"
#include "TreeNode.h"
namespace XiebsLib
{
template <typename T>
class GTreeNode : public TreeNode<T>
{
public:
LinkList<GTreeNode<T>*> child;
};
}
#endif // GTREENODE_H
GTree.h
bool insert(TreeNode<T>* node)
{
bool ret = true;
if(node != nullptr)
{
if(this->m_root == nullptr) //判断根结点是否为空
{
node->parent = nullptr;
this->m_root = node;
}
else
{
GTreeNode<T>* np = find(node->parent); //先查找父结点在不在
if(np != nullptr)
{
GTreeNode<T>* n = dynamic_cast<GTreeNode<T>*>(node);
if(np->child.find(n) < 0) //防止反复插入父节点
{
np->child.insert(n); //在父节点子类链表里面插入结点
}
}
else
{
THROW_EXCEPTION(InvalidOperationException, "Invalid parent tree node");
}
}
}
else
{
THROW_EXCEPTION(InvalidParameterException, "parameter node cannot be null");
}
return ret;
}
bool insert(const T& value, TreeNode<T>* parent)
{
bool ret = true;
GTreeNode<T>* node = new GTreeNode<T>();
if(node != nullptr)
{
node->value = value;
node->parent = parent;
insert(node);
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "no memory to create new tree node");
}
return ret;
}
main.cpp
#include <iostream>
#include "GTree.h"
using namespace std;
using namespace XiebsLib;
int main()
{
GTree<char> t;
GTreeNode<char>* node = nullptr;
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);
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;
}
小结:
1、插入操作是构建树的唯一操作
2、构建插入操作时必须指明结点间的父子关系
3、插入操作必须正确处理指向父结点的指针
4、插入数据元素是需要从堆空间中创建结点