二叉树的各种操作
1、树的递归遍历
2、求二叉树中节点的个数
3、求二叉树中叶子节点的个数
4、求二叉树的深度
5、求第k层节点数
6、树的非递归遍历
7、求一棵二叉树的镜像
8、判断两棵树的结构是否相同
9、判断一棵树是否平衡
10、将二叉查找树变为有序的双向链表
11、判断一棵树是否是另一棵树的子结构
12、重建二叉树
13、判断是否为二叉搜索树的后序遍历序列
14、二叉树中和为某一值的路径
15、判断一棵二叉树是否对称
16、创建一个高度最小的二叉查找树
17、判断是否为二叉查找树
18、找出两个节点的公共祖先
19、打印节点数值总和等于某个给定值的所有路径
下面是树的结构:
typedef struct treeNode {
int data;
struct treeNode* left;
struct treeNode* right;
}Tree;
#define max(a,b) (((a)>(b))?(a):(b))
1、树的递归遍历
void pre_traverse(Tree *T) //前序遍历
{
if (T)
{
printf("%d",T->data);
if (T->left)
pre_traverse(T->left);
if (T->right)
pre_traverse(T->right);
}
}
void mid_traverse(Tree *T) //中序遍历
{
if (T)
{
if (T->left)
mid_traverse(T->left);
printf("%d",T->data);
if (T->right)
mid_traverse(T->right);
}
}
void beh_traverse(Tree *T) //后序遍历
{
if (T)
{
if (T->left)
beh_traverse(T->left);
if (T->right)
beh_traverse(T->right);
printf("%d",T->data);
}
}
void level_traverse(Tree* T) //层次遍历
{
queue<int>q;
if (T) {
q.push(T->data);
while(!q.empty()) {
printf("%d",q.front());
q.pop();
if (T->left)q.push(T->left->data);
if (T->right)q.push(T->right->data);
}
}
}
2、求二叉树中节点的个数
int getNodes(Tree *T)
{
if (T == NULL)
return 0;
else
return getNodes(T->left) + getNodes(T->right) + 1;
}
3、求二叉树中叶子节点的个数
int getLeafNodes(Tree* T)
{
if (T == NULL)
return 0;
if (T->left == NULL && T->right == NULL)
return 1;
int leftLeafNodes = getLeafNodes(T->left);
int rightLeafNodes = getLeafNodes(T->right);
return leftLeafNodes + rightLeafNodes;
}
4、求二叉树的深度
int Depth(Tree *T)
{
if (T == NULL)
return 0;
else
return max(Depth(T->left), Depth(T->right)) + 1;
}
5、求第k层节点数
int getLevelNodes(Tree *T,int k)
{
if (T == NULL || k==0)
return 0;
if (k == 1)
return 1;
return getLevelNodes(T->left, k - 1) + getLevelNodes(T->right,k-1);
}
6、树的非递归遍历
void preOrdertrvael(Tree *T) //非递归前序遍历
{
if (T == NULL)return;
stack<Tree*>s;
Tree *temp=T;
s.push(temp);
while (!s.empty())
{
temp = s.top();
printf("%d\n",temp->data);
s.pop();
if (T->right)
s.push(T->right);
if (T->left)
s.push(T->left);
}
}
void midOrdertravel(Tree *T) //非递归中序遍历
{
if (T == NULL)return;
stack<Tree*>s;
Tree *temp = T;
while (temp != NULL || !s.empty())
{
if (temp) {
s.push(temp);
temp = temp->left;
}
else {
temp = s.top();
s.pop();
printf("%d",temp->data);
temp = temp->right;
}
}
}
void postOrdertravel(Tree *T) //非递归后序遍历
{
if (T == NULL)return;
stack<Tree*>s1;
stack<Tree*>s2;
Tree *temp = T;
s1.push(temp);
while (!s1.empty())
{
temp = s1.top();
s1.pop();
s2.push(temp);
if (temp->left)
s1.push(temp->left);
if (temp->right)
s1.push(temp->right);
}
while (!s2.empty())
{
temp = s2.top();
printf("%d",temp->data);
s2.pop();
}
}
void levelOrdertravel(Tree *T) //树的非递归层次遍历
{
if (T == NULL)
return;
queue<Tree*>q;
Tree* temp = T;
q.push(temp);
while (!q.empty())
{
temp = q.front();
printf("%d",temp->data);
if (temp->left)
q.push(temp->left);
if (temp->right)
q.push(temp->right);
}
}
7、求一棵二叉树的镜像
方法1:
Tree* MirrorTree(Tree *T)
{
if (T == NULL)
return;
Tree* pLeft = MirrorTree(T->left);
Tree* pRight = MirrorTree(T->right);
T->left = pRight;
T->right = pLeft;
return T;
}
方法2:
void MirrorRecursively(TreeNode *pNode)
{
if (pNode == NULL)return;
if (pNode->left == NULL && pNode->left == NULL)return;
TreeNode *temp = pNode->left;
pNode->left = pNode->right;
pNode->right = temp;
if (pNode->left)
MirrorRecursively(pNode->left);
if (pNode->right)
MirrorRecursively(pNode->right);
}
8、判断两棵树的结构是否相同
bool CompareTreeStruct(Tree *T1, Tree *T2)
{
if (T1 == NULL && T2 == NULL)
return true;
if (T1 != T2)
return false;
bool leftResult = CompareTreeStruct(T1->left,T2->left);
bool rightResult = CompareTreeStruct(T1->right,T2->right);
return leftResult && rightResult;
}
9、判断一棵树是否平衡
方法1:
bool isAvl(Tree* T)
{
int depth;
return isAvlTree(T,depth);
}
bool isAvlTree(Tree *T,int depth)
{
int leftDepth, rightDepth;
if (T == NULL) {
depth = 0;
return true;
}
if (isAvlTree(T->left, leftDepth) && isAvlTree(T->right, rightDepth))
{
if (abs(leftDepth - rightDepth) <= 1) {
depth = max(leftDepth,rightDepth)+1;
return true;
}
}
return false;
}
方法2:
int checkHeight(TreeNode *root)
{
if (root == NULL)return 0;
int left = checkHeight(root->left);
if (left == -1)
return -1;
int right = checkHeight(root->right);
if (right == -1)
return -1;
int diff = abs(right-left);
if (diff > 1)
return -1;
else
return max(left,right)+1;
}
bool isBalanced(TreeNode *root)
{
if(checkHeight(root)==-1)
return false;
else
return true;
}
10、将二叉查找树变为有序的双向链表
方法1:
void TreeToList(Tree* T, Tree* &pFirst, Tree* &pLast)
{
Tree* pLeftFirst(NULL), *pLeftLast(NULL), *pRightFirst(NULL), *pRightLast(NULL);
if (T == NULL) {
pFirst = NULL;
pLast = NULL;
return;
}
if (T->left == NULL) {
pFirst = T;
}
else {
TreeToList(T->left, pLeftFirst, pLeftLast);
pLeftLast->right = T;
T->left = pLeftLast;
pFirst = pLeftFirst;
}
if (T->right == NULL) {
pLast = T;
}
else {
TreeToList(T->right, pRightFirst, pRightLast);
pRightFirst->left = T;
T->right = pRightFirst;
pLast = pRightFirst;
}
}
方法2:
void ConvertNode(TreeNode *pNode, TreeNode **pLastNodeInList)
{
if (pNode == NULL)return;
TreeNode *pCurrent = pNode;
if (pCurrent->left != NULL)
ConvertNode(pCurrent->left,pLastNodeInList);
pCurrent->left = *pLastNodeInList;
if (*pLastNodeInList != NULL)
(*pLastNodeInList)->right = pCurrent;
*pLastNodeInList = pCurrent;
if (pCurrent->right != NULL)
ConvertNode(pCurrent->right,pLastNodeInList);
}
TreeNode *Convert(TreeNode *pRoot)
{
TreeNode *pLastNodeInList = NULL;
ConvertNode(pRoot,&pLastNodeInList);
TreeNode *pHeadOfList = pLastNodeInList;
while (pHeadOfList && pHeadOfList->left != NULL)
pHeadOfList = pHeadOfList->left;
return pHeadOfList;
}
11、判断一棵树是否是另一棵树的子结构
bool DoesTree1HaveTree2(TreeNode *pRoot1, TreeNode *pRoot2)
{
if (pRoot2 == NULL)
return true;
if (pRoot1 == NULL)
return false;
if (pRoot1->value != pRoot2->value)
return false;
return DoesTree1HaveTree2(pRoot1->left, pRoot2->left) &&
DoesTree1HaveTree2(pRoot1->right, pRoot2->right);
}
bool HasSubtree(TreeNode *pRoot1, TreeNode *pRoot2)
{
bool result = false;
if (pRoot1 != NULL && pRoot2 != NULL) {
if (pRoot1->value == pRoot2->value)
result = DoesTree1HaveTree2(pRoot1,pRoot2);
if (!result)
result = HasSubtree(pRoot1->left,pRoot2);
if (!result)
result = HasSubtree(pRoot1->right,pRoot2);
}
}
12、输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
TreeNode *construct(int *preorder, int *inorder, int length)
{
if(preorder == NULL || inorder == NULL || length <= 0)
return NULL;
return constructCore(preorder, preorder + length - 1, inorder, inorder + length - 1);
}
TreeNode *constructCore(int *s_preorder, int *e_preorder, int *s_inorder, int *e_inorder)
{
int rootvalue = s_preorder[0]; //前序遍历序列的第一个数字是根结点的值
TreeNode *root = new TreeNode();
root->value = rootvalue;
root->left = root->right = NULL;
if (s_preorder == e_preorder) {
if (s_inorder == e_inorder && *s_inorder == *e_inorder)
return root;
else
throw std::exception("Invaild input.");
}
//在中序遍历中找到根结点的值
int *rootInorder = s_inorder;
while (rootInorder <= e_inorder && *rootInorder != rootvalue)
++rootInorder;
if (rootInorder == e_inorder && *rootInorder != rootvalue)
throw std::exception("Invaild input.");
int leftLength = rootInorder - s_inorder;
int *leftPreorderEnd = s_preorder + leftLength;
if (leftLength > 0) {
root->left = constructCore(s_preorder,leftPreorderEnd,s_inorder,rootInorder-1);
}
if (leftLength < e_preorder - s_preorder) {
root->right =constructCore(leftPreorderEnd+1,e_preorder,rootInorder+1,e_inorder);
}
return root;
}
13、输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。假设输入的数组的任意两个数字互不相同。
bool VerifySquenceOfBST(int sequence[], int length)
{
if (sequence == NULL || length <= 0)return false;
int root = sequence[length-1];
int i = 0;
for (; i < length-1; i++) {
if (sequence[i] > root)
break;
}
int j = i;
for (; j < length - 1; j++) {
if (sequence[j] < root)
return false;
}
bool left = true;
if(i>0)
left = VerifySquenceOfBST(sequence,i);
bool right = true;
if(i<length-1)
right = VerifySquenceOfBST(sequence+i,length-i-1);
return left && right;
}
14、输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
void FindPath(TreeNode *pRoot, int expectedSum, vector<int>&path, int currentSum)
{
currentSum += pRoot->value;
path.push_back(pRoot->value);
bool isLeaf = pRoot->left == NULL && pRoot->right == NULL;
if (currentSum == expectedSum && isLeaf)
{
printf("A path is found: ");
vector<int>::iterator iter = path.begin();
for (; iter != path.end(); ++iter)
printf("%d\t",*iter);
printf("\n");
}
if (pRoot->left != NULL)
FindPath(pRoot->left,expectedSum,path,currentSum);
if (pRoot->right != NULL)
FindPath(pRoot->right,expectedSum,path,currentSum);
path.pop_back();
}
void FindPath(TreeNode *pRoot, int expectedSum)
{
if (pRoot == NULL)return;
vector<int>path;
int currentSum = 0;
FindPath(pRoot,expectedSum,path,currentSum);
}
15、请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的.
bool isTreeSymmertic(TreeNode *pHead1,TreeNode *pHead2){
if(pHead1==NULL && pHead2==NULL)
return true;
if(pHead1==NULL)
return false;
if(pHead2==NULL)
return false;
return (pHead1->val==pHead2->val) && isTreeSymmertic(pHead1->left,pHead2->right) &&
isTreeSymmertic(pHead1->right,pHead2->left);
}
bool isSymmetrical(TreeNode* pRoot)
{
if(pRoot==NULL)
return true;
bool res=isTreeSymmertic(pRoot->left,pRoot->right);
return res;
}
16、给定一个有序整数数组,元素各不相同且按升序排列,编写一个算法,创建一棵高度最小的二叉查找树。
TreeNode *BST(vector<int>a, int start,int end)
{
if (end < start)
return NULL;
int mid = (start+end)/2;
TreeNode *node = new TreeNode();
node->val = a[mid];
node->left = BST(a,start,mid-1);
node->right = BST(a,mid+1,end);
return node;
}
TreeNode *createBST(vector<int>a)
{
return BST(a,0,a.size()-1);
}
17、实现一个函数,检查一棵二叉树是否为二叉查找树。
方法1:
bool checkIsBST(TreeNode *root, int &data)
{
if (root == NULL)return true;
if (!checkIsBST(root->left,data))
return false;
if (root->val <= data)
return false;
data = root->val;
if (!checkIsBST(root->right,data))
return false;
return true;
}
bool checkBST(TreeNode *root)
{
int data = INT_MIN;;
return checkIsBST(root,data);
}
方法2:
bool checkBST1(TreeNode *root, int min, int max)
{
if (root == NULL)return true;
if (root->val < min || root->val > max)return false;
if (!checkBST1(root->left, min, root->val) ||
!checkBST1(root->left, root->val, max))
return false;
}
bool checkBST1(TreeNode *root)
{
return checkBST1(root,INT_MIN,INT_MAX);
}
17、设计并实现一个算法,找出二叉树种某两个节点的第一个公共祖先。不得将额外的节点存储在另外的数据结构中。注意:这不一定是二叉查找树。
bool covers(TreeNode *node, TreeNode *p)
{
if (node == NULL)return false;
if (node == p)return true;
return covers(node->left, p) || covers(node->right,p);
}
TreeNode *commonHelper(TreeNode *node, TreeNode *p, TreeNode * q)
{
if (node == NULL)return NULL;
if (node == p || node == q)return node;
int is_p_on_left = covers(node->left,p);
int is_q_on_left = covers(node->left,q);
if (is_p_on_left != is_q_on_left)
return node;
int is_on_left = (is_p_on_left == 1 && is_q_on_left == 1);
TreeNode *is_side = is_on_left? node->left : node->right;
return commonHelper(is_side, p, q);
}
TreeNode *commonAncestor(TreeNode *root,TreeNode *p, TreeNode *q)
{
if (!covers(root, p) || !covers(root, q))return NULL;
return commonHelper(root,p,q);
}
19、给定一棵二叉树,其中每个节点都含有一个数值。设计一个算法,打印节点数值总和等于某个给定值得所有路径。注意,路径不一定非得从二叉树的根节点或叶节点开始或结束。
void FindSum(TreeNode *node, int sum, vector<int>path, int level)
{
if (node == NULL)return;
path[level] = node->data;
int t = 0;
for (int i = level; i >= 0; i--) {
t += path[i];
if (t == sum)
print(path,i,level);
}
FindSum(node->left,sum,path,level+1);
FindSum(node->right,sum,path,level+1);
path[level = INT_MIN];
}
void FindSum(TreeNode *node, int sum)
{
int dept = depth(node);
vector<int>path(dept);
FindSum(node,sum,path,0);
}