算法导论学习笔记——二叉查找树
2011-08-27 04:59
405 查看
//SearchTree类 public class SearchTree { /** * 中序遍历:根据二叉查找树的性质,中序遍历将按排列顺序输出树中的所有关键字。 * @param root */ public static void inorderTree(Node root){ if(root!=null){ inorderTree(root.getLchild()); System.out.println(root.getKey()); inorderTree(root.getRchild()); } } /** * 关键字查询:该过程从树的根结点开始进行查找,并沿着树下降。 * 对碰到的每个结点,比较其关键字。如果两个关键字相同,则查找结束; * 如果结点关键字大于查询关键字,则继续查找结点的左子树;如果结点关键字小于或等于查询关键字,则继续查找结点的右子树。 * @param root * @param value * @return */ public static Node treeSearch(Node root,int value){ Node temp = root; while(temp!=null&&temp.getKey()!=value){ if(value<temp.getKey()) temp = temp.getLchild(); else temp = temp.getRchild(); } if(value==temp.getKey()) return temp; else return null; } /** * 最大关键字结点:要查找二叉树中具有最大关键字的结点, * 只要从根结点开始,沿着各结点的right指针查询下去,直到遇到NULL为止。 * @param root * @return */ public static Node treeMax(Node root){ Node temp = root; while(null!=temp.getRchild()){ temp = temp.getRchild(); } return temp; } /** *最小关键字结点: 要查找二叉树中具有最小关键字的结点,只要从根结点开始,沿着各结点的left指针查询下去,直到遇到NULL为止。 * @param root * @return */ public static Node treeMin(Node root){ Node temp = root; while(null!=temp.getLchild()){ temp = temp.getLchild(); } return temp; } /** * 前趋结点:给定一个二叉查找树中的结点,它的前趋结点是在中序遍历顺序下它的前一个结点。 * 如果给定查询结点的左子树不为空,则它的前趋结点是左子树中的最大关键字结点; * 如果左子树为空,需要向上判断每一个父结点,直到父结点为空或者遍历结点是父结点的右子结点时,根据中序遍历性质,该父结点即为查询结点的前趋。 * @param root * @return */ public static Node treePredecessor(Node node){ Node preNode = null; Node tempNode = null; if(node.getLchild()!=null) return treeMax(node.getLchild()); System.out.println("----"); preNode = node.getParent(); tempNode = node; while(preNode!=null&&preNode.getRchild()!=tempNode){ tempNode = preNode; preNode = preNode.getParent(); } return preNode; } /** * 后继结点:与前趋结点相反,它是在中序遍历顺序下的后一个结点。 * 如果给定查询结点的右子树不为空,则它的后继结点是右子树中的最小关键字结点; * 如果右子树为空,需要向上判断每一个父结点,直到父结点为空或者遍历结点是父结点的左子结点时,则该父结点即为查询结点的后继。 * @param node * @return */ public static Node treeSuccessor(Node node){ Node preNode = null; Node tempNode = null; if(node.getRchild()!=null) return treeMin(node.getRchild()); preNode = node.getParent(); tempNode = node; while(preNode!=null&&preNode.getLchild()!=tempNode){ tempNode = preNode; preNode = preNode.getParent(); } return preNode; } /** * 插入操作:插入操作从根结点开始,沿树下降,并不断比较当前结点与要插入结点的关键字, * 以决定向左转或向右转,直到当前结点为空,这个空所在的位置即是将要插入的位置。 * 最后,修改插入结点的父结点指针,并根据与父结点关键字的比较结果,修改父结点的子结点指针。 * 如果父结点为空,说明二叉查找树是空的,这时,将新插入结点作为树的根结点。 * 由于每次都将新结点插入到叶子结点的位置,通过这种插入操作构建的二叉查找树往往很不平衡,高度值较大,使得查询操作的运行时间较大。 * @param root * @param node */ public static void treeInsert(Node root,Node node){ Node tempNode = root; Node parentNode = null; while(tempNode!=null){ parentNode = tempNode; if(node.getKey()<tempNode.getKey()) tempNode = tempNode.getLchild(); else tempNode = tempNode.getRchild(); } if(null==parentNode) root = node; else if(node.getKey()<parentNode.getKey()){ parentNode.setLchild(node); }else{ parentNode.setRchild(node); } node.setParent(parentNode); } /** * 删除操作有三种情况: * 1)如果要删除的结点没有子结点,则只要修改其父结点的对应子结点指针为空; * 2)如果要删除的结点只有一个子结点,则可以通过其子结点与其父结点间建立一条链接来删除该结点; * 3)如果要删除的结点有两个子结点,可以先删除该结点的后继结点(这里的后继结点一定在右子树中,并且该后继结点不可能有左子结点), * 再用后继结点的内容来替换要删除结点的内容(实际上,这里使用前趋结点来替换也是可行的)。 * 下面的操作分为四个步骤: * 1)确定要删除的结点(当没有子结点或只有一个子结点时就是该结点本身;当有两个子结点时就是该结点的后继结点); * 2)确定要删除结点的子结点,这里,要么没有子结点,要么只有一个; * 3)在要删除结点的父子结点之间建立链接,如果父结点为空,说明要删除的是树的根结点; * 4)如果删除的是后继结点,则进行内容替换。 * @param root * @param node */ public static void treeDelete(Node root,Node node){ Node tempNode = null; Node childNode = null; //步骤1 if(node.getLchild()==null||node.getRchild()==null) tempNode = node; else tempNode = treeSuccessor(node); //步骤2 if(tempNode.getLchild()!=null) childNode = tempNode.getLchild(); else childNode = tempNode.getRchild(); //步骤3 if(childNode!=null) childNode.setParent(tempNode.getParent()); if(tempNode.getParent()==null) root = childNode; else if(tempNode==tempNode.getParent().getLchild()) tempNode.getParent().setLchild(childNode); else tempNode.getParent().setRchild(childNode); //步骤4 if(tempNode!=node) node.setKey(tempNode.getKey()); } //test..... public static void main(String args[]){ int arr[]={15,5,3,12,10,13,6,7,16,20,18,23}; Node root = new Node(15); for(int i = 1;i<arr.length;i++) treeInsert(root,new Node(arr[i])); /* inorderTree(root);*/ /* Node temp = treeSearch(root,18); * if(null!=temp) System.out.println(temp.getKey());*/ /* Node temp = treeMax(root); * if(null!=temp) System.out.println(temp.getKey());*/ /* Node temp = treeMin(root); * if(null!=temp) System.out.println(temp.getKey());*/ Node node = treeSearch(root,5); Node temp = treePredecessor(node); if(null!=temp) System.out.println(temp.getKey()); /* Node temp = treeSuccessor(node); if(null!=temp) System.out.println(temp.getKey());*/ /* treeDelete(root,new Node(5)); inorderTree(root);*/ } }
Node类:
public class Node { private int key; private Node lchild; private Node rchild; private Node parent; public Node(int key){ this.key = key; this.lchild = null; this.rchild = null; this.parent = null; } public Node(int key,Node lchild,Node rchild,Node parent){ this.key = key; this.lchild = lchild; this.rchild = rchild; this.parent = parent; } public int getKey() { return key; } public void setKey(int key) { this.key = key; } public Node getLchild() { return lchild; } public void setLchild(Node lchild) { this.lchild = lchild; } public Node getRchild() { return rchild; } public void setRchild(Node rchild) { this.rchild = rchild; } public Node getParent() { return parent; } public void setParent(Node parent) { this.parent = parent; }
相关文章推荐
- 算法导论学习笔记(10)——动态规划之最优二叉查找树
- 算法导论学习笔记——第12章 二叉查找树
- 算法导论学习笔记(5)——二叉查找树
- 算法导论学习笔记-第十二章-二叉查找树
- 算法导论学习笔记(八):二叉查找树
- 《算法导论》学习笔记--第十二章 二叉查找树
- 算法导论学习笔记1---排序算法(平台:gcc 4.6.7)
- 算法导论学习笔记——红黑树
- 算法导论学习笔记(九):红黑树
- 算法导论学习笔记-第十五章-动态规划
- 算法导论学习笔记(3)---计数排序
- 算法导论第一节学习笔记
- 算法导论学习笔记(1)
- 算法导论学习笔记——合并排序
- 算法导论学习笔记之三--如何理解和记忆master定理
- 算法导论学习笔记——第9章 中位数和顺序统计学
- 算法导论学习笔记(1)---堆排序
- 《算法导论》笔记 第12章 *12.4 随机构造的二叉查找树
- 算法导论学习笔记(4)——利用链接法实现哈希表
- 算法导论-堆排序学习笔记