本篇带来的是二叉树基础部分的内容。还有一种向下调整建堆的方法……待补充。
#include <iostream>
#include <stack>
using namespace std;
// 结构体定义
template <class BTDataType>
struct BinaryTreeNode
{
BTDataType _data;
BinaryTreeNode *_left;
BinaryTreeNode *_right;
BinaryTreeNode(const BTDataType &data) : _data(data), _left(nullptr), _right(nullptr) {}
};
template <class BTDataType>
class BinaryTree
{
typedef BinaryTreeNode<BTDataType> BTNode;
public:
BinaryTree() : root(nullptr) {}
void BinaryTreeCreate()
{
root = new BTNode(1);
BTNode *_node2 = new BTNode(2);
BTNode *_node3 = new BTNode(3);
BTNode *_node4 = new BTNode(4);
BTNode *_node5 = new BTNode(5);
BTNode *_node6 = new BTNode(6);
BTNode *_node7 = new BTNode(7);
root->_left = _node2;
root->_right = _node4;
_node2->_right = _node3;
_node4->_left = _node5;
_node4->_right = _node6;
_node5->_right = _node7;
_node7->_right = new BTNode(8);
}
// 下面是函数接口(因为root对外界是不可见的,所以只能叠甲进行操作)
// 树的递归遍历
void preOrder()
{
BinaryTreePreOrder(root);
cout << endl;
}
void inOrder()
{
BinaryTreeInOrder(root);
cout << endl;
}
void postOrder()
{
BinaryTreePostOrder(root);
cout << endl;
}
// 树的非递归遍历
void preOrder(int)
{
// 根左右
BTNode *_root = root;
stack<BTNode*> s;
while(_root||!s.empty())
{
if(_root)
{
s.push(_root);
cout << _root->_data << "->";
_root = _root->_left;
}
else
{
BTNode *temp = s.top();
s.pop();
_root = temp->_right;
}
}
cout << endl;
}
void inOrder(int)
{
// 左根右
BTNode *_root = root;
stack<BTNode*> s;
while (_root||!s.empty())
{
// 一路左下,直到寻找到左孩子为空的位置,把栈顶元素从栈中弹出,并且访问该元素
if(_root)
{
s.push(_root);
_root = _root->_left;
}
else
{
// 此时,让_root指针指向栈顶元素的右孩子,因为左边已经没有元素可以去访问了,然后重复完整操作。
// 当右孩子为空的时候,说明这棵子树访问完毕,可以访问之前的节点了
BTNode *temp = s.top();
s.pop();
cout << temp->_data << "->";
_root = temp->_right;
}
}
cout << endl;
}
void postOrder(int)
{
BTNode* _root=root;
BTNode *_repeat = nullptr;
stack<BTNode*> s;
while(_root||!s.empty())
{
// 左右根
if(_root)
{
s.push(_root);
_root = _root->_left;
}
else
{
BTNode* temp=s.top();
if(temp->_right&&temp->_right!=_repeat)
{
_root = temp->_right;
}
else
{
cout << temp->_data << "->";
_repeat = temp;
s.pop();
_root = nullptr;
}
}
}
}
int getTreeSize()
{
return BinaryTreeSize(root);
}
int getLeafSize()
{
return BinaryTreeLeafSize(root);
}
int getLevelSize(int k)
{
return BinaryTreeLevelKSize(root, k);
}
int getBTNodes()
{
return countNodes(root);
}
bool isComplete()
{
return BinaryTreeComplete(root);
}
BTNode *BTNodeFind(BTDataType &x)
{
return BinaryTreeFind(root, x);
}
~BinaryTree()
{
DestroyTree(root);
}
protected:
// 前序遍历
void BinaryTreePreOrder(BTNode *root)
{
if (root == nullptr)
{
cout << "NULL->";
return;
}
cout << root->_data << "->";
BinaryTreePreOrder(root->_left);
BinaryTreePreOrder(root->_right);
}
// 中序遍历
void BinaryTreeInOrder(BTNode *root)
{
if (root == nullptr)
{
cout << "NULL->";
return;
}
BinaryTreeInOrder(root->_left);
cout << root->_data << "->";
BinaryTreeInOrder(root->_right);
}
// 后序遍历
void BinaryTreePostOrder(BTNode *root)
{
if (root == nullptr)
{
cout << "NULL->";
return;
}
BinaryTreePostOrder(root->_left);
BinaryTreePostOrder(root->_right);
cout << root->_data << "->";
}
// 计算二叉树的最大高度
int BinaryTreeSize(BTNode *root)
{
if (root == nullptr)
return 0;
int leftTreeHeight = BinaryTreeSize(root->_left);
int rightTreeHeight = BinaryTreeSize(root->_right);
return (leftTreeHeight > rightTreeHeight ? leftTreeHeight : rightTreeHeight)+1;
}
// 计算二叉树的叶子节点数
int BinaryTreeLeafSize(BTNode *root)
{
// 根节点为空则返回0
if (root == nullptr)
return 0;
// 若左右子树均为空,则为叶子节点
if (root->_left == nullptr && root->_right == nullptr)
return 1;
// 本节点非叶子节点则递归计算本节点的左右子树的叶子节点数
return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}
// 计算第K层节点的个数
// 因为传入的是根节点,所以可以把根节点层数视为反向的第K层,然后再递归计算,当k>1的时候说明该节点还不是我所需要求的层数的节点,当k=1的时候说明该节点为我需要的节点,就返回1,否则递归计算左右子树的节点个数
int BinaryTreeLevelKSize(BTNode *root, int k)
{
if (root == nullptr)
{
return 0;
}
if (k == 1)
return 1;
return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);
}
// 获取二叉树的总结点个数
int countNodes(BTNode *root)
{
if (!root)
return 0;
return 1 + countNodes(root->_left) + countNodes(root->_right);
}
// 判断完全二叉树的辅助函数
bool isCompleteUtil(BTNode *root, int index, int numberNodes)
{
if (!root)
return true;
// 当前节点的索引大于了节点总数量则返回false
if (index >= numberNodes)
return false;
// 思想的本质是数组(顺序存储)
bool left = isCompleteUtil(root->_left, 2 * index + 1, numberNodes);
bool right = isCompleteUtil(root->_right, 2 * index + 2, numberNodes);
return left && right;
}
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode *root)
{
int numberNodes = countNodes(root);
return isCompleteUtil(root, 0, numberNodes);
}
void DestroyTree(BTNode *root)
{
if (!root)
return;
DestroyTree(root->_left);
DestroyTree(root->_right);
delete root;
}
BTNode *BinaryTreeFind(BTNode *root, BTDataType &x)
{
if (root == nullptr)
{
return nullptr;
}
if (root->_data == x)
{
return root;
}
BTNode *leftTree = BinaryTreeFind(root->_left, x);
BTNode *rightTree = BinaryTreeFind(root->_right, x);
if (leftTree)
{
return leftTree;
}
return rightTree;
}
BTNode *root;
};