zoukankan      html  css  js  c++  java
  • 复杂数据结构(一)树

    层次关系结构:树

    树的概念:树是N个节点的集合

    A节点称为根节点,A为B C D的父节点,反之就是子节点,B C D分别为各自的兄弟节点

    节点的度:一个节点的子树的数量 称为该节点的度

    树的度:一棵树中,最大的节点的度称为树的度

    叶节点或终端节点:度为0的节点称为叶节点

    节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推

    树的高度或深度:树中节点的最大层次

    image

    也可这么表示 不过就没有上图那么直观了

    (A(B(E)),(C(F(J)),(G(K,L))),(D(H),(I(M,N))))

    简单可分为:

    无序树:树中任意节点的子结点之间没有顺序关系,这种树称为无序树,也称为自由树

    有序树:树中任意节点的子结点之间有顺序关系,这种树称为有序树



    二叉树:每个节点最多含有两个子树的树称为二叉树

    image

    两种特殊的二叉树:

    完全二叉树:除最后一层外,每一层上的节点数均达到最大值,在最后一层上只缺少右边的若干节点

    满二叉树:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点或0个子节点的二叉树,满二叉树一定是完全二叉树

    image

    根据二叉树的定义,可得知其具有以下性质:
    (1)在二叉树中,第i层的结点总数最多有2i-1个结点
    (2)深度为k的二叉树最多有2k-1个结点(k>=1),最少有k个结点
    (3)对于一棵二叉树,如果其叶结点数为n0,而度为2的结点总数为n2,则n0=n2+1
    (4)具有n个结点的完全二叉树的深度k为:k=[log2n]+1

    二叉树的存储:

    顺序存储结构

    image

    链式存储结构

    image

    二叉树的常规操作:

    1.定义二叉链式结构
    2.初始化二叉树
    3.添加结点到二叉树
    4.获取二叉树左右子树
    5.获取二叉树状态
    6.在二叉树中查找
    7.清空二叉树

    #include <stdio.h> 
    #include <stdlib.h> 
    #define QUEUE_MAXSIZE 50
    typedef char DATA;       //定义元素类型 
    typedef struct ChainTree  //定义二叉树结点类型 
    {
        DATA data;    //元素数据
        struct ChainTree *left;    //左子树结点指针
        struct ChainTree *right;    //右子树结点指针
    }ChainBinTree;
    ChainBinTree *BinTreeInit(ChainBinTree *node) //初始化二叉树根结点 
    {
         if(node!=NULL) //若二叉树根结点不为空 
             return node;
         else
             return NULL;
    }
    int BinTreeAddNode(ChainBinTree *bt,ChainBinTree *node,int n) //添加数据到二叉树 
    //bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树 
    {
        if(bt==NULL)
        {
            printf("父结点不存在,请先设置父结点!
    ");
            return 0;
        } 
        switch(n)
        {
            case 1: //添加到左结点 
                if(bt->left) //左子树不为空 
                {
                    printf("左子树结点不为空!
    ");
                    return 0;
                }else
                    bt->left=node;
                break;
            case 2://添加到右结点
                if( bt->right) //右子树不为空 
                {
                    printf("右子树结点不为空!
    "); 
                    return 0;
                }else
                    bt->right=node;
                break;
            default:
                printf("参数错误!
    ");
                return 0;
        }
        return 1;
    }
    ChainBinTree *BinTreeLeft(ChainBinTree *bt) //返回左子结点 
    {
        if(bt)
            return bt->left;
        else
            return NULL;
    }
    ChainBinTree *BinTreeRight(ChainBinTree *bt) //返回右子结点 
    {
        if(bt)
            return bt->right;
        else
            return NULL;
    }
    int BinTreeIsEmpty(ChainBinTree *bt) //检查二叉树是否为空,为空则返回1,否则返回0 
    {
        if(bt)
            return 0;
        else
            return 1;
    } 
    int BinTreeDepth(ChainBinTree *bt) //求二叉树深度
    {
        int dep1,dep2;
        if(bt==NULL)
            return 0; //对于空树,深度为0
        else
        {
            dep1 = BinTreeDepth(bt->left); //左子树深度 (递归调用)
            dep2 = BinTreeDepth(bt->right); //右子树深度 (递归调用)
            if(dep1>dep2)
               return dep1 + 1; 
            else
                return dep2 + 1; 
        } 
    } 
    ChainBinTree *BinTreeFind(ChainBinTree *bt,DATA data) //在二叉树中查找值为data的结点 
    {
        ChainBinTree *p;
        if(bt==NULL)
            return NULL;
        else
        {
            if(bt->data==data)
                return bt; 
            else{ // 分别向左右子树递归查找 
                if(p=BinTreeFind(bt->left,data))
                    return p;
                else if(p=BinTreeFind(bt->right, data)) 
                    return p;
                else
                    return NULL; 
            } 
        } 
    } 
    void BinTreeClear(ChainBinTree *bt) // 清空二叉树,使之变为一棵空树
    {
         if(bt)
         {
             BinTreeClear(bt->left); //清空左子树 
             BinTreeClear(bt->right);//清空右子树 
             free(bt);//释放当前结点所占内存 
             bt=NULL;
         }
         return; 
    }

    二叉树的遍历:

    先序遍历(DLR):称为先根次序遍历,即先访问根结点,再按先序遍历左子树,最后按先序遍历右子树。
    中序遍历(LDR):称为中根次序遍历,即先按中序遍历左子树,再访问根结点,最后按中序遍历右子树。
    后序遍历(LRD):称为后根次数遍历,即先按后序遍历左子树,再按后序遍历右子树,最后访问根结点。
    按层遍历:按二叉树的层进行遍历,可更直观地从图中得出遍历的结果。

    void BinTree_DLR(ChainBinTree *bt,void (*oper)(ChainBinTree *p))  //先序遍历 
    {     
         if(bt)//树不为空,则执行如下操作 
         {
             oper(bt); //处理结点的数据 
             BinTree_DLR(bt->left,oper);
             BinTree_DLR(bt->right,oper);
         }
         return; 
    } 
    void BinTree_LDR(ChainBinTree *bt,void(*oper)(ChainBinTree *p))  //中序遍历 
    {
         if(bt)//树不为空,则执行如下操作 
         {
             BinTree_LDR(bt->left,oper); //中序遍历左子树
             oper(bt);//处理结点数据 
             BinTree_LDR(bt->right,oper); //中序遍历右子树/
         }
         return; 
    } 
    void BinTree_LRD(ChainBinTree *bt,void (*oper)(ChainBinTree *p)) //后序遍历
    {
         if(bt)
         {
             BinTree_LRD(bt->left,oper); //后序遍历左子树 
             BinTree_LRD(bt->right,oper); //后序遍历右子树/
             oper(bt); //处理结点数据
         }
         return; 
    }
    
    void oper(ChainBinTree *p) //操作二叉树结点数据 
    {
         printf("%c ",p->data); //输出数据
         return;
    }
    
    void BinTree_Level(ChainBinTree *bt,void (*oper)(ChainBinTree *p)) //按层遍历 
    {
         ChainBinTree *p;
         ChainBinTree *q[QUEUE_MAXSIZE]; //定义一个顺序栈 
         int head=0,tail=0;//队首、队尾序号 
         if(bt)//若队首指针不为空     
         {
             tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列队尾序号 
             q[tail] = bt;//将二叉树根指针进队
         }
         while(head!=tail) //队列不为空,进行循环 
         {
             head=(head+1)%QUEUE_MAXSIZE; //计算循环队列的队首序号 
             p=q[head]; //获取队首元素 
             oper(p);//处理队首元素 
             if(p->left!=NULL) //若结点存在左子树,则左子树指针进队 
             {
                 tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号 
                 q[tail]=p->left;//将左子树指针进队 
             }
                     
             if(p->right!=NULL)//若结点存在右孩子,则右孩子结点指针进队 
             {
                 tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号 
                 q[tail]=p->right;//将右子树指针进队 
             }
         }
         return; 
    }

     

  • 相关阅读:
    win10 mysql5.7忘记密码如何解决
    win10 mysql5.7指定某个配置文件启动
    kubernetes配置(kubeconfig)对多集群的访问
    kubernetes中kubeconfig的用法
    rancher v2.2.4创建kubernetes集群出现[etcd] Failed to bring up Etcd Plane: [etcd] Etcd Cluster is not healthy
    kubernetes 强制删除istio-system空间,强制删除pod
    rancher2.0 自定义应用商店(catalog)
    docker-compose安装及docker-compose.yml详解
    细述kubernetes开发流程
    轻松了解DNS劫持
  • 原文地址:https://www.cnblogs.com/moguwang/p/5278760.html
Copyright © 2011-2022 走看看