• 二叉排序树(B-Tree)-c实现


    这个二叉排序树写完了,虽然还有些bug,但还是很高兴的。

    主要实现二叉排序树的构建。(*表示稍微重要点)

    二叉排序树的打印。

    二叉排序树的删除。

    代码里的三种情况都测了

    顺便附送一个简单的中序遍历,递归。

    代码现在还有很多内存泄漏,不想改了,明天或者下周改。

    主要遇到的小问题:1.排序树的打印,本想链式结构打印出来,但是控制不好,就换了一种简单的方法。

                              2.内存malloc和free还有很大问题。tips:为什么一般malloc之后,内存释放后NULL指针,现在有点明白,free 那块malloc的内存,不然会形成很多内存碎片,而此时的指针还是指向原先的那块内存地址,只不过数据被free掉了,,p= NULL,这样把指针内容清掉。

                              3.最不该的错误是2个,一个笔误把=写成了==,找了半个小时的bug,另一个是类型转换,漏掉一个&, PrintBTree((BTREE*) &delNode);//here I forget the sybol &

      1 #include <stdio.h>
      2 #define  ISLCHILD 1
      3 #define  ISRCHILD 2
      4 
      5 typedef int  DATATYPE;
      6 typedef struct treenode
      7 {
      8     DATATYPE data;
      9     struct treenode *parent;
     10     struct treenode *lchild;
     11     struct treenode *rchild;
     12 }TreeNode;
     13 
     14 typedef TreeNode* BTREE;
     15 TreeNode* InitBTree(DATATYPE oriData[], int size);
     16 //TreeNode * GetRootNode(DATATYPE data);
     17 TreeNode * GetRootNode(DATATYPE data, TreeNode* newTreeNode);
     18 TreeNode *InsertNode(TreeNode* parNode, DATATYPE data);
     19 TreeNode *GetFixNode(BTREE *btree, DATATYPE data);
     20 void PrintBTree(BTREE* btree);
     21 void PrintTreeNode(TreeNode* );
     22 void PrintViewTreeNode(TreeNode* treeNode, int num);
     23 void PrintNTab(int i);
     24 void DeleteNode(BTREE* btree, DATATYPE delData);
     25 int IsLeafNode(TreeNode* Node);
     26 TreeNode* GetNodePos(BTREE* btree, DATATYPE Data);
     27 int IsLchild(TreeNode* pareNode,  DATATYPE sonNode);
     28 int IsHasOneChlid(TreeNode *Node);
     29 int IsHasTwoChlid(TreeNode *Node);
     30 
     31 TreeNode* GetMaxNodePos(BTREE* btree);
     32 void PreTravel(BTREE *btree);
     33 //中序遍历
     34 void PreTravel(BTREE *btree)
     35 {
     36     TreeNode* curTreeNode = *btree;
     37     if(IsLeafNode(curTreeNode))
     38     {
     39         printf("%d ", curTreeNode->data);
     40     }
     41     else
     42     {
     43         if((*btree)->lchild!=NULL)
     44         {
     45             PreTravel((BTREE*)&((*btree)->lchild));
     46         }
     47         printf("%d ", curTreeNode->data);
     48         if((*btree)->rchild!=NULL)
     49         {
     50             PreTravel((BTREE*)&((*btree)->rchild));
     51         }
     52 
     53     }
     54     return ;
     55 }
     56 
     57 TreeNode* GetMaxNodePos(BTREE* btree)
     58 {
     59     TreeNode* maxTreeNode = *btree;
     60     while(maxTreeNode)
     61     {
     62         printf("NodeValue[%d]
    ", maxTreeNode->data);
     63         printf("NodeValue[%d]
    ", maxTreeNode->data);
     64         printf("NodeValue[%d]
    ", maxTreeNode->data);
     65 
     66         if(maxTreeNode->rchild == NULL)
     67         {
     68             break;
     69             //return maxTreeNode;
     70         }else{
     71             maxTreeNode = maxTreeNode->rchild;
     72         }
     73     }
     74     return maxTreeNode;
     75 }
     76 
     77 
     78 /*1=> has 2 childrean*/
     79 int IsHasTwoChlid(TreeNode *Node)
     80 {
     81     return ((Node->lchild!=NULL)&&(Node->rchild!=NULL));
     82 }
     83 
     84 int IsHasOneChlid(TreeNode *Node)
     85 {
     86     if((Node->lchild !=NULL)&&(Node->rchild == NULL))
     87         return ISLCHILD;
     88     if((Node->lchild ==NULL)&&(Node->rchild != NULL))
     89         return ISRCHILD;
     90     return 0;
     91 }
     92 
     93 /* 1——> isLchild */
     94 int IsLchild(TreeNode* pareNode, DATATYPE sonNode)
     95 {
     96     return (pareNode->lchild->data == sonNode);
     97 }
     98 TreeNode* GetNodePos(BTREE* btree, DATATYPE data)
     99 {
    100     //TreeNode* curTreeNode = (TreeNode*)malloc(sizeof(TreeNode));
    101     TreeNode* curTreeNode = *btree;
    102     while(//(curTreeNode->data!= data )
    103           1&&(curTreeNode != NULL))
    104     {
    105         if(data == curTreeNode->data)
    106         {
    107             break;
    108         }
    109         else  if(data> curTreeNode->data)
    110         {
    111             curTreeNode = curTreeNode->rchild;
    112         }
    113         else  if(data < curTreeNode->data)
    114         {
    115             curTreeNode = curTreeNode->lchild;
    116         }
    117 
    118     }
    119     return curTreeNode;
    120 }
    121 
    122 
    123 /*1 -> isleaf*/
    124 int IsLeafNode(TreeNode* Node)
    125 {
    126     return ((Node->lchild == NULL)&&(Node->rchild == NULL));
    127 }
    128 
    129 /*
    130 RULE:其删除一个节点需要考虑对应节点的状态,具体的说就是,是否存在左右节点,等等。需要按照以下情况讨论。
    131 
    132 1.查找待删除节点,在查找的同时需要记录一下待删除节点的父亲。
    133 
    134 2.如果待删除节点的左右节点都不存在,那么直接删除(叶子节点)。
    135 
    136 3.如果待删除节点左子树存在右子树不存在,或者左子树不存在右子树存在。直接将其子树中存在的一边候补上来即可。
    137 
    138 4.如果待删除节点左右子树都在,这个情况是最复杂的。需要按照二叉排序树的性质从其左子树或者有子树中选择节点补到待删除节点的位置。
    139 
    140     如果从左子树中选,就应该选择左子树中最右边的那个叶子节点(这里肯定是叶子,如果不是叶子,那么就不是最右边的节点)
    141 
    142     如果从右子树中选,就应该选择有子树中最左边的那个叶子节点。
    143 */
    144 void DeleteNode(BTREE* btree, DATATYPE delData)
    145 {
    146     TreeNode *delNode  = GetNodePos(btree, delData);
    147 
    148     if(delNode == NULL)
    149     {
    150         printf("delNode not exist.
    ");
    151         return ;
    152     }
    153     /*叶子节点*/
    154     if(IsLeafNode(delNode))
    155     {
    156         printf("delNode is leaf node,del directly.
    ");
    157         if(IsLchild(delNode->parent, delData))
    158         {
    159             /*in left tree*/
    160             delNode->parent->lchild = NULL;
    161             delNode = NULL;
    162         }
    163         else
    164         {
    165             delNode->parent->rchild = NULL;
    166             delNode = NULL;
    167         }
    168         return ;
    169 
    170     }
    171 
    172     /*只有一个孩子节点,直接删除*/
    173     if(IsHasOneChlid(delNode) == ISLCHILD)
    174     {
    175         delNode->lchild->parent = delNode->parent;
    176         /*judge the del is the left or right*/
    177         if(IsLchild(delNode->parent, delNode->data))
    178         {
    179             delNode->parent->lchild = delNode->lchild;
    180 
    181         }
    182         else
    183         {
    184             delNode->parent->rchild = delNode->lchild;
    185         }
    186         delNode = NULL;
    187         return ;
    188     }
    189     else if(IsHasOneChlid(delNode) == ISRCHILD)
    190     {
    191         delNode->rchild->parent = delNode->parent;
    192         /*judge the del is the left or right*/
    193         if(IsLchild(delNode->parent, delNode->data))
    194         {
    195             delNode->parent->lchild = delNode->rchild;
    196 
    197         }
    198         else
    199         {
    200             delNode->parent->rchild = delNode->rchild;
    201         }
    202 
    203         delNode = NULL;
    204         return ;
    205     }
    206     //有左右孩子节点,找出左/右中的最大/小的,替换删除的节点
    207     /*I chose the left max to replace the delnode*/
    208     if(IsHasTwoChlid(delNode))
    209     {
    210 #if 0
    211         printf("TTTTTTTTTTTTTTTTTTTTTTTB
    ");
    212         PrintBTree((BTREE*) &delNode);//here I forget the sybol &
    213         printf("TTTTTTTTTTTTTTTTTTTTTTTE
    ");
    214 #else
    215         TreeNode* maxTreeNode = GetMaxNodePos((BTREE*)&delNode);
    216         printf("MaxTreeNode[%d]
    ", maxTreeNode->data);
    217         maxTreeNode->parent->rchild = NULL;//here =  writes to ==  then ^ ^
    218         maxTreeNode->parent = NULL;
    219         delNode->data = maxTreeNode->data;
    220         maxTreeNode = NULL;
    221 #endif
    222         return ;
    223     }
    224 }
    225 
    226 void PrintNTab(int num)
    227 {
    228     int i = 0;
    229 
    230     while(i<num)
    231     {
    232        printf("    ");
    233        i++;
    234     }
    235 }
    236 
    237 void PrintViewTreeNode(TreeNode* treeNode, int num)
    238 {
    239     num++;
    240     printf("%d", treeNode->data);
    241     if(treeNode->lchild == NULL)
    242     {
    243         printf("
    ");
    244         PrintNTab(num);
    245         printf("*");
    246     }
    247     else
    248     {    printf("
    ");
    249          PrintNTab(num);
    250          PrintViewTreeNode(treeNode->lchild, num);
    251     }
    252     if(treeNode->rchild == NULL)
    253     {
    254         printf("
    ");
    255         PrintNTab(num);
    256         printf("&");
    257 
    258     }
    259     else
    260     {
    261         printf("
    ");
    262         PrintNTab(num);
    263         PrintViewTreeNode(treeNode->rchild, num);
    264 
    265     }
    266 
    267 
    268 }
    269 
    270 /*这个看不出来树的结构了,需要重新写打印方法。*/
    271 void PrintTreeNode(TreeNode* treeNode)
    272 {
    273     if((treeNode->lchild == NULL)
    274             &&(treeNode->rchild == NULL))
    275     {
    276        printf("%d
    ", treeNode->data);
    277     }
    278     else
    279     {
    280         if((treeNode->lchild != NULL)
    281                 || (treeNode->rchild != NULL))
    282         {
    283             printf("%d ", treeNode->data);
    284             if(treeNode->lchild != NULL)
    285             {
    286                 printf("--->");
    287                 PrintTreeNode(treeNode->lchild);
    288             }
    289             printf("%d ", treeNode->data);
    290             if(treeNode->rchild != NULL)
    291             {
    292                 printf("===>");
    293                 PrintTreeNode(treeNode->rchild);
    294             }
    295         }
    296     }
    297     return ;
    298 }
    299 
    300 void PrintBTree(BTREE* btree)
    301 {
    302     int num = 0;
    303     if(btree==NULL)
    304     {
    305         printf("empty tree.
    ");
    306     }
    307     printf("TreeView Rule---若一个节点有左右孩子节点,则父节点一行一列,左右孩子不同行同一列,若无做孩子,则打印的数据用*代替,如果无有孩子则打印的数据用&代替"
    308            "另外树的层次用4个空格来体现,比如第1列代表第一层,第5列代表第二层。
    "
    309            );
    310     printf("***********TREE View BEGIN***********
    ");
    311     //PrintTreeNode((*btree));
    312     PrintViewTreeNode(*btree, num);
    313     printf("
    ");
    314     printf("***********TREE View END ***********
    ");
    315     printf("
    ");
    316 
    317     printf("***********TREE View BEGIN***********
    ");
    318     printf("rules:
    	---> lchild.
    	 ===> rchild
    ");
    319     PrintTreeNode(*btree);
    320     printf("
    ");
    321     printf("***********TREE View END ***********
    ");
    322 
    323 }
    324 
    325 
    326 TreeNode* InitBTree(DATATYPE oriData[],  int size)
    327 {
    328     BTREE* btree = NULL;
    329     btree = (BTREE*)malloc(sizeof(BTREE));
    330     *btree = (TreeNode*)malloc(sizeof(TreeNode));
    331     int pos = size;
    332     GetRootNode(oriData[0], *btree);
    333     TreeNode *posNode = (TreeNode*)malloc(sizeof(TreeNode));
    334     while(pos>1)
    335     {
    336         printf("********begin one*************
    ");
    337         printf("pos = [%d] index =[%d] data[%d]
    ", pos, size-pos+1, oriData[size-pos+1]);
    338         posNode = GetFixNode(btree, oriData[size-pos+1]);
    339         printf("Parent = [%d] Insert data=[%d]  
    ", posNode->data, oriData[size-pos+1] );
    340         InsertNode(posNode, oriData[size-pos+1]);
    341         pos--;
    342         printf("********end one*************
    
    ");
    343 
    344     }
    345 
    346     printf("********btree data %d*************
    
    ", (*btree)->data);
    347 
    348     return *btree;
    349 
    350 }
    351 
    352 TreeNode * GetRootNode(DATATYPE data, TreeNode* newTreeNode)
    353 {
    354     //newTreeNode = (TreeNode*)malloc(sizeof(TreeNode));
    355     newTreeNode->data = data;
    356     newTreeNode->parent = NULL;
    357     newTreeNode->lchild = NULL;
    358     newTreeNode->rchild = NULL;
    359     return newTreeNode;
    360 }
    361 //将一个值插入节点的L/R子树上
    362 TreeNode *InsertNode(TreeNode* parNode, DATATYPE data)
    363 {
    364     if(data == parNode->data)
    365     {
    366         printf("invaild data %d
    ", data);
    367         printf("invaild para here at line %d.
    ", __LINE__);
    368         return NULL;
    369     }
    370     TreeNode* sonTreeNode = (TreeNode*)malloc(sizeof(TreeNode));
    371     sonTreeNode->data = data;
    372     sonTreeNode->lchild = NULL;
    373     sonTreeNode->rchild = NULL;
    374     sonTreeNode->parent = parNode;//这里要不要考虑这个链接???
    375     if(data < parNode->data)
    376     {
    377          parNode->lchild = sonTreeNode;
    378     }
    379     else{
    380         parNode->rchild = sonTreeNode;
    381     }
    382     return sonTreeNode;
    383 }
    384 //查找合适的位置来插入新元素(find parent)
    385 TreeNode *GetFixNode(BTREE *btree, DATATYPE data)
    386 {
    387      if((btree == NULL ))
    388      {
    389          return NULL;
    390      }
    391 
    392      if(((*btree)->lchild == NULL)
    393              &&((*btree)->rchild == NULL))
    394      {
    395          //InsertNode(*btree ,data);
    396          printf("insert under root 
    ");
    397          return *btree;
    398      }
    399      TreeNode* curTreeNode = (TreeNode*)malloc(sizeof(TreeNode));
    400      curTreeNode = *btree;
    401      while( (curTreeNode->lchild != NULL)
    402            ||(curTreeNode->rchild !=NULL) )
    403      {
    404          if(data > curTreeNode->data)
    405          {
    406              //printf("insert R 
    ");
    407              printf(" data=[%d] curData=[%d] insert R 
    ", data, curTreeNode->data);
    408              if(curTreeNode->rchild != NULL)
    409              {
    410                  printf("curTreeNode->rchild != NULL rchild[%d]
    ", curTreeNode->rchild->data);
    411                  curTreeNode = curTreeNode->rchild;
    412 
    413              }else{
    414 
    415                  break;
    416              }
    417          }
    418          else if(data < curTreeNode->data)
    419          {
    420              printf(" data=[%d] curData=[%d] insert L 
    ", data, curTreeNode->data);
    421              if(curTreeNode->lchild != NULL)
    422              {
    423                  curTreeNode = curTreeNode->lchild;
    424 
    425              }else{
    426 
    427                  break;
    428              }
    429          }
    430          else
    431          {
    432              printf("invaild elem here at line %d.
    ", __LINE__);
    433              return NULL;
    434          }
    435 
    436      }
    437      return curTreeNode;
    438 
    439 }
    440 
    441 int main(void)
    442 {
    443     printf("	Hello World!
    ");
    444     int arr[12]={4, 5, 2, 1,3, 6, 8, 9, 7, 22, 11, 33};
    445 
    446     //int arr[5]={22, 11, 33, 15, 9};
    447     BTREE *btree = NULL;
    448     btree = (BTREE*)malloc(sizeof(BTREE));
    449     *btree = (TreeNode*)malloc(sizeof(TreeNode));
    450     *btree = InitBTree(arr, 12);
    451     //*btree = InitBTree(arr, 5);
    452     PrintBTree(btree);
    453     TreeNode* curTreeNode = (TreeNode*)malloc(sizeof(TreeNode));
    454 
    455     DeleteNode(btree, 11);
    456     PrintBTree(btree);
    457     printf("中序遍历:
    ");
    458     PreTravel(btree);
    459 
    460 
    461     return 0;
    462 }

    运行结构也贴上来:

            Hello World!
    ********begin one*************
    pos = [12] index =[1] data[5]
    insert under root
    Parent = [4] Insert data=[5]
    ********end one*************

    ********begin one*************
    pos = [11] index =[2] data[2]
     data=[2] curData=[4] insert L
    Parent = [4] Insert data=[2]
    ********end one*************

    ********begin one*************
    pos = [10] index =[3] data[1]
     data=[1] curData=[4] insert L
    Parent = [2] Insert data=[1]
    ********end one*************

    ********begin one*************
    pos = [9] index =[4] data[3]
     data=[3] curData=[4] insert L
     data=[3] curData=[2] insert R
    Parent = [2] Insert data=[3]
    ********end one*************

    ********begin one*************
    pos = [8] index =[5] data[6]
     data=[6] curData=[4] insert R
    curTreeNode->rchild != NULL rchild[5]
    Parent = [5] Insert data=[6]
    ********end one*************

    ********begin one*************
    pos = [7] index =[6] data[8]
     data=[8] curData=[4] insert R
    curTreeNode->rchild != NULL rchild[5]
     data=[8] curData=[5] insert R
    curTreeNode->rchild != NULL rchild[6]
    Parent = [6] Insert data=[8]
    ********end one*************

    ********begin one*************
    pos = [6] index =[7] data[9]
     data=[9] curData=[4] insert R
    curTreeNode->rchild != NULL rchild[5]
     data=[9] curData=[5] insert R
    curTreeNode->rchild != NULL rchild[6]
     data=[9] curData=[6] insert R
    curTreeNode->rchild != NULL rchild[8]
    Parent = [8] Insert data=[9]
    ********end one*************

    ********begin one*************
    pos = [5] index =[8] data[7]
     data=[7] curData=[4] insert R
    curTreeNode->rchild != NULL rchild[5]
     data=[7] curData=[5] insert R
    curTreeNode->rchild != NULL rchild[6]
     data=[7] curData=[6] insert R
    curTreeNode->rchild != NULL rchild[8]
     data=[7] curData=[8] insert L
    Parent = [8] Insert data=[7]
    ********end one*************

    ********begin one*************
    pos = [4] index =[9] data[22]
     data=[22] curData=[4] insert R
    curTreeNode->rchild != NULL rchild[5]
     data=[22] curData=[5] insert R
    curTreeNode->rchild != NULL rchild[6]
     data=[22] curData=[6] insert R
    curTreeNode->rchild != NULL rchild[8]
     data=[22] curData=[8] insert R
    curTreeNode->rchild != NULL rchild[9]
    Parent = [9] Insert data=[22]
    ********end one*************

    ********begin one*************
    pos = [3] index =[10] data[11]
     data=[11] curData=[4] insert R
    curTreeNode->rchild != NULL rchild[5]
     data=[11] curData=[5] insert R
    curTreeNode->rchild != NULL rchild[6]
     data=[11] curData=[6] insert R
    curTreeNode->rchild != NULL rchild[8]
     data=[11] curData=[8] insert R
    curTreeNode->rchild != NULL rchild[9]
     data=[11] curData=[9] insert R
    curTreeNode->rchild != NULL rchild[22]
    Parent = [22] Insert data=[11]
    ********end one*************

    ********begin one*************
    pos = [2] index =[11] data[33]
     data=[33] curData=[4] insert R
    curTreeNode->rchild != NULL rchild[5]
     data=[33] curData=[5] insert R
    curTreeNode->rchild != NULL rchild[6]
     data=[33] curData=[6] insert R
    curTreeNode->rchild != NULL rchild[8]
     data=[33] curData=[8] insert R
    curTreeNode->rchild != NULL rchild[9]
     data=[33] curData=[9] insert R
    curTreeNode->rchild != NULL rchild[22]
     data=[33] curData=[22] insert R
    Parent = [22] Insert data=[33]
    ********end one*************

    ********btree data 4*************

    TreeView Rule---若一个节点有左右孩子节点,则父节点一行一列,左右孩子不同行同一列,若无做孩子,则打印的数据用*代替,如果无有孩子则打印的数据用&代替另外树的层次用4个空格来体现,比如第1列代表第一层,第5列代表第二层。
    ***********TREE View BEGIN***********
    4
        2
            1
                *
                &
            3
                *
                &
        5
            *
            6
                *
                8
                    7
                        *
                        &
                    9
                        *
                        22
                            11
                                *
                                &
                            33
                                *
                                &
    ***********TREE View END ***********

    ***********TREE View BEGIN***********
    rules:
            ---> lchild.
             ===> rchild
    4 --->2 --->1
    2 ===>3
    4 ===>5 5 ===>6 6 ===>8 --->7
    8 ===>9 9 ===>22 --->11
    22 ===>33

    ***********TREE View END ***********
    delNode is leaf node,del directly.
    TreeView Rule---若一个节点有左右孩子节点,则父节点一行一列,左右孩子不同行同一列,若无做孩子,则打印的数据用*代替,如果无有孩子则打印的数据用&代替另外树的层次用4个空格来体现,比如第1列代表第一层,第5列代表第二层。
    ***********TREE View BEGIN***********
    4
        2
            1
                *
                &
            3
                *
                &
        5
            *
            6
                *
                8
                    7
                        *
                        &
                    9
                        *
                        22
                            *
                            33
                                *
                                &
    ***********TREE View END ***********

    ***********TREE View BEGIN***********
    rules:
            ---> lchild.
             ===> rchild
    4 --->2 --->1
    2 ===>3
    4 ===>5 5 ===>6 6 ===>8 --->7
    8 ===>9 9 ===>22 22 ===>33

    ***********TREE View END ***********
    中序遍历:
    1 2 3 4 5 6 7 8 9 22 33

    
    
  • 相关阅读:
    WPF DataGrid
    邮箱格式验证
    Spring Cloud微服务学习笔记
    你必须知道的MySQL知识点
    你必须掌握的分布式事务知识点
    重试操作下如何实现幂等?
    你必须掌握的关于JVM知识点
    RocketMQ开发者指南
    二分查找解题套路框架
    回溯算法解题套路框架
  • 原文地址:https://www.cnblogs.com/ashen/p/5739043.html
Copyright © 2020-2023  润新知