层遍历:从上到下、从左到右,如图所示:
图示为举例进行层遍历顺序
以上图为例,进行分析用栈还是队列?
入栈顺序:根 右 左 //必须通过根节点去保存左右孩子
出栈:栈顶元素 //也就是后面入进来的先出
入栈:a
出:a
入:c b
出:b
入:c e d
那么问题来了:此时应该遍历c 但是c被压在栈底出不来,只能先访问d和e,所以无法用栈进行层次遍历,只能用队列进行遍历
入队顺序:根节点、左孩子、右孩子
出队顺序:出队头元素
① 将根节点入队
② 判断树是否为空,不为空,则队头元素进行入出队
③ 将刚出队元素的左右孩子进行入队
④ 将①②③循环,直至队列为空时,停止
(说明:灰色字母是已经出队元素,下划线代表目前队尾元素,蓝色是刚入队元素)
入队:a //首先判断树是否为空,不为空,则入树根a
出队:a //队头元素
入:a b c //先入a的左孩子b,再入a的右孩子c
出:b //队头元素
入:a b c d e //c还未出队所以还在,然后入b的左右孩子de
出:c //队头元素
入:a b c d e f g //de还未出队所以还在,然后入c的左右孩子fg
出:d e f //出队头元素d,d无左右孩子,继续出队头元素e,e无左右孩子,继续出队头元素f
入: g h //入f的左右孩子gh
出:g h //出队头元素g,g无左右孩子,继续出队头元素h
此时数组为空,说明入队的数据均已出队,所有节点访问完毕
伪代码:
代码:
- typedef struct node
- {
- char value;//当前节点值
- struct node* left;//指向当前节点左孩子指针
- struct node* right;//指向当前节点右孩子指针
- }Node;
-
- //层次遍历
- void LevOrder(Node* root)
- {
- queue
qq;//定义队列qq,存储指向每个结点的指针 - if(root == NULL)
- {
- return;
- }
- Node* front = NULL;//定义指向队头的指针
- qq.push(root);//将根节点入队
- while(!qq.empty())
- {
- front = qq.front();//先获取队头,才能在出队后访问其左右孩子
- qq.pop();//队头出队
- printf("%c", front->value);//输出队头的value
- //将当前front的左右孩子入队
- if (front->left != NULL)
- qq.push(front->left);
- //不用输出左右孩子,因为pop出队头后,左右孩子会成为新对头,每次只用输出队头元素
- if(front->right != NULL)
- qq.push(front->right);
- }
- printf("%\n");
- }
完整代码:
-
- typedef struct node
- {
- char value;//当前节点值
- struct node* left;//指向当前节点左孩子指针
- struct node* right;//指向当前节点右孩子指针
- }Node;
-
- typedef struct tree
- {
- Node* root;
- }Tree;
-
- void InitTree(Tree* t)
- {
- t->root = NULL;
- }
-
- //先序遍历创建二叉树
- Node* Create(const char*& str) //因为要修改字符串就加了引用&
- {
- if (*str == '*')
- return NULL;
- else
- {
- Node* newnode = (Node*)malloc(sizeof(Node));
- if (newnode != NULL)
- {
- newnode->value = *str;
- newnode->left = Create(++str);
- newnode->right = Create(++str);
- return newnode;
- }
- }
- }
-
-
- //层次遍历
- void LevOrder(Node* root)
- {
- queue
qq;//定义队列qq,存储指向每个结点的指针 - if(root == NULL)
- {
- return;
- }
- Node* front = NULL;//定义指向队头的指针
- qq.push(root);//将根节点入队
- while(!qq.empty())
- {
- front = qq.front();//先获取队头,才能在出队后访问其左右孩子
- qq.pop();//队头出队
- printf("%c", front->value);//输出队头的value
- //将当前front的左右孩子入队
- if (front->left != NULL)
- qq.push(front->left);
- //不用输出左右孩子,因为pop出队头后,左右孩子会成为新对头,每次只用输出队头元素
- if(front->right != NULL)
- qq.push(front->right);
- }
- printf("\n");
- }
-
- int main()
- {
- Tree t;
- InitTree(&t);
- const char* str = "ABDG**HI****CE*J**F**";
- t.root = Create(str);
- printf("层次遍历二叉树:\n");
- LevOrder(t.root);
- printf("\n");
- }
运行结果: