概述
面试题54:二叉搜索树的第k个结点
给定一棵二叉搜索树,请找出其中的第k大的结点。
左边都比中间小,右边都比中间大,所以用中序遍历(左中右)就可以实现按结点的值从小到大遍历,遍历时候进行计数即可。
#include<bits/stdc++.h>
#include "../Utilities/BinaryTree.h"
using namespace std;
//递归函数:输入二叉(子)树根,输入k,在其上找中序遍历(剩下的)第k个结点
//k用引用传递,其改变可以影响到上面的递归层,k在调用中每找到一个就减小1
const BinaryTreeNode* KthNodeCore(const BinaryTreeNode* pRoot, unsigned int& k) {
const BinaryTreeNode* target = nullptr;//存要找的目标结点
if(pRoot->m_pLeft != nullptr)//左子树存在
//递归第向左子树调用,一直到没有左子树的结点才是第一个结点
//所以递归调用中的k没有发生改变
target = KthNodeCore(pRoot->m_pLeft, k);
if(target == nullptr) {//如果没有左子树了,或者左子树上找不到第k结点(左子树结点不够)
if(k == 1)//如果是找第1个结点(这种时候只能是没有左子树了)
target = pRoot;//这个"中"就是第1个结点
k--;//把这个结点减去
//如果没有满足上面的if,就是仅仅把这个结点减去
//这时没有更新target,即在这一层上还没有找到第k个结点
}
//接下来要在这个结点的右子树上找剩下的k=k-1个结点了(k值已经用k--更新)
//第一个条件:这一层的左子树和根结点都找完了结点还是不够
//第二个条件:右子树存在,这时才能向右子树找
if(target == nullptr && pRoot->m_pRight != nullptr)
//向右子树找,递归调用(右子树的每个结点也要按这个左中右顺序)
target = KthNodeCore(pRoot->m_pRight, k);
//返回上一层
return target;//如果等于nullptr表示要找的结点不在这层(个子树)上
}
//找给定二叉树中序遍历的第k个结点
const BinaryTreeNode* KthNode(const BinaryTreeNode* pRoot, unsigned int k) {
if(pRoot == nullptr || k == 0)//仅仅多了一个输入合法性检查
return nullptr;
return KthNodeCore(pRoot, k);
}
// 8
// 6 10
// 5 7 9 11
int main() {
BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8);
BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10);
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
BinaryTreeNode* pNode7 = CreateBinaryTreeNode(7);
BinaryTreeNode* pNode9 = CreateBinaryTreeNode(9);
BinaryTreeNode* pNode11 = CreateBinaryTreeNode(11);
ConnectTreeNodes(pNode8, pNode6, pNode10);
ConnectTreeNodes(pNode6, pNode5, pNode7);
ConnectTreeNodes(pNode10, pNode9, pNode11);
cout<<KthNode(pNode8,5)->m_nValue<<endl;
DestroyTree(pNode8);//9
return 0;
}
面试题55-1:二叉树的深度
输入一棵二叉树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
#include<bits/stdc++.h>
#include"../Utilities/BinaryTree.h"
using namespace std;
//递归函数:给定二叉树求其树高
int TreeDepth(const BinaryTreeNode* pRoot) {
if(pRoot == nullptr)//递归出口:空结点高度为0
return 0;
int nLeft = TreeDepth(pRoot->m_pLeft);//递归求左子树高
int nRight = TreeDepth(pRoot->m_pRight);//递归求右子树高
//返回max(左,右)+本子树的根节点高度1
return (nLeft > nRight) ? (nLeft + 1) : (nRight + 1);
}
// 1
// /
// 2 3
// /
// 4 5 6
// /
// 7
int main() {
BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);
BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
BinaryTreeNode* pNode7 = CreateBinaryTreeNode(7);
ConnectTreeNodes(pNode1, pNode2, pNode3);
ConnectTreeNodes(pNode2, pNode4, pNode5);
ConnectTreeNodes(pNode3, nullptr, pNode6);
ConnectTreeNodes(pNode5, pNode7, nullptr);
cout<<TreeDepth(pNode1)<<endl;//4
DestroyTree(pNode1);
return 0;
}
面试题55-2:平衡二叉树
输入一棵二叉树的根结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
可以在遍历整棵树,每个节点都用上面55-1的函数计算一下深左右子树的深度,如果上面的树计算过了,下面的树再计算就会有重复计算:
如果能先遍历下面的结点,计算完再遍历上面的结点就不用重复计算了,显然用后序遍历(左右中)。
而且使用后序遍历,计算完左右子树的高度之后可以立刻判断中结点位置是否符合平衡二叉树;而且无需重复计算中结点的高度,还是用 m a x ( 左 , 右 ) + 1 max(左,右)+1 max(左,右)+1即可。
#include<bits/stdc++.h>
#include"../Utilities/BinaryTree.h"
using namespace std;
//递归函数:判断二叉树是不是平衡二叉树,并将高度保存在第二个参数指代的内存中
bool IsBalanced(const BinaryTreeNode* pRoot, int* pDepth) {
//递归出口
if(pRoot == nullptr) {//空结点
*pDepth = 0;//空结点没有高度(高度是0)
return true;//空结点没有左右子树,认为是平衡的
}
int left, right;//存左右子树的高度
//递归调用判断左右子树平衡,计算保存左右子树的高度
if(IsBalanced(pRoot->m_pLeft, &left)
&& IsBalanced(pRoot->m_pRight, &right)) {//如果左右子树都是平衡的才继续判断
int diff = left - right;//左右子树高度差
if(diff <= 1 && diff >= -1) {//在[-1,1]内该子树就是平衡的
*pDepth = 1 + (left > right ? left : right);//高度=max(左,右)+1
return true;//平衡返回true
}
}
//如果左右子树不都是平衡的,不必再继续判断了
return false;
}
//判断一棵二叉树是不是平衡二叉树
bool IsBalanced_Solution(const BinaryTreeNode* pRoot) {
int depth = 0;//用于保存二叉树的高度计算结果
return IsBalanced(pRoot, &depth);//调用递归函数判断
}
// 不是完全二叉树,但是平衡二叉树
// 1
// /
// 2 3
// /
// 4 5 6
// /
// 7
int main() {
BinaryTreeNode* pNode1 = CreateBinaryTreeNode(1);
BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
BinaryTreeNode* pNode7 = CreateBinaryTreeNode(7);
ConnectTreeNodes(pNode1, pNode2, pNode3);
ConnectTreeNodes(pNode2, pNode4, pNode5);
ConnectTreeNodes(pNode3, nullptr, pNode6);
ConnectTreeNodes(pNode5, pNode7, nullptr);
cout<<boolalpha<<IsBalanced_Solution(pNode1)<<endl;//true
DestroyTree(pNode1);
return 0;
}
最后
以上就是香蕉大树为你收集整理的【二叉树】BST的第k大结点,二叉树的深度,平衡二叉树的全部内容,希望文章能够帮你解决【二叉树】BST的第k大结点,二叉树的深度,平衡二叉树所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复