二叉树遍历:访问树所有结点的过程叫做树遍历,并且在遍历过程中,每个结点只能被处理一次。遍历的目标是按照某种特定顺序访问树的所有结点。
遍历的分类(D表示当前结点,L表示当前结点的左侧结点,R表示当前结点的右侧结点):
- 前序遍历(DLR)
- 中序遍历(LDR)
- 后序遍历(LRD)
- 层序遍历:这种遍历方式不需要依赖顺序,是从图的广度优先遍历方法启发而来。
前序遍历
概念:表示的是先访问中间结点,然后是该中间结点的左子结点,完成后再访问该中间结点的右子结点。因此根据这条规则可以得到上图的访问顺序是A-B-D-E-C-F-G。
- 访问根结点;
- 按照前序遍历方式遍历左子树;
- 然后按照前序遍历方式遍历右子树。
代码实现
void PreOrder(BinaryTreeNode root){
if(root != null){
System.out.println(root.getData);
PreOrder(root.getLeft());
PreOrder(root.getRight());
}
}
时间复杂度O(n),空间复杂度O(n)。
非递归前序遍历
这里采用的非递归的方式需要实现前序遍历,需要引入栈操作。
也就是先操作根结点,然后操作左子树,判断该左子树是否还有子树,没有则操作根结点的右子树,如果有则继续操作该左子树的树,并将已经操作的结点存放在栈中进行保存。
代码实现:
void PreOrederNonRecursive(BinaryTreeNode root){
if(root == null){
return null;
}
LLStack s = new LLStack();
while(true){
while(root != null){
System.out.println(root.getData());
S.push(root);
root = root.getLeft();
}
if(S.isEmpty()){
break;
}
root = (BinaryTreeNode)S.pop();
root = root.getRight();
}
return;
}
时间复杂度O(n),空间复杂度O(n)。
中序遍历
概念:已知前序遍历的情况下就比较好理解,是在确定了根结点后,先判断该根结点是否有左子树,如果没有则先操作根结点,然后再操作右子树。如果具有左子树,则先操作左子树,然后根结点,再右子树。上图访问顺序为D-B-E-A-F-C-G。
代码实现:
void InOrder(BinaryTreeNode root){
if(root != null){
InOrder(root.getLeft());
System.out.println(root.getData());
InOrder.(root.getRight());
}
}
时间复杂度O(n),空间复杂度O(n)。
非递归中序遍历
同样这里也是采用栈进行数据的存取操作。
代码实现:
void InOrderNonRecursive(BinaryTreeNode root){
if(root == null){
return null;
}
LLStack s = new LLStack();
While(true){
While(root != null){
S.push(root);
root = root.getLeft();
}
if(stack.isEmpty()){
break;
}
root = (BinaryTreeNode)s.pop();
System.out.println(root.getData());
root = root.getRight();
}
return;
}
时间复杂度O(n),空间复杂度O(n)。
后序遍历
概念:上图访问顺序为G-C-F-A-E-B-C。
代码实现:
void PostOrder(BinaryTreeNode root){
if(root != null){
InOrder(root.getRight());
System.out.println(root.getData());
InOrder.(root.getLeft();
}
}
时间复杂度O(n),空间复杂度O(n)。
非递归实现
void PostOrderNonRecursive(BinaryTreeNode root){
if(root == null){
return null;
}
LLStack s = new LLStack();
While(true){
While(root != null){
S.push(root);
root = root.getRight();
}
if(stack.isEmpty()){
break;
}
root = (BinaryTreeNode)s.pop();
System.out.println(root.getData());
root = root.getLeft();
}
return;
}
时间复杂度O(n),空间复杂度O(n)。
层序遍历
概念:
- 访问根节点;
- 在访问第i层的时候,将i+1层的结点按顺序保存在队列中;
- 进入下一层并访问该层的所有结点;
- 重复上述操作指导所有的结点都访问完成。
代码实现:
void LevelOrder(BinaryTreeNode root){
BinaryTreeNode temp;
LLQueue q = new LLQueue();
if(root == null){
return null;
}
q.enQueue(root);
While(!q.isEmpty()){
temp = q.deQueue();
//处理当前结点
System.out.println(temp.getData());
if(temp.getLeft()){
q.enQueue(temp.getLeft());
}
if(temp.getRight()){
q.enQueue(temp.getRight());
}
q.deleteQueue();
}
}
时间复杂度O(n),空间复杂度O(n)。