zoukankan      html  css  js  c++  java
  • 二叉搜索树

    一、二叉搜索树的特点

    二叉搜索树的特点:对于树中的每个节点X,它的左子树中所有关键字值小于X的关键字值,而它的右子树中所有关键字值大于X的关键字值。

    根据这个性质,对一个二叉树进行中序遍历,如果是单调递增的,则可以说明这个树是二叉搜索树

    LeetCode题目98:验证二叉搜索树(https://leetcode-cn.com/problems/validate-binary-search-tree/)就可以对这个二叉树进行中序遍历,然后判断是否单调递增的,如果是单调递增的,说明是二叉搜索树。否则不是二叉搜索树。

     

    二、二叉搜索树的查找

    过程:首先和根节点进行比较,如果等于根节点,则返回。如果小于根节点,则在根节点的左子树进行查找。如果大于根节点,则在根节点的右子树进行查找。

     1 /* 查找以t为根节点的树中,是否包含x */
     2 Position Find(ElementType x, SearchTree t)
     3 {
     4     if (t == NULL) {
     5         return NULL;
     6     } else if (x < t->element) {
     7         return Find(x, t->left);
     8     } else if (x > t->element) {
     9         return Find(x, t->right);
    10     } else {
    11         return t;
    12     }
    13 }
    View Code

     

    三、查找最大值和最小值

    查找最小值:从根开始,如果有左儿子,则向左进行。直到左儿子为空,则当前节点为最小值。

     1 Position FindMin(SearchTree t)
     2 {
     3     if (t == NULL) {
     4         return NULL;
     5     } else if (t->left == NULL) {
     6         return t;
     7     } else {
     8         return FindMin(t->left);
     9     }
    10 }
    View Code

    查找最大值:从根开始,如果有右儿子,则向右进行。直到右儿子为空,则当前节点为最大值。

     1 Position FindMax(SearchTree t)
     2 {
     3     if (t == NULL) {
     4         return NULL;
     5     }
     6 
     7     while (t->right != NULL)
     8     {
     9         t = t->right;
    10     }
    11     return t;  
    12 }
    View Code

    这里查找最小值运用了递归,而查找最大值运用了非递归实现。

     

    四、二叉搜索树的插入

    二叉搜索树的插入过程和查找类似。新插入的节点一般在遍历的路径上的最后一点上,即叶子节点。如果待插入的数据比当前节点的数据大,并且当前节点的右儿子为空,则将待插入的节点插到右儿子位置上。如果右儿子不为空,则再递归的遍历右儿子。如果小于当前节点,则对左儿子做类似的处理就行。

     1 SearchTree Insert(ElementType x, SearchTree t)
     2 {
     3     if (t == NULL) {
     4         /* 插入第一个节点 */
     5         t = (SearchTree)malloc(sizeof(struct TreeNode));
     6         if (t == NULL) {
     7             return NULL;
     8         }
     9         t->element = x;
    10         t->left = NULL;
    11         t->right = NULL;
    12     } else if (x < t->element) {
    13         t->left = Insert(x, t->left);
    14     } else if (x > t->element) {
    15         t->right = Insert(x, t->right);
    16     }
    17     return t;
    18 }
    View Code

     

    五、二叉搜索树的删除

    二叉搜索树的删除分为以下几个情况:

    1、待删除的节点是一个叶子节点,即它没有左右儿子。此时只要将它的父节点指向NULL即可。

    2、如果节点有一个儿子,则该节点可以在其父节点调整指针绕过该节点后删除。

    3、如果有两个儿子,一般的删除策略是用其右子树中最小的数据代替该节点的数据并递归地删除那个节点。因为右子树中最小地节点不可能有左儿子(如果有,则说明不是最小的),所以第二次删除更容易。(其实也就是将有两个儿子的情况转为容易处理的情况1或者2)。

     1 /* 删除策略
     2  * 1、如果待删除节点只有一个儿子,则将该节点的父节点的儿子节点指针指向该节点的儿子节点,
     3  * 然后删除该节点.
     4  * 2、如果待删除节点有两个儿子,用右子树中最小的数据代替该节点的数据并递归地删除那个节点。
     5  * 因为右子树中最小地节点不可能有左儿子,所以第二次删除更容易.
     6  */
     7  SearchTree Delete(ElementType x, SearchTree t)
     8  {
     9      Position tmp;
    10      if (t == NULL) {  
    11          return NULL;
    12      }
    13      if (x < t->element) {
    14          t->left = Delete(x, t->left);
    15      } else if (x > t->element) {
    16          t->right = Delete(x, t->right);
    17      } else if (t->left && t->right) {
    18          tmp = FindMin(t->right);
    19          t->element = tmp->element;
    20          t->right = Delete(t->element, t->right);
    21      } else {
    22          tmp = t;
    23          if (t->left) {
    24              t = t->left;
    25          } else if (t->right) {
    26              t = t->right;
    27          }
    28          free(tmp);
    29          tmp = NULL;
    30      }
    31      return t;
    32  }
    View Code

    六、建立一棵空树

     1 SearchTree MakeEmpty(SearchTree t)
     2 {
     3     if (t != NULL) {
     4         MakeEmpty(t->left);
     5         MakeEmpty(t->right);
     6         free(t);
     7         t = NULL;
     8     }
     9     return NULL;
    10 }
    View Code

    附录:

    完整代码:

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 #define ElementType int
      5 struct TreeNode;
      6 typedef struct TreeNode *Position;
      7 typedef struct TreeNode *SearchTree;
      8 
      9 SearchTree MakeEmpty(SearchTree t);
     10 Position Find(ElementType x, SearchTree t);
     11 Position FindMin(SearchTree t);
     12 Position FindMax(SearchTree t);
     13 SearchTree Insert(ElementType x, SearchTree t);
     14 SearchTree Delete(ElementType x, SearchTree t);
     15 
     16 struct TreeNode
     17 {
     18     ElementType element;
     19     SearchTree left;
     20     SearchTree right;
     21 };
     22 
     23 SearchTree MakeEmpty(SearchTree t)
     24 {
     25     if (t != NULL) {
     26         MakeEmpty(t->left);
     27         MakeEmpty(t->right);
     28         free(t);
     29         t = NULL;
     30     }
     31     return NULL;
     32 }
     33 
     34 /* 查找以t为根节点的树中,是否包含x */
     35 Position Find(ElementType x, SearchTree t)
     36 {
     37     if (t == NULL) {
     38         return NULL;
     39     } else if (x < t->element) {
     40         return Find(x, t->left);
     41     } else if (x > t->element) {
     42         return Find(x, t->right);
     43     } else {
     44         return t;
     45     }
     46 }
     47 
     48 Position FindMin(SearchTree t)
     49 {
     50     if (t == NULL) {
     51         return NULL;
     52     } else if (t->left == NULL) {
     53         return t;
     54     } else {
     55         return FindMin(t->left);
     56     }
     57 }
     58 
     59 Position FindMax(SearchTree t)
     60 {
     61     if (t == NULL) {
     62         return NULL;
     63     }
     64 
     65     while (t->right != NULL)
     66     {
     67         t = t->right;
     68     }
     69     return t;  
     70 }
     71 
     72 SearchTree Insert(ElementType x, SearchTree t)
     73 {
     74     if (t == NULL) {
     75         /* 插入第一个节点 */
     76         t = (SearchTree)malloc(sizeof(struct TreeNode));
     77         if (t == NULL) {
     78             return NULL;
     79         }
     80         t->element = x;
     81         t->left = NULL;
     82         t->right = NULL;
     83     } else if (x < t->element) {
     84         t->left = Insert(x, t->left);
     85     } else if (x > t->element) {
     86         t->right = Insert(x, t->right);
     87     }
     88     return t;
     89 }
     90 
     91 /* 删除策略
     92  * 1、如果待删除节点只有一个儿子,则将该节点的父节点的儿子节点指针指向该节点的儿子节点,
     93  * 然后删除该节点.
     94  * 2、如果待删除节点有两个儿子,用右子树中最小的数据代替该节点的数据并递归地删除那个节点。
     95  * 因为右子树中最小地节点不可能有左儿子,所以第二次删除更容易.
     96  */
     97  SearchTree Delete(ElementType x, SearchTree t)
     98  {
     99      Position tmp;
    100      if (t == NULL) {  
    101          return NULL;
    102      }
    103      if (x < t->element) {
    104          t->left = Delete(x, t->left);
    105      } else if (x > t->element) {
    106          t->right = Delete(x, t->right);
    107      } else if (t->left && t->right) {
    108          tmp = FindMin(t->right);
    109          t->element = tmp->element;
    110          t->right = Delete(t->element, t->right);
    111      } else {
    112          tmp = t;
    113          if (t->left) {
    114              t = t->left;
    115          } else if (t->right) {
    116              t = t->right;
    117          }
    118          free(tmp);
    119          tmp = NULL;
    120      }
    121      return t;
    122  }
    123 
    124  void PrintfTree(SearchTree t)
    125  {
    126      if (t == NULL) {
    127          return;
    128      }
    129      printf("%d ", t->element);
    130      PrintfTree(t->left);
    131      PrintfTree(t->right);
    132      return;
    133  }
    134 
    135  int main()
    136  {
    137      ElementType i;
    138      SearchTree binary_tree = NULL;
    139 
    140      /******** Insert *********/
    141      for (i = 1; i < 11; i++) {
    142          binary_tree = Insert(i, binary_tree);
    143      }
    144      PrintfTree(binary_tree);
    145      printf("
    ");
    146 
    147     /******** Find *********/
    148      Position pos = NULL;
    149      pos = Find(6, binary_tree);
    150      if (pos != NULL) {
    151          printf("find %d
    ", pos->element);
    152      } else {
    153          printf("Not find 6
    ");
    154      }
    155      pos = Find(11, binary_tree);
    156      if (pos != NULL) {
    157          printf("find %d
    ", pos->element);
    158      } else {
    159          printf("Not find 11
    ");
    160      }
    161 
    162     /******** FindMin *********/
    163      Position min = NULL;
    164      min = FindMin(binary_tree);
    165      if (min) {
    166          printf("find min, min: %d
    ", min->element);
    167      } else {
    168          printf("not find min
    ");
    169      }
    170 
    171     /******** FindMax *********/
    172      Position max = NULL;
    173      max = FindMax(binary_tree);
    174      if (max) {
    175          printf("find max, max: %d
    ", max->element);
    176      } else {
    177          printf("not find max
    ");
    178      }
    179 
    180 
    181     Position del = NULL;
    182     del = Delete(8, binary_tree);
    183     PrintfTree(binary_tree);
    184     printf("
    ");
    185 
    186     binary_tree = MakeEmpty(binary_tree);
    187     PrintfTree(binary_tree);
    188     return 0;
    189  }
    View Code
  • 相关阅读:
    POJ
    POJ
    hdu 1569 &1565 (二分图带权最大独立集
    ZOJ
    POJ
    python-socket作业
    ACM-ICPC 2018 焦作赛区网络预赛 F. Modular Production Line (区间K覆盖-最小费用流)
    ACM-ICPC 2018 焦作赛区网络预赛 E. Jiu Yuan Wants to Eat (树链剖分-线性变换线段树)
    POJ 2987
    ACM-ICPC 2018 南京赛区网络预赛 G. Lpl and Energy-saving Lamps (弱线段树)
  • 原文地址:https://www.cnblogs.com/LydiammZuo/p/11893982.html
Copyright © 2011-2022 走看看