树的相关术语:
结点的度:一个结点的子树的数量。
树的度:该树中结点的最大度数。
叶结点和分支结点:度为0的结点和度不为0的结点。
树的深度:树中结点的最大层数。
有序树和无序树:树中每个结点的各子树看成是从左到右有次序的称为有序树(一般都是),反之无序
森林:m(m>0)棵互不相交的树的集合。
树的表示:(A(B(E,F(I,J)),C,D(G,H)))
二叉树的概念:
1. 五种基本形态:空,仅有根结点,仅有左子树,仅有右子树,有左右子树.
2. 与树的区别:最大度为2;结点有左右之分。
3. 满二叉树:除最下一层结点外,每层都有2个子结点。
完全二叉树:除最后一层外,其他各层的结点数都达到最大个数;且最后一层从左往右结点连续。
4. 性质:
(1)在二叉树的第i层上至多有2^(i-1)个结点。
(2)深度为k的二叉树至多有2^k-1个结点(k≥1),最少有k个结点。
(3)对任何一颗二叉树,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1。
(4)具有n个节点的完全二叉树的深度为[log2n]+1,其中[log2n]+1是向下取整。
(5)如果有一颗有n个节点的完全二叉树的节点按层次序编号,对任一层的节点i(1<=i<=n)有
1.如果i=1,则节点是二叉树的根,无双亲,如果i>1,则其双亲节点为[i/2],向下取整
2.如果2i>n那么节点i没有左孩子,否则其左孩子为2i
3.如果2i+1>n那么节点没有右孩子,否则右孩子为2i+1
5. 二叉树的储存:
(1)顺序储存结构:一般按从上至下和从左到右的顺序将树中的结点顺序存储在一维数组中。
一般用于储存完全二叉树,若不是完全二叉树可以将其转化为完全二叉树(虚设结点#)。但会造成空间的大量浪费。#define Maxsize 100 //假设一维数组最多存放100个元素
typedef char Datatype; //假设二叉树元素的数据类型为字符
typedef struct
{ Datatype bt[Maxsize];
int btnum;
}Btseq;
(2)链式储存结构:
二叉链表结构:每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。其结点结构为:
三叉链表结构:链表结点增加一个双亲字段parent,用来指向其双亲结点。这种存储结构既便于查找孩子结点,又便于查找双亲结点;但增加了空间开销。
#define datatype char //定义二叉树元素的数据类型为字符
typedef struct node //定义结点由数据域,左右指针组成
{ Datatype data;
struct node *lchild,*rchild;
}Bitree;
Bitree *root=NULL;//定义二叉树根结点指针
6.遍历
(1)前序遍历,先访问根结点,在遍历左子树,最后遍历右子树。简记根-左-右。ABDCEFGH
(2)中序遍历,先遍历左子树,在访问根结点,最后遍历右子树。简记左-根-右。BDAFEHGC
(3)后序遍历,先遍历左子树,在遍历右子树,最后访问根结点。简记左-右-根。DBFHGECA
线索二叉树:
当以二叉链表来保存二叉树时,只能找到结点的左右孩子信息,不能直接得到结点在的前驱和后继信息,只有在遍历过程中才能得到这种信息。我们知道,在n个结点的二叉链表栈必定存在n+1个空链域,因此,可以利用这些空链域来存放这些结点信息。所以作如下规定:若结点右左子树,则其lchild域指向其左孩子,否则令lchild域指向其前驱;若结点有右子树,其rchild域指向其右孩子,否则指向其后继。
这种在结点的空指针中存放该节点的前驱和后驱结点的指针称为线索。
这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树。
根据线索性质不同可分为先序线索二叉树、中序线索二叉树、后序线索二叉树。typedef char DATA; //定义元素类型
typedef enum
{
SubTree,//子树
Thread //线索
}NodeFlag; //枚举值SubTree(子树)和Thread(线索)分别为0,1
typedef struct ThreadTree //定义线索二叉树结点类型
{
DATA data;//元素数据
NodeFlag lflag; //左标志
NodeFlag rflag; //右标志
struct ThreadTree *left;//左子树结点指针
struct ThreadTree *right;//右子树结点指针
}ThreadBinTree;