查看: 1354|回复: 0

[原创] 二叉树的操作,自己写的 C 语言版

[复制链接]
  • TA的每日心情
    开心
    2024-1-16 17:48
  • 签到天数: 592 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2019-4-21 18:32:46 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 robe.zhang 于 2019-4-22 14:28 编辑

    树的操作,前面半部分是测试程序,后面直接上代码:
    代码也推送guthub 了:https://github.com/robe-zhang/mys_y6ulx/tree/master/application/struct_tree.c

    测试程序 的输出,先随机生成 16 个 0 - 99 之间的整数,然后按照先后顺序插入树中
    之后访问树中的没一个结点,打印出每个节点的数据和父子结点关系
    [图片1]https://github.com/robe-zhang/mys_y6ulx/blob/master/application/struct_tree1.png
    找出每一个结点的,左树最右边的数据,和右树最左边的数据,其实是找值最接近的节点。
    [图片2]https://github.com/robe-zhang/mys_y6ulx/tree/master/application/struct_tree2.png
    从树中随机位置提取一个节点,并删除这个节点,打印删除前后树的结构
    [图片3]https://github.com/robe-zhang/mys_y6ulx/tree/master/application/struct_tree3.png
    (树的显示结构:根节点在最左边,相同深度的节点,垂直对齐)

    1. /*        **********************************************
    2. *         数据结构:二叉树 -- C语言程序
    3. *        简介:左树比当前节点数据小,右树等于或大于当前结点数据。
    4. *        作者:robe.zhang (82796620@qq.com)
    5. *        日期:2019.04.21
    6. *        *********************************************
    7. */

    8. #include <stdio.h>
    9. #include <linux/input.h>
    10. #include <unistd.h>
    11. #include <stdlib.h>
    12. #include <fcntl.h>
    13. #include <time.h>
    14. #include <string.h>

    15. /*        **********************************************
    16. *         二叉树节点结构体:
    17. *        data:节点的数据
    18. *        lp:左树指针
    19. *        rp:右树指针
    20. *        **********************************************
    21. */
    22. struct node{
    23.         int data;
    24.         struct node *lp;
    25.         struct node *rp;
    26. };
    27. typedef struct node node_t;

    28. /*        **********************************************
    29. *         二叉树节点操作方法: 插入
    30. *        root: 要插入的树的根节点
    31. *        value:要插入的节点的数据
    32. *        return: -1;malloc出错,0:插入正常。
    33. *        **********************************************
    34. */
    35. int insert_node(node_t** root, int value){
    36.         if( *root == NULL){
    37.                 *root = malloc(sizeof(struct node));
    38.                 if(*root == NULL){
    39.                         printf("malloc error.\n");
    40.                         return -1;
    41.                 }
    42.                 (*root)->data = value ;
    43.                 (*root)->lp = NULL;
    44.                 (*root)->rp = NULL;
    45.         }else{
    46.                 if( value >= (*root)->data ){
    47.                         insert_node(&((*root)->rp),value);
    48.                 }else{
    49.                         insert_node(&((*root)->lp),value);
    50.                 }
    51.         }
    52.         return 0;
    53. }

    54. /*        **********************************************
    55. *         二叉树节点操作方法: 查找                 search_node
    56. *        root:要查找节点的树根
    57. *        value:要查找的节点的值
    58. *        temp:函数内部当作中间变量使用的
    59. *        parent:用于接受查找到的节点的父节点
    60. *        this:用于接受查找到的节点
    61. *        **********************************************
    62. */

    63. int search_node(node_t** root, int value, node_t** temp,node_t** parent, node_t** this){
    64.         if((*root) != NULL){
    65.                 if( (*root)->data == value ){
    66.                         *this = *root;
    67.                         *parent = *temp;
    68.                         return 0;
    69.                 }
    70.                 *temp = *root;
    71.                 if( value > (*root)->data  ){
    72.                         search_node(&((*root)->rp),value,temp,parent,this);
    73.                 }
    74.                 if( value < (*root)->data ){
    75.                         search_node(&((*root)->lp),value,temp,parent,this);
    76.                 }
    77.         }
    78.         return 0;
    79. }

    80. int search_node_l(node_t** root,node_t** temp, node_t** parent, node_t** this){
    81.         if( *root != NULL ){
    82.                 if((*root)->lp == NULL){
    83.                         *this = *root;
    84.                         *parent = *temp;
    85.                         return 0;
    86.                 }
    87.                 *temp = *root;
    88.                 search_node_l(&((*root)->lp),temp,parent,this);
    89.         }
    90.         return 0;
    91. }

    92. int search_node_r(node_t** root, node_t** temp, node_t** parent, node_t** this){
    93.         if( *root != NULL ){
    94.                 if((*root)->rp == NULL){
    95.                         *this = *root;
    96.                         *parent = *temp;
    97.                         return 0;
    98.                 }
    99.                 *temp = *root;
    100.                 search_node_l(&((*root)->rp),temp,parent,this);
    101.         }
    102.         return 0;
    103. }

    104. /*        **********************************************
    105. *         二叉树节点操作方法: 删除
    106. *        root:要删除节点的树的根
    107. *        value:要删除的节点的值
    108. *        删除算法:
    109. *        1,找到删除节点
    110. *        2,查找删除节点的替代节点(右树最左节点)(插入算法时候,大于等于都插入右子节点)
    111. *        3,把替代节点先从树中去除,不free。
    112. *        4,用替代节点去替换要删除节点。
    113. *        5,free 删除节点
    114. *        **********************************************
    115. */

    116. int delete_node(node_t** root, int value){
    117.         node_t *delp=NULL,*del=NULL,*temp=NULL;        
    118.         node_t *delp_=NULL,*del_=NULL,*temp_=NULL;
    119.         int ret = 0;
    120.         node_t *rep;

    121.         search_node(root,value,&temp,&delp,&del);
    122.         if(*root == NULL){                                                                        //树根不存在
    123.                 ret=-2;
    124.                 goto end_delete_node;
    125.         }
    126.         if( del == NULL){                                                                        //要删除的节点不存在
    127.                 ret=-1;
    128.                 goto end_delete_node;
    129.         }
    130.         search_node_l(&(del->rp),&temp_,&delp_,&del_);
    131.         if(delp_!=NULL){                                                                        //找替换的节点,先处理替换节点
    132.                 if(del_->rp != NULL){
    133.                         delp_->lp = del_->rp;
    134.                 }else{
    135.                         delp_->lp = NULL;
    136.                 }
    137.                 ret = ret + 1 ;
    138.         }else{
    139.                 if(del_!=NULL){
    140.                         if(del_->rp != NULL){
    141.                                 del->rp = del_->rp;
    142.                         }else{
    143.                                 del->rp = NULL;
    144.                         }
    145.                         ret = ret + 2 ;
    146.                 }
    147.         }
    148.         if(delp!=NULL){                                                                                //删除节点有父节点
    149.                 if(del_!=NULL){
    150.                         del_->rp = del->rp;
    151.                         del_->lp = del->lp;
    152.                         del->rp = NULL;
    153.                         del->lp = NULL;
    154.                         if(delp->rp == del){
    155.                                 delp->rp = del_;
    156.                         }else{
    157.                                 delp->lp = del_;
    158.                         }
    159.                         ret = ret + 4 ;
    160.                 }else{
    161.                         if(delp->lp == del){
    162.                                 delp->lp = del->lp;
    163.                         }else{
    164.                                 delp->rp = del->lp;
    165.                         }
    166.                 }
    167.                 free(del);
    168.         }else{                                //删除节点无父节点,删除的是根节点
    169.                 if((del!=NULL)){
    170.                         if(del_!=NULL){                                                                //删除节点存在,是根节点,有替代节点
    171.                                 del_->rp = del->rp;
    172.                                 del_->lp = del->lp;
    173.                                 del->rp = NULL;
    174.                                 del->lp = NULL;
    175.                                 (*root) = del_;
    176.                                 free(del);
    177.                                 ret = ret + 8 ;;
    178.                         }else{                                                                                //删除节点存在,是根节点,没有替代节点
    179.                                 temp = *root;
    180.                                 *root = (*root)->lp;
    181.                                 free(temp);
    182.                                 temp = NULL;
    183.                         }
    184.                 };
    185.         }
    186. #if 0
    187. #endif
    188.         end_delete_node:
    189.         return ret;
    190. }


    191. /*        **********************************************
    192. *         二叉树节点操作方法:  打印
    193. *        root:要打印的树的根
    194. *        position: 打印格式
    195. *        **********************************************
    196. */
    197. int print_tree(node_t** root, int position){
    198.         int loop;

    199.         if ( (*root) != NULL ) {
    200.                 print_tree(&((*root)->lp), position + 4);
    201.                 for (loop = 0; loop < position; loop++) {
    202.                         printf(" ");
    203.                 }
    204.                 printf("%d\n", ((*root)->data));
    205.                 print_tree(&((*root)->rp), position + 4);
    206.         }
    207.         return 0;
    208. }

    209. /*        **********************************************
    210. *         二叉树应用程序
    211. *        **********************************************
    212. */
    213. #define SIZE_OF_DATA 0x10

    214. int main(void)
    215. {
    216.         int arr[SIZE_OF_DATA];

    217.         int i;
    218.         node_t *rootPtr = NULL ;
    219.         node_t *nodep = NULL;
    220.         node_t *nodes = NULL;
    221.         node_t *nodet = NULL;
    222.         node_t *temp = NULL;
    223.         int ret =0;
    224.         

    225.         srand(time(NULL));
    226.         printf("\n================ general %2d rand data ==========\n\n",SIZE_OF_DATA);

    227.         
    228.         for (i = 0; i < SIZE_OF_DATA; i++) {
    229.                 arr[i] = rand()%100;
    230.                 printf("%4d", arr[i]);
    231.         }
    232.         
    233.         printf("\n\n=========== insert and print the tree ===========\n\n");

    234.         for (i = 0; i < SIZE_OF_DATA; i++) {
    235.                 insert_node(&rootPtr, arr[i]);
    236.         }
    237.         print_tree(&rootPtr, 2);

    238.         printf("\n\n=============== node search result ==============\n\n");

    239.         for (i = 0; i < SIZE_OF_DATA; i++) {
    240.                 nodep = NULL;
    241.                 nodes = NULL;
    242.                 temp = NULL;
    243.                 ret = search_node(&rootPtr,arr[i],&temp,&nodep,&nodes);
    244.                 printf("No.%2d: data is [%2d]. parent is ",i+1,arr[i]);
    245.                 if(nodep==NULL)printf("[null]");
    246.                 if(nodep!=NULL)printf("[%4d]",nodep->data);
    247.                 printf(" left child is ");
    248.                 if(nodes->lp == NULL )
    249.                         printf("[null]");
    250.                 if(nodes->lp != NULL )
    251.                         printf("[%4d]",nodes->lp->data);
    252.                 printf(" right child is ");
    253.                
    254.                 if(nodes->rp != NULL )
    255.                         printf("[%4d].\n",nodes->rp->data);
    256.                 if(nodes->rp == NULL )
    257.                         printf("[null].\n");
    258.         }

    259.         printf("\n\n=================  search node =================\n\n");

    260.         for (i = 0; i < SIZE_OF_DATA; i++) {
    261.                 nodep = NULL;
    262.                 nodes = NULL;
    263.                 temp = NULL;
    264.                 search_node(&rootPtr,arr[i],&temp,&nodep,&nodes);
    265.                 printf("No.%2d: data is [%2d]. r-tree left is ",i+1,arr[i]);
    266.                 nodet = nodes;
    267.                 nodep = NULL;
    268.                 nodes = NULL;
    269.                 temp = NULL;
    270.                 search_node_l(&(nodet->rp),&temp,&nodep,&nodes);
    271.                 if(nodes==NULL)printf("[null].\n");
    272.                 if(nodes!=NULL)printf("[%4d].\n",nodes->data);
    273.         }
    274.         printf("\n");
    275.         for (i = 0; i < SIZE_OF_DATA; i++) {
    276.                 nodep = NULL;
    277.                 nodes = NULL;
    278.                 temp = NULL;
    279.                 search_node(&rootPtr,arr[i],&temp,&nodep,&nodes);
    280.                 printf("No.%2d: data is [%2d]. l-tree right is ",i+1,arr[i]);
    281.                 nodet = nodes;
    282.                 nodep = NULL;
    283.                 nodes = NULL;
    284.                 temp = NULL;
    285.                 search_node_r(&(nodet->lp),&temp,&nodep,&nodes);
    286.                 if(nodes==NULL)printf("[null].\n");
    287.                 if(nodes!=NULL)printf("[%4d].\n",nodes->data);
    288.         }

    289.         printf("\n\n================ delete a node  ================\n\n");

    290.         print_tree(&rootPtr, 2);
    291.         
    292.         i = rand()%SIZE_OF_DATA -1 ;
    293.         delete_node(&rootPtr,arr[i]);
    294.         printf("------------------ delete [ %d ] ------------\n",arr[i]);
    295.         print_tree(&rootPtr, 2);

    296.         printf("\n\n==================== end  =====================\n\n");
    297.         
    298.         return 0;

    299. }
    复制代码




    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-4-20 03:45 , Processed in 0.119079 second(s), 15 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.