一、判断一个二叉树A中是否包含另外一棵二叉树B
思路:首先在A中找到与B的根节点值一样的节点R,然后判断A中以R为根节点的子树是不是包含二叉树B。
bool ifContains(BinaryTreeNode * treeA,BinaryTreeNode * treeB){ bool result = false; if(treeB == NULL) result = true; if(treeA != NULL && treeB != NULL){ if(treeA -> value == treeB -> value) result = isSubTree(treeA,treeB); if(!result) result = ifContains(treeA -> left,treeB); if(!result) result = ifContains(treeA -> right,treeB); } return result; } bool isSubTree(BinaryTreeNode * treeA,BinaryTreeNode * treeB){ if(treeB == NULL) return true; if(treeA == NULL || treeA -> value != treeB -> value) return false; return isSubTree(treeA -> left,treeB -> left) && isSubTree(treeA -> right,treeB -> right); }
二、二叉树的镜像
思路:前序遍历一棵树的每个节点,如果遍历到的节点有子节点,就交换它的两个子节点,当交换完所有非叶子节点的左右节点后,就得到树的镜像。
代码:
void * Mirror(BinaryTreeNode * pRoot){ //这里判断一下左右子节点是不是同时为空,可以提高效率 if((pRoot == NULL) || (pRoot -> left == NULL && pRoot -> right == NULL)) return; BinaryTreeNode * pLeft = pRoot -> left; BinaryTreeNode * pRight = pRoot -> right; BinaryTreeNode * ptemp = pRoot -> left; pLeft = pRight; pRight = ptemp; if(pRoot -> left != NULL) Mirror(pRoot -> left); if(pRoot -> right != NULL) Mirror(pRoot -> right); }
三、二叉树的深度
利用前序遍历的方法实现:
int BinaryTreeDepth(BTN * pRoot){ if(pRoot == NULL) return 0; int leftDepth = BinaryTreeDepth(pRoot -> left); int rightDepth = BinaryTreeDepth(pRoot -> right); return (leftDepth > rightDepth)?(leftDepth + 1):(rightDepth + 1); }
引申:输入一颗二叉树的根结点,判断该树是不是平衡二叉树,如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是平衡二叉树。
方法一:根据刚才求二叉树深度的函数求出每个结点的左右子树的深度,然后判断是不是平衡二叉树,如果每个结点都是,那么整个树就是。
bool isBalanceTree(BTN * pRoot){ if(pRoot == NULL) return true; int leftDepth = BinaryTreeDepth(pRoot -> left); int rightDepth = BinaryTreeDepth(pRoot -> right); if(leftDepth - rightDepth > 1 || leftDepth - rightDepth < -1) return false; return isBalanceTree(pRoot -> left)&&isBalanceTree(pRoot -> right); }
方法二:上面的方法有很大的弊端,那就是时间复杂度太大,结点越靠近叶子结点,它被重复遍历的次数越多。
//这个函数其实要给掉用它的函数返回两个值,一是以这个结点为根结点的树是否是平衡二叉树, //二是以该结点为根结点的树的深度是多少,因此我们需要定义一个int型的变量作为参数让它进入函数体得到 //二叉树的深度 bool isBalanceTree(BTN * pRoot,int * depth){ if(pRoot == NULL){ *depth = 0; return true; } int depthOfLeft; int depthOfRight; int depthDiff; if(isBalanceTree(pRoot -> left,&depthOfLeft) && isBalanceTree(pRoot -> right),&depthOfRight){ depthDiff = depthOfLeft - depthOfRight; if(depthDiff < -1 || depthDiff > 1) return false; *depth = (depthOfLeft > depthOfRight)?(depthOfLeft + 1):(depthOfRight + 1); return true; } return false; } bool isBalanceTree(BTN * pRoot){ int depth = 0; return isBalanceTree(pRoot,&depth); }
后来又写的一份代码:
bool isBalanceTree(BiNode * root,int &depth){ if(root == NULL){ depth = 0; return true; } int leftDepth; int rightDepth; int diffDepth; bool isLeft = isBalanceTree(root ->lchild,leftDepth); bool isRight = isBalanceTree(root ->rchild,rightDepth); depth = leftDepth >= rightDepth ? leftDepth+1 : rightDepth+1; diffDepth = leftDepth - rightDepth; if(diffDepth > 1 || diffDepth < -1) return false; return isLeft && isRight; } bool isBalanceTree(BiNode * root){ int depth; return isBalanceTree(root,depth); }
四、求二叉树第k层有多少个节点
这个问题不要这么想,我先知道第k-1层有多少个节点,然后看第k-1层节点的左右分支有多少不为null,这个问题要用递归的方式实现:
求以root为根的二叉树第k层有多少个节点相当于求以root->lchild为根的二叉树第k-1层的节点数与以root->rchild为根的二叉树第k-1层的节点数之和。
1.当root为null时,节点数为0;
2.当root不为null时,求第k层节点个数:
k == 1,节点数为1;
k > 1,这个要递归;
k < 1,节点数为0;
int numOfKthLevel(BiNode * root,int k){ if(root == NULL || k < 1) return 0; if(k == 1) return 1; return numOfKthLevel(root ->lchild,k-1) + numOfKthLevel(root ->rchild,k-1); }
五、根据一个数组构建一个搜索二叉树
BiNode* createBiTreeByArray(int nodeValues[],int length){ if(length <= 0) return NULL; BiNode * root = NULL; for(int i = 0; i < length; i++){ root = insertNode(root,nodeValues[i]); } return root; } //这个函数的作用是将value插入root为根结点的搜索二叉树中,并将根节点返回 BiNode* insertNode(BiNode * root,int value){ BiNode* node; if(!(node = (BiNode*)malloc(sizeof(BiNode)))) return NULL; node ->data = value; node ->lchild = NULL; node ->rchild = NULL; if(root == NULL) return node; if(root ->data > value) //这里很重要,我们将root->lchild看成根,将value插入以root->lchild为根结点的搜索二叉树中,并将root->lchild返回重新链接到root上 root->lchild = insertNode(root->lchild,value); else root ->rchild = insertNode(root ->rchild,value); return root; }
六、求二叉树中节点的最大距离
即二叉树中相距最远的两个节点之间的距离。
递归解法:
(1)如果二叉树为空,返回0,同时记录左子树和右子树的深度,都为0
(2)如果二叉树不为空,最大距离要么是左子树中的最大距离,要么是右子树中的最大距离,要么是左子树节点中到根节点的最大距离+右子树节点中到根节点的最大距离,同时记录左子树和右子树节点中到根节点的最大距离。
int max(int first,int second){ return (first >= second) ? first:second; } //maxLeft是root左子树的高度,maxRight是root右子树的高度 int getMaxDistance(BiNode * root,int & leftHeight,int & rightHeight){ if(root == NULL){ leftHeight = 0; rightHeight = 0; return 0; } int maxDistance; int leftMaxDistance,rightMaxDistance; int llHeight,lrHeight,rlHeight,rrHeight; if(root ->lchild == NULL){ leftHeight = 0; leftMaxDistance = 0; } else{ leftMaxDistance = getMaxDistance(root ->lchild,llHeight,lrHeight); leftHeight = max(llHeight,lrHeight) + 1; } if(root ->rchild == NULL){ rightHeight = 0; rightMaxDistance = 0; }else{ rightMaxDistance = getMaxDistance(root ->rchild,rlHeight,rrHeight); rightHeight = max(rlHeight,rrHeight) + 1; } maxDistance = max(max(leftMaxDistance,rightMaxDistance),leftHeight+rightHeight); return maxDistance; }
自己写的另外一种方法,但是不太好,因为返回值是以root为根节点的树的高度,最大距离作为参数放在函数头中
int maxDistance(BiNode * root,int & maxDis){ if(root == NULL){ maxDis = 0; return 0; } int maxDisLeft,maxDisRight,leftHeight,rightHeight,height; leftHeight = maxDistance(root ->lchild,maxDisLeft); rightHeight = maxDistance(root ->rchild,maxDisRight); height = leftHeight >= rightHeight ? leftHeight + 1 : rightHeight + 1; maxDis = maxDisLeft >= maxDisRight ? maxDisLeft : maxDisRight; maxDis = maxDis >= (leftHeight + rightHeight) ? maxDis : (leftHeight + rightHeight); return height; }