1.二叉树中和为某一值的路径
题目:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整树的所有路径。从树的根节点开始往下直到叶节点所经的结点形成一条路径。
分析:由于路径是从根节点出发的,所以选择前序遍历,当访问到一个结点时,把该结点添加到路径,并累加该结点的值,如果该结点为叶子结点并且路径中结点值的和刚好等于输入的整数,则该路径符合要求,如果当前结点不是叶子结点,则继续访问它的子节点。
实现代码:
void FindPath(TreeNode* root, int num,
vector<vector<int>>& ret, vector<int>& path){
if(root == NULL){
return;
}
if(root->val > num){
return;
}
path.push_back(root->val);
if((root->val) == num && (root->left == NULL && root->right == NULL)){
ret.push_back(path);
path.pop_back();
}
else{
FindPath(root->left, num - root->val, ret, path);
FindPath(root->right, num - root->val, ret, path);
path.pop_back();
}
}
vector<vector<int>> FindPath(TreeNode* root,int expectNumber) {
vector<vector<int>> ret;
vector<int> path;
if(root == NULL){
return ret;
}
FindPath(root, expectNumber, ret, path);
return ret;
}
2.二叉搜索树与双向链表
题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表,要求不能创建任何新的结点,只能调整树中结点指针的指向。
分析:在二叉搜索树中,左子结点的值总是小于父节点的值,右子节点的值总是大于父节点的值,因为要求转换成排序的双向链表,可以中序遍历这棵二叉搜索树,因此在转换时,原先指向左子结点的指针调整为指向前一个结点的指针,原先指向右子节点的指针调整为指向后一个结点的指针。当遍历到根节点时,将根节点和它的左子树值最大的结点链接,和右子树最小的结点链接。
实现代码:
TreeNode* ConvertNode(TreeNode* pRoot, TreeNode*& LastNode)
{
if(pRoot == NULL){
return NULL;
}
TreeNode* left = ConvertNode(pRoot->left,LastNode);
if(left != NULL){
LastNode->right = pRoot;
pRoot->left = LastNode;
}
LastNode = pRoot;
TreeNode* right = ConvertNode(pRoot->right,LastNode);
if(pRoot->right != NULL){
right->left = pRoot;
pRoot->right = right;
}
return left != NULL ? left:pRoot;
}
TreeNode* Convert(TreeNode* pRootOfTree)
{
if(pRootOfTree == NULL){
return NULL;
}
TreeNode* LastNode = NULL;
if(pRootOfTree->left == NULL && pRootOfTree->right == NULL){
LastNode = pRootOfTree;
return pRootOfTree;
}
return ConvertNode(pRootOfTree, LastNode);
}
3.二叉树的深度
实现代码:
int TreeDepth(TreeNode* pRoot)
{
if(pRoot == NULL){
return 0;
}
int left = TreeDepth(pRoot->left);
int right = TreeDepth(pRoot->right);
return left>right ? left+1:right+1;
}
4.判断一棵树是不是平衡二叉树
方法一:调用求二叉树深度的函数得到它的左右子树深度,如果每个结点的左右子树深度相差的绝对值不超过一,则是平衡二叉树。
实现代码:
bool IsBalanced_Solution(TreeNode* pRoot)
{
if(pRoot == NULL){
return true;
}
int left = TreeDepth(pRoot->left);
int right = TreeDepth(pRoot->right);
int dif = abs(left - right);
if(dif > 1){
return false;
}
return IsBalanced_Solution(pRoot->left) && IsBalanced_Solution(pRoot->right);
}
方法二:用后序遍历的方法遍历二叉树的结点,在遍历到每个节点之前就已经遍历了它的左右子树。只要在遍历每个结点时记下它的深度,这样就可以只需遍历一次判断出每个结点是否平衡。
实现代码:
bool IsBalanced(TreeNode *root, int& depth){
if(root == NULL){
return true;
}
int left = 0;
int right = 0;
if(IsBalanced(root->left,left) && IsBalanced(root->right, right)){
int dif = abs(left - right);
if(dif <= 1){
depth = (left > right ? left : right) + 1;
return true;
}
}
return false;
}
bool IsBalanced_Solution(TreeNode* pRoot) {
int depth = 0;
return IsBalanced(pRoot, depth);
}
5.二叉树的下一个结点
题目:给定一棵二叉树和其中一个结点,如何找出中序遍历顺序的下一个结点?树中的结点除了有两个分别指向左右子结点的指针外,还有一个指向父节点指针。
分析:1.如果一个结点有右子树,则它的下一个结点就是指向它的右子树中最左的子节点;
2.如果一个结点没有右子树,并且该结点是它父亲结点的左子节点,那么它的下一个节点就是它的父亲结点;
3.如果一个结点既没有右子树并且该结点是它父亲结点的右子结点,这种情况下就得沿着它的父节点的指针向上遍历,直到找到一个结点是它父亲结点的左子结点的结点,如果存在,那么这个结点就是要找的结点。
实现代码:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
if(pNode == NULL){
return NULL;
}
TreeLinkNode* pNext = NULL;
if(pNode->right != NULL){
TreeLinkNode* cur = pNode->right;
while(cur->left != NULL){
cur = cur->left;
}
pNext = cur;
}
else if(pNode->parent != NULL){
TreeLinkNode* cur = pNode;
TreeLinkNode* pParent = pNode->parent;
while(pParent != NULL && cur == pParent->right){
cur = pParent;
pParent = pParent->parent;
}
pNext = pParent;
}
retur3n pNext;
}
6.对称的二叉树
题目:请实现一个函数,判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
分析:可以定义一种与前序遍历对称的遍历算法,即先遍历根节点,再遍历它的右子结点,最后遍历它的左子结点。如果得到的遍历序列与前序遍历得到的一样,那么这棵树就是对称的。
实现代码:
bool isSymmetrical(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot1 == NULL && pRoot2 == NULL)
{
return true;
}
if(pRoot1 == NULL || pRoot2 == NULL)
{
return false;
}
if(pRoot1->val != pRoot2->val)
{
return false;
}
return isSymmetrical(pRoot1->left, pRoot2->right)
&& isSymmetrical(pRoot1->right, pRoot2->left);
}
bool isSymmetrical(TreeNode* pRoot)
{
return isSymmetrical(pRoot, pRoot);
}