跳转到主内容
极星编程网:以代码为星,赴技术山海!

数据结构-二叉排序树(图文详细版)

文章目录 ⭐前言⭐ 🍓一,二分搜索树的特性 1,中序遍历的序列是递增的序列 2,中序遍历的下一个节点,称后继节点,即比当前节点大的最小节点 3,中序遍历的前一个节点,称前驱节点,即比当前节点小的最大节点 🍒二,添加节点 1,思路 2,代码实现 🍌三,删除任意节点 1,思路 2,示例分析 3,代码实现 🍎四,查找节点 1,思路 2,代码实现 🍇五,总结 1,二分搜索树的优缺点 2,时间-空间复杂度 ⭐前言⭐ 二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树。

二叉排序树或者是一棵空树,或者是具有下列特点的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值; (3)左、右子树也分别为二叉排序树; 🍓一,二分搜索树的特性 1,中序遍历的序列是递增的序列 public LinkedList inorder(TreeNode root, LinkedList arr) { if (root == null) return arr; inorder(root.left, arr); arr.add(root.val); inorder(root.right, arr); return arr; }

2,中序遍历的下一个节点,称后继节点,即比当前节点大的最小节点 public int successor(TreeNode root) { root = root.right; while (root.left != null) root = root.left; return root; } 3,中序遍历的前一个节点,称前驱节点,即比当前节点小的最大节点 public int predecessor(TreeNode root) { root = root.left; while (root.right != null) root = root.right; return root; }

🍒二,添加节点 1,思路 🌸(1)比较根节点和value的值 🌸(2)把value添加在叶子节点

2,代码实现

/**

* 添加值为value的节点 */ public Node add(Node root, int value) { if(root == null){ //走到叶子节点添加 root = new Node(value); size++; return root; } //比较value和根节点的大小 if(value < root.val){ root.left = add(root.left,value); }else{ root.right = add(root.right,value); } return root; }

🍌三,删除任意节点 1,思路 (1)若value < root.val,则在左子树进行删除 (2)若value >root.val,则在右子树进行删除 (3)若value == root.val,此节点就是要删除的 ① 该节点是叶子,直接删除 ②该节点只有左子树,将前驱节点代替根节点,删除前驱节点 ③该节点只有右子树,将后继节点代替根节点,删除后继节点 (4)返回根节点root

2,示例分析 (1)要删除的节点为叶子节点,可以直接删除

(2)删除的节点不是叶子节点,只有右节点,则该节点可以由该节点的后继节点替代,然后可以从后继节点的位置递归向下操作以删除后继节点。

(3)删除的节点不是叶子节点,只有左节点。

这意味着它的后继节点在它的上面,但是我们并不想返回。

我们可以使用它的前驱节点进行替代,然后再递归的向下删除前驱节点。

3,代码实现

/**

* 二叉搜索树的根节点 root,值 key,删除key 对应的节点 */ public TreeNode deleteNode(TreeNode root, int key) { if(root == null) { return null; } if(key < root.val){ //在左子树删除 root.left = deleteNode(root.left,key); }else if(key > root.val){ //在右子树删除 root.right = deleteNode(root.right,key); }else{ //node是叶子 if(root.left ==null && root.right == null){ root = null; //只有右子树 }else if(root.right != null){ root.val = sucessor(root); root.right = deleteNode(root.right,root.val); }else{ //只有左子树 root.val = predecessor(root); root.left = deleteNode(root.left,root.val); } } return root; } //找到后继节点,返回根结点的值 public int sucessor(TreeNode root) { root = root.right; while(root.left != null){ root = root.left; } return root.val; } //找到前驱节点,返回根结点的值 public int predecessor(TreeNode root) { root = root.left; while(root.right != null){ root = root.right; } return root.val; }

🍎四,查找节点 1,思路 🍎 (1)查找二分搜索树是否包含指定值-二分查找 🍎 (2)返回二分搜索树的最小值 🍎 (3)返回二分搜索树的最大值

2,代码实现

/**

* 判断以root为根节点的二分搜索树中是否包含指定元素val */ public boolean contains(Node root,int val){ if(root == null){ return false; } //根节点就是val if(root.val == val){ return true; }else if(val < root.val){ //在左树中寻找 contains(root.left,val); } return contains(root.right,val); }

🍇五,总结 1,二分搜索树的优缺点 (1)⭐优势⭐ 查找元素、插入元素、删除元素的时间复杂度都是O(logn)。

还可以方便的回答很多数据之间关系的问题:min,max,floor,ceil,rank,select (2)⭐局限性⭐ 当将一组数据以近乎有序的顺序插入空二分搜索树中时,几乎每一个节点都是父节点的右孩子,二分搜索树近乎退化成了一个链表,相关算法时间复杂度都退化成了O(N)。

因此有了平衡二叉树,不会退化成链表,如:红黑树等。

2,时间-空间复杂度 🍓二叉排序树是平衡的,则n个节点的二叉排序树的高度为,其查找效率为,近似于折半查找。

如果二叉排序树完全不平衡,则其深度可达到n,查找效率为O(n),退化为顺序查找。

一般的,二叉排序树的查找性能在到O(n)之间。

因此,为了获得较好的查找性能,就要构造一棵平衡的二叉排序树。

🍓二叉树的空间复杂度:因为需要建立排序二叉树,所以空间复杂度为O(n)

相关文章