二叉搜索树及中序遍历

二叉搜索树的概念

二叉搜索树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根节点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。 

二叉搜索树及中序遍历_第1张图片 图1                              二叉搜索树及中序遍历_第2张图片图2

类似图1,此处3比5小,不是二叉搜索树,中序遍历得出的序列为[1, 5, 3, 4, 6]可以看出,并不是逐个递增的。图2是二叉搜索树,中序遍历得出的序列[1, 2, 3, 4, 5, 6]

二叉搜索树的性质

二叉树由于左子树的结点的值均小于根节点的值,右子树的结点的值均大于根节点的值。所以二叉搜索树可以根据中序遍历,转换成值递增的一维数组。 因此大部分的二叉搜索树的题目都可以先直接使用中序遍历,然后进行相应的操作。

中序遍历的方式可以递归,也可以迭代,迭代写法方便对序列进行操作,所以尽量使用迭代中序遍历。写法可以参考往期博客。

https://blog.csdn.net/weixin_42835209/article/details/115321081?spm=1001.2014.3001.5501

 

二叉搜索树相关leetcode题解

leetcode-98. 验证二叉搜索树

 

思路:根据中序遍历把二叉树转换成List,逐个比较是否依次递增。利用了二叉搜索树的特性,方法较为暴力。

import java.util.ArrayList;
import java.util.List;

import 树.TreeNode;

public class IsValidBST {

	public static void main(String[] args) {
		TreeNode root1 = new TreeNode(1);
		TreeNode root2 = new TreeNode(1);
//		TreeNode root3 = new TreeNode(6);
//		TreeNode root4 = new TreeNode(3);
//		TreeNode root5 = new TreeNode(7);
		
		root1.left = root2;
//		root1.right = root3;
//		root3.left = root4;
//		root3.right = root5;
		IsValidBST ivbst = new IsValidBST();
		
		System.out.println(ivbst.isValidBST(root1));
	}
	List list = new ArrayList();
	public List midOrderTraversal(TreeNode root){
		if(root == null) {
			return list;
		}
		midOrderTraversal(root.left);
		list.add(root.val);
		midOrderTraversal(root.right);
		return list;
	}
	
    public boolean isValidBST(TreeNode root) {
    	if(root == null) {
    		return true;
    	}
    	List arr = midOrderTraversal(root);
    	for(int i=1;i

 

leetcode-99. 恢复二叉搜索树

 

思路:1. 根据中序遍历,把树转换成List。2. 根据List找到对应的x和y,x为第一个比后面的数大的数字,y为最后一个比x小的数。交换树中对应x结点和y结点的值。


import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import 树.TreeNode;

public class RecoverTree {

	public static void main(String[] args) {
		TreeNode root1 = new TreeNode(1);
		TreeNode root2 = new TreeNode(3);
		TreeNode root3 = new TreeNode(2);

		
		root1.left = root2;
		root2.right = root3;
		RecoverTree rt = new RecoverTree();
		rt.recoverTree(root1);
	}
	
	
    public void recoverTree(TreeNode root) {
    	List nums = new ArrayList();
    	inorder(root, nums);
    	int [] swapped = findTwoSwapped(nums);
    	recover(root, 2, swapped[0], swapped[1]);

    }
    
    public void inorder(TreeNode root, List nums) {
    	if(root == null) {
    		return;
    	}
    	inorder(root.left, nums);
    	nums.add(root.val);
    	inorder(root.right, nums);
    }
    
    public int[] findTwoSwapped(List nums) {
    	int n = nums.size();
    	int x = -1, y = -1;
    	for(int i=1;i

 

leetcode-230. 二叉搜索树中第K小的元素

 

思路:把二叉树转换成List,按索引取数字,第k小对应的索引为k-1。

import java.util.ArrayList;
import java.util.List;

import 树.TreeNode;

public class KthSmallest {

	public static void main(String[] args) {

	}

    public int kthSmallest(TreeNode root, int k) {
    	List nums = new ArrayList<>();
    	
    	inorder(root, nums);
    	return nums.get(k-1);
    }
    
    public void inorder(TreeNode root, List nums) {
    	if(root == null) {
    		return;
    	}
    	inorder(root.left, nums);
    	nums.add(root.val);
    	inorder(root.right, nums);
    }
}

 

leetcode-二叉搜索树中的中序后继

 

思路:用迭代写法的中序遍历,定义一个flag初始化为false,代表是否找到p。如果找到p,则置flag为true,则下一次迭代时得到的node则为p的后继。由于中序遍历取数都是在栈中弹栈才取的,所以需要在弹栈的时候进行flag的判断和修改。

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import 树.TreeNode;

public class InorderSuccessor {
	public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
		if(root == null) {
			return null;
		}
		
		// 迭代中序遍历
		Stack stack = new Stack<>();
		boolean flag = false;
		while(root!=null || !stack.empty()) {
			while(root!=null) {
				stack.push(root);
				root = root.left;
			}
			TreeNode node = stack.pop();
			if(flag == true) {
				return node;
			}
			// 判断p的值是否相等,如果相等,则设置为true,获得下一次遍历的值
			if(node.val == p.val) {
				flag = true;
			}
			if(node.right != null) {
				root = node.right;
			}
		}
		return null;
	}
	
}

 

leetcode-最接近的二叉搜索树值II

 

思路:先实现中序遍历,用一个map记录<差值,原值>,在java中转换成TreeMap进行升序排序。得到差值小的排在前面,则根据k得到前k个差值最小的数字,即最接近的数字进行返回。

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
import java.util.TreeMap;

import 树.TreeNode;

public class ClosestKValues {

	List closestKValues(TreeNode root, double target, int k){
		List res = new ArrayList();
		if(root == null) {
			return res;
		}
		Stack stack = new Stack<>();
		Map map = new HashMap();
		while(!stack.empty() || root != null) {
			while(root != null) {
				stack.push(root);
				root = root.left;
			}
			TreeNode node = stack.pop();
			map.put(Math.abs(node.val-target), node.val);
			if(node.right != null) {
				root = node.right;
			}
		}
		
		TreeMap sorted = new TreeMap<>(map);
		System.out.println(sorted.toString());
		List arr = new ArrayList(sorted.values());
		for(int i=0;i

 

总结

总而言之,只要是二叉搜索树的题目,都可以实现中序遍历先。中序遍历可以先额外写一个递归的中序遍历函数返回各种参数,也可以直接用迭代的中序遍历直接在迭代体中进行一系列操作。主要是要掌握各种数据结构容器的使用,并深刻理解树的遍历的写法。

你可能感兴趣的:(数据结构,二叉树,leetcode)