问题: 判断一棵二叉树是否为二叉搜索树
二叉树节点定义如下:
struct BTNode {
int data;
BTNode *pLeft;
BTNode *pRight;
};
二叉搜索树定义如下:
二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树:
若它的左子树不空,则左子树上所有结点的值均小于它的根节点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根节点的值;
它的左右子树也分别为二叉搜索树。
解法一: 暴力搜索法。
二叉树上任一结点必须满足,其左子树上所有结点均小于它,右子树上所有结点均大于它。
bool isSubTreeLessThan(BTNode *pRoot, int x)
{
if (!pRoot)
return true;
return (pRoot->data < x &&
isSubTreeLessThan(pRoot-pLeft, x) &&
isSubTreeLessThan(pRoot->pRight, x));
}
bool isSubTreeGreaterThan(BTNode *pRoot, int x)
{
if (!pRoot)
return true;
return (pRoot->data > x &&
isSubTreeGreaterThan(pRoot->pLeft, x) &&
isSubTreeGreaterThan(pRoot->pRight, x));
}
bool isBSTBruteForce(BTNode *pRoot)
{
if (!pRoot)
return true;
return (isSubTreeLessThan(pRoot->pLeft, pRoot->data) &&
isSubTreeGreaterThan(pRoot->pRight, pRoot->data) &&
isBSTBruteForce(pRoot->pLeft) &&
isBSTBruteForce(pRoot->pRight));
}
一种类似的解法:任一结点的值大于左子树的最大值,小于右子树的最小值。
int maxSubTreeValue(BTNode *pRoot)
{
assert(pRoot);
int ret = pRoot->data;
if (!pRoot->pLeft && !pRoot->pRight)
return ret;
if (pRoot->pLeft)
ret = max(ret, maxSubTreeValue(pRoot->pLeft));
if (pRoot->pRight)
ret = max(ret, maxSubTreeValue(pRoot->pRight));
return ret;
}
int minSubTreeValue(BTNode *pRoot)
{
assert(pRoot);
int ret = pRoot->data;
if (!pRoot->pLeft && !pRoot->pRight)
return ret;
if (pRoot->pLeft)
ret = min(ret, minSubTreeValue(pRoot->pLeft));
if (pRoot->pRight)
ret = min(ret, minSubTreeValue(pRoot->pRight));
return ret;
}
bool isBSTBruteForce(BTNode *pRoot)
{
if (!pRoot)
return true;
if (pRoot->pLeft && pRoot->data <= maxSubTreeValue(pRoot->pLeft))
return false;
if (pRoot->pRight && pRoot->data >= minSubTreeValue(pRoot->pRight))
return false;
if (!isBSTBruteForce(pRoot->pLeft) || !isBSTBruteForce(pRoot->pRight))
return false;
return true;
}
解法二:
挖掘每个结点的取值范围
bool isBSTAux(BTNode *pRoot, int Min, int Max)
{
if (!pRoot)
return true;
if (pRoot->data <= Min || pRoot->data >= Max)
return false;
return (isBSTAux(pRoot->pLeft, Min, pRoot->data) &&
isBSTAux(pRoot->pRight, pRoot->data, Max));
}
bool isBST(BTNode *pRoot)
{
return isBSTAux(pRoot, INT_MIN, INT_MAX);
}
解法三:中序遍历
二叉搜索树的中序遍历结果是从小到大有序产生的,该算法时间复杂度为O(N)
bool isBSTInOrder(BTNode *pRoot, int &prev)
{
if (!pRoot)
return true;
if (isBSTInOrder(pRoot->pLeft, prev))
{
if (p->data > prev)
{
prev = p->data;
return isBSTInOrder(pRoot->pRight, prev);
}
else
return false;
}
else
return false;
}
bool isBST(BTNode *pRoot)
{
int prev = INT_MIN;
return isBSTInOrder(pRoot, prev);
}
解法四:Morris Traversal 方法中序遍历,参考 Morris Traversal 遍历二叉树