基本概念

  1. 根节点
  2. 内部节点
  3. 叶节点
  4. 相交
  5. 孩子
  6. 双亲
  7. 兄弟
  8. 度:树各个节点度的最大值
  9. 深度或高度
  10. 森林

树的存储结构

双亲表示法

以一组连续空间存储树的节点,在每个节点中,附设一个指示器指示其双亲节点到链表中的位置。

#define MAX_TREE_SIZE 100
typedef int TElemType;
typedef struct
{
    TElemType data; /* 节点数据 */
    int parent; /* 双亲位置 */
} PTNode;
typedef struct
{
    PTNode nodes[MAX_TREE_SIZE]; /* 节点数组 */
    int r, n; /* 根的位置和节点数 */
} PTree;

孩子表示法

每个节点有多个指针域,其中每个指针指向一棵子树的根节点,我们把这种方法叫做多重链表表示法。

方案一

指针域的个数等于树的度。

缺点:对于树中各节点的度相差很大时,比较浪费空间,因为很多节点的指针域是空的。

方案二

每个节点指针域的个数等于该节点的度,专门取一个位置来存储节点指针域的个数。

缺点:各个节点的链表是不相同的结构,加上需要维护节点度的数值,在运算上会带来时间上的损耗。

孩子表示法概念

把每个节点的孩子节点排列起来,以单链表作存储结构,则n个节点有n个孩子链表,如果是叶子节点则此单链表为空。然后n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中。

#define MAX_TREE_SIZE 100
typedef struct CTNode /* 孩子节点 */
{
    int child; /* 节点下标 */
    struct CTNode *next;
} *ChildPtr;

typedef struct /* 表头结构 */
{
    TElemType data;/* 节点数据 */
    ChildPtr firstChild;
} CTBox;

typedef struct /* 树结构 */
{
    CTBox nodes[MAX_TREE_SIZE]; /* 节点数组 */
    int r, n; /* 根的位置和节点数 */
} CTree;

上述结构对于查找某个节点的孩子、兄弟只需要查找这个节点的孩子单链表即可。对于遍历整棵树只需要对节点的数组循环即可。

对于查找某个节点的双亲是比较麻烦的,需要遍历整棵树。那么在CTBox结构中加入一个parent字段,这就是改进版的孩子表示法,我们把这种方法叫做双亲孩子表示法

孩子兄弟表示法

任意一棵树,它的节点第一个孩子如果存在就是唯一的,它的右兄弟如果存在也是唯一的。因此,我们设置两个指针,分别指向该节点的第一个孩子和此节点的右兄弟。

/* 树的孩子兄弟表示法结构定义*/
typedef struct CSNode
{
    TElemType data;
    struct CSNode *firstChild, *rightSib;
} CSNode, *CSTree;

孩子兄弟表示法的最大好处就是通过变形,它把一颗复杂的树变成了一棵二叉树

二叉树

定义

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

特点

  1. 每个节点最多两棵子树,不存在度大于2的节点。
  2. 左子树和右子树是有序的。
  3. 即使树中某节点只有一棵子树,也要区分它是左子树还是右子树。

基本形态

  1. 空二叉树
  2. 只有一个根节点
  3. 根节点只有左子树
  4. 根节点只有右子树
  5. 根节点既有左子树又有右子树

特殊二叉树

斜树

所有的节点都只有左子树的二叉树叫做左斜树。所有节点都只有右子树的二叉树叫做右斜树。这两者统称为斜树。

满二叉树

在一棵二叉树中,如果所有分支节点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。

完全二叉树

对一棵具有n个节点的二叉树按层序编号,如果编号为i(1<=i<=n)的节点与同样深度的满二叉树中编号为i的节点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树。

二叉树性质

结论

  1. 在二叉树的第i层上至多有(2^i-1)个节点(i>=1)
  2. 深度为k的二叉树至多有(2^k)-1个节点(k>=1)
  3. 对任何一棵二叉树T,如果其终端(叶子)节点数为n0,度为2的节点数为n2,则n0 = n2 + 1
  4. 具有n个节点的完全二叉树的深度为[logn] + 1([x]表示不大于x的最大整数所有log都是以2为底数,下文都是如此)
  5. 如果对一棵有n个节点的完全二叉树(其深度为[logn]+1)的节点按层序编号(从第1层到第[logn]+1层,每层从左到右),对任一节点i(1<=i<=n)有:
    1> 如果i=1,则节点i是二叉树的根,无双亲;如果i>1,则其双亲是节点[i/2]
    2> 如果2i>n,则节点i无左孩子(节点i为叶子节点);否则其左孩子是节点2i
    3> 如果2i+1>n,则节点i无有孩子;否则其右孩子是节点2i+1

推理

二叉树第1层有2^0个节点
二叉树第2层有2^1个节点
根据数学归纳法可知二叉树第i层有(2^i-1)个节点

深度为1的二叉树至多有2^0个节点
深度为2的二叉树至多有2^0 + 2^1个节点
根据等差数列求和可知深度为k的二叉树至多有(2^k)-1个节点(k>=1)

树T节点总数为:n = n0(叶子) + n1(度为1) + n2(度为2)
树T分支线总数为:n - 1 = n1 + 2n2
由上述可以推导出:n0 = n2 + 1

根据满二叉树定义可知,深度为k的满二叉树的节点数为n = (2^k)-1,则可推出完全二叉树的节点数n <= (2^k)-1。由于完全二叉树
的叶子节点只会出现在最下面的两层,那么n>(2k-1)-1。又由于n是整数,则(2k-1) =< n < (2^k)。等式两边取对数可知,k-1 =< logn < k,因此深度k为logn + 1且k为整数。

二叉树存储结构

二叉树顺序存储结构

二叉树顺序存储结构就是用一维数组存储二叉树中的节点,并且节点的存储位置即是数组的下标要能体现节点之间的逻辑关系。顺序存储结构一般只用于完全二叉树。

二叉树链式存储结构

二叉树每个节点最多有两个孩子,每个节点由一个数据域和两个指针域组成,这样的链表我们称为二叉链表。结构定义如下所示:

typedef struct BiTNode
{
    TElemType data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
左孩子指针 数据域 右孩子指针
lchild data rchild

二叉树遍历

二叉树遍历(traversing binary tree):指从根节点出发,按照某种次序依次访问二叉树中所有节点,使得每个节点有且仅被访问一次。

二叉树遍历方法

前序遍历

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

中序遍历

若二叉树为空,则空操作返回,否则从根节点开始,中序遍历根节点的左子树,然后才是访问根节点最后中序遍历右子树

后序遍历

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

层序遍历

若树为空,则空操作返回,否则从树的第一层,也就是根节点开始访问,从上而下逐层遍历,在同一层中,从左到右的顺序对节点逐个访问

二叉树遍历性质

  • 已知前序遍历序列和中序遍历序列,可以唯一确定一棵二叉树。
  • 已知后序遍历序列和中序遍历序列,可以唯一确定一棵二叉树。

二叉树建立

将二叉树中每个节点的空指针引出一个虚节点,其值为一特定值(如:'#'),我们称这种处理后的二叉树为原二叉树的扩展二叉树。扩展二叉树可以做到一个遍历序列确定一棵二叉树。

/* 输入前序遍历的扩展二叉树方式来创建二叉树 */
void CreateBiTree(BiTree *T)
{
    ElemType ch;
    cin >> ch;
    if ('#' == ch)
    {
        *T = NULL;
    }
    else
    {
        *T = (BiTree) malloc(sizeof(BiTNode));
        if (!*T)
        {
            exit(OVERFLOW);
        }
        (*T)->data = ch;
        CreateBiTree(&(*T)->lchild);
        CreateBiTree(&(*T)->rchild);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容

  • 树的概述 树是一种非常常用的数据结构,树与前面介绍的线性表,栈,队列等线性结构不同,树是一种非线性结构 1.树的定...
    Jack921阅读 4,452评论 1 31
  • 二叉树的定义#### 二叉树是n(n>=0)个具有相同类型的元素的有限集合,当n=0时称为空二叉树,当n>0时,数...
    kylinxiang阅读 1,394评论 0 2
  • 四、树与二叉树 1. 二叉树的顺序存储结构 二叉树的顺序存储就是用数组存储二叉树。二叉树的每个结点在顺序存储中都有...
    MinoyJet阅读 1,528评论 0 7
  • 前面讲到的顺序表、栈和队列都是一对一的线性结构,这节讲一对多的线性结构——树。「一对多」就是指一个元素只能有一个前...
    Alent阅读 2,237评论 1 28
  • 认知UI设计师 UI表面上看是用户与界面两个组成部分,但实际上还包...
    设计师杨先生阅读 3,106评论 1 7