二叉树的各种操作

二叉树的各种操作
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);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值