代码随想录 第八章 二叉树:二叉搜索树

纸上得来终觉浅,觉知此事要躬行

二叉搜索树的定义。

若它的左子树不为空,则左子树上所有节点的值均小于它的根节点的值。

若它的右字树不为空,则右子树上所有节点的值均大于它的根节点的值。

它的左、右子树也分别为二叉搜索树。

二叉搜索树是有序数,这就决定了二叉搜索树的递归遍历、迭代遍历和普通二叉树都不一样。

15、在二叉搜索树中寻找节点

leetcode700:

确定一个节点是否存在二叉搜索树中,如果在,则返回这个节点,如果不在,则返回null。

(1)、递归法

因为二叉搜索树的节点是有序的,所以可以有方向地搜索。如果root->val大于val,则搜索左子树,如果root->val小于val,则搜索右子树,如果没有找到目标节点,则返回null。

#include<iostream>
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<BitNode*> 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<BitNode*> 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;
	}
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值