树和二叉树
二叉树的性质
n = n0 + n1 +n2
n0 = n2 +1
n-1 = n1 + 2*n2(总度数为n-1)
满二叉树: 满的
完全二叉树:现有的节点编号和满二叉树的一致

具有n个结点的完全二叉树的深度为

已知编号i,求双亲的编号?(完全二叉树)
i/2 向下取整
已知编号i,左孩子的节点是2i,右孩子是2i+1
二叉树的存储结构
顺序存储结构

链式存储结构

n个结点的二叉树链式存储中,共有n+1个空指针域
证明:n个结点的二叉树,除了根节点以外,其余的结点都有上一个双亲结点指来的指针,因此一共有n-1个指针域被利用,所以剩下了n+1个指针域为空
二叉链表缺点:很难找到双亲结点
带双亲指针的二叉链表(三叉链表)

遍历二叉树
遍历的递归算法



遍历的非递归算法
先序遍历
先序遍历:相当于第一次遇到元素就直接遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22void PreOrder(BiTNode *root)
{
BiTNode *p,*node[MAX]; //p用来更新当前指向的结点 node[]用来当栈
int top = 0;
p = root;
do{
while(p!=NULL) //一直滑到最左边
{
visit(p->data);//直接开始遍历
node[top] = p; //入栈
top ++;
p = p->lch;
}
if(top>0) //既然滑到了最左边,那说明之前滑过去的已经遍历完了,直接回退最后一次的null,然后指向最左边节点的右孩子
{
top --;
p = node[top];
p = p->rch;
}
}while(!(top == 0 && p==NULL)) //只有当栈为空,且p指向null的时候,才标志着遍历结束
}中序遍历
中序遍历:相当于第二次遇到元素的时候执行操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21void MidOrder(BiTNode *root)
{
BiTNode *p,*node[MAX]; //p用来更新当前指向的结点 node[]用来当栈
int top = 0;
p = root;
{
while(p!=NULL)
{
node[top] = p;
top++;
p = p->lch;
}
if(top>0)
{
top--;
p = node[top];
visit(p->data);
p = node[top]->rch;
}
}while(!(top==0 && p==NULL));
}后序遍历
后序遍历:相当于第三次碰到元素的时候进行操作
例题
1.计算节点个数

- 二叉树nb的地方,就在于它的结构,容易实现递归
- 因此,可直接设置递归:
- 如果f(b) == NULL,那f(b) = 0;(递归终止条件)
- 如果f(b)!=NULL,那f(b) = f(b->lch)+f(b->rch)
1 | int compute_node(BitTree *node) |
2.计算叶子节点个数

- 同上一题一样,只不过是改改返回时的条件
- 只有当一个节点没有左节点和右节点的时候,再把它算数
1 | int compute_yezi(BiTree *node) |
3.复制二叉树

1 | void copy_tree(BiTree *backup,BiTree *copy) |
4.交换左右子树

1 | void change(BiTree *backup,BiTree *change) |
5.构建二叉树

- 非递归求解的话,就要用到栈
- 递归求解比较简洁
1 | void creat_tree(BiTree *node,char*s) |
6.求二叉树高度

别什么都想扯到遍历上,要有递归的“分治思想”
二叉树的高度,就是左子树和右子树中,更高的那一支的高度加一,可以用递归求解
1 | int height(BiTree t) //因为不需要做修改,所以直接传参即可 |
7.删除二叉树

1 | void destory(BitTree *t) |
- 只能使用类后序遍历的方法,因为节点信息必须最后删除,不然信息会丢失
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 WHAT AM I ?!
