zoukankan      html  css  js  c++  java
  • 06数据结构——树

    6.2 树的定义

    树是 n (n >= 0) 个结点的有限集。n=0 时称为空树。在任意一棵非空树种:(1)有且仅有一个特定的称为根的结点;(2)当 n>1 时,其余结点可分为 m (m > 0) 个互不相交的有限集,其中每一个集合本身又是一棵树,并且称为根的子树。如下图所示:

    6.3树的抽象数据类型

    6.4  树的存储结构

    6.5 二叉树

    6.5.1 二叉树定义

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

     

    二叉树具有五种基本形态:

    • 空二叉树
    • 只有一个根结点
    • 根结点只有左子树
    • 根结点只有右子树
    • 根结点既有左子树又有右子树

     

    6.5.2特殊二叉树

    直白点说,在同一层里面左边的二叉树必须是满的。

    6.6二叉树的性质

     性质1.在二叉树的第i层上至多有2i-1个结点(i>=1);

     性质 2.深度为k的二叉树最多有2k-1个结点;

     性质3.对任何一棵二叉树T,如果其叶子结点数为n0,度为2的结点数为n2,则n0 = n2 + 1;

      性质4.具有n个结点的完全二叉树的深度为[log2n] + 1,[x]表示不大于x的最大整数;

      性质5.

    6.7二叉树的存储结构

     

    ·

    6.8  遍历二叉树

    二叉树的遍历是指从根结点出发,按照某种次序依次访问二叉树所有结点,使得每个结点被访问一次且仅被访问一次。

    二叉树遍历方法
    • 前序遍历
      若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树。


       
       

    前序遍历次序:ABDGHCEIF

    • 中序遍历
      若二叉树为空,则空操作返回,否则从根结点开始(注意并不是先访问根结点),中序遍历根结点的左子树,然后访问根结点,最后中序遍历右子树。
     
     

    中序遍历次序:GDHBAEICF

    • 后序遍历
      若二叉树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点。
     
     

    后序遍历次序:GHDBIEFCA

    • 层次遍历
      若二叉树为空,则空操作返回,否则从树的第一层,
     
     

    层次遍历次序:ABCDEFGHI

    6.11  树转化为二叉树

    6.12 赫夫曼树

     #01 二叉树顺序结构实现

    #include "stdio.h"    
    #include "stdlib.h"   
    #include "io.h"  
    #include "math.h"  
    #include "time.h"
    
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    
    #define MAXSIZE 100 /* 存储空间初始分配量 */
    #define MAX_TREE_SIZE 100 /* 二叉树的最大结点数 */
    
    typedef int Status;        /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
    typedef int TElemType;  /* 树结点的数据类型,目前暂定为整型 */
    typedef TElemType SqBiTree[MAX_TREE_SIZE]; /* 0号单元存储根结点  */
    
    typedef struct
    {
        int level,order; /* 结点的层,本层序号(按满二叉树计算) */
    }Position;
    
    TElemType Nil=0; /*  设整型以0为空 */
    
    Status visit(TElemType c)
    {
        printf("%d ",c);
        return OK;
    }
    
    /* 构造空二叉树T。因为T是固定数组,不会改变,故不需要& */
    Status InitBiTree(SqBiTree T)
    {
        int i;
        for(i=0;i<MAX_TREE_SIZE;i++)
            T[i]=Nil; /* 初值为空 */
        return OK;
    }
    
    /* 按层序次序输入二叉树中结点的值(字符型或整型), 构造顺序存储的二叉树T */
    Status CreateBiTree(SqBiTree T)
    { 
        int i=0;
         printf("请按层序输入结点的值(整型),0表示空结点,输999结束。结点数≤%d:
    ",MAX_TREE_SIZE);
        while(i<10)
        {
            T[i]=i+1;
            
            if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil) /* 此结点(不空)无双亲且不是根 */
            {
                printf("出现无双亲的非根结点%d
    ",T[i]);
                exit(ERROR);
            }
            i++;
        }
        while(i<MAX_TREE_SIZE)
        {
            T[i]=Nil; /* 将空赋值给T的后面的结点 */
            i++;
        }
    
        return OK;
    }
    
    #define ClearBiTree InitBiTree /* 在顺序存储结构中,两函数完全一样 */
    
    /* 初始条件: 二叉树T存在 */
    /* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
    Status BiTreeEmpty(SqBiTree T)
    { 
        if(T[0]==Nil) /* 根结点为空,则树空 */
            return TRUE;
        else
            return FALSE;
    }
    
    /* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
    int BiTreeDepth(SqBiTree T)
    { 
       int i,j=-1;
       for(i=MAX_TREE_SIZE-1;i>=0;i--) /* 找到最后一个结点 */
         if(T[i]!=Nil)
           break;
       i++; 
       do
         j++;
       while(i>=powl(2,j));/* 计算2的j次幂。 */
       return j;
    }
    
    /* 初始条件: 二叉树T存在 */
    /* 操作结果:  当T不空,用e返回T的根,返回OK;否则返回ERROR,e无定义 */
    Status Root(SqBiTree T,TElemType *e)
    { 
        if(BiTreeEmpty(T)) /* T空 */
            return ERROR;
        else
        {    
            *e=T[0];
            return OK;
        }
    }
    
    /* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */
    /* 操作结果: 返回处于位置e(层,本层序号)的结点的值 */
    TElemType Value(SqBiTree T,Position e)
    { 
         return T[(int)powl(2,e.level-1)+e.order-2];
    }
    
    /* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */
    /* 操作结果: 给处于位置e(层,本层序号)的结点赋新值value */
    Status Assign(SqBiTree T,Position e,TElemType value)
    { 
        int i=(int)powl(2,e.level-1)+e.order-2; /* 将层、本层序号转为矩阵的序号 */
        if(value!=Nil&&T[(i+1)/2-1]==Nil) /* 给叶子赋非空值但双亲为空 */
            return ERROR;
        else if(value==Nil&&(T[i*2+1]!=Nil||T[i*2+2]!=Nil)) /*  给双亲赋空值但有叶子(不空) */
            return ERROR;
        T[i]=value;
        return OK;
    }
    
    /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 若e是T的非根结点,则返回它的双亲,否则返回"空" */
    TElemType Parent(SqBiTree T,TElemType e)
    { 
        int i;
        if(T[0]==Nil) /* 空树 */
            return Nil;
        for(i=1;i<=MAX_TREE_SIZE-1;i++)
            if(T[i]==e) /* 找到e */
                return T[(i+1)/2-1];
        return Nil; /* 没找到e */
    }
    
    
    /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的左孩子。若e无左孩子,则返回"空" */
    TElemType LeftChild(SqBiTree T,TElemType e)
    { 
        int i;
        if(T[0]==Nil) /* 空树 */
            return Nil;
        for(i=0;i<=MAX_TREE_SIZE-1;i++)
            if(T[i]==e) /* 找到e */
                return T[i*2+1];
        return Nil; /* 没找到e */
    }
    
    /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的右孩子。若e无右孩子,则返回"空" */
    TElemType RightChild(SqBiTree T,TElemType e)
    { 
        int i;
        if(T[0]==Nil) /* 空树 */
            return Nil;
        for(i=0;i<=MAX_TREE_SIZE-1;i++)
            if(T[i]==e) /* 找到e */
                return T[i*2+2];
        return Nil; /* 没找到e */
    }
    
    /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回"空" */
    TElemType LeftSibling(SqBiTree T,TElemType e)
    { 
        int i;
        if(T[0]==Nil) /* 空树 */
            return Nil;
        for(i=1;i<=MAX_TREE_SIZE-1;i++)
            if(T[i]==e&&i%2==0) /* 找到e且其序号为偶数(是右孩子) */
                return T[i-1];
        return Nil; /* 没找到e */
    }
    
    /* 初始条件: 二叉树T存在,e是T中某个结点 */
    /* 操作结果: 返回e的右兄弟。若e是T的右孩子或无右兄弟,则返回"空" */
    TElemType RightSibling(SqBiTree T,TElemType e)
    { 
        int i;
        if(T[0]==Nil) /* 空树 */
            return Nil;
        for(i=1;i<=MAX_TREE_SIZE-1;i++)
            if(T[i]==e&&i%2) /* 找到e且其序号为奇数(是左孩子) */
                return T[i+1];
        return Nil; /* 没找到e */
    }
    
    /* PreOrderTraverse()调用 */
    void PreTraverse(SqBiTree T,int e)
    { 
        visit(T[e]);
        if(T[2*e+1]!=Nil) /* 左子树不空 */
            PreTraverse(T,2*e+1);
        if(T[2*e+2]!=Nil) /* 右子树不空 */
            PreTraverse(T,2*e+2);
    }
    
    /* 初始条件: 二叉树存在 */
    /* 操作结果: 先序遍历T。 */
    Status PreOrderTraverse(SqBiTree T)
    { 
        if(!BiTreeEmpty(T)) /* 树不空 */
         PreTraverse(T,0);
        printf("
    ");
        return OK;
    }
    
    /* InOrderTraverse()调用 */
    void InTraverse(SqBiTree T,int e)
    { 
        if(T[2*e+1]!=Nil) /* 左子树不空 */
            InTraverse(T,2*e+1);
        visit(T[e]);
        if(T[2*e+2]!=Nil) /* 右子树不空 */
            InTraverse(T,2*e+2);
    }
    
    /* 初始条件: 二叉树存在 */
    /* 操作结果: 中序遍历T。 */
    Status InOrderTraverse(SqBiTree T)
    { 
        if(!BiTreeEmpty(T)) /* 树不空 */
            InTraverse(T,0);
        printf("
    ");
        return OK;
    }
    
    /* PostOrderTraverse()调用 */
    void PostTraverse(SqBiTree T,int e)
    { 
        if(T[2*e+1]!=Nil) /* 左子树不空 */
            PostTraverse(T,2*e+1);
        if(T[2*e+2]!=Nil) /* 右子树不空 */
            PostTraverse(T,2*e+2);
        visit(T[e]);
    }
    
    /* 初始条件: 二叉树T存在 */
    /* 操作结果: 后序遍历T。 */
    Status PostOrderTraverse(SqBiTree T)
    { 
        if(!BiTreeEmpty(T)) /* 树不空 */
            PostTraverse(T,0);
        printf("
    ");
        return OK;
    }
    
    /* 层序遍历二叉树 */
    void LevelOrderTraverse(SqBiTree T)
    { 
        int i=MAX_TREE_SIZE-1,j;
        while(T[i]==Nil)
            i--; /* 找到最后一个非空结点的序号 */
        for(j=0;j<=i;j++)  /* 从根结点起,按层序遍历二叉树 */
            if(T[j]!=Nil)
                visit(T[j]); /* 只遍历非空的结点 */
        printf("
    ");
    }
    
    /* 逐层、按本层序号输出二叉树 */
    void Print(SqBiTree T)
    { 
        int j,k;
        Position p;
        TElemType e;
        for(j=1;j<=BiTreeDepth(T);j++)
        {
            printf("第%d层: ",j);
            for(k=1;k<=powl(2,j-1);k++)
            {
                p.level=j;
                p.order=k;
                e=Value(T,p);
                if(e!=Nil)
                    printf("%d:%d ",k,e);
            }
            printf("
    ");
        }
    }
    
    
    int main()
    {
        Status i;
        Position p;
        TElemType e;
        SqBiTree T;
        InitBiTree(T);
        CreateBiTree(T);
        printf("建立二叉树后,树空否?%d(1:是 0:否) 树的深度=%d
    ",BiTreeEmpty(T),BiTreeDepth(T));
        i=Root(T,&e);
        if(i)
            printf("二叉树的根为:%d
    ",e);
        else
            printf("树空,无根
    ");
        printf("层序遍历二叉树:
    ");
        LevelOrderTraverse(T);
        printf("前序遍历二叉树:
    ");
        PreOrderTraverse(T);
        printf("中序遍历二叉树:
    ");
        InOrderTraverse(T);
        printf("后序遍历二叉树:
    ");
        PostOrderTraverse(T);
        printf("修改结点的层号3本层序号2。");
        p.level=3;
        p.order=2;
        e=Value(T,p);
        printf("待修改结点的原值为%d请输入新值:50 ",e);
        e=50;
        Assign(T,p,e);
        printf("前序遍历二叉树:
    ");
        PreOrderTraverse(T);
        printf("结点%d的双亲为%d,左右孩子分别为",e,Parent(T,e));
        printf("%d,%d,左右兄弟分别为",LeftChild(T,e),RightChild(T,e));
        printf("%d,%d
    ",LeftSibling(T,e),RightSibling(T,e));
        ClearBiTree(T);
        printf("清除二叉树后,树空否?%d(1:是 0:否) 树的深度=%d
    ",BiTreeEmpty(T),BiTreeDepth(T));
        i=Root(T,&e);
        if(i)
            printf("二叉树的根为:%d
    ",e);
        else
            printf("树空,无根
    ");
        
        return 0;
    }

    #02 二叉树链表实现

    //    二叉树的实现(C语言)
    //    链表,递归实现
    
    
    #include<stdio.h>
    #include<malloc.h>
    #include<stdlib.h>
    
    typedef char Elementtype;    //    定义数据类型,可根据需要自行定制
    typedef struct TreeNode * Node;    //    Node相当于struct treeNode *
    //    定义数节点结构
    typedef struct TreeNode {
        Elementtype Element;
        Node left;    //    树节点的左子节点
        Node right;    //    树节点的右子节点
    }TREE,*PTREE;
    
    //    函数声明
    void CreatTree(PTREE *);    //    树的先序创建函数
    void PreOrderTree(PTREE );    //    树的前序遍历函数
    void InOrderTree(PTREE );    //    树的中序遍历
    void PostOrderTree(PTREE );    //    树的后序遍历
    void LeafOfTree(PTREE );    //    打印树的叶子节点函数
    int  Get_Leaf_Num(PTREE );    //    获取树叶子节点个数
    int Get_Height(PTREE );    //    获取树的高度
    
    
    //    主函数
    int main() {
    
        PTREE Root;
        printf("请先序输入二叉树的节点数据: ");
        CreatTree(&Root);
        printf("
    前序遍历结果为:");
        PreOrderTree(Root);
        printf("
    中序遍历结果为:");
        InOrderTree(Root);
        printf("
    后序遍历结果为:");
        PostOrderTree(Root);
        printf("
    打印叶子节点为:");
        LeafOfTree(Root);
        printf("
    叶子节点个数为:%d", Get_Leaf_Num(Root));
        printf("
    二叉树的高度为:%d", Get_Height(Root));
        printf("
    ");
    
        return 0;
    }
    
    //    定义树先序创建函数
    void CreatTree(PTREE *Root) {
        char val=0;    //    用于下面存放数据
        val=getchar();    //    输入数据值
        //    如果输入'*',则指向为空
        if (val == '*')
            (*Root) = NULL;
        //    如果输入非'*',则给数据域赋值
        else {
            (*Root) = (PTREE)malloc(sizeof(TREE));    //    申请内存空间
            if ((*Root) == NULL) {
                printf("创建节点失败,无法分配可用内存...");
                exit(-1);
            }
            else {
                (*Root)->Element = val;    //    给节点数据域赋值
                CreatTree(&(*Root)->left);
                CreatTree(&(*Root)->right);
            }
        }
    }
    //    树的前序遍历函数定义
    void PreOrderTree(PTREE Root) {
    
        if (Root == NULL)
            return;
        else {
            putchar(Root->Element);
            PreOrderTree(Root->left);
            PreOrderTree(Root->right);
    
        }
    }
    //    树的中序遍历函数定义
    void InOrderTree(PTREE Root) {
    
        if (Root == NULL)
            return;
        else {
            InOrderTree(Root->left);
            putchar(Root->Element);
            InOrderTree(Root->right);
    
        }
    }
    
    //    树的后序遍历函数定义
    void PostOrderTree(PTREE Root) {
    
        if (Root==NULL)
            return ;
        else{
            PostOrderTree(Root->left);
            PostOrderTree(Root->right);
            putchar( Root->Element);
        }
    }
    
    
    
    //    打印树的叶子节点函数定义
    void LeafOfTree(PTREE Tree) {
        if (Tree == NULL)
            return ;
    
        else {
            if (Tree->left == NULL&&Tree->right == NULL)
                putchar(Tree->Element);
            else {
                LeafOfTree(Tree->left);
                LeafOfTree(Tree->right);
            }
        }
    
    }
    
    //    获取树的叶子节点个数函数定义
    int Get_Leaf_Num(PTREE Tree) {
        if (Tree == NULL)
            return 0;
        if (Tree->left == NULL&&Tree->right == NULL)
            return 1;
        //递归整个树的叶子节点个数 = 左子树叶子节点的个数 + 右子树叶子节点的个数
        return Get_Leaf_Num(Tree->left) + Get_Leaf_Num(Tree->right);
    }
    //    获取树高的函数定义
    int Get_Height(PTREE Tree) {
        int Height = 0;
        if (Tree == NULL)
            return 0;
    
        //树的高度 = max(左子树的高度,右子树的高度) + 1
        else
        {
            int L_Height = Get_Height(Tree->left);
            int R_Height = Get_Height(Tree->right);
            Height = L_Height >= R_Height ? L_Height + 1 : R_Height + 1;
        }
        return Height;
    }

  • 相关阅读:
    无题
    生活真像小说
    草样年华
    Intentional Programming
    厌倦说话
    解释 Intentional Programming
    开始折腾iphone cdma 恢复,降级,刷机,越狱,手编,写号
    新手如何成为更好的图形设计师
    Grunt.js 初使用
    有抱负的程序员应看的10个TED演讲
  • 原文地址:https://www.cnblogs.com/xinmomoyan/p/10726396.html
Copyright © 2011-2022 走看看