树的概念
树的特点
- 一种非线性的数据结构
- 有一个根结点,可以有两个或以上的后继结点
- 由节点或顶点和边组成的(非线性的)且不存在着任何环的一种数据结构。没有节点的树称为空(null
或empty)树。- 一棵非空的树包括一个根或多个附加节点,所有节点构成一个多级分层结构。
树的基本术语
- 节点的度:一个节点含有的子树的个数称为该节点的度;
- 树的度:一棵树中,最大的节点的度称为树的度;
- 叶子节点:度为0的节点称为叶节点;
- 父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;
- 子节点:一个节点含有的子树的根节点称为该节点的子节点;
- 根节点:树的第一个节点,叫根节点
- 兄弟节点:具有相同父节点的节点互称为兄弟节点;
- 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
- 树的高度或深度:树中节点的最大层次;
- 堂兄弟节点:双亲在同一层的节点互为堂兄弟;
- 节点的祖先:从根到该节点所经分支上的所有节点;
- 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
- 森林:多棵互不相交的树的集合称为森林;
树的定义
树的节点
定义一个只有纯虚函数的类,每一个数的节点都继承自这一个节点类,然后通过这个节点的接口统计进行
调用
#pragma once
#include<vector>
#include<string>
class Node
{
public:
//虚析构函数
virtual ~Node() = default;
//添加子节点
virtual void addChild(Node* node) = 0;
//移除子节点
virtual void removeChild(Node* node) = 0;
//获取全部子节点
virtual std::vector<Node*>getChildren() = 0;
//获取名称
virtual std::string getName() = 0;
//执行节点的函数
virtual void fn(std::string s) = 0;
};
定义树的节点
实现树的节点
#pragma once
#include"Node.h"
class TreeNode:public Node
{
std::string str;
std::vector<Node*>vec;
public:
TreeNode(std::string str);
//继承Node
virtual void addChild(Node* node) override;
virtual void removeChild(Node* node) override;
//获取全部子节点
virtual std::vector<Node*>getChildren() override;
//获取名称
virtual std::string getName() override;
//执行节点的函数
virtual void fn(std::string s) override;
};
class FileNode :public Node {
std::string str;
std::vector<Node*>vec;
public:
FileNode(std::string str);
virtual void addChild(Node* node) override;
virtual void removeChild(Node* node) override;
//获取全部子节点
virtual std::vector<Node*>getChildren() override;
//获取名称
virtual std::string getName() override;
//执行节点的函数
virtual void fn(std::string s) override;
};
class PageNode :public Node {
public:
std::string str;
std::vector<Node*>vec; //子节点
std::vector<int>nums;
PageNode(std::string str);
virtual void addChild(Node* node) override;
virtual void removeChild(Node* node) override;
//获取全部子节点
virtual std::vector<Node*>getChildren() override;
//获取名称
virtual std::string getName() override;
//执行节点的函数
virtual void fn(std::string s) override;
};
#include "TreeNode.h"
#include<iostream>
using namespace std;
TreeNode::TreeNode(std::string str):str(str)
{
}
void TreeNode::addChild(Node* node)
{
//从尾部插入数据
vec.push_back(node);
}
void TreeNode::removeChild(Node* node)
{
auto it = find(vec.begin(), vec.end(), node);
if (it != vec.end())
{
//找到并移除
vec.erase(it);
}
}
std::vector<Node*> TreeNode::getChildren()
{
return vec;
}
std::string TreeNode::getName()
{
return str;
}
void TreeNode::fn(std::string s)
{
if (s == "蔡文姬放大")
{
cout << "敌人掉血!" << endl;
}
else if (s == "")
{
cout << "刷经验!" << endl;
}
}
FileNode::FileNode(std::string str):str(str)
{
}
void FileNode::addChild(Node* node)
{
vec.push_back(node);
}
void FileNode::removeChild(Node* node)
{
auto it = find(vec.begin(), vec.end(), node);
if (it != vec.end())
{
vec.erase(it);
}
}
std::vector<Node*> FileNode::getChildren()
{
return vec;
}
std::string FileNode::getName()
{
return str;
}
void FileNode::fn(std::string s)
{
if (s == "蔡文姬放大")
{
cout << "队友回血" << endl;
}
else if (s == "")
{
cout << "刷经验!" << endl;
}
}
PageNode::PageNode(std::string str):str(str)
{
}
void PageNode::addChild(Node* node)
{
vec.push_back(node);
}
void PageNode::removeChild(Node* node)
{
auto it = find(vec.begin(), vec.end(), node);
if (it != vec.end())
{
vec.erase(it);
}
}
std::vector<Node*> PageNode::getChildren()
{
return vec;
}
std::string PageNode::getName()
{
return str;
}
void PageNode::fn(std::string s)
{
if (s == "蔡文姬放大")
{
cout << "队友回血+1" << endl;
}
else if (s == "")
{
cout << "刷经验+2" << endl;
}
}
树的遍历
#pragma once
#include"Node.h"
class Tree
{
Node* root;
public:
Tree(Node* root);
~Tree();
//遍历子树 递归方式
void traverse();
//遍历子树, 非递归
void For(std::string cmd = "");
private:
void _traverse(Node* node, int depth);
};
#include "Tree.h"
#include<iostream>
#include <stack>
using namespace std;
Tree::Tree(Node* root):root(root)
{
}
Tree::~Tree()
{
}
void Tree::traverse()
{
//从根节点递归
_traverse(root, 0);
}
void Tree::_traverse(Node* node, int depth)
{
if (node == nullptr)
{
return;
}
for (int i = 0; i < depth; i++)
{
cout << " ";
}
cout << node->getName();
//获取子节点
vector<Node*>chrildren = node->getChildren();
for (Node* e : chrildren)
{
_traverse(e, depth+1);
}
}
void Tree::For(std::string cmd)
{
stack<Node*>st;
st.push(root);
while (!st.empty())
{
Node* node = st.top();
st.pop();
node->fn(cmd);
for (Node* n : node->getChildren())
{
if (n != nullptr)
{
st.push(n);
}
}
}
}
总结
- 了解数据结构的基本概念
- 使用多态的特性实现树的节点
- 实现一个树的管理对象
- 通过管理对象对树进行操作