二叉树的之字形遍历

给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)
例如:
给定的二叉树是{3,9,20,15,7,#,#},
在这里插入图片描述

该二叉树之字形层序遍历的结果是
3
20 9
15 7

输入格式
一行字符串,只包含大写字母和#。
此处采用完全二叉树的顺序存储结构

输出格式
若干行,之字形输出树的结点,每一行输出树的一层。

输入样例
ABC###D##

输出样例
A
C B
D

基本思路:
1、通过观察题意,我们可以发现,这个题目构造二叉树的时候可以通过完全二叉树的顺序存储结构进行构造.
那么问题来了,怎样来通过顺序存储结构来构建二叉树?其实,通过顺序存储结构构建二叉树最大的问题在于我们怎么知道当前这个节点的左右子节点,或者这个节点父节点。通过学习,我们可以将当前节点的下标定位i,那么它的左子节点的下标就是2 * i,右子节点就是2 * i + 1,父节点的下标就是 i / 2。(值得注意的是,如果是这样的话,那么需要定义一个节点数组,并且节点是从下标为1开始算起的。否则,如果节点的下标从0开始的话,那么左子节点的下标就是2 * i +1,右子节点的下标就是2 * i + 2。

顺序存储结构构建二叉树对应的代码:

// 按先序次序输入二叉树中结点的值(一个字符),’#’字符表示空树,
Status CreateBiTree(Node &T,char *msg) {
    
  int i,len = strlen(msg);
  char ch;
  Node arr[MAX_SIZE];//定义结构体指针数组,用于存放节点
  int check[MAX_SIZE] = {
   0};//check数组用于表示当前下标的节点是否为其他节点的子节点,值为1表示是,否则不是
  for(i = 1; i <= len;i++){
   
      ch = msg[i - 1];
      if (ch=='#') arr[i] = NULL;//如果字符为#,表示空树,将当前节点变成NULL
      else {
   
        arr[i] = (Node)malloc(sizeof(struct BiTNode))
        if (arr[i] == NULL){
    
           printf("创建节点失败!!!\n");
           return ERROR;
        }
        arr[i]->data = ch; // 生成节点,并给当前这个节点赋值
        arr[i]->lchild = arr[i]->rchild = NULL;
      }
  }
  for(i = 1; i <= len / 2; i++){
   
      if(arr[i] == NULL)//如果当前节点为NULL,那么就不需要构建它的子节点,直接跳到更换循环变量i这一步(即执行i++)
        continue;
        /*
        这里之所以不需要判断i * 2 <= len,是因为for循环中已经做好了判断,
        如果当前这个i <= len / 2,那么i * 2始终不会发生越界
        */
      arr[i]->lchild = arr[i * 2];
      check[i * 2] = 1;
      if(i * 2 + 1 <= len) {
    
      //这里之所以要这样,是因为避免i * 2 + 1发生越界,从而发生错误
        arr[i]->rchild = arr[i * 2 + 1];
        check[i * 2 + 1] = 1;
       }
  }
  /*
  将根节点复制给T(因为输入的是一个先序序列,那么第一个必然是根节点,所以
  arr[1]就是根节点,如果输入的不是不是先序序列,那么我们需要定义一个check
  数组,表示这个节点是否为其他节点的子节点,如果值为0,表示不是其他节点的
  子节点,也就是说这个节点是二叉树的根节点,否则,值为1的时候,表示这个节
  点是其他节点的子节点
  */
  /*
  //通过check数组查找根节点(如果输入的字符串不是先序序列的时候,就需要查找根节点)
  for(i = 1; i <= len; i++){
     if(check[i] == 0) //值为0,表示当前下标对应的节点是根节点
         break;
  }
  T = arr[i];
  */
  T = arr[i];
  return OK;
} 

2、字形遍历:
基本思路:通过观察输出样例,我们可以发现,如果是奇数层,他是从左到右开始遍历的,反之,如果是偶数层,那么他是从右到左开始遍历的。那么问题来了,我们需要怎样实现呢?
起初我的思路是,这个问题本质上依旧是一个层序遍历,只是入队的时候需要改变一下顺序一下即可。于是写好代码并运行:

如果是通过队列实现,只是通过改变入队的顺序的话,那么对应的样例:
ABCDEFGHIJ,那么本应该输出:
在这里插入图片描述

错误代码(思路错误)

#include "stdio.h"
#include "malloc.h"
#include<string.h>
#include<stdlib.h>
#define OK  1
#define ERROR  0
#define MAX_SIZE 100
typedef int  Status;

typedef char  ElemType;
typedef struct BiTNode * Node;
typedef Node * List;
struct BiTNode{
   
  ElemType data;
  Node lchild,rchild;//左右孩子指针
};

typedef struct Queue{
   
   List arr;
   int front;
   int rear;
}Queue;
int init(Queue &queue){
   
   queue.arr = (List)malloc(sizeof(List) * MAX_SIZE);
   if(queue.arr == NULL){
   
     printf("创建队列错误!!!/n");
     exit(0);
   }
   int i;
   for(i = 0; i < MAX_SIZE; i++){
   
     queue.arr[i] = (Node)malloc(sizeof(struct BiTNode));
     if(queue.arr[i] == NULL){
   
        printf("创建节点失败!!!\n");
        exit(0);
     }
   }
   queue.front = queue.rear = 0;
   return OK;
}

int push(Queue &queue,Node e){
   
   if((queue.rear + 1) % MAX_SIZE == queue.front){
   
     printf("队列为满!!!\n");
     exit(0);
   }
   queue.arr[queue.rear++] = e;
   queue.rear %= MAX_SIZE;
   return OK;
}
int pop(Queue &queue,Node &e){
   
   if(queue.front == queue.rear){
   
     printf("栈为空!!!\n");
     exit(0);
   }
   e = queue.arr[queue.front++];
   queue.front %= MAX_SIZE;
   return OK;
}
int isEmpty(Queue &queue){
   
   return queue.front == queue.rear
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值