一、二叉树的逻辑结构
1、特点:
(1)每个节点最多两颗子树
(2)是有顺序的。次序不能颠倒
(3)与树差别很大
注:树与二叉树的比较
2、特殊的二叉树
(1)满二叉树
叶子结点只能出现在最后一层,在同一层!!!
只有度为0和度为2的结点!!!
(2)完全二叉树
叶子结点只能出现在最下两层并且最下层的叶子结点都集中在二叉树的左面。
如果有度为1的结点,只可能有一个,且该结点只有左孩子
深度为K的完全二叉树在K-1层一定是满二叉树。
二、二叉树的基本性质
三、二叉树的存储结构
1、顺序存储结构
一般只存储完全二叉树
按照完全二叉树编号
2、二叉链表
struct BiNode
{
DataType data;
BiNode *lchild,*rchild;
};
3、三叉链表
在二叉链表中增加了 parent 指针
三叉链表的静态链表形式
缺点:不适合频繁修改的树
四、二叉树的遍历
1、前序遍历
int preorder(bitree_t *b)
{
if (b == NULL) // 递归结束条件
return 0;
printf("%d ", b->data); // 先访问根
preorder(b->lchild); // 再访问左
preorder(b->rchild); // 最后访问右
return 0;
}
2、中序遍历
int inorder(bitree_t *b)
{
if (b == NULL) // 递归结束条件
return 0;
inorder(b->lchild); // 先访问左
printf("%d ", b->data); // 再访问根
inorder(b->rchild); // 最后访问右
}
3、后序遍历
int postorder(bitree_t *b)
{
if (b == NULL) // 递归结束条件
return 0;
postorder(b->lchild); // 先访问左
postorder(b->rchild); // 再访问右
printf("%d ", b->data); // 最后访问根
}
4、层序遍历
代码思路:
(1)队列Q初始化
(2)如果二叉树非空,将根指针入队
(3)循环直到队列Q为空
q=队列Q的队头元素出队
访问结点q的数据域
若结点存在左孩子,则将左孩子指针入队
若结点存在右孩子,则将右孩子指针入队
五、二叉树的创建
递归创建:(两种方式)
Status CreateBitree(BiTree &T)
{
scanf(&ch);
if (ch == "#")
T = NULL;
else
{
if (!(T = (BiTNode *)malloc(sizeof(BiTNode))));
exit(OVERFLOW);
T->data = ch; // 生成根节点
CreateBitree(T->lchild); //左子树
CreateBitree(T->rchild);//右子树
}
return ok;
}
bitree_t *create(int i, int n)
{
bitree_t *r = (bitree_t *)malloc(sizeof(bitree_t));
r->data = i; // 根节点
printf("i=%d\n", i); // 可以给出创建的顺序
if (2 * i <= n)
r->lchild = create(2 * i, n); //递归 左子树
else
r->lchild = NULL;
if (2 * i + 1 <= n)
r->rchild = create(2 * i + 1, n); // 递归,右子树
else
r->rchild = NULL;
}
六、树、森林、二叉树的转换
注:上图中绿色的为左边对应的二叉树,而紫色的为左边对应的树。
1、二叉树和树之间有对应关系
树 | 二叉树 |
兄弟关系 | 双亲和右孩子 |
双亲和长子 | 双亲和左孩子 |
将 树 转化为 二叉树 :
step1:加线:兄弟加线
step2:去线:保留双亲与第一个孩子的连线,删去与其他孩子的连线
step3:层次转换:顺时针转动,使之层次分明
2、森林转化为二叉树
step1:将森林中的每棵树转换成二叉树
step2:从第二棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树根结点的右孩子,当所有二叉树连起来后,此时所得到的二叉树就是由森林转换得到的二叉树。
3、二叉树转换为树或森林
(1) 加线:若某结点x是其双亲y的左孩子,则把结点x的右孩子、右孩子的右孩子、,都与结点y用线连起来;
(2)去线:删去原二叉树中所有的双亲结点与右孩子结点的连线;
(3)层次调整:整理由(1)、(2)两步所得到的树或森林,使之层次分明。