zoukankan      html  css  js  c++  java
  • 第五章 树和二叉树

                   上章回顾

    单链表的基本操作,包括插入、删除以及查找

    双向链表和循环链表的区别

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                 第五章

    第五章

    树和二叉树 树和二叉树

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                    预习检查

    什么是二叉树

    树的遍历有哪几种方式

    树有哪些应用

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                       本章结构

    树和二叉树

    树和二叉树 二叉树

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    树的逻辑结构和存储结构 树的逻辑结构和存储结构

    二叉树

    遍历二叉树 遍历二叉树

                    课程目标

    了解树的定义和基本术语

    了解二叉树的定义、性质、和存储结构

    掌握二叉树的遍历

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 5

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                      5.1 树的逻辑结构和存储结构 5.1.1树型结构实例

    1.家族树

    祖父

    2011-11-13

    6

    伯父 父亲 叔父

    家族关系表示: R={<祖父,伯父>,<祖父,父亲>,<祖父,叔父>,

    堂兄 堂姐 侄儿

    本人 堂弟

    <伯父,堂兄>,<伯父,堂姐>,<父亲,本人>, <叔父,堂弟>,<堂兄,侄儿>}

    (b) 家族谱系的关系表示 图5-1家族树

    (a) 家族树

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                            5.1 书的目录结构 2.书的目录结构

    线性表和广义表 栈和队列 树 图 线性表广义表栈 队列树 二叉树

    ......

    数据结构

    5-2书的目录

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 7

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                 5.1 树的逻辑结构和存储结构 5.1.2树的定义

    1.树的定义

    树(Tree)是n (n≥0)个结点的有限集(记为T),T为空时称为空树,

    否则它满足以下两个条件:

    (1) 有且仅有一个结点没有前驱,称该结点为根结点(Root);

    (2) 除根结点以外,其余结点可分为m(m≥0)个互不相交的有限集合 T0,Tl,...,Tm-1。其中每个集合又构成一棵树,树T0,Tl ,...,Tm-

    1被称为根结点的子树(SubTree)。每棵子树的根结点有且仅有一个直接 前驱,但可以有0个或多个后继。

    树的逻辑结构表示数据之间的关系是一对多,或者多对一的关系。 它的结构特点具有明显的层次关系,是一种十分重要的非线性的数据结

    构。

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 8

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                       (a)只有根结点的树

    (b)有12个结点的树

    T A

    A

    T1B CT2D

    T3

    5-3树的示例

    5-3(a)是一棵只有一个根结点的树;

    L}A是根,除根结点A之外,其余的11个结点分为三个互不相

    交的集合。T1,T2和T3是根A的三棵子树,且本身又都是一棵

    树。所以树的定嵌入义式是家递园归www.embedclub.com git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 9

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    EGHJK FIL

    5-3(b)是一棵有12个结点的树,即T={A,B,C,...,K,

                 2.树的基本术语

    树的结点包含一个数据元素及若干指向其子树的分支。

    1. 树的结点:包含一个数据元素和指向其子树的所有分支;

    2. 结点的度:一个结点拥有的子树个数,度为零的结点称为叶子; 3. 树的度:树中所有结点的度的最大值 Max(D(I))

    含义:树中最大分支数为树的度;

    4. 结点的层次及树的深度:根为第一层,根的孩子为第二层,若某结 点为第k层,则其孩子为k+1层.

    树中结点的最大层次称为树的深度或高度 5.森林:是m(m≥ 0)棵互不相交的树的集合

    森林与树概念相近,相互很容易转换.

    6.有序树、无序树 如果树中每棵子树从左向右的排列拥有一定的

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git顺序,不得互换,则称为有序树,否则称为无序树。

    2011-11-13 10

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                 7.森林: 是m(m≥0)棵互不相交的树的集合。 在树结构中,结点之间的关系又可以用家族关系描述,定义如

    下:

    8.孩子、双亲: 结点子树的根称为这个结点的孩子,而这个结点又 被称为孩子的双亲。

    9.子孙: 以某结点为根的子树中的所有结点都被称为是该结点的子 孙。

    10.祖先: 从根结点到该结点路径上的所有结点。

    11.兄弟: 同一个双亲的孩子之间互为兄弟。

    12.堂兄弟: 双亲在同一层的结点互为堂兄弟。 git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 11

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                 3.树的基本运算 树的基本运算主要有:

    1. 初始化操作INITIATE(T):创建一棵空树。

    2. 求根函数ROOT(T):求树T的根;ROOT(X):求结点x所在树的

    根。

    3. 求双亲函数PARENT(T,x):在树T中求x的双亲。

    4. 求第i个孩子函数CHILD(T,x,i):在树T中求结点x的第i个孩 子。

    5. 建树函数CREATETREE(x,F):建立以结点x为根,森林F为子 树的树。

    6.遍历树操作TRAVERSE(T):按顺序访问树T中各个结点。 git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 12

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                         5.1.3 树的表示

    树的逻辑表示方法有多种,常见的有 : 1. 树形图表示法

    2. 嵌套集合表示法(文氏图表示法) 3. 凹入表示法

    A

    B

    4. 广义表表示法

    EB HDK G

    E

    F

    (a) 嵌套集合表示法

    K

    L

    A

    FIL J

    G C

    D CH

    (A(B(E(F),G),C,D(H(I),J,K(L))) (c) 广义表表示法

    (b)凹入表示法

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 13

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    I J

                                          5.1.4 树的存储结构

    和线性表一样,树可以用顺序和链式两种存储结构。 树的顺序存储结构适合树中结点比较的情况。根据树的非线性

    结构特点,常用链式存储方式来表示树。树常用的存储方法有:双亲存 储表示法、孩子链表表示法和孩子兄弟链表表示法。

    1.双亲存储表示法 一般采用顺序存储结构实现。用一组地址连续的存储单元来存放树

    的结点,每个结点有两个域: data域-----存放结点的信息; parent域-----存放该结点双亲结点的位置

    序号 data parent 0 A -1

    A 特点:求结点的双 B C

    1 2C0

    亲很容易,但求结 D E F G 点的孩子需要遍历

    D1

    整个向量。

    HI

    2011-11-13

    14

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git(a) 树

    (b)树的双亲存储结构

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    B0

    3 4E1 5F1 6G2 7H4 8I4

                 存储结构描述为:

    #define MaxTreeSize 100 //定义数组空间的大小 typedef char DataType; //定义数据类型 typedef struct

    {

    的位置

    PTree T;

    //T是双亲链表 git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13

    15

    DataType data; int parent;

    //结点数据 //双亲位置域,指示结点的双亲在数组中

    } PTreeNode; typedef struct {

    PTreeNode nodes[MaxTreeSize];

    int n; //结点总数 } PTree;

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                                          2.孩子链表表示法 这是树的链式存储结构。每个结点的孩子用单链表存储,称为孩子链表。

    n个结点可以有n个孩子链表(叶结点的孩子链表为空表)。 n个孩子链表的头指针用一个向量表示。

    B DEF G

    C

    B C∧ D∧

    (a) 树

    (b)树的孩子存储结构 图5-4树的孩子链表结构

    特点:与双亲相 反,求孩子易,求 双亲难。

    A0A

    1

    1

    2

    3

    4E 5F∧ 6G∧

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    16

    2011-11-13

    头指针向量 孩子链表

    2∧ 345∧

    6∧

                 孩子链表表示法的类型说明 typedef struct CNode {

    //DataTypeMaxTreeSize由用户定义 //孩子链表结点

    typedef struct

    {

    typedef struct

    {

    Ctree T;

    //T的孩子链表表示 git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13

    17

    int child;

    //孩子结点在数组中对应的下标 //孩子链表头结点

           struct CNode *next;

    } CNode;

    DataType data;

    //存放树中结点数据 //孩子链表的头指针

           CNode *firstchild;

    } PTNode;

    PTNode nodes[MaxTreeSize];

    int n,root; //树的结点数和根结点的位置 } Ctree;

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                              3.孩子兄弟链表表示法

    孩子兄弟链表表示法也是树的一种链式存储结构。用二叉链表作为 树的存储结构,每个结点的左链域指向该结点的第一个孩子,右链域指 向下一个兄弟结点。

    由于结点中的两个指针指示的分别为孩子兄弟,故称为孩 子-兄弟链表。这种结构也称为二叉链表。

    A∧ B∧C∧

    特点:双亲只管长子

    长子连接兄弟

    ∧DE∧F∧ ∧G∧

    5-5树的孩子-兄弟存储结构 git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 18

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                 树的孩子兄弟链表的存储结构描述为: typedefstructCSNode

    {

    ElemTypedata;

    structCSNode*firstchild,*nextsibling;}CSNode,*CSTree;

    孩子兄弟存储结构的最大优点是可以方便地实现树和二叉树

    的相互转换和树的各种操作。但是,孩子兄弟存储结构的缺点也

    是查找当前结点的双亲结点比较麻烦,需要从树根结点开始逐个 结点比较查找。

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 19

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                 5.1.5 树的遍历 1.树的遍历

    所谓树的遍历,就是按照某种顺序依次访问树中各个结点,并 使得每个结点只被访问一次。也就是把非线性结构的树结点变成 线性序列的一种方式 。

    树的遍历可以按深度优先遍历,也可以按照广度优先(按层 次)遍历。深度优先遍历通常有两种方式:前序遍历和后序遍 历。

    (1)前序遍历的递归定义:

    若树T非空,则:

    访问根结点R;

    按照从左到右的顺序依次前序遍历根结点R的各子树T, 1

    T,...,T2k

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    20

    2011-11-13

                 (2) 后序遍历的递归定义:

    若树T非空,则: 按照从左到右的顺序依次后序遍历根T的各子树Tl,T2,...,Tk; 再访问根结点R

    (3) 广度优先(按层)遍历

    广度优先(按层次)遍历定义为:先访问第一层结点(即树根结点), 再从左至右访问第二层结点,依次按层访问......,直到树中结点全部被 访问为止。对图6-6(a)中的树进行按层次遍历得到树的广度优先遍历序 列为:ABCDEFG

    说明:

    1 前序遍历一棵树恰好等价于前序遍历该树所对应的二叉树。(6.2节将介绍二叉树)

    2 后序遍历树嵌恰入好式等家价园于中www.embeedcclub.com应的二叉树。

    2011-11-13 21

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                 树的先序遍历算法描述如下:

    void Preorder(Btree *root) //先根遍历k叉树

    { if (root!=NULL)

      {

    个子结点

    } }

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    printf(%c ,root->data); //访问根结点 for(i=0;i<k;i++)

    Preorder(root->t[i]); //递归前序遍历每一

    2011-11-13 22

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                 5.2 二叉树 5.2.1二叉树的定义与性质

    二叉树(Binary Tree)是另一种重要的树型结构。是度为2的

    有序树,它的特点是每个结点至多有两棵子树。和树结构的定义 类似,二叉树的定义也可以用递归形式给出。

    1.二叉树的递归定义

    二叉树(BinaryTree)是n(n≥0)个结点 的有限集。它或者是空

    集(n=0),或者同时满足以下两个条件:

    (1) 有且仅有一个根结点;

    (2) 其余的结点分成两棵互不相交的左子树和右子树。

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 23

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                       二叉树与树有区别:树至少应有一个结点,而二叉树可以为空;树 的子树没有顺序,但如果二叉树的根结点只有一棵子树,必须明确区分 它是左子树还是右子树,因为两者将构成不同形态的二叉树。因此,二 叉树不是树的特例。它们是两种不同的数据结构。

    二叉树有5种基本形态:

    (a) (b) (c) (d) (e)

    (a) 空二叉树 (b) 只有根结点的二叉树 (c) 右子树为空的二叉树

    (d)左子树为空的二叉树 (e)左右子树均不为空的二叉树 图5-7二叉树的五种基本形态

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 24

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                 两种特殊形态的二叉树:满二叉树和完全二叉树。 (1) 满二叉树(FullBinaryTree)

    深度为k,且有2k-1个结点的二叉树。 特点:(1)每一层上结点数都达到最大

    (2)度为1的结点n1=0,树叶都在最下一层上。 结点层序编号方法:从根结点起从上到下逐层(层内从左到右)对二叉树的

    结点进行连续编号。 1 K=3 n=23-1=7

    23 4567

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    满二叉树

    2011-11-13 25

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                     (2) 完全二叉树(Complete BinaryTree) 深度为k,结点数为n的二叉树,当且仅当每个结点的编号都与相同

    深度的满二叉树中从1到n的结点一一对应时,称为完全二叉树。

    完全二叉树的特点:

    4

    3 5

    1 2

    图5-8 完全二叉树

    (1)每个结点i的左子树的深度Lhi - 其结点i的右子树的深度Rhi 等于0或1; 叶结点只可能出现在层次最大或次最大的两层上。

    (2)完全二叉树结点数n满足2k-1-1<n≤2k-1 git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    (3)满二叉树一定是完全二叉树,反之不成立。

    2011-11-13 26

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                       LH2=0 RH2=1

    11

    LH1=3 RH1=1

    LH2-RH2=0-1=-1

    4

    5

    LH1 -RH1=2

    2

    3

    2

    3

    4

    非完全二叉树

    非完全二叉树

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    27

    2011-11-13

    6

                 2.二叉树的性质

    性质1 在二叉树的第i层上至多有2i-1 个结点(i≥1)。 性质2 深度为k的二叉树至多有2k-1个结点(k≥1)。

    (深度一定,二叉树的最大结点数也确定)

    性质3 二叉树中,终端结点数n0与度为2的结点数n2有如下关系:

    n0=n2+1

    性质4 结点数为n的完全二叉树,其深度为 ⎣log2n⎦ + l

    性质5 在按层序编号的n个结点的完全二叉树中,任意一结点 i(1≤i≤n)有:

    (1) i=1时,结点i是树的根;否则,结点i的双亲为结点 ⎣ i/2 ⎦ (i>1) 。

    (2) 2i>n时,结点i无左孩子,为叶结点;否则,结点i的左孩子为结 点2i。

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    (3) 2i+1>n时,结点i无右孩子;否则,结点i的右孩子为结点2i+1。

    2011-11-13 28

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                               5.2.2 二叉树的存储结构

    同线性表一样,二叉树的存储结构也有顺序和链表两种结构。

    1.顺序存储结构 用一组地址连续的存储单元,以层序顺序存放二叉树的数据元

    素, 结点的相对位置蕴含着结点之间的关系。

    完全二叉树

    1 2 3 4567891011 ABCDEFG0000

    A BC

    DEFG

    即在bt[1]中;

    bt[3]的双亲为⎣3/2⎦ =1,

    其左孩子在bt[2i]=bt[6]中;

    其右孩子在bt[2i+1]=bt[7]中。 git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 29

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                      一般二叉树也按完全二叉树形式存储,无结点处用0表示。

    二叉树

    A BC

    D

    E FG

    12 3456789101112

    ABCDE0 0 0 0 FG0 0 0 0

    这种存储结构仅适合于完全二叉树,既不浪费存储空间,又 能很快确定结点的存放位置、结点的双亲和左右孩子的存放位 置,但对一般二叉树,可能造成存储空间的大量浪费。

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    2011-11-13 30

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                  例如:深度为k,且只有k个结点的右单枝树( 每个非叶结点只有右孩 子),需2k-1个单元,即有2k-1-k个单元被浪费。

    2. 链式存储结构 (二叉链表) 设计不同的结点结构,可以构成不同的链式存储结构。常用的

    有: 二叉链表

    三叉链表

    线索链表 用空链域存放指向前驱或后继的线索

                  由于二叉树每个结点至多只有2个孩子,分别为左孩子和右孩子。因 此可以把每个结点分成三个域:一个域存放结点本身的信息,另外两个 是指针域,分别存放左、右孩子的地址。每个结点的结构表示为:

    {ElemTypedata;

    structnode*lchild;structnode*rchild;

    }BTree,*tree;其中,tree是指向根结点的指针。

    Lchild data rchild

    其中左链域lchild为指向左孩子的指针,右链域rchild为指向右孩子 的指针,数据域data表示结点的值。若某结点没有左孩子或右孩子,其 相应的链域为空指针。

    对应的结构类型定义如下: typedefstructnode

    2011-11-13 32

                                    二叉链表的结点结构

    二叉树

    A

    二叉链表

    A

    B ∧C∧

    D

    E

    ∧D∧∧E∧

    lchild

    data rchild

    B

    C

    说明:

    ● 一个二叉链表由根指针root唯一确定。若二叉树为空,则root=NULL; 若结点的某个孩子不存在,则相应的指针为空。

    ● 具有n个结点的二叉链表中,共有2n个指针域。其中只有n-1个用来指 示结点的左、右孩子,其余的n+1个指针域为空。

    2011-11-13 33

                                                3.带双亲指针的二叉链表 由于经常要在二叉树中寻找某结点的双亲时,可在每个结点上再加一个指向

    其双亲的指针parent,形成一个带双亲指针的二叉链表。就是三叉链表。 三叉链表的结点结构

    二叉树

    三叉链表

    A B∧C∧

    D

    E

    B

    C

    A

    lchild data parent rchild

    D∧∧E∧ 性质6 含有n个结点的二叉链表中,有n+1个空链域。

    二叉树存储方法嵌的嵌选入择式,家主园要依www.embedclub.com种运算的频度。

    2011-11-13 34

                 5.2.3 二叉树的基本运算实现

    1.二叉树的基本运算 (1)Inittree (&T)

    功能:初始化操作 (建立一棵空的二叉树)。 (2)Root(T)

    功能:求二叉树的根。

    (3)Parent(T,x) 功能:求二叉树T中值为x的结点的双亲。 (4)Lchild(T,x) 功能:求结点的左孩子。 (5)Rchild(T,x) 功能:求结点的右孩子。 (6)Traverse(T) 功能:遍历或访问二叉树T。 (7)Creatree(&T)

    功能:创建二叉树T

                 5.3 遍历二叉树和线索二叉树 5.3.1遍历二叉树

    在二叉树的一些应用中,常常要求在树中查找具有某种特征 的结点,或者对树中全部结点逐一进行某种处理。这就引入了遍 历二叉树的问题,即如何按某条搜索路径访问树中的每一个结 点,使得每一个结点仅切仅被访问一次。

    遍历二叉树:指按一定的规律对二叉树的每个结点,访问且 仅访问一次的处理过程。

    遍历对线性结构是容易解决的。而二叉树是非线性的,因而 需要寻找一种规律,使二叉树上的结点能排列在一个线性队列 上,从而便于遍历。

                 访问是一种抽象操作,是对结点的某种处理,例如可以是求结点的 度、或层次、打印结点的信息,或做其他任何工作。

    一次遍历后,使树中结点的非线性排列,按访问的先后顺序变为某 种线性排列。

    遍历的次序:假如以L、D、R分别表示遍历左子树、遍历根结点和遍

    历右子树,遍历整个二叉树则有DLR、LDR、LRD、DRL、RDL、RLD六种遍

    历方案。若规定先左后右,则只有前三种情况,分别规定为: DLR——先(根)序遍历,

    LDR——中(根)序遍历, LRD——后(根)序遍历。

    1.遍历方案

    LDR 中序遍历; LRD 后序遍历; DLR 先序遍历

                 1)中序遍历二叉树 算法思想: 若二叉树非空,则: 1)中序遍历左子树 2)访问根结点 3)中序遍历右子树

    2)后序遍历二叉树 算法思想: 若二叉树非空,则: 1)后序遍历左子树 2)后序遍历右子树 3)访问根结点

    算法描述:

    void Inorder (BiTree bt){ //bt为根结点指针

    算法描述:

    void Postorder (BiTree bt){ //bt为根结点指针

    if( bt){//根非空 Inorder (bt->lchild) ; visit(bt->data); Inorder (bt->rchild) ;

    if( bt){

    Postorder (bt->lchild) ; Postorder (bt->rchild) ; visit(bt->data);

    }}

    2011-11-13

    38

                                   3)先序遍历二叉树 算法思想: 若二叉树非空,则: 1)访问根结点 2)先序遍历左子树 3)先序遍历右子树

    算法描述:

    void Preorder (BiTree bt){ //bt为根结点指针

    例:表达式 a+b ×(c-d)-e/f -

    Preorder (bt->rchild) ; }

    a

    ×e b-

    f

    +/ +

    遍历结果:

    中序: a+b × c - d - e / f 后序: abcd - × + ef / - 先序:- +a×b-cd/ef

    cd

    }

    if( bt){//根非空 visit(bt->data);

    Preorder (bt->lchild) ;

                 2.遍历算法 (1)先序遍历的递归算法如下(假定结点的元素值为字符型):

    #include<stdio.h>typedefcharElemType;typedefstructnode

    {ElemTypedata;

    //定义链表结构 //定义结点值

    structnode*lchild;

    //定义左子结点指针 //定义右子结点指针

    structnode*rchild;}BTree;preorder(BTree*root){if(root!=NULL)

    //前序遍历

    //如果不是空结点 {printf(%c ,root->data);//输出当前结点值

    preorder(root->lchild);//递归前序遍历左子结点

    preorder(root->rchild);//递归前序遍历右子结点 }

    return;//结束 }

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

    40

    2011-11-13

                 (2)中序遍历的递归算法如下(假定结点的元素值为字符型):

    voidinorder(BTree*root){if(root!=NULL)

    //中序遍历 //如果不是空结点

    {inorder(root->lchild);printf(%c ,root->data);//输出当前结点值

    inorder(root->rchild);}

    }

    (3) 后序遍历的算法实现

    voidpostorder(BTree*root){if(root!=NULL)

    //后序遍历 //如果不是空结点 //递归后序遍历左子结点

    {postorder(root->lchild);postorder(root->rchild);//递归后序遍历右子结点 printf(“%c ”,root->data);//输出当前结点值

    }}

    //递归中序遍历左子结点 //递归中序遍历右子结点

    2011-11-13 41

                 通过上述三种不同的遍历方式得到三种不同的线性序列,它们 的共同的特点是有且仅有一个开始结点和一个终端结点,其余各 结点都有且仅有一个前驱结点和一个后继结点。

    从二叉树的遍历定义可知,三种遍历算法的不同之处仅在于 访问根结点和遍历左右子树的先后关系。如果在算法中隐去和递 归无关的语句printf(),则三种遍历算法是完全相同的。遍历二叉

    树的算法中的基本操作是访问结点,显然,不论按那种方式进行 遍历,对含n个结点的二叉树,其时间复杂度均为O(n)。所含辅

    助空间为遍历过程中占的最大容量,即树的深度。最坏的情况下

    为n,则空间复杂度也为O(n)。 

                 3.二叉链表的构造 (1) 基本思想

    利用遍历可以实现对结点的一些操作,如求结点的双亲,求 结点的孩子等。还可以在遍历过程中生成结点,建立二叉树的存 储结构。前面介绍过用栈建立二叉树,此处介绍一种基于先序遍 历的二叉树构造方式,即以二叉树的先序序列为输入构造二叉链 表。先序序列中必须加入虚结点以示空指针的位置。

    (2) 构造算法(举例说明)

                 【例5-4】建立图5-8 (a)所示二叉树,其输入的先序序列是:ABC∮∮DE∮G∮∮F∮∮∮。 【解】假设虚结点输入时以空格字符表示,相应的构造算法为:

    void CreateBinTree (BTree **T)

    { //构造二叉链表。T是指向根指针的指针,故修改*T就修改了实参(根指针)本身

    char ch;

    if((ch=getchar())==“ ”) *T=NULL; //读入空格,将相应指针置空 else //读入非空格

    { *T=(BTree *)malloc(sizeof(BTree)); //生成结点

    } }

    (*T)->data=ch; CreateBinTree(&(*T)->lchild); //构造左子树 CreateBinTree(&(*T)->rchild); //构造右子树

    调用该算法时,应将待建立的二叉链表的根指针的地址作为实参。 

                 阶段小节

      二叉树的性质有哪些

      遍历二叉树的三种方式之间的主要不同点

      树的遍历除了使用递归方式还可以使用什么方式

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                         本章总结

    树和二叉树

    树和二叉树 二叉树

    讲解二叉树的定义性质和存储

         结构

    树的逻辑结构和存储结构 树的逻辑结构和存储结构

    主要讲解树的逻辑结构和存储

         结构

    二叉树

    遍历二叉树 遍历二叉树

    重点讲解如何遍历二叉树

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                              实验1 实验内容

    题目:创建一棵二叉树,加入n个节点,对此二叉树进行遍历。 实验目的

    熟悉树的存储结构、掌握树的创建、遍历操作。

    实验分析

    定义树的结构体

    创建树,生成新的树节点并插入二叉树中

    对树进行遍历,遍历可以考虑使用递归

    git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

  • 相关阅读:
    hdu4639 hehe ——斐波纳契数列,找规律
    codefoces round193a
    codeforces 192e
    abbyy cup a
    年中总结
    codeforces 192a
    codeforces 192b
    codeforces 192 c
    codeforces 192 D
    codeforces magic five --快速幂模
  • 原文地址:https://www.cnblogs.com/askDing/p/5443663.html
Copyright © 2011-2022 走看看