博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

06数据结构——树

Posted on 2019-04-17 21:44  心默默言  阅读(206)  评论(0编辑  收藏  举报

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:\n",MAX_TREE_SIZE);
    while(i<10)
    {
        T[i]=i+1;
        
        if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil) /* 此结点(不空)无双亲且不是根 */
        {
            printf("出现无双亲的非根结点%d\n",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("\n");
    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("\n");
    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("\n");
    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("\n");
}

/* 逐层、按本层序号输出二叉树 */
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("\n");
    }
}


int main()
{
    Status i;
    Position p;
    TElemType e;
    SqBiTree T;
    InitBiTree(T);
    CreateBiTree(T);
    printf("建立二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));
    i=Root(T,&e);
    if(i)
        printf("二叉树的根为:%d\n",e);
    else
        printf("树空,无根\n");
    printf("层序遍历二叉树:\n");
    LevelOrderTraverse(T);
    printf("前序遍历二叉树:\n");
    PreOrderTraverse(T);
    printf("中序遍历二叉树:\n");
    InOrderTraverse(T);
    printf("后序遍历二叉树:\n");
    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("前序遍历二叉树:\n");
    PreOrderTraverse(T);
    printf("结点%d的双亲为%d,左右孩子分别为",e,Parent(T,e));
    printf("%d,%d,左右兄弟分别为",LeftChild(T,e),RightChild(T,e));
    printf("%d,%d\n",LeftSibling(T,e),RightSibling(T,e));
    ClearBiTree(T);
    printf("清除二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));
    i=Root(T,&e);
    if(i)
        printf("二叉树的根为:%d\n",e);
    else
        printf("树空,无根\n");
    
    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("\n前序遍历结果为:");
    PreOrderTree(Root);
    printf("\n中序遍历结果为:");
    InOrderTree(Root);
    printf("\n后序遍历结果为:");
    PostOrderTree(Root);
    printf("\n打印叶子节点为:");
    LeafOfTree(Root);
    printf("\n叶子节点个数为:%d", Get_Leaf_Num(Root));
    printf("\n二叉树的高度为:%d", Get_Height(Root));
    printf("\n");

    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;
}