• 二叉树之一


    二叉树

    一、树简介

    1. 树是一种借助于复杂节点结构完成的一种数据结构。
      树(Tree)是n(n>=0)个结点的有限集。n=0时称为空树。在任意一颗非空树中:

      • 有且仅有一个特定的称为根(Root)的结点;
      • 当n>1时,其余结点可分为m(m>0)个互不相交的有限集(T_1)(T_2)、......、(T_n),其中每一个集合本身又是一棵树,并且称为根的子树。
      • 此外,树的定义还需要强调:
        • n>0时根结点是唯一的,不可能存在多个根结点,数据结构中的树只能有一个根结点。
        • m>0时,子树的个数没有限制,但它们一定是互不相交的。
      • 节点的度
        度就是说明本节点 具有的孩子节点的数目,类似于图算法当中的出度和入度(degree).
      • 节点关系
        父亲节点,孩子节点。
      • 树深度
        先说明的概念,从root开始为第一层,依次类推得到深度。
        深度为(k)的满二叉树,具有(2^{k+1}-1)个节点,也就是一个简单的等比数列求和,不难理解。

    二、二叉树

    1. 二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。

    2. 性质

      1. 在二叉树的第i层上最多有2i-1 个节点 。(i>=1)

      2. 二叉树中如果深度为k,那么最多有(2^k-1)个节点。(k>=1)

      3. (n_0=n_2+1), (n_0)表示度数为0的节点数,(n_2)表示度数为2的节点数。

      4. 在完全二叉树中,具有n个节点的完全二叉树的深度为(lfloor {log_2n} floor)+1。

      5. 若对含 n 个结点的完全二叉树从上到下且从左至右进行 1 至 n 的编号,则对完全二叉树中任意一个编号为$ i$ 的结点有如下特性:

        (1) 若 i=1,则该结点是二叉树的根,无双亲, 否则,编号为 (lfloorfrac{i}{2} floor)的结点为其双亲结点;
        (2) 若 ({2i}gt{n}),则该结点无左孩子, 否则,编号为 2i 的结点为其左孩子结点;
        (3) 若({2i+1}gt{n}),则该结点无右孩子结点, 否则,编号为2i+1 的结点为其右孩子结点。

    3. 二叉树的存储结构

      1. 顺序存储结构

        顺序

        一般情况之下这种存储结构只是简单适用于完全二叉树,在一般情况之下很浪费内存,尤其是右斜树,普适性比较低。

      2. 链式存储结构

        链式

        这种结构包括两个左右指针数据域,声明如下:

        typedef struct Node{
            ElemType data;//数据
            struct Node *lchild, *rchild;//左右孩子指针
        } BiTNode, *BiTree;
        
    4. 二叉树的遍历

      遍历

      1. 前序遍历

        前序遍历就是从二叉树的根结点rote出发,当第一次到达结点时就输出结点数据,按照先向左,再向右的方向访问。

        前序

        pre-order: A, B, D, G, H, C, E, I, F

      2. 中序遍历

        中序遍历:就是左->中->右

        前序

        in-order: G, D, H, B, A, E, I, C, F

      3. 后序遍历

        后序遍历就是左->右->中

        前序

        post-order: G, H, D, B, I, E, F, C, A

      4. 层序遍历(逐层)

        前序

    5. 实现代码

      由于二叉树借助于递归,代码很简单:

      /*二叉树的前序遍历递归算法*/
      void PreOrderTraverse(BiTree T)
      {
          if(T==NULL)
          return;
          printf("%c", T->data);  /*显示结点数据,可以更改为其他对结点操作*/
          PreOrderTraverse(T->lchild);    /*再先序遍历左子树*/
          PreOrderTraverse(T->rchild);    /*最后先序遍历右子树*/
      }
      
      
      /*二叉树的中序遍历递归算法*/
      void InOrderTraverse(BiTree T)
      {
          if(T==NULL)
          return;
          InOrderTraverse(T->lchild); /*中序遍历左子树*/
          printf("%c", T->data);  /*显示结点数据,可以更改为其他对结点操作*/
          InOrderTraverse(T->rchild); /*最后中序遍历右子树*/
      }
      
      
      /*二叉树的后序遍历递归算法*/
      void PostOrderTraverse(BiTree T)
      {
          if(T==NULL)
          return;
          PostOrderTraverse(T->lchild);   /*先后序遍历左子树*/
          PostOrderTraverse(T->rchild);   /*再后续遍历右子树*/
          printf("%c", T->data);  /*显示结点数据,可以更改为其他对结点操作*/
      }
         //完全版本
       #include<bits/stdc++.h>
       using namespace std;
       const int _max = 3001;
      
       typedef struct Node{
           int data;//数据
           struct Node *lchild, *rchild;//左右孩子指针
       }BiTNode, *BiTree;
      
       BiTree add(BiTree root, int node)    ///插入结点+
       {
           BiTree newnode;
           BiTree currentnode;
           BiTree parentnode;
      
           newnode = (BiTree)malloc(sizeof(BiTNode));
            newnode->data = node;
            newnode->lchild = NULL;
            newnode->rchild = NULL;
      
            if(root == NULL)         ///第一个结点建立
                return newnode;
            else
            {
                currentnode = root; ///储存当前结点
                while(currentnode != NULL)     ///当前结点不为空         
                {
                    parentnode = currentnode;  ///储存父结点
                    if(currentnode->data > node)
                       currentnode = currentnode->lchild;  ///左子树
                    else
                        currentnode = currentnode->rchild; ///右子树
                }
                if(parentnode->data > node)
                    parentnode->lchild = newnode;
                else
                    parentnode->rchild = newnode;
            }
            return root;
        }
      
        BiTree create(int *data, int len)
        {
            BiTree root = NULL;
            for(int i = 1; i <= len; i++)
            {
                root = add(root, data[i]);
            }
            return root;
        }
      
       BiTree build_BiTree(int len, int arr[]){
           new BiTree[len];
           for(int i = 0; i < len; i++){
      
      
           }
       }
       void travel_pre(BiTree T){
           if(T==NULL)
               return;
           cout<<T->data<<" ";  /*显示结点数据,可以更改为其他对结点操作*/
           travel_pre(T->lchild);    /*再先序遍历左子树*/
           travel_pre(T->rchild);    /*最后先序遍历右子树*/
      
       }
       void travel_in(BiTree T){
           if(T==NULL)
               return;
           travel_in(T->lchild);    /*再先序遍历左子树*/
           cout<< T->data<<" ";  /*显示结点数据,可以更改为其他对结点操作*/
           travel_in(T->rchild);    /*最后先序遍历右子树*/
       }
      
       int main()
       {
           int num_of_cases;
           int arr[_max];
           while(cin>>num_of_cases && num_of_cases != 0){
               for(int i = 1; i <= num_of_cases; i++){
                   cin >>arr[i];
               }
               BiTree ans = create(arr,num_of_cases);
               travel_in(ans);
               cout<<endl;
               travel_pre(ans);
               cout<<endl;
           }
       }
      
    抬起头,永远年轻,永远热泪盈眶!
  • 相关阅读:
    Flink实战(八十):FLINK-SQL使用基础(七)Flink SQL Clien读取Kafka数据流式写入Hive(用hive 管理kafka元数据)
    离线电商数仓(六十九)之即席查询(二)kylin使用
    离线电商数仓(六十八)之即席查询(一)kylin简介与安装
    离线电商数仓(六十七)之数据质量监控(三)Griffin(四) 安装及使用(二)
    离线电商数仓(六十六)之数据质量监控(二)Griffin(三) 安装及使用(一)
    Virtio-fs介绍与性能优化
    overlayfs mount shared =+ kata + OCI bundle rootfs
    Getting started with containerd
    Container Runtime
    containerd
  • 原文地址:https://www.cnblogs.com/marvin-Hua-manlou/p/13852733.html
Copyright © 2020-2023  润新知