C++之数据结构(树)

树的概念

树的特点

  1. 一种非线性的数据结构
  2. 有一个根结点,可以有两个或以上的后继结点
  3. 由节点或顶点和边组成的(非线性的)且不存在着任何环的一种数据结构。没有节点的树称为空(null
    或empty)树。
  4. 一棵非空的树包括一个根或多个附加节点,所有节点构成一个多级分层结构。

树的基本术语

  • 节点的度:一个节点含有的子树的个数称为该节点的度;
  • 树的度:一棵树中,最大的节点的度称为树的度;
  • 叶子节点:度为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);
			}
		}
	}
}



总结

  1. 了解数据结构的基本概念
  2. 使用多态的特性实现树的节点
  3. 实现一个树的管理对象
  4. 通过管理对象对树进行操作
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值