二叉树 的一些性质 和 各种遍历 (划划水 萌新 大佬勿喷 以及度娘真好用

树(懒得打字直接放图    (

以下部分来自百度百科

二叉树

在计算机科学中,二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(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个节点的二叉树,称为满二叉树。这种树的特点是每一层上的节点数都是最大节点数。而在一棵二叉树中,除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则此二叉树为完全二叉树。具有n个节点的完全二叉树的深度为log2n+1。深度为k的完全二叉树,至少有2^(k-1)个节点,至多有2^k-1个节点。
二叉树是递归定义的,其结点有左右子树之分,逻辑上二叉树有五种基本形态:
(1)空二叉树——如图(a);
(2)只有一个根结点的二叉树——如图(b);
(3)只有左子树——如图(c);
(4)只有右子树——如图(d);
(5)完全二叉树——如图(e)。
注意:尽管二叉树与树有许多相似之处,但二叉树不是树的特殊情形。

类型

(1)完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
(2)满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
(3)平衡二叉树——平衡二叉树又被称为AVL树(区别于AVL算法),它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

相关术语

树的结点:包含一个数据元素及若干指向子树的分支;
孩子结点:结点的子树的根称为该结点的孩子;
双亲结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲;
兄弟结点:同一双亲的孩子结点; 堂兄结点:同一层上结点;
祖先结点: 从根到该结点的所经分支上的所有结点子孙结点:以某结点为根的子树中任一结点都称为该结点的子孙
结点层:根结点的层定义为1;根的孩子为第二层结点,依此类推;
树的深度:树中最大的结点层
结点的度:结点子树的个数
树的度: 树中最大的结点度。
叶子结点:也叫终端结点,是度为 0 的结点;
分枝结点:度不为0的结点;
有序树:子树有序的树,如:家族树;
无序树:不考虑子树的顺序;

二叉树性质

(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. 树中结点的最大度数没有限制,而二叉树结点的最大度数为2;
2. 树的结点无左、右之分,而二叉树的结点有左、右之分。

各种遍历(没有线索二叉树)
先/前序遍历
首先访问根,再先序遍历左(右)子树,最后先序遍历右(左)子树,C语言代码如下:
void QWE1 ( tree * a )
{
   
printf ( "%c" , a -> a );//此时a结点中存的字符可以理解为根
   
if ( a -> ltree !=NULL )
       
QWE1 ( a -> ltree );//a的左子树
   
if ( a -> rtree !=NULL )
       
QWE1 ( a -> rtree );//a的右子树
}
中序遍历
首先中序遍历左(右)子树,再访问根,最后中序遍历右(左)子树,C语言代码如下
void QWE2 ( struct qwe * a )
{
   
if ( a -> ltree != 0 )
       
QWE2 ( a -> ltree ); //a的左子树

   
printf ( "%c" , a -> a ); //此时a结点中存的字符可以理解为根

   
if ( a -> rtree != 0 )
       
QWE2 ( a -> rtree );//a的右子树
}
后序遍历
首先后序遍历左(右)子树,再后序遍历右(左)子树,最后访问根,C语言代码如下
void QWE3 ( struct qwe * a )
{
   
if ( a -> ltree != 0 )
       
QWE3 ( a -> ltree );//a的左子树

   
if ( a -> rtree != 0 )
       
QWE3 ( a -> rtree );//a的右子树

   
printf ( "%c" , a -> a );//此时a结点中存的字符可以理解为根
}

层次遍历
即按照层次访问,通常用队列来做。访问根,访问子女,再访问子女的子女(越往后的层次越低)(两个子女的级别相同)
//先输出第一个根节点的东西之后调用函数
void QWE4 ( struct qwe * a )
{
   
if ( a -> ltree != 0 )
       
printf ( "%c" , a -> ltree -> a );//a的左子树
   
if ( a -> rtree != 0 )
       
printf ( "%c" , a -> rtree -> a );//a的右子树
   
if ( a -> ltree != 0 )
       
QWE4 ( a -> ltree );//a的左子树
   
if ( a -> rtree != 0 )
       
QWE4 ( a -> rtree ); //a的右子树
}

二叉树的构建

    一般的是用递归函数调用  其实如果是满二叉树数组也可以  就是1->2,3;2->4,5;3->6,7,,,,,,i->2*i,2*i+1;

//一般的

tree* QWE()
{
   
char a;
    tree
*t;
    t
=NULL;
    t
=new tree();//new是自动配适返回类型
   
scanf("%c",&a);
    t
->a=a;
   
if(a=='#')
       
return 0;
   
else
   
{ t->ltree=QWE();
        t
->rtree=QWE();
       
return t;
   
}
};//先序遍历构建的(多组输入int o=0,d;
tree* QWE(char *q)
{
   
char a;
   
tree *t;
    t
=NULL;
    t=new tree();//new是自动配适返回类型
    t
->a=*(q+o);
   
if(t->a=='#')
    
{
         d
--;
       
return 0;
    
}
   
else
   
{
        t
->c=d;
        o
++;
        t
->ltree=QWE(q);
        o
++;
        t
->rtree=QWE(q);
       
return t;
   
}
};

//加个题  划一划水   面的看不懂代码  SDIBT 2749

二叉树操作
Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%lld & %lld

Description

根据给定的字符串生成二叉树并前序、中序、后序此二叉树。

Input

给定一字符串,其中#表示空。

例:上图输入为

HDB#A##C##G#FE###

Output

分别输出此二叉树前序、中序和后序。

Sample Input

HDB#A##C##G#FE###

Sample Output

HDBACGFE
BADCHGEF
ABCDEFGH

Hint

做完的同学还可以线索化二叉树后再进行先序、中序和后序遍历。

//

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<deque>
#include<stack>
#include<queue>
#include<algorithm>
#include<math.h>
#include<deque>
using namespace std;
struct qwe{
    char a;
    struct qwe *ltree;
    struct qwe *rtree;
};
struct qwe *A;
struct qwe* QWE()
{
    char a;
    struct qwe *t;
    t=NULL;
    t=new struct qwe();
    scanf("%c",&a);
    t->a=a;
    if(a=='#')
        return 0;
    else
    {
        t->ltree=QWE();
        t->rtree=QWE();
        return t;
    }
};
void QWE1(struct qwe *a)
{
    printf("%c",a->a);
    if(a->ltree!=0)
        QWE1(a->ltree);
    if(a->rtree!=0)
        QWE1(a->rtree);
}
void QWE2(struct qwe *a)
{
    if(a->ltree!=0)
        QWE2(a->ltree);

    printf("%c",a->a);

    if(a->rtree!=0)
        QWE2(a->rtree);
}
void QWE3(struct qwe *a)
{
    if(a->ltree!=0)
        QWE3(a->ltree);

    if(a->rtree!=0)
        QWE3(a->rtree);

    printf("%c",a->a);
}
int main()
{
    int b,c,d,i,j,k;
    struct qwe *a;
    a=new struct qwe();
    a=QWE();
    QWE1(a);
    printf("\n");
    QWE2(a);
    printf("\n");
    QWE3(a);
    printf("\n");
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_41886199/article/details/80501114