二叉树性质
- 二叉树第i层叶子数最多为2i−12^{i-1}2i−1
- 深度为i的二叉树的节点数最多为 2i−12^{i}-12i−1
- 在二叉树中, 叶子数为n0n_{0}n0, 度为2的节点数为n2n_{2}n2, 则满足 :n0=n2+1n_{0} = n_{2}+1n0=n2+1 证明: n0+n1+n2=n0∗0+n1∗1+n2∗2+1n_{0} + n_{1} + n_{2} = n_{0} * 0 + n_{1} *1 + n_{2} * 2 +1n0+n1+n2=n0∗0+n1∗1+n2∗2+1
- n个节点的完全二叉树的深度为 ⌊log2n⌋+1\left\lfloor log_{2}n\right\rfloor+1⌊log2n⌋+1, 证明利用节点为n的二叉树满足: 2k−1−1<n≤2k−12^{k-1} -1< n \leq 2^{k}-12k−1−1<n≤2k−1.
- 满二叉树一定是完全二叉树, 反之不成立.
- 对于一个完全二叉树编号, 编号1 的为根节点, 对于编号为i的节点, 如果2i<=n2i<=n2i<=n, 存在i的左子节点; 若2i+1<=n2i+1<=n2i+1<=n,存在i的右子节点. 对于节点i来说, 它的父节点为 ⌊i2⌋\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); }