节点node[算法导论]二叉排序树(Binary Search Tree)
新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正
1. 二叉排序树的定义
它或者是一棵空树;或者是拥有下列性子的二叉树:
(1)若左子树不空,则左子树上全部结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上全部结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
2. java实现代码(注:以下代码参考网上优良代码,均已编写实现)
/* * 注:该代码实现了二叉查找树的全部操作:包括,插入、删除、查找、排序输出、前驱、后继等。 * */ import java.util.ArrayList; import java.util.List; public class BinarySearchTree { // 二叉查找树的根节点 private TreeNode root = null ; private List<TreeNode> nodelist = new ArrayList<TreeNode>(); // 二叉树的节点类 private class TreeNode{ private int key ; private TreeNode leftChild ; private TreeNode rightChild ; private TreeNode parent ; // 构造器 public TreeNode(int key , TreeNode leftChild , TreeNode rightChild , TreeNode parent) { this.key = key ; this.leftChild = leftChild ; this.rightChild = rightChild ; this.parent = parent ; } public int getKey() { return key ; } public String toString() { String leftkey = (leftChild == null ? "" : String.valueOf(leftChild.key)); String rightkey = (rightChild == null ? "" : String.valueOf(rightChild.key)); return "("+leftkey+","+key+","+rightkey+")"; } } /* * 判断二叉查找树是不是为空;若为空,返回true,否则返回false * */ public boolean isEmpty() { if(root == null){ return true ; }else{ return false ; } } /* * 对于某些二叉查找树操作(比如删除关键字)来说,若树为空,则抛出异常。 * */ public void TreeEmpty() throws Exception { if(isEmpty()){ throw new Exception("树为空!"); } } /* * 在二叉查找树中查询给定关键字的节点 * */ public TreeNode search(int key) { TreeNode pNode = root ; while(pNode!=null && pNode.key !=key) { if(key<pNode.key){ pNode = pNode.leftChild; }else{ pNode = pNode.rightChild; } } return pNode ; } /* * 获得二叉查找树中的最小关键字节点 * */ public TreeNode minTreeNode(TreeNode node)throws Exception{ if(node == null) throw new Exception("树为空!"); TreeNode pNode = node ; while(pNode.leftChild!=null) { pNode = pNode.leftChild ; } return pNode ; } /* * 获得二叉查找树中的最大关键字的节点 * */ public TreeNode maxTreeNode(TreeNode node)throws Exception{ if(node == null) throw new Exception("树为空!"); TreeNode pNode = node ; while(pNode.rightChild!=null) { pNode = pNode.rightChild ; } return pNode ; } /* * 查找给定节点在中序遍历下的后继节点 * */ public TreeNode successor(TreeNode node)throws Exception{ if(node == null) return null ; // 若该节点的右子树不为空,则它的后继节点为右子树中的最小关键字节点 if(node.rightChild!=null){ return minTreeNode(node.rightChild); } // 右子树为空的情况 TreeNode pNode = node.parent ; while(pNode!=null && node == pNode.rightChild){ node = pNode ; pNode = pNode.parent; } return pNode ; } /* * 查找给定节点在中序遍历下的前驱节点 * */ public TreeNode precursor(TreeNode node)throws Exception{ if(node == null) return null; // 若节点的左子树不为空,则它的前驱节点就是左子树中的最大节点 if(node.leftChild!=null){ return maxTreeNode(node.leftChild); } // 左子树为空的情况 TreeNode pNode = node.parent ; while(pNode!=null&&node==pNode.leftChild){ node = pNode ; pNode = pNode.parent; } return pNode ; } /* * 将给定的关键字插入到二叉查找树中 * */ public void insert(int key){ TreeNode node = null ; TreeNode newNode = new TreeNode(key,null,null,null); TreeNode pNode = root ; if(root==null){ root = newNode ; return ; } while(pNode!=null){ node = pNode ; if(key<pNode.key){ pNode = pNode.leftChild ; }else if(key > pNode.key){ pNode = pNode.rightChild; }else{ // 树中已存在给定的关键字节点了 return ; } } if(key<node.key){ node.leftChild = newNode ; newNode.parent = node ; }else{ node.rightChild = newNode ; newNode.parent = node ; } } /* * 从二叉查找树中删除给定的节点 * */ public void delete(int key)throws Exception{ TreeNode pNode = search(key); if(pNode == null){ throw new Exception("树中不存在要删除的关键字!"); } delete(pNode); } private void delete(TreeNode pNode)throws Exception{ if(pNode.leftChild ==null && pNode.rightChild ==null){// 第一种情况:要删除的节点既无左孩子,又无右孩子 TreeNode parentNode = pNode.parent ; if(pNode == parentNode.leftChild){ parentNode.leftChild = null ; }else{ parentNode.rightChild = null ; } return ; } if(pNode.leftChild == null && pNode.rightChild != null){// 第二种情况:要删除节点的左子树为空,右子树不为空 TreeNode parentNode = pNode.parent ; if(pNode == parentNode.leftChild){ parentNode.leftChild = pNode.rightChild; pNode.rightChild.parent = parentNode; }else{ parentNode.rightChild = pNode.rightChild; pNode.rightChild.parent = parentNode; } return ; } if(pNode.leftChild !=null && pNode.rightChild ==null){// 第三种情况,要删除节点的左子树不为空,右子树为空 TreeNode parentNode = pNode.parent ; if(pNode == parentNode.leftChild){ parentNode.leftChild = pNode.leftChild ; pNode.leftChild.parent = parentNode; }else{ parentNode.rightChild = pNode.leftChild; pNode.leftChild.parent = parentNode; } return ; } // 第四种情况,要删除节点的左右子树都不为空,则删除该节点的后继,并用该结点的后继代替该结点 TreeNode successorNode = successor(pNode); delete(successorNode); pNode.key = successorNode.key; } /* * 获得二叉查找树中中序遍历的【节点】列表 * */ public List<TreeNode> inorderTraverseList(){ if(nodelist!=null){ nodelist.clear(); } inorderTraverse(root); return nodelist; } public void inorderTraverse(TreeNode root){ if(root!=null){ inorderTraverse(root.leftChild); nodelist.add(root); inorderTraverse(root.rightChild); } } /* * 获得二叉查找树中中序遍历的【关键字】列表 * */ public String toStringOfOrderList(){ StringBuilder sBuilder = new StringBuilder("["); for(TreeNode p : inorderTraverseList()){ sBuilder.append(p.key); sBuilder.append(" "); } sBuilder.append("]"); return sBuilder.toString(); } /* * 获得二叉查找树的字符串表示 * */ public String toString() { StringBuilder sBuilder = new StringBuilder("["); for(TreeNode p : inorderTraverseList()){ sBuilder.append(p); // 注:这里是和上面的区分 sBuilder.append(" "); } sBuilder.append("]"); return sBuilder.toString(); } public TreeNode getRoot() { return root ; } public static void testNode(BinarySearchTree bst , TreeNode pNode)throws Exception { System.out.println("本结点: " + pNode); System.out.println("前趋结点: " + bst.precursor(pNode)); System.out.println("后继结点: " + bst.successor(pNode)); } public static void testTraverse(BinarySearchTree bst) { System.out.println("二叉树遍历:" + bst); System.out.println("二叉查找树转换为有序列表: " + bst.toStringOfOrderList()); } public static void main(String[] args) { try{ int delkey = 15 ; BinarySearchTree bst = new BinarySearchTree(); System.out.println("二叉查找树是不是为空?"+(bst.isEmpty()?"是":"否")); int[] keys = new int[]{15,6,18,3,7,13,20,2,9,4}; for(int key : keys){ bst.insert(key); } System.out.println("二叉查找树是不是为空?"+(bst.isEmpty()?"是":"否")); TreeNode minkeyNode = bst.minTreeNode(bst.getRoot()); System.out.println("最小关键字:"+minkeyNode.getKey()); testNode(bst,minkeyNode); TreeNode maxKeyNode = bst.maxTreeNode(bst.getRoot()); System.out.println("最大关键字: " + maxKeyNode.getKey()); testNode(bst, maxKeyNode); System.out.println("根结点关键字: " + bst.getRoot().getKey()); testNode(bst, bst.getRoot()); testTraverse(bst); System.out.println("删除关键字6后的二叉查找树:"); bst.delete(delkey); System.out.println("删除根节点后的根节点:"+bst.getRoot().getKey()); testNode(bst,bst.getRoot()); testTraverse(bst); System.out.println("****************************** "); }catch(Exception e){ System.out.println(e.getMessage()); e.printStackTrace(); } } }
3. 代码运行结果:
保持天天的学习,加油!!!
文章结束给大家分享下程序员的一些笑话语录: 一条狗在街上闲逛,看见橱窗里一张告示:「招聘程序员。会编程,有团队精神,至少精通两种语言。均等机会。」
那条狗就进去申请,但是被拒绝了。
「我不能雇一条狗在公司里做事。」经理说。
狗不服气,指着告示上「均等机会」几字抗议。
经理没法,叹了口气,不屑地问道:「你会编程吗?」
那条狗默默地走到电脑前,编了个程序,运作准确。
「你有团队精神吗?」经理问。
那条狗掉头看了看门外,一大群野狗在外面虎视耽耽。
「我真的不能雇狗做这份工作。」经理气急败坏地说。
「就算会编程、有团队精神,但是我需要的雇员至少要能精通两种语言。」
那条狗抬头看着经理说:「喵-噢。」
---------------------------------
原创文章 By
节点和node
---------------------------------