二叉树性质
- 二叉树第i层叶子数最多为 2 i − 1 2^{i-1} 2i−1
- 深度为i的二叉树的节点数最多为 2 i − 1 2^{i}-1 2i−1
- 在二叉树中, 叶子数为 n 0 n_{0} n0, 度为2的节点数为 n 2 n_{2} n2, 则满足 : n 0 = n 2 + 1 n_{0} = n_{2}+1 n0=n2+1 证明: n 0 + n 1 + n 2 = n 0 ∗ 0 + n 1 ∗ 1 + n 2 ∗ 2 + 1 n_{0} + n_{1} + n_{2} = n_{0} * 0 + n_{1} *1 + n_{2} * 2 +1 n0+n1+n2=n0∗0+n1∗1+n2∗2+1
- n个节点的完全二叉树的深度为 ⌊ l o g 2 n ⌋ + 1 \left\lfloor log_{2}n\right\rfloor+1 ⌊log2n⌋+1, 证明利用节点为n的二叉树满足: 2 k − 1 − 1 < n ≤ 2 k − 1 2^{k-1} -1< n \leq 2^{k}-1 2k−1−1<n≤2k−1.
- 满二叉树一定是完全二叉树, 反之不成立.
- 对于一个完全二叉树编号, 编号1 的为根节点, 对于编号为i的节点, 如果 2 i < = n 2i<=n 2i<=n, 存在i的左子节点; 若 2 i + 1 < = n 2i+1<=n 2i+1<=n,存在i的右子节点. 对于节点i来说, 它的父节点为 ⌊ i 2 ⌋ \left\lfloor \frac{i}{2}\right\rfloor ⌊2i⌋.
二叉树的存储
- 顺序存储
思路: 利用完全二叉树的节点关系, 对于一般的二叉树, 补全为完全二叉树.
但是对于一些情况(如左、右斜偏二叉树),会有很多空间的浪费.
- 链式存储
解决顺序浪费空间问题.
1. 二叉链表
typedef struct BiTreeNode{
ElemType data;
struct BiTreeNode *lchild,*rchild;
}BiTreeNode, *BiTree;
2. 三叉链表(多了父节点指针)
typedef struct BiTreeNode{
ElemType data;
struct BiTreeNode *lchild,*rchild, *parent;
}BiTreeNode, *BiTree;
二叉树的遍历
递归遍历
- 前序遍历
void PreOrder(BiTree bt) { if(bt != NULL) { cout << bt->data; PreOrder(bt -> lchild); PreOrder(bt -> rchild); } }
- 中序遍历
void InOrder(BiTree bt) { if(bt != NULL) { InOrder(bt->lchild); cout << bt->data; InOrder(bt->rchild); } }
- 后序遍历
void LaOrder(BiTree bt) { if(bt != NULL) { LaOrder(bt->lchild); LaOrder(bt->rchild); cout << bt->data; } }
层次遍历
void layerOrder(BiTree bt) {
queue<BiTreeNode*> q;
if(bt != NULL) {
q.push(bt);
BiTreeNode* tmpNode;
while(!q.empty()) {
tmpNode = q.front();
q.pop();
cout << tmpNode->data; //操作
if(tmpNode -> lchild != NULL) q.push(tmpNode -> lchild);
if(tmpNode -> rchild != NULL) q.push(tmpNode -> rchild);
}
}
}
二叉树遍历应用
-
利用前序和中序建立树
void PreInOrder(ElemType *PreOrder, int pStart, int pEnd, ElemType *InOrder,int iStart, int iEnd,BiTree *bt){ (*bt) = new BiTreeNode; (*bt) -> data = PreOrder[pStart]; int i = iStart; while(PreOrder[pStart] != InOrder[i]) i++; // 找到中序中的位置, 便于划分左右子树 if(i == iStart) (*bt)->lchild = NULL; else PreInOrder(PreOrder,pStart + 1, pStart + i - iStart, InOrder, iStart , i-1, &((*bt)->lchild) ); if(i == iEnd) (*bt)->rchild = NULL; else PreInOrder(PreOrder,pStart + i - iStart + 1,pEnd, InOrder,i+1,iEnd,&((*bt)->rchild)); }
-
计算叶子节点
//计算叶子节点 int countLeaf(BiTree bt) { if(bt == NULL) return 0;//空树 if(bt->lchild == NULL && bt->rchild == NULL) return 1; return countLeaf(bt->lchild) + countLeaf(bt->rchild); }
-
计算深度
//计算深度 int countDeep(BiTree bt) { if(bt == NULL) return 0; if(bt->lchild == NULL && bt->rchild == NULL) return 1; else return countDeep(bt->lchild) > countDeep(bt->rchild)? countDeep(bt->lchild)+1:countDeep(bt->rchild)+1; }
-
创建二叉树
//创建二叉树 void createBiTree(ElemType *PreOrder,ElemType *InOrder,int n,BiTree *bt) { if(n <= 0 ) (*bt) = NULL; PreInOrder(PreOrder, 0, n-1, InOrder, 0, n-1, bt); }