纸上得来终觉浅,觉知此事要躬行
二叉搜索树的定义。
若它的左子树不为空,则左子树上所有节点的值均小于它的根节点的值。
若它的右字树不为空,则右子树上所有节点的值均大于它的根节点的值。
它的左、右子树也分别为二叉搜索树。
二叉搜索树是有序数,这就决定了二叉搜索树的递归遍历、迭代遍历和普通二叉树都不一样。
15、在二叉搜索树中寻找节点
leetcode700:
确定一个节点是否存在二叉搜索树中,如果在,则返回这个节点,如果不在,则返回null。
(1)、递归法
因为二叉搜索树的节点是有序的,所以可以有方向地搜索。如果root->val大于val,则搜索左子树,如果root->val小于val,则搜索右子树,如果没有找到目标节点,则返回null。
- #include
- using namespace std;
-
- typedef struct _tag_BitNode {
- int data;
- _tag_BitNode* left;
- _tag_BitNode* right;
- _tag_BitNode(int val) {
- data = val;
- left = nullptr;
- right = nullptr;
- }
- }BitNode,*BitNodePtr;
-
- BitNode* SearchBST(BitNode* root, int val) {
- if (root == nullptr || root->data == val) {
- return root;
- }
- if (root->data > val) {
- return SearchBST(root->left, val);
- }
- if (root->data < val) {
- return SearchBST(root->right, val);
- }
- return nullptr;
- }
-
- void main() {
- BitNode node0(4), node1(2), node2(7);
- BitNode node3(1), node4(3), node5(6), node6(8);
- node0.left = &node1;
- node0.right = &node2;
- node1.left = &node3;
- node1.right = &node4;
- node2.left = &node5;
- node2.right = &node6;
-
- BitNode* ret = SearchBST(&node0, 3);
- cout << "hell world" << endl;
- }
(2)、迭代法
一提到二叉树遍历的迭代法,读者可能立刻想到使用栈模拟深度遍历,使用队列模拟广度遍历。但对于二叉搜索树就不一样了,基于二叉搜索树的特殊性,也就是节点的有序性,不适用辅助栈或者队列就可以写成迭代法。
对于一般二叉树,递归过程中还有回溯的过程。例如,遍历一个左方向的分支到头了,就需要调头,再遍历右分支。而对于二叉搜索树,不需要回溯的过程,基于节点的有序性就可以确定搜索方向。
- BitNode* SearchBSTIter(BitNode* root,int val) {
- while (root != nullptr) {
- if (root->data > val) {
- root = root->left;
- }
- else if (root->data < val) {
- root = root->right;
- }
- else {
- return root;
- }
- }
- return nullptr;
- }
本节介绍了二叉搜索树的遍历方式,基于二叉搜索树的特性,遍历的时候要比普票的二叉树简单得多,一些读者很容易忽略二叉搜索树的特性而写出很复杂的代码。所以针对二叉搜索树的题目,一定要利用其特性。
16、验证二叉搜索树
leetcode98:验证二叉搜索树
判断二叉树是不是二叉搜索树的条件如下:
(1)、若它的左子树不为空,则左子树上所有节点的值均小于它的根节点的值。
(2)、若它的右子树不为空,则右子树上所有节点的值均大于它的根节点的值。
(3)、它的左、右字树也分别为二叉搜索树。
采用中序遍历时,输出的二叉树搜索树节点的数值是有序序列。基于这个特性,验证二叉搜索树就相当于判断一个序列是不是递增的。
递归法:
可以采用中序遍历将二叉搜索树转变成一个数组,只要比较这个数组是不是有序的即可,如果数组是有序的,则是二叉搜索树。
- class Solution {
- private:
- vector<int> vec;
- void Inorder(BitNode* root) {
- if (root == nullptr) {
- return ;
- }
- Inorder(root->left);
- vec.push_back(root->data);
- Inorder(root->right);
- }
- public:
- bool IsValidBST(BitNode* root) {
- vec.clear();
- Inorder(root);
- for (int i = 1; i < vec.size(); i++) {
- if (vec[i] < vec[i - 1]) {
- return false;
- }
- }
- return true;
- }
- };
迭代法:
- bool IsValidBSF(BitNode* root) {
- stack
st; - BitNode* cur = root;
- BitNode* pre = nullptr;
- while (cur != nullptr || !st.empty()) {
- if (cur != nullptr) {
- st.push(cur);
- cur = cur->left;
- }
- else {
- cur = st.top();
- st.pop();
- if (pre != nullptr && cur->data <= pre->data) {
- return false;
- }
- pre = cur;
- cur = cur->right;
- }
- }
- return true;
- }
17、二叉搜索树的最小绝对值
leetcode530:二叉搜索树中的最小绝对值
给出一颗树所有节点为非负值的二叉搜索树,请计算树中任意两个节点的差的绝对值的最小值。
(1)、递归法
注意是二叉搜索树,二叉搜素树是有序的。遇到二叉搜索树上求最值,求差值问题,就把它想象成在一个有序数组上求最值、求差值,这样就简单多了。
- class Solution {
- private:
- vector<int> vec;
- void TraverSal(BitNode* root) {
- if (root == nullptr) {
- return;
- }
- TraverSal(root->left);
- vec.push_back(root->data);
- TraverSal(root->right);
- }
- public:
- int GetMinimumDifference(BitNode* root) {
- vec.clear();
- TraverSal(root);
- if (vec.size() < 2) {
- return 0;
- }
- int result = INT_MAX;
- for (int i = 1; i < vec.size(); i++) {
- result = min(result, (vec[i] - vec[i - 1]));
- }
- return result;
- }
- };
其实对二叉树进行中序遍历的过程中,我们可以直接找到相邻两个节点的差值:用一个pre节点记录cur节点的前一个节点。
- class Solution {
- private:
- int result = INT_MAX;
- BitNode* pre = nullptr;
- void TraverSal(BitNode* cur) {
- if (cur == nullptr) {
- return;
- }
- TraverSal(cur->left);
- if (pre != nullptr) {
- result = min(result, cur->data - pre->data);
- }
- pre = cur;
- TraverSal(cur->right);
- }
- public:
- int GetMinimumDifference(BitNode* root) {
- TraverSal(root);
- return result;
- }
- };
迭代法:
下面给出一种中序遍历的迭代法
- class Solution {
- public:
- int GetMinimumDifference(BitNode* root) {
- stack
st; - BitNode* cur = root;
- BitNode* pre = nullptr;
- int result = INT_MAX;
- while (cur != nullptr || !st.empty()) {
- if (cur != nullptr) {
- st.push(cur);
- cur = cur->left;
- }
- else {
- BitNode* node = st.top();
- st.pop();
- if (pre != nullptr) {
- result = min(result, cur->data - pre->data);
- }
- pre = cur;
- cur = cur->right;
- }
- }
- return result;
- }
- };