zoukankan      html  css  js  c++  java
  • 数据结构 ---- 二叉搜索树

    一直对于二叉搜索树(又叫二叉排序树,也叫二叉查找树),没有非常好的理解,决定花点时间来学习and总结。


    二叉搜索树也是二叉树的一种。(就像堆也就二叉树的一种一样。。。

    仅仅只是,二叉搜索树也是有其它要求:对于全部的子树,其根节点的值大于左子树上的全部结点的值。而小于右子树上全部结点的值的值。。

    对于错误的理解:对于全部的结点,要大于其左结点,小于其右结点。。(PS:这样的理解是错误的,一定要注意。。

    另一点须要注意的是:我们的大于和小于都应该是严格的。


    ========== 以下主要针对。其建立、增删改查这些操作来进行说明 ==============

    ====== 对于全部的数据结构,我们对其增删改查都应该有比較清楚的认识==========

    首先我们定义一下二叉树的结构(链式结构):

    <span style="font-size:18px;"><span style="font-size:18px;"># 结点的数据结构
    typedef int ElementType;
    typedef struct
    {
        ElementType Element;
        ElementType *left;
        ElementType *right;
    }TreeNode;
    
    # 有必要差别一下结点和树的差别。
    详细来说的话:
    结点的话,就是有数据+空间。

    树的话,就是一个指向树的头结点的指针。

    如今,我说给你你棵树,肯定就是给你一个指向头结点的指针。 </span></span>



    MakeEmpty:

    所谓makeempty就是一个用来初始化一个空的二叉搜索树。(注意这个‘为’字 = =)

    这里是初始化,我们理解为:如今给你一棵树(可能不是一棵空树),我们怎样来初始化。

    ========== 插一腿 =========

    有必要解释一下。新建和初始化,我对这两个概念理解上的差别。

    比方:
    如今我要新建一棵二叉树:

           新建二叉树的话,就是要新建一个的root结点(或者说新建一个指向root结点的指针)。

    如今我要初始化一棵二叉树:

           初始化二叉树的话。就是如今一棵二叉树已经建好了,我要初始化他。在没有插入不论什么一个结点的时候。初始化就显的比較尴尬了。不用分配空间,不用初始化数据。

    ppps:对于这两个概念的差别还是有待更加深刻的理解(特别是树)。有待以后学习。

    对于这个 问题,我又了解了一些情况。

    这儿有一个帖子,讨论的比較有>>>>>>http://bbs.csdn.net/topics/360102904

    加上自己的一点理解:创建的话,你仅仅须要指定。你如今已经创建了一个你的数据结构。而初始化的话,就是你须要对你的数据进行处理。。。

    比方如今你要创建和初始化一棵树(不管是什么样的数):

    创建一棵树。就是你要个给出这棵树的一个接口(头结点)。想一想,对于给你一棵树,你会得到什么?就是该树得头结点啊。

    那么对于初始化呢?初始化一棵树的话,我们就须要对说有的结点进行空间的分配和数据的存储。。

    如今对于新建和初始化应该有非常清楚的理解。

    。。


    =========================

    Code:

    <span style="font-size:18px;"><span style="font-size:18px;">返回的是一棵树。

    而不是。。。。 TreeNode* MakeEmpty(TreeNode* tree) { if(tree != NULL){ MakeEmpty(tree -> left); MakeEmpty(tree -> right); free(tree); } return NULL; } </span></span>



    Find。 FindMin and FindMax:

    对于查找来说,我们的二叉搜索树还是有一定的优势的。

    (这也是为什么我们的二叉搜索树也叫二叉查找树)。

    对于全部类型的查找(不管是找什么样元素。存在的,不存在的,最大的。最小的),我们的平均查找时间为log(n)。n为该树中的全部结点。



    <span style="font-size:18px;">// 返回值为结点的地址。

    // 寻找值为x的结点。

    TreeNode* Find(ElementType x, TreeNode* T) { if(T == NULL) return NULL; if(T -> Element > x ){ return Find(x, TreeNode -> left); } else if(T -> Element < x) { return Find(x, TreeNode -> right); } return T; } // 寻找最小值的结点。

    。 TreeNode* FindMin(TreeNode* T) { if(T == NULL) return NULL; if(T -> left == NULL){ return T; } return FindMin(T -> left); } // 寻找最大值的结点。。

    TreeNode* FindMax(TreeNode* T) { if(T == NULL) return NULL; if(T -> right == NULL) { return T; } return FindMax(T -> right); } </span>


    对于二叉搜索树的查找操作还是比較简单的。。。

    对于他的递归写法非常是简单。当然,对于其的循环写法就更加的简单了。

    。。


    Insert:

    插入的话。我们最优(或者说,最简单)的做法就是。把须要插入的结点插入为叶子结点。

    时间复杂度的话,就是logn。

    <span style="font-size:18px;">// 插入
    TreeNode* Insert(ElementType x, TreeNode* T)
    {
        if(T == NULL){
            T = (TreeNode*)malloc(sizeof(TreeNode));
            T -> Element = x;
            T -> right = T -> left = NULL;
        }
        if(x > T -> Element){
            T -> right = Insert(x, T -> right);
        }
        else if(x < T -> Element){
            T -> left = Insert(x, left);
        }
        return T; // 不要忘了返回插入以后的二叉树。

    }</span>



    Delete:
    对于二叉搜索树的删除。  是全部操作中最难的一个。

    (这和其它的数据结构一样,最难的操作就是删除。)

    删除的情况有非常多情况:
    1,删除的是叶子结点:

          最简单的应该就是删除的叶子结点了。

    删除叶子对于其它的结点没有不论什么的联系,所以,直接删除就能够了。

    2,删除的结点仅仅有一个棵子树:

          对于仅仅有一棵仅仅树的结点。也是比較简单的,我们直接把该结点的唯一子树把该结点替换了就能够了。。

    3。删除的结点有两棵子树:

         最麻烦的应该就是删除这样的类型的结点了,那么我们详细应该怎么做呢?我们这样想。我们删除这个结点以后应该用谁来取代他的位置。以至于仍然还是棵二叉搜索树呢?   该节点应该小于其右子树的全部节点。大于其左子树的结点。 ------   这就是我们的线索。

    所以我们应该找到其左子树上的最大的结点,或者是其右子树上的最小的结点。


    Code:

    
    TreeNode* Delete(ElementType x, TreeNode* T)
    {
        if(T == NULL) return NULL;
        
        if(x > T -> Element){
            T -> right = Delete(x, T -> right);
        }
        else if(x < T -> Element){
            T -> left = Delete(x, T -> left);
        }
        // 找到须要删除的结点= =
        if(x -> left && x -> right){ // 有两棵子树
            // 用其右子树上最小值的结点取代该结点
            TreeNode* submin = FindMin(T -> right);
            T -> Element = submin -> Element;
            T -> right = Delete(T -> Element, T -> right);
            // 用其左子树上最大值的结点取代该结点
            TreeNode* summax = FindMax(T -> left);
            T -> Element = summax -> Element;
            T -> left = Delete(T -> Element, T -> left);
        }
        else{ // 有一棵子树或者没有子树
            TreeNode* tmp = T;
            if(T -> left == NULL){
                T = T -> right;
            }
            else if(T -> right == NULL){
                T = T -> left;
            }
            free(tmp);
        }
    }
    

    到此为止,我们的二叉搜索树的基本操作就是这些,仅仅是一些非常基础的一些东西,希望以后有所补充。




  • 相关阅读:
    bzoj3028食物 关于(1+x+x^2+x^3+x^4+...)^k的第i项系数就是c(i+k−1,k−1)的证明
    一个好玩的题--倒水
    HDU4372(第一类斯特林数)
    MySQL常用基本语句
    腾讯windows客户端一面
    腾讯PC客户端开发方向一面
    LeetCode数据库175
    Intern Day47
    Intern Day46
    Intern Day46
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6845293.html
Copyright © 2011-2022 走看看