一、什么是二叉排序树
二、如何判断一棵二叉树为二叉排序树
// 将二叉排序树的非递归中序遍历代码拿来稍微改一下就行了
template<typename T>
bool Tree<T>::isSortedTree()
{
int lastValue = 0;
std::stack<_TreeNode*> _st;
_TreeNode *p = root;
// 借助二叉树的非递归的思想来判断二叉树是否为二叉搜索树
while(p != nullptr || !_st.empty())
{
// 将左子树加入到栈中
while(p != nullptr)
{
_st.push(p);
p = p->left;
}
if(!_st.empty())
{
p = _st.top(); // 得到栈顶元素
_st.pop(); // 出栈
// 如果第一次弹出或者lastValue小于当前节点, 给lastValue重新赋值
if(lastValue == 0 || lastValue < p->data)
lastValue = p->data;
// 如果lastValue大于当前节点值, 则返回false
if(lastValue > p->data)
return false;
p = p->right; //指向右子节点, 下一次循环时就会中序遍历右子树
}
}
// 走到这里说明二叉树为二叉搜索树, 返回false
return true;
}
三、测试代码
- 下面是一个二叉搜索树的实现代码,其中包含树的中序遍历,和我们的isSortedTree()方法
- 代码如下:
#include <iostream>
#include <stack>
using namespace std;
// 二叉搜索树
template<typename T>
class Tree
{
private:
// 树节点
typedef struct treeNode{
treeNode(T _data, struct treeNode *_left, struct treeNode *right) : data(_data), left(_left), right(right) { }
T data;
struct treeNode *left;
struct treeNode *right;
}_TreeNode;
private:
// 根节点
_TreeNode *root;
public:
// 构造函数, 使用数组构造一棵二叉搜索树
Tree(T arr[], size_t len);
// 判断该树是否为二叉搜索树
bool isSortedTree();
// 非递归中序遍历
void InOrderTreeUnRec()
{
if(root == nullptr)
return;
InOrderTreeUnRec(root);
std::cout << std::endl;
}
private:
void InOrderTreeUnRec(_TreeNode *node);
private:
// 将一个节点插入刀二叉搜索树中
void insertNode(T elem);
};
template<typename T>
Tree<T>::Tree(T arr[], size_t len)
{
root = nullptr;
// 循环将节点插入到二叉搜索树中
for(int i = 0; i < len; ++i)
insertNode(arr[i]);
}
template<typename T>
void Tree<T>::insertNode(T elem)
{
// 创建一个新的节点
_TreeNode *newNode = new _TreeNode(elem, nullptr, nullptr);
// 如果根节点为空, 将其作为根节点
if(root == nullptr)
{
root = newNode;
return;
}
// 指向于根节点
_TreeNode *step = root, *temp;
while(step != nullptr)
{
// 先记录下这个节点
temp = step;
// 如果新节点大于该节点, 向右偏移
if(newNode->data > step->data)
step = step->right;
// 如果新节点小于该节点, 向左偏移
else if(newNode->data < step->data)
step = step->left;
}
// 偏移完成之后, temp一定指向于尾节点, 然后将新节点与尾节点比较, 将其插入左边还是右边
if(temp->data > newNode->data)
temp->left = newNode;
else
temp->right = newNode;
}
template<typename T>
void Tree<T>::InOrderTreeUnRec(_TreeNode *node)
{
std::stack<_TreeNode*> _st;
_TreeNode *p = node;
// 如果节点不为空: 说明还有节点可以判断
// 如果栈不为空: 如果节点为空, 但是栈不为空, 说明要回退了
while(p != nullptr || !_st.empty())
{
// 逐渐将左节点加入到栈中
while(p != nullptr)
{
_st.push(p); //把遍历的节点全部压栈
p = p->left;
}
// 栈不为空, 将节点出栈, 然后右节点压入栈
if(!_st.empty())
{
p = _st.top(); // 得到栈顶内容
_st.pop(); // 出栈
std::cout << p->data << " ";
p = p->right; // 指定右子节点, 下一次循环时就会中序遍历右子树
}
}
}
template<typename T>
bool Tree<T>::isSortedTree()
{
int lastValue = 0;
std::stack<_TreeNode*> _st;
_TreeNode *p = root;
// 借助二叉树的非递归的思想来判断二叉树是否为二叉搜索树
while(p != nullptr || !_st.empty())
{
// 将左子树加入到栈中
while(p != nullptr)
{
_st.push(p);
p = p->left;
}
if(!_st.empty())
{
p = _st.top(); // 得到栈顶元素
_st.pop(); // 出栈
// 如果第一次弹出或者lastValue小于当前节点, 给lastValue重新赋值
if(lastValue == 0 || lastValue < p->data)
lastValue = p->data;
// 如果lastValue大于当前节点值, 则返回false
if(lastValue > p->data)
return false;
p = p->right; //指向右子节点, 下一次循环时就会中序遍历右子树
}
}
// 走到这里说明二叉树为二叉搜索树, 返回false
return true;
}
int main()
{
int arr[] = {5, 3, 7, 2, 4, 6, 8, 1};
Tree<int> *myTree = new Tree<int>(arr, sizeof(arr) / sizeof(int));
// 非递归中序遍历
std::cout << "InOrderTreeUnRec: ";
myTree->InOrderTreeUnRec();
std::cout << std::endl;
// 打印判断是否为二叉排序树的结果
std::cout << boolalpha << myTree->isSortedTree() << std::endl;
return 0;
}