漫画算法-小灰的算法之旅(10)
二叉树的广度优先遍历
如果说深度优先遍历是在一个方向上“一头扎到底”那么广度优先遍历则恰恰相反;先在各个方向上各走一步,再在各个方向上走出第二步、第三步…直到各个方向全部走完。
二叉树的层序遍历
层序遍历:就是二叉树按照从根节点到叶子节点的层次关系,一层一层横向遍历各个节点。
思路:采用**队列(FIFO)**来作为辅助结构,先将根节点放入到队列中,然后不断遍历队列。首先拿出根节点,根节点的左子树、右子树不为空,就将它们入队列;然后在依次遍历队列,将节点出队列,如果节点的左子树、右子树不为空,则将它们入队列;重复遍历队列,直到队列为空为准。
上图就是一个二叉树的层序遍历,每个节点左侧的序号代表该节点的输出顺序。可是,二叉树同一层次的节点之间是没有直接关联的,如何体现这种层序遍历呢?这里同样需要借助一个数据结构来辅助工作,这个数据结构就是队列。
二叉树的层序遍历步骤如下:
- 根节点1进入队列
- 根节点1出队列,输出节点1,并得到节点1的左孩子节点2,右孩子节点3,让节点2,节点3入队列。
- 节点2出队列,输出节点2,并得到节点2的左孩子节点4,右孩子节点5.让节点4和节点5入队列。
- 节点3出队列,输出节点3,并得到节点3点的右孩子节点6,让节点6入队列。
- 节点4出队列,输出节点4,由于节点4没有孩子节点,所以没有新节点入队列。
- 节点5出队列,输出节点5,由于节点5也没有孩子节点,所以没有新节点入队列。
- 节点6出队列,输出节点6,由于节点6也没有孩子节点,所以没有新节点入队列。
至此,所有的节点都遍历输出完毕。
代码实现
/**
* 二叉树的层序遍历
* param root 二叉树根节点
*
*/
public static void levelOrderTraveral(TreeNode root){
Queue<TreeNode> queue=new LinkedList<TreeNode>();
queue.offer(root);
while(!queue.isEmpty()){ // 如果队列不为空
TreeNode node=queue.poll(); //出队列
System.out.println(node.data);
if(node.leftChild !=null){
queue.offer(node.leftChild);// 如果节点左子树不为空,入队列
}
if(node.rightChild !=null){
queue.offer(node.rightChild);//如果节点右子树不为空,出队列
}
}
}
golang实现
// 二叉树的层序遍历 先将根节点入队列,遍历队列,判断节点是否存在根节点
func levelOrderTraveral(root *TreeNode) {
ret :=[][]interface{}{} //二维数组记录层序以及每层都节点数量
if root ==nil {
return
}
queue :=[]*TreeNode{root}
for i:=0;len(queue)>0;i++ { // 遍历层序
ret =append(ret,[]interface{}{})
temp :=[]*TreeNode{}
for j :=0;j<len(queue);j++ { //遍历每层都节点数量
node :=queue[j]
log.Println(node.Value)
ret[i]=append(ret[i],node.Value)
if node.LeftChild!=nil{
temp=append(temp,node.LeftChild)
}
if node.RightChild!=nil {
temp=append(temp,node.RightChild)
}
}
queue=temp
}
log.Println("ret:",ret)
}
type TreeNode struct {
Value interface{}
LeftChild *TreeNode
RightChild *TreeNode
}
func (node *TreeNode) setValue(v interface{}) {
if node ==nil {
log.Println("setting value to nil node")
return
}
node.Value=v
}
func NewNode(v interface{}) *TreeNode {
return &TreeNode{
Value: v,
}
}
func main(){
// 构造二叉树
root := NewNode(3)
root.LeftChild=&TreeNode{}
root.LeftChild.setValue(2)
root.LeftChild.LeftChild=NewNode(9)
root.LeftChild.RightChild=NewNode(10)
root.RightChild=NewNode(8)
root.RightChild.RightChild=NewNode(4)
log.Println("层序遍历")
levelOrderTraveral(root)
}
时间复杂度
- 时间复杂度:O(n)
- 空间复杂度:O(n)