二叉树的基本操作(定义、遍历、高度、生成)【数据结构】

二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。
二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2^{i-1}个结点;深度为k的二叉树至多有2^k-1个结点;对任何一棵二叉树T,如果其终端结点数为n_0,度为2的结点数为n_2,则n_0=n_2+1。
一棵深度为k,且有2^k-1个节点称之为满二叉树;深度为k,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中,序号为1至n的节点对应时,称之为完全二叉树。
(1)完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
(2)满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
(3)平衡二叉树——平衡二叉树又被称为AVL树(区别于AVL算法),它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

二叉树性质

(1) 在非空二叉树中,第i层的结点总数不超过
 , i>=1;
(2) 深度为h的二叉树最多有
 个结点(h>=1),最少有h个结点;
(3) 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
(4) 具有n个结点的完全二叉树的深度为
(5)有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:
若I为结点编号则 如果I>1,则其父结点的编号为I/2;
如果2*I<=N,则其左儿子(即左子树的根结点)的编号为2*I;若2*I>N,则无左儿子;
如果2*I+1<=N,则其右儿子的结点编号为2*I+1;若2*I+1>N,则无右儿子。
(6)给定N个节点,能构成h(N)种不同的二叉树。
h(N)为卡特拉数的第N项。h(n)=C(2*n,n)/(n+1)。
(7)设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和J=I+2i

二叉树的存储结构

(1). 顺序存储结构
#define MaxSize 100
    typedef struct{
    DataType bt[MaxSize];
        int btnum;
    }Btseq;

(2). 链式存储结构
typedef struct Node{
   DataType Data;
      struct Node *Left, *Right;
   }BinTree;


//===================================================
//define a Bintree
struct BinTree{
    ElementType Data;
    BinTree *Left;
    BinTree * Right;
}
//===================================================

//中序递归遍历
void InOrderTraversal(BinTree BT){
    if(!IsEmpty(BT)){
        InOrderTraversal(BT->Left);
        printf("%d", BT->Data);
        InOrderTraversal(BT->Right);
    }
}
//===================================================

//中序非递归遍历
void InOrderTraversal(BinTree BT){
    BinTree T;
    Stack S = CreateStack(MaxSize);
    
    T =BT;
    while(T || !IsEmpty(S)){
        while(T){
            Push(S, T);
            T = T->Left;
        }
        if(!IsEmpty(S)){
            T = Pop(S);
            printf("%d", T->Data);
            T = T->Right;
        }
    }
}
//====================================================

//先序递归遍历
void PreOrderTraversal(BinTree BT){
    if(BT){
        printf("%d", BT->Data);
        PreOrderTraversal(BT->Left);
        PreOrderTraversal(BT->Right);
    }
}
//====================================================

//先序非递归遍历
void PreOrderTraversal(BinTree BT){
    BinTree T = BT;
    Stack S;
    while(T || !IsEmpty(S)){
        while(T){
            printf("%d", T->Data);
            Push(S, T);
            T = T->Left;
        }
        if(!IsEmpty(S)){
            T = Pop(S);
            T = T->Right;
        }
    }
}
//====================================================

//后序递归遍历
void PostOrderTraversal(BinTree BT){
    if(BT){
        PostOrderTraversal(BT->Left);
        PostOrderTraversal(BT->Right);
        printf("%d", BT->Data);
    }
}
//=====================================================

//后续非递归遍历
void PostOrderTraversal(BinTree BT){
    BinTree T = BT;
    Stack S1 = CreateStack(MaxSize);
    Stack S2 = CreateStack(MaxSize);  /*创建并初始化堆栈S1,S2*/
    while(T || !IsEmpty(S1) || !IsEmpty(S2)){
        while(T){  /*一直向左并将沿途结点压入堆栈*/
            Push(S1, T);
            T = T->Left;
        }
        if(!IsEmpty(S1)){
            T = Pop(S1); /*结点弹出堆栈1*/
            Push(S2,T);
            T = T->Right; /*转向右子树*/
            if(!T && !IsEmpty(S2)){
                T = Pop(S2); /*结点弹出堆栈2*/
                printf(“%d\n”, T->Data); /*(访问) 打印结点*/
            }
        }
    }
}

//递归求树的高度 Method 1:
int max1 = 0;
void BT_Depth1(BinTree BT, int depth){
    if(BT){
        if(BT->Left)
            BT_Depth1(BT->Left, depth+1);
        if(BT->Right)
            BT_Depth1(BT->Right, dep+1);
    }
    if(depth > max1)
        max1 = depth;
    return max1;
}

//递归求树的高度Method 2
void Height(BinTree BT){
    if(BT){
        int m = Height(BT->Left);
        int n = Height(BT->Right);
        return (m>n) ? (m+1) : (n+1);
    }
}
//======================================================

//层序遍历
//1. 先根结点入队,然后从队列中取出一个元素
//2. 访问该元素所指结点
//3. 若该元素所指结点的左、右孩子结点非空,则将其左、右孩子的指针顺序入队
void LevelOrderTraversal(BinTree T){
    Queue Q;
    BinTree T = BT;
    if(!BT)
        return;
    Q = CreateQueue(MaxSize);
    AddQ(Q, BT);
    while(!IsEmptyQ(Q)){
        T = DeleteQ(Q);
        printf("%d\n", T->Data);
        if(T->Left)
            AddQ(Q, T->Left);
        if(T->Right)
            AddQ(Q, T->Right);
    }
}
//=============================================================

//层序生成二叉树
BinTree CreateBinTree(){
    int Data;
    BinTree BT, T;
    Queue Q = CreateQueue(MaxSize);
    scanf("%d", &Data);
    if(!Data)
        return NULL;
    else{
        BT = (BinTree)malloc(sizeof(BinTree));
        BT->Data = Data;
        AddQ(Q, BT);
    }
    while(!IsEmptyQ(Q)){
        T = Delete(Q);
        scanf("%d", &Data);
        if(!Data)
            T->Left = NULL;
        else{
            T->Left = (BinTree)malloc(sizeof(BinTree));
            T->Left->Data = Data;
            AddQ(Q, T->Left);
        }
        scanf("%d", &Data);
        if(!Data)
            T->Right = NULL;
        else{
            T->Right = (BinTree)malloc(sizeof(BinTree));
            T->Right->Data = Data;
            AddQ(Q, T->Right)
        }
    }
    return BT;
}
//================================================================











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值