博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
算法导论:二叉搜索树
阅读量:7197 次
发布时间:2019-06-29

本文共 7910 字,大约阅读时间需要 26 分钟。

定义:

(0)二叉树

(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;

(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;

(3)左、右子树也分别为二叉排序树

数据结构定义

public class TreeNode {    public int val;    public TreeNode left;    public TreeNode right;    public TreeNode(int val){        this.val = val;        this.left = left=null;        this.right = right=null;    }}

 

插入元素

由于元素互异,插入元素的位置一定在叶子结点,递归插入程序

public TreeNode insertTree(TreeNode root,int key){        if(root == null){            root = new TreeNode(key);            return root;        }else if(key < root.val){            root.left = insertTree(root.left,key);        }else{            root.right = insertTree(root.right,key);        }        return root;    }

查找最小值

根据二叉搜索树的定义:左孩子比根节点小,右孩子比根节点大,最小值一定在最左的子树上,同时该子树一定没有左孩子,可以一直left的找

 

/**     * 递归找最小值     * @param root     * @return     */    public TreeNode iterativeTreeMin(TreeNode root){        if(root.left!=null&&root.left.left==null)            return root.left;        return iterativeTreeMin(root.left);    }    /**     * 查找最小节点,最小节点一定在下层的最左侧,同时该节点不能有左孩子     * 时间复杂度O(h)     * @param root     * @return     */    public TreeNode treeMin(TreeNode root){        while(root.left!=null){            root = root.left;        }        return root;    }

查找最大值

最大值一定在最右的子树,同时这个子树一定没有右孩子

/**     * 递归查找最大值     * @param root     * @return     */    public TreeNode iterativeTreeMax(TreeNode root){        if(root.right!=null&&root.right.right==null)            return root.right;        return iterativeTreeMax(root.right);    }    /**     * 查找最大结点,最大结点一定在下层的最右侧,同时该节点不能有右孩子     * 时间复杂度O(h)     * @param root     * @return     */    public TreeNode treeMax(TreeNode root){        while(root.right!=null){            root = root.right;        }        return root;    }

查找结点是否存在

递归和非递归

 

/**     * 循环方式查找 key是否在排序二叉树中     * 这个效率更高,具体多少?     * @param root     * @param key     * @return     */    public TreeNode iterativeTreeSearch(TreeNode root,TreeNode key){        while(root!=null &&root.val!=key.val){            if(key.val < root.val)                root = root.left;            else                root = root.right;        }        return root;    }    /**     * 递归查找 key节点是否在二叉树root中.     * 时间复杂度O(h)     * @param root     * @param key     * @return     */    public TreeNode treeSearch(TreeNode root,TreeNode key){        if(key == null || key.val == root.val){            return key;        }        if(key.val < root.val)            return treeSearch(root.left,key);        else            return treeSearch(root.right,key);    }

前序遍历

遍历规则:根左右

/**     * 递归前序遍历     * @param root     * @param result     */    public void preorderTree(TreeNode root,ArrayList
result){ if(root==null) return; result.add(root.val); preorderTree(root.left,result); preorderTree(root.right,result); }

递归的一般都能写出来,如何写出非递归程序?

遍历规则:根左右

对两层三个结点情况:先输出根结点,在输出左结点的时候需要先保存右结点的值,输出左结点,再输出保存的右结点

对树的层数多的时候,这里需要保存右结点所在的子树,输出左结点值,对左结点同上操作。

这里利用栈保存中间结点。

/**     * 循环前序遍历     * @param root     * @param result     */    public void iterativePreorderTree(TreeNode root,ArrayList
result){ Stack
stack = new Stack
(); while(root!=null || !stack.empty()){ result.add(root.val); if(root.right!=null) stack.push(root.right); root = root.left; if(root == null && !stack.empty()){ root = stack.pop(); } } }

中序遍历

遍历规则:左根右

递归很简单

/**     * 递归中序遍历二叉树     * 时间复杂度O(N)     * @param root     * @param result     */    public  void inorderTree(TreeNode root,ArrayList
result){ if(root == null) return; inorderTree(root.left,result); result.add(root.val); inorderTree(root.right,result); }

 

非递归方式,需要利用栈保存左结点信息

/**     * 循环方式中序遍历,用栈存放中间节点     * @param root     * @param result     */    public void iterativeInorderTree(TreeNode root,ArrayList
result){ Stack
stack = new Stack
(); while(root!=null || !stack.empty()){ while(root!=null){ // 向左侧走 stack.push(root); root = root.left; } root = stack.pop();// 取出最左侧的结点 result.add(root.val); root = root.right; // 最左侧节点的右节点,若不存在在上面的while循环也会运行 } }

后序遍历

遍历规则:左右根

递归方式

/**     * 递归后续遍历     * @param root     * @param result     */    public void postorderTree(TreeNode root,ArrayList
result){ if(root == null) return; postorderTree(root.left,result); postorderTree(root.right,result); result.add(root.val); }

非递归

理解不透

/**     * 非递归后序遍历     * @param root     * @param result     */    public void iterativePostorderTree(TreeNode root,ArrayList
result){ Stack
stack = new Stack
(); if (root == null) return; boolean flag = true; while(flag){ while(root.left != null || root.right != null){ if (root.left != null){ stack.push(root); root = root.left; } else{ stack.push(root); root = root.right; } } TreeNode y = stack.peek(); while (root == y.right || y.right == null){ result.add(root.val); stack.pop(); if (stack.empty()){ flag = false; result.add(y.val); break; } root = y; y = stack.peek(); } if (root == y.left && y.right != null){ result.add(root.val); root = y.right; } } }

版本2

 

/**     * 后序遍历非递归 2      * @param root     * @param result     */    public void iterativePostorderTree2(TreeNode root,ArrayList
result){ Stack
stack = new Stack
(); TreeNode prev = null; // previously traversed node TreeNode curr = root; if (root == null) { return; } stack.push(root); while (!stack.empty()) { curr = stack.peek(); if (prev == null || prev.left == curr || prev.right == curr) { // traverse down the tree if (curr.left != null) { stack.push(curr.left); } else if (curr.right != null) { stack.push(curr.right); } } else if (curr.left == prev) { // traverse up the tree from the left if (curr.right != null) { stack.push(curr.right); } } else { // traverse up the tree from the right result.add(curr.val); stack.pop(); } prev = curr; } }

 

求树的深度

递归

 

/**     * 递归求树的深度     * @param root     * @param hight     * @return     */    public int depth(TreeNode root,int hight){        if(root == null)            return hight;        return Math.max(depth(root.left,hight), depth(root.right,hight))+1;    }

 

 

 

层次遍历

规则:每一次打印一个结点的时候,如果该结点有子结点,则把该结点的子结点放到一个队列的尾部。接下来到队列的头部取出最早进入队列的结点。

重复前面的打印操作,直到队列中所有的结点都被打印出来为止。

public void levelOrder(TreeNode root,ArrayList
> tree){ Queue
queue = new LinkedList
(); if(root == null) return ; queue.offer(root); while(!queue.isEmpty()){ ArrayList
list = new ArrayList
(); int size = queue.size(); for(int i=0;i

 

转载地址:http://cxtkm.baihongyu.com/

你可能感兴趣的文章
2019亚洲物联网安全创新国际峰会将于5月在上海开幕!
查看>>
C#反射的实现
查看>>
【想法】滴滴更新迭代功能
查看>>
aircrack-ng破解WiFi密码
查看>>
iOS设备中WiFi、蓝牙和飞行模式的开启与关闭
查看>>
事务传播行为和特性
查看>>
[Ting's笔记Day3]解决Git常见错误non-fast-forward问题
查看>>
浅谈测试部领导者的工作职责
查看>>
严重: Servlet.service() for servlet jsp threw exception java.lang.IllegalStateException: getOutput...
查看>>
Android开发网上的一些重要知识点[经验分享]
查看>>
Guid.NewGuid().ToString()的几种格式
查看>>
vc中异常捕捉的最后一道屏障-SetUnhandledExceptionFilter
查看>>
Windows下免oracle client的PLSQL的配置
查看>>
Solr -- Solr Facet 2
查看>>
java中的垃圾回收
查看>>
解释string类型的输入操作符和getline函数分别如何处理空白符
查看>>
客户端域用户时钟同步
查看>>
bzoj3991[SDOI2015]寻宝游戏
查看>>
将数字转换为字符串(int2str)
查看>>
解决「matplotlib 图例中文乱码」问题
查看>>