树
树的结构如下图,其实际是类似链表的结构,只不过后续连接的不止一个数据
template <typename T>
//树结构的定义(未包含实现功能)
class Tree
{
int size; //子节点数量
public:
T data; //数据
Tree **childs; //子节点 用数组指针来存放
}
这种形式画出来的连接图类似树状图而称为树结构,其中一些关于特殊的树概念:
二叉树:就是一棵树的孩子,只有两个分为左孩子和右孩子。
template <typename type>
class TreeNode //二叉树节点
{
type data;
TreeNode *left; //二叉树的左子树
TreeNode *right; //二叉树的右子树
}
满二叉树:深度为k且有2^k-1个结点的二叉树,即除了叶外其他节点的都有两个孩子,如下图
完全二叉树:当二叉树的深度为h时,它的h层节点必须都是连续靠左并不可隔开的(满二叉树也符合),并且1~h-1层的结点数都达到最大个数(即1~h-1层为一个满二叉树),如下图:
上面的类是直接以树结构的原理直接实现的,其实还有一种以数组的形式来实现,通常用于来实现完全二叉树。以数组下标表示节点的位置,根节点为1,数组0的位置不管,左孩子的下标为父节点的两倍,右孩子的下标为父节点的两倍加一。
template<typename T>
class ArrayTree
{
vector<T> tree;
public:
ArrayTree()
{
tree.resize(1); //根节点为1
}
void addTree(T v)
{
tree.push_back(v);
}
T get_left(int index,T val)
{
if (index*2<tree.size())
{
return tree[index * 2];
}
else
{
cout << "下标越界" << endl;
throw std::out_of_range("下标越界");
}
}
T get_right(int index, T val)
{
if (index * 2+1<tree.size())
{
return tree[index * 2+1];
}
else
{
cout << "下标越界" << endl;
throw std::out_of_range("下标越界");
}
}
T get_parent(int index, T val)
{
if (index<tree.size()&&index!=1)
{
return tree[index/2];
}
else
{
cout << "下标越界" << endl;
throw std::out_of_range("下标越界");
}
}
};
堆
堆分为最小堆和最大堆,以最大堆为例,其为满二叉树且父节点都比子节点大。
通常取出一堆数据的最大(最小)的几个,用堆来实现效率最高(比如游戏实现战力排行榜,可以用堆来存储战力,就不用遍历所有数据),这就是堆排序,每次取出堆顶(最值),把满二叉树最后的叶(数组的最后一个放到顶),再根据规则移动再次形成最大堆(最小堆)。