二叉树系列5:建立二叉搜索树
来源:互联网 发布:超级基因优化液好看吗 编辑:程序博客网 时间:2024/06/05 16:58
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
二叉排序树的查找过程和次优二叉树类似,通常采取二叉链表作为二叉排序树的存储结构。中序遍历二叉排序树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,O(log(n))。
1 插入
/** * 二叉树的插入操作 */ public boolean add(TreeNode t, int val) { if (t == null) { t = new TreeNode(val); return true; } // 如果父节点等于要插入的值,则说明该值已存在,所以不新建任何节点,返回false if (t.val == val) { return false; } // 如果val 小于 父节点的值,则新节点应该为其左子树中 else if (val < t.val) { // 如果左子树为空,则新建节点, 并将这个节点设为左孩子 if (t.left == null) { t.left = new TreeNode(val); return true; } else { return add(t.left, val); } } else { if (t.right == null) { t.right = new TreeNode(val); return true; } else { return add(t.right, val); } } } /** 非递归中序遍历二叉树 */ public ArrayList<TreeNode> inorderTraversal(TreeNode t) { if (t == null) { return null; } Stack<TreeNode> stack = new Stack<>(); ArrayList<TreeNode> aList = new ArrayList<>(); TreeNode p = t; while (p != null || !stack.isEmpty()) { // 如果目前访问的节点不为空,则尝试先访问它的左子树 if (p != null) { stack.push(p); // 开始访问左子树 p = p.left; } // 如果 p为null说明访问的左节点为空,将先前压入栈的父节点pop,打印,并且开始访问右子树 else { p = stack.pop(); // 打印父节点 aList.add(p); // 开始访问右子树 p = p.right; } } return aList; }
2 删除
- 首先,找到这个要删除的节点
- 如果它是叶子节点就可以直接删除
- 如果它只有一个子节点,则让它的子节点代替它的位置就好了
- 如果它有两个子节点,则找到右子树的最小值,这个值一定是一个叶子,所以先将这个最小值复值给要删除的节点的值域,然后删除这个最小值节点,由于是叶子节点,所以很容易删除
private TreeNode remove(TreeNode t, int val) { if (t == null) { return null; } // 第一步是,找到要删除的节点 // 小于0,说明该节点在左子树中 if (val - t.val < 0) { t.left = remove(t.left, val); } // 大于0,说明该节点在右子树中 else if (val - t.val > 0) { t.right = remove(t.right, val); } // 等于0,说明找到了 else { // 如果这是一个叶子,则直接删除这个节点 if (t.left == null && t.right == null) { t = null; } // 如果该节点有一个儿子 else if (t.left == null ^ t.right == null) { return t = (t.left != null ? t.left : t.right); } // 如果有两个儿子 else if (t.left != null && t.right != null) { TreeNode minNode = findMin(t.right); t.val = minNode.val; t.right = remove(t.right, minNode.val); } } return t; }
private TreeNode findMin(TreeNode t) { if (t == null) { return null; } else if (t.left == null) { return t; } else { return findMin(t.left); } }
3 测试
public class Main { public static void main(String[] args) { TreeNode binarySearchTree = new TreeNode(8); BinaryTreeTest testTree = new BinaryTreeTest(); testTree.add(binarySearchTree, 22); testTree.add(binarySearchTree, 3); testTree.add(binarySearchTree, 13); testTree.add(binarySearchTree, 5); testTree.add(binarySearchTree, 7); testTree.add(binarySearchTree, 27); System.out.println("\n通过插入新建了一个二叉搜索树,然后输出其中序遍历的结果"); ArrayList<TreeNode> aList = testTree.inorderTraversal(binarySearchTree); for (TreeNode treeNode : aList) { System.out.printf("%-5d", treeNode.val); } testTree.remove(binarySearchTree, 7); System.out.println("\n删除已经存在的 7"); aList = testTree.inorderTraversal(binarySearchTree); for (TreeNode treeNode : aList) { System.out.printf("%-5d", treeNode.val); } }}
输出:
通过插入新建了一个二叉搜索树,然后输出其中序遍历的结果3 5 7 8 13 22 27 删除已经存在的 73 5 8 13 22 27
0 0
- 二叉树系列5:建立二叉搜索树
- 建立二叉搜索树
- 二叉搜索树的建立
- 递归建立二叉搜索树
- 数组建立二叉搜索树
- 递归实现二叉搜索树建立
- 二叉搜索树建立及求树高
- 二叉搜索树的建立 插入 删除
- 二叉树系列之二:二叉搜索树
- 二叉树--二叉搜索树
- 【二叉树】二叉搜索树
- 二叉树- 二叉搜索树
- 九度OJ 1009: 二叉搜索树 两棵树的判等+二叉搜索树的建立
- 【二叉搜索数】HDU3791二叉搜索树
- 二叉树系列四:Leetcode#98判断二叉树是否为二叉搜索树(BST)
- 递归建立二叉树
- 二叉树的建立
- 二叉树建立
- Codeforces 622E (树DP)
- spring学习笔记(23)基于tx/aop配置切面增强事务
- 值传递、指针传递、引用传递
- MyDynamicFEM项目之一git
- 甜品店切蛋糕问题(动态规划,Go语言实现)
- 二叉树系列5:建立二叉搜索树
- rvm 安装 ruby 之后,必须执行 /bin/bash --login 才能执行 ruby 命令
- 强迫症的自我恢复
- 欧拉函数
- SDUT 3513 皮卡丘的梦想 (二进制+线段树) -- 解题报告
- 如何克服拖延症
- 点击elevator楼梯跳转效果
- 【Mysql错误】Unable to connect to remote host. Catalog download has failed.
- server 设置VPN