面试总结之——Tree

    二叉树BinaryTree定义为任何父结点只能有两个子结点。完全二叉树CompleteBinaryTree定义为非叶结点其左右结点都非空,叶结点都集中在树的左边。二叉搜索树BinarySerachTree定义为父结点的值大于其左子结点,小于其右子结点,其左右子树为二叉搜索树。二叉平衡树AVL定义为首先为二叉搜索树,其次其左右结点的深度相差不超过1。

    一般面试题无非都是对基本知识的一个包装后者一个变形。基本知识点:二叉树的深度、二叉树的结点个数、二叉树的遍历、二叉搜索树的插入及查找等等。二叉树问题的解决办法主要是通过递归,将参数压入栈。非递归方法比如说遍历其实可以自己引入数据结构入Stack Queue,利用这些数据结构对数据的操作来实现对树的先后访问。我们知道一般可以用空间换时间性能的提高,对于一些求树的特性或者判断树的特性的问题如:LCA、MaxDistance、最大SubBSTree等问题,采用后序遍历方法将计算的结果返回给上一层判断时间性能一般比先序遍历性能要好。

二叉树节点定义如下:

struct BinaryTreeNode

{

        int m_nValue;

        BinaryTreeNode *m_pLeft;

        BinaryTreeNode *m_pRight;

}BTNode,BSTNode;


1、二叉树基本问题:A:创建二叉搜索树 B:二叉树节点数目 C:二叉树深度 D:二叉树最小值  E:二叉树查找 

2、遍历:前序遍历、中序遍历、后序遍历、层序遍历 递归实现  非递归实现

3、序列化、反序列化二叉树/二叉搜索树

4、构建二叉树:中序遍历和先序遍历/后序遍历构建二叉树

5、构建二叉树:将有序数组转为平衡二叉搜索树

6、构建二叉树:将有序单链表转为平衡的二叉搜索树

7、转换:二叉搜索树转换成有序的双向循环链表

8、求二叉树第K层的结点个数

9、求二叉树中叶子结点的个数

10、求二叉树中和为某一值的所有路径

11、求二叉树的镜像

12、求二叉树中两个节点的最低公共祖先节点LCA

13、求二叉树中节点的最大距离

14、求二叉树中最大的子树,且子树为二叉搜索树

15、判断一棵树是否是二叉搜索树

16、判断一棵树是否为完全二叉树



1、二叉树基本问题:A:创建二叉搜索树 B:二叉树节点数目 C:二叉树深度 D:二叉搜索树最值  E:二叉搜索树查找

      A:创建二叉树

BTNode* CreateNode(int nData)
{
	BTNode *pNode = (BTNode*)malloc(sizeof(BTNode));

	pNode->m_nValue = nData;
	pNode->m_pLeft  = NULL;
	pNode->m_pRight = NULL;

	return pNode;
}

BSTNode* InsertNode2BST(BSTNode* pRoot, int nData)
{
	if (pRoot == NULL)
	{
		return CreateNode(nData);
	}

	if (nData >= pRoot->m_nValue)
	{
		pRoot->m_pLeft = InsertNode2BST(pRoot->m_pLeft, nData);
	}else
	{
		pRoot->m_pRight = InsertNode2BST(pRoot->m_pRight, nData);
	}

	return pRoot;
}
BSTNode* CreateBSTree(int Num[], int length)
{
	if (Num == NULL || length <= 0)
	{
		return NULL;
	}
	
	BSTreeNode* pRoot = NULL;
	for (int i=0; i<length; i++)
	{
		InsertNode2BST(pRoot, Num[i]);
	}

	return pRoot;
}

    B:二叉树结点个数

int GetBTNodeSize(BTNode* pRoot)
{
	if (pRoot == NULL)
	{
		return 0;
	}

	return GetBTNodeSize(pRoot->m_pLeft) + GetBTNodeSize(pRoot->m_pRight) + 1;
}

    C:二叉树深度

int GetBTDepth(BTNode* pRoot)
{
	if (pRoot == NULL)
	{
		return 0;
	}

	return max(GetBTDepth(pRoot->m_pLeft), GetBTDepth(pRoot->m_pRight)) + 1;
}

    D:二叉搜索树最值

int GetBSTMinValue(BTNode* pRoot)
{
	assert(pRoot != NULL);
	BTNode* pLeft = pRoot;

	while (pLeft)
	{
		pLeft = pLeft->m_pLeft;
	}

	return pLeft->m_nValue;
}

int GetBSTMaxValue(BTNode* pRoot)
{
	assert(pRoot != NULL);
	BTNode* pRight = pRoot;

	while (pRight)
	{
		pRight = pRight->m_pRight;
	}

	return pRight->m_nValue;
}

    E:二叉搜索树查找

bool LookUp(BTNode* pRoot, int target)
{
	if (pRoot == NULL)
	{
		return false;
	}

	if (pRoot->m_nValue == target)
	{
		return true;
	}

	if (target < pRoot->m_nValue)
	{
		return LookUp(pRoot->m_pLeft, target);
	}else
	{
		return LookUp(pRoot->m_pRight, target);
	}

}

2、遍历:前序遍历、中序遍历、后序遍历、层序遍历 递归实现  非递归实现

递归调用

先序遍历

/************************************************************************/
/* PreOrder先序遍历                                                                   
/************************************************************************/
void PrintByPreOrder_Recursion(BTNode* pRoot)  
{  
	if (pRoot == NULL)  
		return;  
	visit(pRoot);  
	PrintByPreOrder_Recursion(pRoot->m_pLeft);  
	PrintByPreOrder_Recursion(pRoot->m_pRight);  
}  

中序遍历

/************************************************************************/
/* InOrder遍历   中序遍历                                                                
/************************************************************************/
void PrintByInOrder_Recursion(BTNode* pRoot)  
{  
	if (pRoot == NULL)  
		return;    
	PrintByInOrder_Recursion(pRoot->m_pLeft);  
	visit(pRoot);
	PrintByInOrder_Recursion(pRoot->m_pRight);  
}

后序遍历

/************************************************************************/
/* PostOrder遍历   后序遍历                                                                
/************************************************************************/
void PrintByPostOrder_Recursion(BTNode* pRoot)  
{  
	if (pRoot == NULL)  
		return;    
	PrintByPostOrder_Recursion(pRoot->m_pLeft);  
	PrintByPostOrder_Recursion(pRoot->m_pRight); 
	visit(pRoot);
}

层序遍历

/************************************************************************/
/* LevelOrder遍历   层序遍历                                                                
/************************************************************************/
void PrintByLevelOrder_Recursion(BTNode* pRoot, int level)
{
	if (pRoot == NULL || level <= 0)
	{
		return ;
	}

	if (level == 1)
	{
		visit(pRoot);
		return;
	}

	PrintByLevelOrder_Recursion(pRoot->m_pLeft, level-1);
	PrintByLevelOrder_Recursion(pRoot->m_pRight, level-1);
}

void PrintByLevelOrder_Recursion(BTNode* pRoot)  
{  
	if (pRoot == NULL)  
		return; 

	int depth = GetBTDepth(pRoot);

	for (int i=1; i<=depth; i++)
	{
		PrintByLevelOrder_Recursion(pRoot, i);
		printf("\n");//换行
	}
}

非递归遍历

先序遍历
/************************************************************************/
/* 非递归实现 PreOrder先序遍历                                                                 
/************************************************************************/
void PrintByPreOrder(BTNode* pRoot)
{
	if (pRoot == NULL)
	{
		return;
	}

	stack<BTNode*> stack_BT;
	stack_BT.push(pRoot);

	while (!stack_BT.empty())
	{
		BTNode* pTop = stack_BT.top();
		visit(pTop);
		stack_BT.pop();

		if (pTop->m_pLeft != NULL)
		{
			stack_BT.push(pTop->m_pLeft);
		}

		if (pTop->m_pRight != NULL)
		{
			stack_BT.push(pTop->m_pRight);
		}
	}

	return;
}

中序遍历1
/************************************************************************/
/* 非递归实现 InOrder中序遍历                                                                
/************************************************************************/
void PrintByInOrder_1(BTNode* pRoot)
{
	if (pRoot == NULL)
	{
		return;
	}

	stack<BTNode*> stack_BT;
	
	while (pRoot != NULL || !stack_BT.empty())
	{
		if (pRoot != NULL)
		{
			stack_BT.push(pRoot);
			pRoot = pRoot->m_pLeft;
		}else
		{
			pRoot = stack_BT.top();
			visit(pRoot);
			stack_BT.pop();

			pRoot = pRoot->m_pRight;
		}
	}

	return;
}

中序遍历2
 void PrintByInOrder_2(BTNode* pRoot)
{
	if (pRoot == NULL)
	{
		return;
	}

	stack<BTNode*> stack_BT;
	stack_BT.push(pRoot);

	while (!stack_BT.empty())
	{
		BTNode* pTop = stack_BT.top();

		if (pTop->m_pLeft != NULL)
		{
			stack_BT.push(pTop->m_pLeft);
		}else
		{
			visit(pTop);
			stack_BT.pop();

			if (pTop->m_pRight != NULL)
			{
				stack_BT.push(pTop->m_pRight);
			}
		}
	}

	return;
}

后序遍历1
/************************************************************************/
/* 非递归实现 PostOrder 后序遍历    
/* 1、用两个Stack实现  2、用一个Stack实现 加入一个标志位 null
/************************************************************************/
void PrintByPostOrder_1(BTNode* pRoot)
{
	if (pRoot == NULL)
	{
		return;
	}

	stack<BTNode*> stack_BT;
	stack<BTNode*> stack_out;

	stack_BT.push(pRoot);

	while (!stack_BT.empty())
	{
		BTNode* pTop = stack_BT.top();
		stack_BT.pop();
		stack_out.push(pTop);

		if (pTop->m_pLeft != NULL)
		{
			stack_BT.push(pTop->m_pLeft);
		}

		if (pTop->m_pRight != NULL)
		{
			stack_BT.push(pTop->m_pRight);
		}
	}

	while (!stack_out.empty())
	{
		BTNode* pTop = stack_out.top();
		stack_out.pop();

		visit(pTop);
	}

	return;
}

后序遍历2
void PrintByPostOrder_2(BTNode* pRoot)
{
	if (pRoot == NULL)
	{
		return;
	}

	stack<BTNode*> stack_BT;
	stack_BT.push(pRoot);

	while (!stack_BT.empty())
	{
		BTNode* pTop = stack_BT.top();

		if (pTop == NULL)//访问父结点
		{
			stack_BT.pop();
			pTop = stack_BT.top();
			stack_BT.pop();

			visit(pTop);
			continue;
		}

		if (pTop->m_pLeft != NULL || pTop->m_pRight != NULL)
		{
			stack_BT.push(NULL);

			if (pTop->m_pLeft != NULL)
			{
				stack_BT.push(pTop->m_pRight);
			}

			if (pTop->m_pRight != NULL)
			{
				stack_BT.push(pTop->m_pLeft);
			}
		}else//访问叶节点
		{
			stack_BT.pop();

			visit(pTop);
		}

	}

	return;
}

层序遍历1
/************************************************************************/
/* 非递归实现 LevelOrder 层序遍历    
/* 1、用两个Queue实现  2、用一个Queue实现 加入一个标志位 null
/************************************************************************/
void swap(queue<BTNode*>& dst_queue, queue<BTNode*>& src_queue)
{
	while (!src_queue.empty()) {  
		BTNode* pFront = src_queue.front();  
		src_queue.pop();  
		dst_queue.push(pFront);  
	}  
}

void PrintByLevelOrder_1(BTNode* pRoot)
{
	if (pRoot == NULL)
	{
		return ;
	}

	queue<BTNode*> queue_BT1;
	queue<BTNode*> queue_BT2;

	queue_BT1.push(pRoot);

	while (!queue_BT1.empty())
	{
		BTNode* pFront = queue_BT1.front();

		if (pFront->m_pLeft != NULL)
		{
			queue_BT2.push(pFront->m_pLeft);
		}

		if (pFront->m_pRight != NULL)
		{
			queue_BT2.push(pFront->m_pRight);
		}

		visit(pFront);
		queue_BT1.pop();

		if (queue_BT1.empty())
		{
			swap(queue_BT1, queue_BT2);
			printf("\n");//换行
		}
	}
}

层序遍历2
void PrintByLevelOrder_2(BTNode* pRoot)
{
	if (pRoot == NULL)
	{
		return ;
	}

	queue<BTNode*> queue_BT;

	queue_BT.push(pRoot);
	queue_BT.push(NULL);

	while (!queue_BT.empty())
	{
		BTNode* pFront = queue_BT.front();
		queue_BT.pop();

		if (pFront == NULL)
		{
			printf("\n");
			if (!queue_BT.empty())
			{
				queue_BT.push(NULL);
				continue;
			}else
				break;

		}

		visit(pFront);

		if (pFront->m_pLeft)
		{
			queue_BT.push(pFront->m_pLeft);
		}

		if (pFront->m_pRight)
		{
			queue_BT.push(pFront->m_pRight);
		}
	}
}


3、序列化、反序列化二叉树/二叉搜索树

/************************************************************************/
/* 保存二叉搜索树到文件中,需要从文件中恢复二叉搜索树                                                                   
/* 1、中序遍历无法恢复BSTree
/* 2、后序遍历可以恢复BSTree 但是从文件中读取数据有先后顺序
/* 2、前序遍历也可也恢复BSTree,同时也满足从文件中读一个数据就构建一个结点

/* 如果换成二叉树 则为了能够在重构二叉树时结点能够插入到正确的位置,
/* 在使用先序遍历保存二叉树到文件中的时候需要把NULL结点也保存起来(可以使用特殊符号如“#”来标识NULL结点)。
/************************************************************************/
void WriteBSTree2File(BSTreeNode* pRoot, std::ofstream& f_out)
{
	if (pRoot == NULL || f_out == NULL)
	{
		return;
	}

	f_out<<pRoot->m_nValue<<"\n";
	WriteBSTree2File(pRoot->m_pLeft, f_out);
	WriteBSTree2File(pRoot->m_pRight, f_out);

	return;
}

BSTreeNode* BuildBSTreeFromFile(std::ifstream& f_in)
{
	if (f_in == NULL)
	{
		return NULL;
	}

	int value = 0;
	f_in>>value;
	BSTreeNode* pRoot = CreateNode(value);

	while (!f_in.eof())
	{
		int mValue = 0;
		f_in>>mValue;
		if (mValue == 0)//写入txt的时候最后一个数据多写了一个分行符号 暂没找到更好办法
		{
			break;
		}

		BSTreeNode* pAdd = pRoot;

		while (pAdd)
		{
			if (mValue <= pAdd->m_nValue && pAdd->m_pLeft)
			{
				pAdd = pAdd->m_pLeft;
			}else if (mValue <= pAdd->m_nValue)
			{
				pAdd->m_pLeft = CreateNode(mValue);
				break;
			}

			if (mValue > pAdd->m_nValue && pAdd->m_pRight)
			{
				pAdd = pAdd->m_pRight;
			}else if (mValue > pAdd->m_nValue)
			{
				pAdd->m_pRight = CreateNode(mValue);
				break;
			}
		}
	}
	return pRoot;

}
4、构建二叉树:中序遍历和先序遍历/后序遍历构建二叉树

前序+中序 以及 中序+后序可以重构二叉树  前序+后序不能重构二叉树 但是如果是二叉搜索前序和后序也是可以重构出来的。

前序遍历+中序遍历

/************************************************************************/
/* 构建二叉树:中序遍历和先序遍历/后序遍历构建二叉树                                                                     
/************************************************************************/
BTNode* BuildBTreeFromPreInOrder(int preOrder[], int inOrder[], int length)
{
	if (preOrder == NULL || inOrder == NULL || length < 0)
	{
		return NULL;
	}

	int parent = preOrder[0];
	BTNode* pRoot = CreateNode(parent);
	int partition = 0;
	while (partition < length)
	{
		if (inOrder[partition] == parent)
		{
			break;
		}

		partition++;
	}
	int left_length = partition;
	int right_length = length - partition - 1;

	if (left_length > 0)
	{
		pRoot->m_pLeft = BuildBTreeFromPreInOrder(preOrder + 1, inOrder, left_length);
	}

	if (right_length > 0)
	{
		pRoot->m_pRight = BuildBTreeFromPreInOrder(preOrder + partition + 1, inOrder + partition + 1, right_length);
	}

	return pRoot;
}

中序遍历+后序遍历

 BTNode* BuildBTreeFromInPostOrder(int inOrder[], int postOrder[], int length)
{
	if (inOrder == NULL || postOrder == NULL || length < 0)
	{
		return NULL;
	}

	int parent = postOrder[length-1];
	BTNode* pRoot = CreateNode(parent);
	int partition = 0;
	while (partition < length)
	{
		if (inOrder[partition] == parent)
		{
			break;
		}

		partition++;
	}
	int left_length = partition;
	int right_length = length - partition - 1;

	if (left_length > 0)
	{
		pRoot->m_pLeft = BuildBTreeFromPreInOrder(inOrder, postOrder, left_length);
	}

	if (right_length > 0)
	{
		pRoot->m_pRight = BuildBTreeFromPreInOrder(inOrder + partition + 1, postOrder + partition, right_length);
	}

	return pRoot;
}

5、构建二叉树:将有序数组转为平衡二叉搜索树

/************************************************************************/
/* 构建二叉树:将有序数组转为平衡二叉搜索树   
/* 给定一个有序数组,数组元素升序排列,直接选择有序数组的中间元素作为根结点。
/* 选择了中间元素作为根结点并创建后,剩下的元素分为两部分,可以看作是两个数组。
/* 这样剩下的元素在根结点左边的作为左子树,右边的作为右子树
/************************************************************************/
BSTreeNode* SortedArrayToBST(int nArray[], int begin, int end)
{
	if (nArray == NULL || begin > end)
	{
		return NULL;
	}

	int mid = begin + (end - begin)/2;
	BSTreeNode* pRoot = CreateNode(nArray[mid]);
	pRoot->m_pLeft  = SortedArrayToBST(nArray, begin, mid - 1);
	pRoot->m_pRight = SortedArrayToBST(nArray, mid + 1, end);

	return pRoot;
}

BSTreeNode* SortedArrayToBST(int nArray[], int length)
{
	return SortedArrayToBST(nArray, 0, length-1);
}
6、构建二叉树:将有序单链表转为平衡的二叉搜索树

由于单链表升序排列,可以参照前面的文章将有序数组转换为平衡二叉搜索树, 先求的链表中的结点的值保存在数组中,然后采用相同的方法实现,时间复杂度为O(N)。
下面是一种直接从链表遍历的算法

BSTreeNode* BuildBSTreeFromList(ListNode*& pHead, int begin, int end)
{
	if (pHead == NULL || begin > end)
	{
		return NULL;
	}

	int mid = begin + (end - begin)/2;
	BSTreeNode* pLeftChild = BuildBSTreeFromList(pHead, begin ,mid-1);
	BSTreeNode* pRoot = CreateNode(pHead->m_nValue);
	pRoot->m_pLeft = pLeftChild;
	pHead = pHead->m_pNext;
	pRoot->m_pRight = BuildBSTreeFromList(pHead, mid+1, end);
	return pRoot;
}

BSTreeNode* BuildBSTreeFromList(ListNode* pHead)
{
	if (pHead == NULL)
	{
		return NULL;
	}

	int count = 0;
	ListNode* pTemp = pHead;
	while (pTemp)
	{
		count++;
		pTemp = pTemp->m_pNext;
	}
	printf("count:%d",count);

	return BuildBSTreeFromList(pHead, 0 ,count-1);
}
7、转换:二叉搜索树转换成有序的双向循环链表

/************************************************************************/
/* 转换:二叉搜索树转换成有序的双向循环链表                                                                 
/* 相当于得到BST的中序遍历结果  采用后序遍历 自底而上
/************************************************************************/
BSTNode* ConvertBST2DList(BSTNode* pRoot)// 
{
	if (pRoot == NULL)
	{
		return NULL;
	}
	//叶结点
	if (pRoot->m_pLeft == NULL && pRoot->m_pRight == NULL)
	{
		return pRoot;
	}

	if (pRoot->m_pLeft != NULL)
	{
		ConvertBST2DList(pRoot->m_pLeft);
		BSTNode* pRight = pRoot->m_pLeft;

		while (pRight->m_pRight)//注意不能调用null指针的数据
		{
			pRight = pRight->m_pRight;
		}
		pRight->m_pRight = pRoot;
		pRoot->m_pLeft = pRight;

	}

	if (pRoot->m_pRight != NULL)
	{
		ConvertBST2DList(pRoot->m_pRight);

		BSTNode* pLeft = pRoot->m_pRight;
		while (pLeft->m_pLeft)
		{
			pLeft = pLeft->m_pLeft;
		}
		pLeft->m_pLeft = pRoot;
		pRoot->m_pRight = pLeft;
	}


	return pRoot;
}

8、求二叉树第K层的节点个数

/************************************************************************/
/* 求二叉树第K层的节点个数                                                                  
/************************************************************************/
int GetKthNodesNum(BTNode* pRoot, int k)
{
	if (pRoot == NULL || k < 0)
	{
		return 0;
	}

	if (k == 1)
	{
		return 1;
	}
	
	return GetKthNodesNum(pRoot->m_pLeft, k-1) + GetKthNodesNum(pRoot->m_pRight, k-1);

}

9、求二叉树中叶子节点的个数


/************************************************************************/
/* 求叶结点个数                                                                     
/************************************************************************/
int GetLeafNodesNum(BTNode* pRoot)
{
	if (pRoot == NULL)
	{
		return 0;
	}

	if (pRoot->m_pLeft == NULL && pRoot->m_pRight == NULL)
	{
		return 1;
	}

	return GetLeafNodesNum(pRoot->m_pLeft) + GetLeafNodesNum(pRoot->m_pRight);
}
10、求二叉树中和为某一值的所有路径

/************************************************************************/
/* 求二叉树中和为某一值的所有路径                                                                    
/************************************************************************/
void FindPathInBSTree(BinaryTreeNode* pTreeNode, int expectedSum,std::vector<int>& path, int& currentSum)
{
	if(!pTreeNode)
		return;

	currentSum += pTreeNode->m_nValue;
	path.push_back(pTreeNode->m_nValue);

	bool isLeaf = (!pTreeNode->m_pLeft && !pTreeNode->m_pRight);
	if(currentSum == expectedSum && isLeaf)
	{    
		std::vector<int>::iterator iter = path.begin();
		for(; iter != path.end(); ++ iter)
			std::cout << *iter << '\t';
		std::cout << std::endl;
	}

	if(pTreeNode->m_pLeft)
		FindPathInBSTree(pTreeNode->m_pLeft, expectedSum, path, currentSum);
	if(pTreeNode->m_pRight)
		FindPathInBSTree(pTreeNode->m_pRight, expectedSum, path, currentSum);

	currentSum -= pTreeNode->m_nValue;
	path.pop_back();
} 

11、求二叉树的镜像

/************************************************************************/
/* 得到二叉树的镜像                                                                   
/************************************************************************/
BTNode* GetMirrorBTree(BTNode* pRoot)
{	
	if (pRoot == NULL)
	{
		return NULL;
	}

	GetMirrorBTree(pRoot->m_pLeft);
	GetMirrorBTree(pRoot->m_pRight);

	BTNode* pTemp = pRoot->m_pLeft;
	pRoot->m_pLeft = pRoot->m_pRight;
	pRoot->m_pRight = pTemp;

	return pRoot;
}

12、求二叉树中两个节点的最低公共祖先节点LCA

/************************************************************************/
/*求二叉树中两个结点的最低公共祖先结点LCA
/*1、当两个结点中任何一个不在树中 输出Null
/************************************************************************/
bool IfHasNode(BTNode* pRoot, BTNode* pNode)
{
	//输入为空指针 则输出false
	if (pRoot == NULL || pNode == NULL)
	{
		return false;
	}

	return (pRoot == pNode) || IfHasNode(pRoot->m_pLeft, pNode) || IfHasNode(pRoot->m_pRight, pNode);

}
BTNode* LCA(BTNode* pRoot, BTNode* pNode1, BTNode* pNode2)
{
	if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL)
		return NULL;

	//如果一个pRoot和其中任何一个结点相同 则公共结点为pRoot
	if (pRoot == pNode1 || pRoot == pNode2)
	{
		return pRoot;
	}

	bool flag_left_node1 = IfHasNode(pRoot->m_pLeft, pNode1);
	bool flag_left_node2 = IfHasNode(pRoot->m_pLeft, pNode2);
	if (flag_left_node1 == 1 && flag_left_node2 == 1)
	{
		return LCA(pRoot->m_pLeft, pNode1, pNode2);
	}

	bool flag_right_node1 = IfHasNode(pRoot->m_pRight, pNode1);
	bool flag_right_node2 = IfHasNode(pRoot->m_pRight, pNode2);
	if (flag_right_node1 == 1 && flag_right_node2 == 1)
	{
		return LCA(pRoot->m_pRight, pNode1, pNode2);
	}

	//如果pNode1 和 pNode2不存在树中 则应该返回null;
	if ( (flag_left_node1 || flag_left_node2) && (flag_right_node1 || flag_right_node2))
		return pRoot;
	else
		return NULL;

}

BTNode* LCA2(BTNode* pRoot, BTNode* pNode1, BTNode* pNode2)
{
	if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL)
	{
		return NULL;
	}

	if (pRoot == pNode1 || pRoot == pNode2)
	{
		return pRoot;
	}//并没有考虑其中一个结点是否在树中的情况

	BTNode* pLeft = LCA2(pRoot->m_pLeft, pNode1, pNode2);
	BTNode* pRight = LCA2(pRoot->m_pRight, pNode1, pNode2);

	if (pLeft && pRight)
	{
		return pRoot;
	}

	return pLeft ? pLeft : pRight;
}

/************************************************************************/
/*当考察对象变成BinarySearchTree时可以利用m_nValue直接判断结点时在Tree的左边 还是右边                                                                    
/************************************************************************/
BSTreeNode* LCA_BST(BSTreeNode* pRoot, BSTreeNode* pNode1, BSTreeNode* pNode2)
{
	if (pRoot == NULL || pNode1 == NULL || pNode2 == pNode2)
	{
		return NULL;
	}

	/*
	if (pRoot == pNode1 || pRoot == pNode2)
	{
		return pRoot;
	}
	//我认为应该判断pNode1 pNode2两个结点是否都在树中 return IfHasNode(pRoot->m_pLeft, pNode1) || IfHasNode(pRoot->m_pRight, pNode1);
	*/

	if (pNode1->m_nValue < pRoot->m_nValue && pNode2->m_nValue < pRoot->m_nValue)
	{
		return LCA_BST(pRoot->m_pLeft, pNode1, pNode2);
	}

	if (pNode1->m_nValue > pRoot->m_nValue && pNode2->m_nValue > pRoot->m_nValue)
	{
		return LCA_BST(pRoot->m_pLeft, pNode1, pNode2);
	}

	return pRoot;
}

13、求二叉树中节点的最大距离

/************************************************************************/
/* 求二叉树中节点的最大距离                                                                     
/************************************************************************/
void GetMaxDistance(BSTreeNode* pRoot, int& maxValue, int& depth)
{
	if (pRoot == NULL)
	{
		maxValue = 0;
		depth = 0;
	}

	if (pRoot->m_pLeft == NULL && pRoot->m_pRight == NULL)//叶结点
	{
		maxValue = 0;
		depth  = 1;

		return;
	}

	int left_maxValue = 0; int right_maxValue = 0; int left_depth = 0; int right_depth = 0;
	if (pRoot->m_pLeft != NULL)
	{
		GetMaxDistance(pRoot->m_pLeft, left_maxValue, left_depth);
	}

	if (pRoot->m_pRight != NULL)
	{
		GetMaxDistance(pRoot->m_pRight, right_maxValue, right_depth);
	}

	depth = max(left_depth, right_depth) + 1;
	maxValue = max(max(left_maxValue, right_maxValue), left_depth + right_depth);

}

int GetMaxDisBetweenNodes(BSTreeNode* pRoot)
{
	//
	if (pRoot == NULL || (pRoot->m_pLeft == NULL && pRoot->m_pLeft == NULL))
	{
		return -1;
	}

	int depth = 0; int maxDis = 0;
	GetMaxDistance(pRoot, maxDis, depth);

	return maxDis;
}


14、求二叉树中最大的子树,且子树为二叉搜索树

#define LEFT  1
#define RIGHT 2
/************************************************************************/
/* 找出二叉树中最大的子树,该子树为二叉搜索树。所谓的子树就是结点最大的树                                                                    
/************************************************************************/
BSTreeNode* GetMaxSubBSTree(BTNode* pRoot, int& count, int& range, int flag )
{
	//空指针
	if (pRoot == NULL)
	{
		return NULL;
	}

	//叶节点
	if (pRoot->m_pLeft == NULL && pRoot->m_pRight == NULL)
	{
		count = 1;
		range = pRoot->m_nValue;
		return pRoot;
	}

	int left_count ; int left_range; int left_flag = LEFT;
	int right_count; int right_range; int right_flag = RIGHT;
	
	//判断左结点
	BSTreeNode* pLeftBST = NULL;
	if (pRoot->m_pLeft)
	{
		pLeftBST = GetMaxSubBSTree(pRoot->m_pLeft, left_count, left_range, left_flag);
	}else
	{
		left_count = 0;
		left_range = pRoot->m_nValue;
	}

	//判断右结点
	BSTreeNode* pRightBST = NULL;
	if (pRoot->m_pRight)
	{
		pRightBST = GetMaxSubBSTree(pRoot->m_pRight, right_count, right_range, right_flag);
	}else
	{ 
		right_count = 0;
		right_range = pRoot->m_nValue;
	}
	
	//左右结点都有BSTree
	if (pRoot->m_pLeft == pLeftBST && pRoot->m_pRight == pRightBST && left_range <= pRoot->m_nValue && right_range >= pRoot->m_nValue)
	{
		count = left_count + right_count + 1;
		range = flag == LEFT ? right_range : left_range;
		
		return pRoot;
	}

	//左右结点只有一个
	if (left_count > right_count)
	{
		count = left_count;
		return pLeftBST;
	}
	else
	{
		count = right_count;
		return pRightBST;
	}

}
BSTreeNode* GetMaxSubBSTree(BTNode* pRoot)
{
	//1、空指针 
	if (pRoot == NULL)
	{
		return NULL;
	}
	//2、叶结点
	if (pRoot->m_pLeft == NULL && pRoot->m_pRight == NULL)
	{
		return pRoot;
	}

	int left_count  = 0; int left_range = ~0xffffffff; int left_flag  = LEFT;
	int right_count = 0; int right_range = 0xffffffff; int right_flag = RIGHT;

	BSTreeNode* pLeft  = GetMaxSubBSTree(pRoot->m_pLeft, left_count, left_range, left_flag);
	BSTreeNode* pRight = GetMaxSubBSTree(pRoot->m_pRight, right_count, right_range, right_flag);

	if (pLeft == pRoot->m_pLeft && pRight == pRoot->m_pRight && left_range <= pRoot->m_nValue && right_range >= pRoot->m_nValue)
	{
		return pRoot;
	}

	if (left_count > right_count)
	{
		return pLeft;
	}else
	{
		return pRight;
	}
	
}

15、判断一棵树是否是二叉搜索树

/************************************************************************/
/* 判断一棵树是否是二叉搜索树                                                                     
/************************************************************************/
bool JudgeIfBSTree(BSTreeNode* pRoot, int upRange, int downRange)
{
	if (pRoot == NULL)
	{
		return false;
	}
	printf("%d %d\n",upRange, downRange);

	bool left_flag = true; bool right_flag = true;

	if ((pRoot->m_nValue < downRange) || (pRoot->m_nValue > upRange))
	{
		return false;
	}

	if (pRoot->m_pLeft != NULL)
	{
		left_flag = JudgeIfBSTree(pRoot->m_pLeft, pRoot->m_nValue, downRange);
	}

	if (pRoot->m_pRight != NULL)
	{
		right_flag = JudgeIfBSTree(pRoot->m_pRight, upRange, pRoot->m_nValue);
	}

	return left_flag&&right_flag;
}
bool JudgeIfBSTree(BSTreeNode* pRoot)
{
	//1、空树怎么定义 输入非法? 单结点 输出合法
	if (pRoot == NULL)
	{
		return false;
	}

	int upRange = 0x7fffffff;
	int downRange = ~upRange;

	return JudgeIfBSTree(pRoot, upRange, downRange);
}


16、判断一棵树是否为完全二叉树

/************************************************************************/
/* 判断一棵二叉树是否是完全二叉树。
/* 二叉树定义如下:除最后一层外,其余每层都是满的,最后一层的叶节点都集中在树的左边
/************************************************************************/
bool JudgeIfCompleteBTree(BTNode* pRoot)
{
	if (pRoot == NULL)
	{
		return false;
	}

	queue< BTNode* > BT_Queue;
	BT_Queue.push(pRoot);
	
	while (!BT_Queue.empty())
	{
		BTNode* pFront = BT_Queue.front();
		BT_Queue.pop();

		if (pFront == NULL)
		{
			break;
		}else
		{
			BT_Queue.push(pFront->m_pLeft);
			BT_Queue.push(pFront->m_pRight);
		}
	}

	while (!BT_Queue.empty())
	{
		BTNode* pFront = BT_Queue.front();
		BT_Queue.pop();

		if (pFront != NULL)
		{
			return false;
		}
	}

	return true;
}


后记:第一次写带代码的bolg,发现csdn的编辑器真难用,要吗是乱码,要吗是怎么调都不行。你说一个格式刷都没有?其实都已经写好了一个后记,深情并茂的,只可惜是剪切出来没保存。。。

bolg还是要写的,而且还要写的更好。用自己的拙笔记录学习的点滴,也方便以后更进一步的学习。




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值