下面是其他函数的一个详解,+表示是public函数,-表示private
| 函数 | 作用 |
|---|---|
| + insert | 插入一个元素 |
| + empty | 二叉树是否为空 |
| + exists | 判断元素是否存在 |
| + clear | 非递归清空二叉树 |
| + erase | 清除指定根节点及其所有子节点 |
| + size | 元素数量 |
| + minmum | 最小值 |
| + maxmum | 最大值 |
| + max_length_between_node | 最大节点距离 |
| + hight | 树高度 |
| - print_binary_tree | 二叉树形式打印二叉树 |
| - count_node | 元素个数 |
| - find | 查找 |
| - maxmum | 最大节点 |
| - minmum | 最小节点 |
| - successor | 后继节点 |
| - hight |
3.1 insert
insert函数在二叉树的构造函数里已经用到了一次,利用数组构建一个二叉树。在那里对insert函数所作的行为进行了讲解,所以这里只放上函数
template<typename T>void binary_tree<T>::insert(const T& data) {if (0 != root_) {tree_node* fast, * slow, * ptemp;fast = slow = ptemp = root_;while (fast != 0) {slow = fast;if (data < slow->data) {fast = slow->lchild;}else if (data > slow->data) {fast = slow->rchild;}else {fast = 0;}// else equal do nothing}if (data < slow->data) {slow->lchild = new tree_node(data);slow->lchild->parent = slow;}else if (data > slow->data) {slow->rchild = new tree_node(data);slow->rchild->parent = slow;}// else equal do nothing}else {root_ = new tree_node(data);}}
3.2 empty
检查二叉树是否为空,只需要判断是否存在根节点root_即可
// 二叉树是否为空bool empty(void) const {return (NULL == root_);}
3.3 exists
exists用来判断某个值是否存在,这个和insert的过程很类似,根据大小来判断,直到找到该值
template<typename T>bool binary_tree<T>::exists(const T& data) const {bool result = false;tree_node* ptr = root_;while (ptr != 0 && !result) {if (ptr->data == data) {result = true; // 这里不再使用break来跳出循环}else if (ptr->data < data) {ptr = ptr->rchild;}else {ptr = ptr->lchild;}}return result;}
3.4 clear
clear用来清空二叉树,既然用来清空二叉树,那就需要遍历。前面学习到了,遍历的3种方式中,最简单的方式就是先序遍历,所以这里就是用先序遍历的套路。
template<T>void binary_tree<T>::clear(void) {stack<tree_node *> node_stack;node_stack.push(root_);tree_node* tmp_node;while (!node_stack.empty() ) { // 先序遍历tmp_node = node_stack.top();node_stack.pop();if (tmp_node->rchild!=0) {node_stack.push(tmp_node->rchild);}if (tmp_node->lchild!=0) {node_stack.push(tmp_node->lchild);}delete tmp_node; // 删除节点}}
3.5 erase
关于这个函数,可能是作者写的时候思路太清晰,不知道这个erase到底应该实现什么样的功能,其源代码如下
template<typename T>void binary_tree<T>::erase(const T& data) {tree_node* iter = find(data);//delete iter;}
上述的代码只找到了data所对应的根节点的位置,但是没有删除。我们在抹除一个节点的时候,要将它的所有子节点一并抹除掉,就像下面这幅图所示

所以,这部分的代码应该和clear类似,只不过此时的根节点是从find函数找到的根节点开始的了
template<typename T>void binary_tree<T>::erase(const T& data) {tree_node* iter = find(data);stack<tree_node *> node_stack;node_stack.push(iter);tree_node* tmp_node;while (!node_stack.empty() ) { // 先序遍历tmp_node = node_stack.top();node_stack.pop();if (tmp_node->rchild!=0) {node_stack.push(tmp_node->rchild);}if (tmp_node->lchild!=0) {node_stack.push(tmp_node->lchild);}delete tmp_node; // 删除节点}}
3.6 size
size是计算元素数量的函数,内部使用count_node函数来实现
template<typename T>int binary_tree<T>::size(void) const {return count_node(root_);}
3.7 minmum
minmum:得到元素的最小值
之前已经说过了,这棵树是按照大小顺序排好的树了,所以其最左边的节点的值就是最小值
template<typename T>T binary_tree<T>::minmum(void) const {const tree_node* p = root_;while (p->lchild) {p = p->lchild;}return p->data;}
3.8 maxmum
maxmum:和minmum相对。最右边的值是其最大值
template<typename T>T binary_tree<T>::maxmum(void) const {const tree_node* p = root_;while (p->rchild) {p = p->rchild;}return p->data;}
3.9 height
height:树的高度
template<typename T>int binary_tree<T>::hight(void) const {return hight(root_);}
其中的height(root_)这句代码中的height是私有函数的height,其定义如下
template<typename T>int binary_tree<T>::hight(const tree_node* _t) const {if (_t == nullptr) {return 0;}if (_t->lchild == nullptr && _t->rchild == nullptr) {return 1;}return 1 + std::max<int>(hight(_t->lchild), hight(_t->rchild));}
上面的代码非常巧妙地利用了递归来计算树的高度,这部分是可以被记住的,因为之前的遍历都是利用的循环,而没有用到递归。现在用了递归以后,可以更加容易理解树的高度的计算过程。

3.10 max_length_between_node
max_length_between_node:节点之间的最大距离
还是上面那幅图的例子,看一下节点之间的距离如何计算,就像下面这幅图,节点c和节点g的距离是如何计算的?
节点距离6 = c的高度+g的高度

template<typename T>int binary_tree<T>::max_length_between_node(void) const {int max_length = 0;const tree_node* ptree = root_;list<tree_node*> listNode;listNode.push_back(root_);while (!listNode.empty()) {auto pnode = listNode.front();listNode.pop_front();if (pnode->lchild != nullptr) {listNode.push_back(pnode->lchild);}if (pnode->rchild != nullptr) {listNode.push_back(pnode->rchild);}int tempBetween = hight(pnode->lchild) + hight(pnode->rchild);max_length = std::max<int>(tempBetween, max_length);}return max_length;}
上述代码,只需要给定一个根节点,便可以根据height函数递归地找到其下面的最高的左子节点和右子节点,然后计算它们的高度之和
3.11 count_node
使用递归形式来进行计算节点数量
template<typename T>int binary_tree<T>::count_node(const tree_node* ptree) const {int num1, num2;if (ptree == NULL)return 0;else {num1 = count_node(ptree->lchild);num2 = count_node(ptree->rchild);return (num1 + num2 + 1);}}
3.12 find
find函数和exists函数基本一样
template<typename T>typename binary_tree<T>::tree_node* binary_tree<T>::find(const T& data) {if (root_) {tree_node* pfind = root_;while (pfind) {if (pfind->data == data) {return pfind;}else if (data < pfind->data) {pfind = pfind->lchild;}elsepfind = pfind->rchild;}}return NULL;}
3.13 minmum和maxmum
和之前的共有函数的minmum和maxmum一样
3.14 successor
目前不知道这个函数拿来干什么用,用处不算很大
template<typename T>typename binary_tree<T>::tree_node* binary_tree<T>::successor(tree_node* t) const {if (t->rchild) {return minmum(t->rchild);}else{tree_node* fast = t->parent, * slow = t;while (fast && fast->rchild == slow) {slow = fast;fast = fast->parent;}return fast;}}
3.15 输出二叉树
下面的函数print_binary_tree是用来输出二叉树的,从bt作为根节点开始输出其子树
template<typename T>void binary_tree<T>::print_binary_tree(ostream& out, const tree_node* bt, int depth) const {// 用右左孩子的方式输出一颗树,先输出右孩子后输出左孩子if (bt) {print_binary_tree(out, bt->rchild, depth + 1);if (depth == 0) {out << bt->data << endl;}else if (depth == 1) {out << " --" << bt->data << endl;}else {int n = depth;while (--n) {cout << " ";}out << " --" << bt->data << endl;}print_binary_tree(out, bt->lchild, depth + 1);}}
上述代码中有一个有趣的句子:out << bt->data << endl
这个out可不是cout写错了,而是本身就是一个ostream&类型的数据。这些ostream类型的数据通过符号<<连接起来向屏幕输出。
从上面的print_binary_tree衍生的函数是从根节点开始输出整棵树的
template<typename T>void binary_tree<T>::print(ostream& out) const {print_binary_tree(out, root_, 0);}
另外,涉及到输出的话一般要对<<进行重载,这个重载<<的代码如下
template<typename T>ostream& operator<<(ostream& out, const binary_tree<T>& tree) {tree.print(out);return out;}
