二叉树
树的遍历
树的遍历顺序,都是以根为主体
- 如果根作为第一个访问的结点 那就是前序遍历
前序遍历是最简单的一个遍历,在拿到一个结点后先判断是不是空结点,如果不是空结点,直接访问自身,依次再判断有无左右结点。
- 如果根放在第二个访问的结点 那就是中序遍历
中序遍历相对麻烦,其操作过程是在拿到一个结点之后先判断有无左子树如果有左子树先访问左子树直至到没有左子树。再进行访问自身,之后考虑右子树。
访问结点的条件:确定以身为根节点,左子树下的所有结点包括左子树结点本身全访问完的情况下才访问自身结点
- 如果根放在第三个访问的结点 那就是后序遍历
后序遍历是三种遍历中最难的一个,在拿到一个结点后先判断有无子树,如果有左子树把它当做根结点继续判断有无左子树直至没有,至此还不能访问任何一个结点还要判断有无右子树如果有右子树跟上面一样,重复判断直至没有
访问自身结点的条件:在这个结点没有左右子树或左右子树已经全都访问完的时候才访问自身结点。
树的结构
二叉树的结构有只有左子树跟右子树两种情况
每一个节点的结构都是一样的
- 节点值
- 左子树
- 右子树
左子树跟右子树的结构类型跟根节点的类型一致
struct TreeNode {
int val; //节点的值
TreeNode *left; //左节点
TreeNode *right; //右节点
TreeNode(int x) : val(x), left(NULL), right(NULL) {} //初始化
};
前序遍历
顺序: 根——>左——>右
中序遍历
顺序: 左——>根——>右
后序遍历
顺序: 左——>右——>根
递归跟迭代
递归
递归是解决树问题最简便也是最容易理解的办法,因为对于每个结点来说要进行的操作一模一样,只需要将要进行的操作包装成一个函数不断的调用自己就可以解决。
用递归解决二叉树的题目只需要考虑
- 1.到哪停止
- 2.遇到分叉怎么解决
- 3.每一个节点的共同需要面对的问题是什么。解决一个节点问题,后面的节点,递归解决就可以了。
- 4.在写递归的时候,要把节点下面的子节点收起来看成我们的递归函数,看成一个节点来解决问题
迭代
迭代需要应用到栈。我们运行一个程序的使用对于内存的占用也是像栈一样先调用先执行,执行完之后在再执行下一个,而递归就相当于堆栈一样,在这个函数没运行完的时候就又调用了自身,就要等后面调用的这个函数运行玩之后才能结束之前的调用,就慢慢的堆了起来。
栈一样先调用先执行,执行完之后在再执行下一个,而递归就相当于堆栈一样,在这个函数没运行完的时候就又调用了自身,就要等后面调用的这个函数运行玩之后才能结束之前的调用,就慢慢的堆了起来。
所以使用迭代的方法就要应用到栈的知识。