树:整体理解

二叉查找树

二叉查找树出现的目的是使查询的速率整体能够维持在O(logn)上,而又不像链表那样查询一定需要O(logN)的时间复杂度,和数组那样在增删上会引起整个数组进行重构导致的效率问题.

二叉查找树的特点

  • 二叉查找树的的左子节点一定比当前节点小,右子节点一定比当前节点大.
  • 二叉查找树不允许存在相同的值.

这样在理想的情况下,二叉查找树的查询效率就在O(logN)上了.
二叉查找树的实现

package Tree;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 * Created by Hammy on 2018/3/3.
 */
public class BST<T extends Comparable> implements BinarySearchTree<T>
{
    public TreeNode<T> root;

    public BST(){
        this.root = null;
    }

    public BST(T data){
        root = new TreeNode<T>(data,null,null);
    }
    @Override
    public boolean isEmpty() {
        return size()==0;
    }

    @Override
    public int size() {
        if(root==null)
            return 0;

        return size(root);
    }

    private int size(TreeNode<T> node){
        if(node==null)
            return 0;

        return size(node.left) + 1 + size(node.right);
    }

    @Override
    public int height() {
        if(root==null){
            return 0;
        }

        return height(root);
    }

    private int height(TreeNode<T> node){
        if(node==null)
            return 0;

        int left = height(node.left);
        int right = height(node.right);

        return (left>right)?(left+1):(right+1);
    }

    @Override
    public String preOrder() {
        StringBuffer stringBuffer = new StringBuffer();
        Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();

        TreeNode<T> tempNode = root;
        while(tempNode!=null||!stack.isEmpty()){
            if(tempNode!=null){
                stringBuffer.append(tempNode.data+",");
                stack.push(tempNode);
                tempNode=tempNode.left;
            }else{
                tempNode=stack.pop();
                tempNode=tempNode.right;
            }
        }
        return stringBuffer.toString();
    }

    @Override
    public String inOrder() {
        StringBuffer stringBuffer = new StringBuffer();
        Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();

        TreeNode<T> tempNode = root;
        while(tempNode!=null||!stack.isEmpty()){
            while(tempNode!=null){
                stack.push(tempNode);
                tempNode=tempNode.left;
            }
            if(!stack.isEmpty()){
                tempNode=stack.pop();
                stringBuffer.append(tempNode.data+",");
                tempNode=tempNode.right;
            }
        }

        return stringBuffer.toString();
    }

    @Override
    public String postOrder() {
        StringBuffer stringBuffer = new StringBuffer();
        Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();

        TreeNode<T> curNode = root;
        TreeNode<T> preNode = root;
        while(curNode!=null||!stack.isEmpty()){
            while(curNode!=null){
                stack.push(curNode);
                curNode=curNode.left;
            }
            if(!stack.isEmpty()){
                TreeNode<T> tempNode = stack.peek().right;
                if(tempNode==null||tempNode==preNode){
                    curNode=stack.pop();
                    stringBuffer.append(curNode.data+",");
                    preNode=curNode;
                    curNode=null;
                }else{
                    curNode=tempNode;
                }
            }
        }

        return stringBuffer.toString();
    }

    @Override
    public String levelOrder() {
        StringBuffer stringBuffer = new StringBuffer();
        Queue<TreeNode<T>> queue = new LinkedList<TreeNode<T>>();

        TreeNode<T> tempNode = root;
        while(tempNode!=null){
            stringBuffer.append(tempNode.data+",");
            if(tempNode.left!=null)
                queue.add(tempNode.left);
            if(tempNode.right!=null)
                queue.add(tempNode.right);

            tempNode=queue.poll();
        }

        return stringBuffer.toString();
    }

    @Override
    public void insert(T data) throws Exception {
        if(data==null)
            throw new Exception("data can't be null");

        root=insert(root,data);
    }

    private TreeNode<T> insert(TreeNode<T> node,T data){
        if(node==null){
            node=new TreeNode<T>(data,null,null);
        }else{
            int compareResult=data.compareTo(node.data);
            if(compareResult<0)
                node.left=insert(node.left,data);
            if(compareResult>0)
                node.right=insert(node.right,data);

        }
        return node;
    }

    @Override
    public T remove(T data) throws Exception {
        if(data==null)
            throw new Exception("data can't be null");

        return remove(root,data).data;
    }

    private TreeNode<T> remove(TreeNode<T> node,T data) throws Exception{
        if(node==null)
            return null;

        int compareResult=data.compareTo(node.data);
        if(compareResult>0){
            node.right=remove(node.right,data);
            return node;
        }
        if(compareResult<0){
            node.left=remove(node.left,data);
            return node;
        }
        //如果要删除节点的左子树为空
        if(node.left==null){
            TreeNode<T> rightNode = node.right;
            node.right=null;

            return rightNode;
        }
        if(node.right==null){
            TreeNode<T> leftNode = node.left;
            node.left=null;

            return leftNode;
        }
        //左右子树都不为空
        TreeNode<T> successorNode = new TreeNode<T>(findMin(node.right).data,null,null);
        successorNode.left=node.left;
        successorNode.right=remove(node.right,data);
        //将原节点set null
        node.left=null;
        node.right=null;
        if(root.data==data)
            root=successorNode;

        return successorNode;
    }

    @Override
    public T findMax() throws Exception {
        if(root==null)
            throw new Exception("data can't be null");

        return findMax(root).data;
    }

    private TreeNode<T> findMax(TreeNode<T> node){
        TreeNode<T> tempNode = node;
        while(tempNode.right!=null){
            tempNode=tempNode.right;
        }

        return tempNode;
    }

    @Override
    public T findMin() throws Exception {
        if(root==null)
            throw new Exception("data can't be null");

        return findMin(root).data;
    }

    private TreeNode<T> findMin(TreeNode<T> node) throws Exception{
        TreeNode<T> tempNode = node;
        while(tempNode.left!=null)
            tempNode=tempNode.left;

        return tempNode;
    }

    @Override
    public boolean contain(T data) throws Exception {
        if(data==null)
            throw new Exception("data can't be null");

        return contain(root,data);
    }

    private boolean contain(TreeNode<T> node,T data){
        if(node==null)
            return false;

        int compareResult=data.compareTo(node.data);
        if(compareResult>0)
            return contain(node.right,data);
        if(compareResult<0)
            return contain(node.left,data);

        return true;
    }
}

二叉查找树会引发的问题,如果当前数据几乎是一个顺序或者逆序的前提下,二叉查找树就把一个偏向一边甚至退化为链表.这样就完全丧失了它存在的意义.

AVL树

AVL树是理想的平衡二叉树,它保证左子节点和右子节点的深度最多相差1,但每次插入和删除二叉树整体都会进行旋转.但它整体的查询的效率维持在了O(logN)

B树

B树这种数据结构的特点就是深度低,这样做的目的是减少访问外存的次数.
B树的节点设计为一个【k,v】对,这样就可以根据k的规则就寻找想找的value值.
特点:

  • 一颗m阶的b-tree最多有m个孩子
  • 除了根节点和叶子节点外,每个节点至少有Ceil(m/2)个孩子
    -所有叶子节点都在同一层.
    -关键字的个数n满足:ceil(m/2)-1<=n<=m-1
  • ki(i=1,…n)为关键字,且关键字升序排序。
  • Pi(i=1,…n)为指向子树根节点的指针。P(i-1)指向的子树的所有节点关键字均小于ki,但都大于k(i-1)

B+树

B+树存在的目的是为了降低b树的深度.特点如下:

  • 非叶子节点只存储键值信息。
  • 所有叶子节点之间都有一个链指针。
  • 数据记录都存放在叶子节点中。

引用:https://www.cnblogs.com/vianzhang/p/7922426.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容

  • B树的定义 一棵m阶的B树满足下列条件: 树中每个结点至多有m个孩子。 除根结点和叶子结点外,其它每个结点至少有m...
    文档随手记阅读 13,130评论 0 25
  • 目录 0.树0.1 一般树的定义0.2 二叉树的定义 1.查找树ADT 2.查找树的实现2.1 二叉查找树2.2 ...
    王侦阅读 7,088评论 0 3
  • B树 1.前言: 动态查找树主要有:二叉查找树(Binary Search Tree),平衡二叉查找树(Balan...
    铁甲依然在_978f阅读 1,443评论 0 4
  • 第八章 忧患 在长清韩宅已经住了一月余,决明的身体虽然缓慢但十分稳健的恢复着,再休养着时日就完全好了。她伤的全是皮...
    文娅君阅读 162评论 0 0