• (原)----2叉查找树 in C


     

       2叉树(Binary Tree):是每个结点最多有左右两棵子2叉树相连接的树结构。

    性质:

    • 高度(height)1:根节点在第0层,树中节点层数的最大值,即外部结点层数的最大值。
    • 一棵有N个内部节点的2叉树有N+1个外部节点。

    图1

    关于2叉树的高度,维基百科2中说的深度,根节点的深度为1。深度为k的2叉树,最多有2k-1个结点。具体以自己参考书为准。

    下面来看看用的比较多的2叉搜索树(图1)

      2叉搜索树(Binary Search Tree)3:也称有序二叉树(ordered binary tree),排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的2叉树:

    1. 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    2. 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    3. 任意节点的左、右子树也分别为二叉查找树。
    4. 没有键值相等的节点(no duplicate nodes)。

    树的遍历(见图1):

    • 前序(preorder):我们访问该结点,然后访问该结点的左子树和右子树。10、6、4、3、5、8、7、9、12、11、13
    //递归前序遍历,中序和后序只需将PRINT()函数放到中间和后面即可
    PRE-TRAVERSE(p_node) IF p_node!=NIL THEN PRINT(p_node) PRE-TRAVERSE(p_node_L_child) PRE-TRAVERSE(p_node_R_child)
    • 中序(inorder):我们访问该结点的左子树,然后访问该结点,最后访问右子树。3、4、5、6、7、8、9、10、11、12、13(结果为递增哦
    //非递归中序,前序和后序将压入tmp_node的顺序换下即可
    NONREC-INTRAVERSE(p_node)
        STACK-PUSH(p_node)
        WHILE STACK!=NIL
            p_node <- STACK-POP()
            IF p_node是树不是数据项
                将p_node结点数据项赋值给tmp_node
                STACK-PUSH(p_node_R_child)
                STACK-PUSH(tmp_node)
                STACK-PUSH(p_node_L_child)
            ELSE
                PRINT(p_node)
    • 后序(postorder):我们访问该结点的左子树和右子树,然后访问该节点。3、5、4、7、9、8、6、11、13、12、10
    • 层序(level-order):从上到下,从左到右的遍历树的结点。10、6、12、4、8、11、13、3、5、7、9
    //层次遍历
    LEVEL-TRAVERSE(p_node)
        QUEUE-IN(p_node)
        WHILE QUEUE != NIL
            p_node <- QUEUE-OUT()
            PRINT(p_node)
            QUEUE-IN(p_node_L_child)
            QUEUE-IN(p_node_R_child)

    CODE:

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #define N 15    
      4 int const *p;    /*指向数组s[]的指针*/
      5 /*************************************************
      6 **树的定义、初始化、插入节点
      7 **前序递归遍历树(中序、后序)
      8 **叶子数、深度、每层结点数
      9 **version:1.0
     10 *************************************************/
     11 /*树的结点*/
     12 typedef struct node
     13 {
     14     int item;
     15     struct node *l,*r;
     16 }tree_node;
     17 typedef struct
     18 {
     19     tree_node tn[N];
     20     int cur;
     21 }m_arr_tree;
     22 /*初始化树*/
     23 void treeInit(m_arr_tree **mat)
     24 {
     25     *mat=(m_arr_tree *)calloc(1,sizeof(m_arr_tree));
     26     (*mat)->cur=0;
     27 }
     28 /*储存树*/
     29 tree_node * treePush(m_arr_tree *mat,int item)
     30 {
     31     mat->tn[mat->cur].item=item;
     32     return mat->tn+mat->cur++;    /*返回该节点的地址,并使数组下标加1*/
     33 }
     34 /*前序插入树的节点*/
     35 tree_node *treePreInsert(m_arr_tree *mat)
     36 {
     37     tree_node *node=NULL;
     38     if(*p==0)    
     39         ++p;
     40     else
     41     {
     42         node=treePush(mat,*p++);
     43         node->l=treePreInsert(mat);
     44         node->r=treePreInsert(mat);
     45     }
     46     return node;
     47 }
     48 /*打印树*/
     49 void printNode(int c,int width)
     50 {
     51     while(width-->0)
     52         printf("#");
     53     printf("%d
    ",c);
     54 
     55 }
     56 /*递归前序遍历,中序和后序只需将打印函数放到中间和后面*/
     57 void preTraverse(tree_node *node,int width)
     58 {
     59     if(node==NULL)
     60     {
     61         printNode(0,width);    /* 打印叶子节点是左右孩子都是0 */
     62         return;
     63     }
     64     printNode(node->item,width);
     65     preTraverse(node->l,width+1);
     66     preTraverse(node->r,width+1);
     67 }
     68 /*树的叶子个数*/
     69 int treeLeaves(tree_node * node)
     70 {
     71     if(node==NULL)
     72         return 0;
     73     if(node->l==NULL && node->r==NULL)
     74         return 1;
     75     int l_count=treeLeaves(node->l);
     76     int r_count=treeLeaves(node->r);
     77     return l_count+r_count;
     78 }
     79 /*树的深度*/
     80 int treeDepth(tree_node * node)
     81 {
     82     if(node==NULL)
     83         return 0;
     84     int l_depth=treeDepth(node->l);
     85     int r_depth=treeDepth(node->r);
     86     if(l_depth>r_depth)
     87         return l_depth+1;
     88     else
     89         return r_depth+1;
     90 
     91 }
     92 /*树的每层结点个数*/
     93 void treeLevelNode(tree_node *node,int lev,int lev_num[])
     94 {
     95     if(node==NULL)
     96         return;
     97     lev_num[lev]++;
     98     treeLevelNode(node->l,lev+1,lev_num);
     99     treeLevelNode(node->r,lev+1,lev_num);
    100 }
    101 /*************************************************
    102 **队列的定义、初始化、入队列、出队列、判断为空
    103 **层次遍历
    104 **version:1.0
    105 *************************************************/
    106 /*定义队列*/
    107 typedef struct 
    108 {
    109     tree_node * que[N];    /*存放树结点的指针*/
    110     int front,tail;
    111 }m_queue;
    112 /*初始化队列*/
    113 void queueInit(m_queue **mq)
    114 {
    115     *mq=(m_queue *)malloc(sizeof(m_queue));
    116     (*mq)->front=0;(*mq)->tail=0;
    117 }
    118 /*入队列*/
    119 void queueIn(m_queue *mq,tree_node *node)
    120 {
    121     mq->tail=(mq->tail+1)%N;
    122     mq->que[mq->tail]=node;
    123 }
    124 /*出队列*/
    125 tree_node* queueOut(m_queue *mq)
    126 {
    127     mq->front=(mq->front+1)%N;
    128     return mq->que[mq->front];
    129 }
    130 /*队列是否为空*/
    131 int queueEmpty(m_queue *mq)
    132 {
    133     if(mq->front == mq->tail)
    134         return 1;
    135     return 0;
    136 }
    137 /*利用队列层次遍历*/
    138 void levelTraverse(tree_node *node)
    139 {
    140     m_queue * mq;    /*声明队列*/
    141     queueInit(&mq);queueIn(mq,node);    /*初始化和向队列放入根结点*/
    142     int node_count=0,node_level_num=2;    /*深度为k,满足2^k-1个结点时,换行*/
    143     while(!queueEmpty(mq))
    144     {
    145         node=queueOut(mq);
    146         printf("%d ",node->item); ++node_count;
    147         if(node_count >= node_level_num-1)
    148         {
    149             putchar('
    ');
    150             node_level_num<<=1;
    151         }
    152         if(node->l)queueIn(mq,node->l);    /*压入弹出结点的左右孩子*/
    153         if(node->r)queueIn(mq,node->r);
    154     }
    155     putchar('
    ');
    156     free(mq);
    157 }
    158 
    159 /*************************************************
    160 **栈的定义、初始化、压栈、弹栈、判断为空
    161 **非递归中序遍历(前序、后序)
    162 **version:1.0
    163 *************************************************/
    164 /*定义栈*/
    165 typedef struct
    166 {
    167     tree_node * sta[N];
    168     int cur;
    169 }m_stack;
    170 /*初始化*/
    171 void stackInit(m_stack **ms)
    172 {
    173     *ms=(m_stack *)malloc(sizeof(m_stack));
    174     (*ms)->cur=0;
    175 }
    176 /*压栈*/
    177 void stackPush(m_stack * ms,tree_node * node)
    178 {
    179     ms->sta[ms->cur++]=node;
    180 }
    181 /*弹出栈*/
    182 tree_node *stackPop(m_stack *ms)
    183 {
    184     return ms->sta[--ms->cur];
    185 }
    186 /*判断为空*/
    187 int stackEmpty(m_stack *ms)
    188 {
    189     if(ms->cur==0)
    190         return 1;
    191     return 0;
    192 }
    193 /*非递归中序遍历栈,弹出元素为数据项,访问它;为一棵树,按希望的顺序压栈*/
    194 void nonRecInTraverse(tree_node *node)
    195 {
    196     m_arr_tree *tmp_mat;    /*存放弹出的数据项*/
    197     treeInit(&tmp_mat);
    198 
    199     m_stack *ms;    /*按希望的顺序保存数据项的栈*/
    200     stackInit(&ms);
    201     stackPush(ms,node);
    202     while(!stackEmpty(ms))
    203     {
    204         node=stackPop(ms);    
    205         if(node->l || node->r)    /*是树继续压栈,否则打印该数据项*/
    206         {
    207             tree_node *new_node=treePush(tmp_mat,node->item);    
    208             if(node->r)stackPush(ms,node->r);
    209             stackPush(ms,new_node);
    210             if(node->l)stackPush(ms,node->l);
    211         }
    212         else
    213             printf("%d ",node->item);
    214     }
    215     putchar('
    ');
    216     free(tmp_mat);
    217     free(ms);
    218 }
    219 
    220 int main()
    221 {
    222     /*0代表外部结点*/
    223     int s[]={10,6,4,3,0,0,5,0,0,8,7,0,0,9,0,0,12,11,0,0,13,0,0};
    224     p=s;    /*将全局指针指向数组s,方便前序初始化树*/
    225     m_arr_tree *head;
    226     treeInit(&head);
    227     treePreInsert(head);
    228 //    preTraverse(head->tn,0);    /*递归前序遍历*/
    229 //    levelTraverse(head->tn);    /*层次遍历*/
    230 //    nonRecInTraverse(head->tn);    /*非递归中序遍历*/
    231 //    printf("
    number of leaves:%d
    ",treeLeaves(head->tn));    /*叶子结点数*/
    232     int d=treeDepth(head->tn);    /*树的深度*/
    233     printf("
     depth of tree : %d
    ",d);
    234     int lev_num[N]={0};    /*每层的节点数*/
    235     treeLevelNode(head->tn,0,lev_num);
    236     while(--d>=0)    /*打印每层节点数*/
    237         printf(" The %d level number of node :%d
    ",d,lev_num[d]);
    238     free(head);
    239     return 0;
    240 }

    参考资料:

    1. Robert Sedgewick,《算法:C语言实现》,中文版
    2. http://zh.wikipedia.org/wiki/%E4%BA%8C%E5%8F%89%E6%A0%91
    3. http://zh.wikipedia.org/wiki/%E4%BA%8C%E5%85%83%E6%90%9C%E5%B0%8B%E6%A8%B9
    4. http://www.zdyi.com/blog/binary-tree/792
    转载请注明:
    
    作者:Timothy_T
    
    地址:http://www.cnblogs.com/jhooon
  • 相关阅读:
    Redis单实例数据迁移到集群
    使用IDEA快速搭建基于Maven的SpringBoot项目(集成使用Redis)
    Linux下Mysql每天自动备份
    java调用webservice
    springmvc后台生成验证码
    Zabbix 监控端口状态并邮件报警
    Zabbix 通过smtp 邮件报警
    Zabbix安装(server和agent)及基本配置
    Spark之 Spark Streaming整合kafka(Java实现版本)
    openlayer 5 获取中心点
  • 原文地址:https://www.cnblogs.com/jhooon/p/3632790.html
Copyright © 2020-2023  润新知