1.二叉树
1.1 二叉树的定义
首先先来回顾一下什么是二叉树:
二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。
二叉树的五种可能的形态:

1.2 二叉树相关术语
- 根节点(root node):位于二叉树顶层的节点,没有父节点。
 - 叶节点(leaf node):没有子节点的节点,其两个指针均指向None 。
 - 边(edge):连接两个节点的线段,即节点引用(指针)。
 - 节点所在的层(level):从顶至底递增,根节点所在层为 1 。
 - 节点的度(degree):节点的子节点的数量。在二叉树中,度的取值范围是 0、1、2 。
 - 二叉树的高度(height):从根节点到最远叶节点所经过的边的数量。
 - 节点的深度(depth):从根节点到该节点所经过的边的数量。
 - 节点的高度(height):从距离该节点最远的叶节点到该节点所经过的边的数量。
 
1.3 二叉树的性质
性质1:二叉树的第 i 层上至多有 个结点(
)
性质2:深度为 k 二叉树至多有 个结点(
)
性质3:对任意一棵二叉树T,如果其叶子数为 ,度为2的结点数为
, 则 
性质4:具有 n () 个结点的完全二叉树的深度为 
 或 
性质5:如果对一棵具有 n 个结点的完全二叉树的结点进行编号,则对任一结
        (1) 若  ,则该结点是二叉树的根,无双亲; 否则,其双亲结点的编号为 
 或 
 ; 
        (2)如果  则结点 
 没有左孩子, 否则,其左孩子的编号为 
; 
        (3)如果  则结点 
 没有右孩子,否则,其右孩子的编号为 
; 
        (4)若  为奇数, 且 
,则其左兄弟为 
, 
                 若  为偶数, 且 
, 则其右兄弟为
 。
2.二叉树的遍历
从二叉树的递归定义可知,一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上,可以按某种次序执行三个操作:
① 访问结点本身(N)
② 遍历该结点的左子树(L)
③ 遍历该结点的右子树(R)
在二叉树中,常见的遍历有先序遍历、中序遍历、后序遍历以及层序遍历,他们的主要思想分别是:
前序遍历:根结点 --> 左子树 --> 右子树
// 先序遍历
void PreOrderTraverse(BiTree T) {
    if (T == NULL) {
        return;
    }
    cout << T->data;
    PreOrderTraverse(T->lchild);
    PreOrderTraverse(T->rchild);
} 
中序遍历:左子树 --> 根结点 --> 右子树
// 中序遍历
void InOrderTraverse(BiTree T) {
    if (T == NULL) {
        return;
    }
    InOrderTraverse(T->lchild);
    cout << T->data;
    InOrderTraverse(T->rchild);
} 
后序遍历:左子树 --> 右子树 --> 根结点
// 后序遍历
void PostOrderTraverse(BiTree T) {
    if (T == NULL) {
        return;
    }
    PostOrderTraverse(T->lchild);
    PostOrderTraverse(T->rchild);
    cout << T->data;
} 

层次遍历:自上而下,自左至右逐层访问树的结点
// 层序遍历
void LevelOrderTraverse(BiTree T) {
    BiTree queue[100]; // 队列
    int front = 0, rear = 0;
    if (T != NULL) { 
        rear = (rear + 1) % 100;  
        queue[rear] = T; 
    }
    while (front != rear) { 
        int levelSize = (rear - front + 100) % 100; // 当前层的结点个数
        for(int i = 0; i < levelSize; ++i){
            front = (front + 1) % 100;
            BiTree p = queue[front];
            cout << p->data;
            // 将当前结点的左右孩子入队 
            if (p->lchild != NULL) { 
                rear = (rear + 1) % 100;
                queue[rear] = p->lchild;
            }
            if (p->rchild != NULL) { 
                rear = (rear + 1) % 100;
                queue[rear] = p->rchild;
            }
        }
        cout << endl;
    }
} 
层序遍历的算法思想:
①初始化一个辅助队列
②根节点入队
③若队列非空,则队头结点出队,访问该结点,并将其左、右孩子插入队尾(如果有的话)
 
// 层序遍历
void LevelOrderTraverse(BiTree T) {
    BiTree queue[100]; // 队列
    int front = 0, rear = 0;
    if (T != NULL) { 
        rear = (rear + 1) % 100;  
        queue[rear] = T; 
    }
    while (front != rear) { 
        int levelSize = (rear - front + 100) % 100; // 当前层的结点个数
        for(int i = 0; i < levelSize; ++i){
            front = (front + 1) % 100;
            BiTree p = queue[front];
            cout << p->data;
            // 将当前结点的左右孩子入队 
            if (p->lchild != NULL) { 
                rear = (rear + 1) % 100;
                queue[rear] = p->lchild;
            }
            if (p->rchild != NULL) { 
                rear = (rear + 1) % 100;
                queue[rear] = p->rchild;
            }
        }
        cout << endl;
    }
}
 

















