树形结构总结
1.树相关
1.1树及相关概念
树是由n个节点组成的有限集合,若n=0,则为空树,每个非空树都有一个根节点。
每个节点可以有多个子节点,没有子节点的节点称为叶子节点。
深度:根节点到任一节点的路径长,根节点的深度为1.
高度:任一节点到叶子节点的最长路径长,所以叶子节点的高度为0.
一棵树的高度等于根节点的高度。
1.2树的表示方法
普通树:
普通树的节点可以有多个子节点
树有多种表示方法:
双亲表示法
孩子表示法
孩子兄弟表示法
1.3树的应用场景
1、创建目录
目录有二级目录,二级目录有三级目录,整个结构就像树一样
2、思维导图
3、huffman编码
4、linux虚拟内存管理
5、B+、B-树(索引)
6、C++STL中的map、mutilmap、set、mutilset
2.二叉树
2.1二叉树的性质
二叉树的节点最多有两个左右子节点(度最多为2),例如:
性质:
1、在二叉树第i层(i>=1)最多有
2
i
−
1
2^{i-1}
2i−1个节点
2、深度为k(k>=0)的二叉树最少有k个节点,最多有 2 k − 1 2^k-1 2k−1个节点
3、对任意一颗非空二叉树,如果其叶子节点数为n1,则其度数为2的非叶子节点数为n2,且n1 = n2 +1
4、具有n个节点的完全二叉树的最小深度为 log 2 ( n + 1 ) \log_{2}{(n+1)} log2(n+1)
2.2满二叉树
如果二叉树的高度为k,其有 2 k − 1 2^k-1 2k−1个节点,则为满二叉树,简单来说就是每个非叶子节点都有两个子节点
2.3完全二叉树
如果二叉树的高度为k,除第k层外,1~k-1层的节点都达到最大(为一颗满二叉树),且第k层的节点编号都与高度为k的满二叉树编号相对应,则为完全二叉树。例如:
2.4堆
具有一定特性的完全二叉树,一般用数组的形式来表示
堆分为大顶堆和小顶堆:
大顶堆:
所有非叶子节点都大于它的左右子节点
公式表示:vec[i] >= vec[2i+1] && vec[i] >= vec[2i+2]
小顶堆:
所有非叶子节点都小于它的左右子节点
公式表示:vec[i] <= vec[2i+1] && vec[i] <= vec[2i+2]
可以看看答主写的堆排序:
各种排序总结
2.5二叉树的基本操作
2.5.1实现
二叉树节点结构
template<typename T>
class BinaryTreeNode
{
public:
T val;
BinaryTreeNode<T>* left = nullptr;
BinaryTreeNode<T>* right = nullptr;
BinaryTreeNode(T data) :val(data){};//构造函数
};
二叉树结构
template<typename T>
class BinaryTree
{
public:
BinaryTree()
{
}
void Add(T data);
void DestoryBinaryTree(BinaryTreeNode<T> * node);
BinaryTreeNode<T>* getRoot()
{
return root;
}
~BinaryTree()
{
DestoryBinaryTree(root);
}
private:
BinaryTreeNode<T> * root = nullptr;
};
增加元素函数
template<typename T>
void BinaryTree<T>::Add(T data)
{
BinaryTreeNode<T> * node = new BinaryTreeNode<T>(data);
queue<BinaryTreeNode<T>*> que;
que.push(root);
if (!this->root)
{
root = node;
return;
}
while (!que.empty())
{
BinaryTreeNode<T> * temp = que.front();
que.pop();
if (!temp->left)
{
temp->left = node;
return;
}
else
{
que.push(temp->left);
}
if (!temp->right)
{
temp->right = node;
return;
}
else
{
que.push(temp->right);
}
}
}
删除元素
template<typename T>
void BinaryTree<T>::DestoryBinaryTree(BinaryTreeNode<T> * node)
{
if (node) //如果有节点
{
if (node->left) //如果存在左孩子
{
DestoryBinaryTree(node->left); //销毁二叉树的左子树
}
if (node->right)
{
DestoryBinaryTree(node->right); //销毁二叉树的右子树
}
}
delete node; //销毁节点
node = nullptr;
}
2.5.2遍历
2.5.2.1层序遍历
void LevelOrder(BinaryTreeNode<T> * node)
{
if (!node)
{
return;
}
queue<BinaryTreeNode<T> *> que;
que.push(node);
while (!que.empty())
{
BinaryTreeNode<T> * temp = que.front();
que.pop();
cout << temp->val << " ";
if (temp->left)
{
que.push(temp->left);
}
if (temp->right)
{
que.push(temp->right);
}
}
}
2.5.2.2前序遍历
递归
void PreOrder(const BinaryTreeNode<T> * node )
{
if (!node)
{
return;
}
cout << node->val << " ";
PreOrder(node->left);
PreOrder(node->right);
}
非递归
void WPreOrder(BinaryTreeNode<T> * node)
{
if (!node)
{
return;
}
stack<BinaryTreeNode<T> *> stk;
BinaryTreeNode<T> * temp = node;
while (!stk.empty() || temp)
{
if (temp)
{
stk.push(temp);
cout << temp->val << " ";
temp = temp->left;
}
else
{
temp = stk.top();
stk.pop();
temp = temp->right;
}
}
}
2.5.2.3中序遍历
递归
void InOrder(const BinaryTreeNode<T> * node)
{
if (!node)
{
return;
}
InOrder(node->left);
cout << node->val << " ";
InOrder(node->right);
}
非递归
void WInOrder(BinaryTreeNode<T> * node)
{
if (!node)
{
return;
}
stack<BinaryTreeNode<T> *> stk;
BinaryTreeNode<T> * temp = node;
while (!stk.empty() || temp)
{
if (temp)
{
stk.push(temp);
temp = temp->left;
}
else
{
temp = stk.top();
stk.pop();
cout << temp->val << " ";
temp = temp->right;
}
}
}
2.5.2.4后序遍历
递归
void PostOrder(const BinaryTreeNode<T> * node)
{
if (!node)
{
return;
}
PostOrder(node->left);
PostOrder(node->right);
cout << node->val << " ";
}
非递归`
void WPostOrder(BinaryTreeNode<T> * node)
{
stack<BinaryTreeNode<T>*> stk1;
stack<BinaryTreeNode<T>*> stk2;
stk1.push(node);
BinaryTreeNode<T>* temp;
while (!stk1.empty())
{
temp = stk1.top();
stk1.pop();
stk2.push(temp);
if (temp->left)
{
stk1.push(temp->left);
}
if (temp->right)
{
stk1.push(temp->right);
}
}
while (!stk2.empty())
{
temp = stk2.top();
stk2.pop();
cout << temp->val << " ";
}
}