数据结构之二叉树2

二叉树的创建

二叉树的创建用到了辅助队列,通过辅助队列来创建二叉树;

void buildBinaryTree(PTree_Node* root, PTree_Queue* phead, PTree_Queue* ptail,Tree_Element val) {
    PTree_Node newTree = (PTree_Node)calloc(1, sizeof(Tree_Node));
    PTree_Queue newQueue = (PTree_Queue)calloc(1, sizeof(Tree_Queue));
    newTree -> val = val;
    newQueue -> insertPos = newTree;
    PTree_Queue cur = *phead;
    //根节点为空,说明树是空的
    if (NULL == *root) {
        *root = newTree;
        *phead = newQueue;
        *ptail = newQueue;
    } else {
        (*ptail) -> snext = newQueue;
        *ptail = newQueue;
        //左孩子为空,赋给左孩子
        if (NULL == cur -> insertPos -> left) {
            cur -> insertPos -> left = newTree;
        //右孩子为空,赋给右孩子
        } else if (NULL == cur -> insertPos -> right) {
            cur -> insertPos -> right = newTree;
            //左右孩子都设置完成的结点,从队列里移除
            *phead = cur -> snext;
            free(cur);
            cur = NULL;
        }
    }
}

二叉树的遍历

前(先)序遍历

1、递归实现

void pre_order(PTree_Node root) {
  if(NULL == root) {
    return;
  }
  visit(root);
  pre_order(root -> left);
  pre_order(root -> right);
}

2、非递归实现

void pre_order(BiTree root) {
  Stack< BiTreeNode> s;
  //初始化一个栈
  init_stack(s);  
  BiTree p = root;
   //栈中有数据,就需要遍历
  while(p || !isEmpty(s)){
    if(p) {
      //根节点先访问
      visit(p);
      //访问后push到栈中,为了遍历右结点使用
      push(s, p);
      //访问完根结点后,就该访问左结点了
      p = p -> left; 
    } else {
      //到这里说明当前结点没有左结点,因此该弹出结点访问右结点
      pop(s, p);
      //访问当前结点的右结点,如果右结点还有左结点又回进行上门的循环
      //直到所有结点都被访问后结束
      p = p -> right;
    }
  }
}

中序遍历

1、递归实现

void in_order(BiTree root) {
  if (NULL == root) {
    return;
  }
  in_order(root -> left);
  visit(root);
  in_order(root -> right);
}

2、非递归实现

void in_order(BiTree root) {
  Stack s;
  init_stack(s);
  BiTree p root;
  while (p || !isEmpty(s)) {
    if (p) {
      push(s, p);
      p = p -> left;
    } else {
      pop(s, p);
      visit(p);
      p = p -> right;
    }
  }
}

后序遍历

1、递归实现

void post_order(BiTree root) {
  if (NULL == root) {
    return;
  }
  post_order(root -> left);
  post_order(root -> right);
  visit(root);
}

2、非递归实现

void post_order(BiTree root) {
  Stack s;
  init_stack(s);
  BiTree p = root;
  while(p || !isEmpty(s)) {
    BiTree visitFlag;
    if(p) {
      push(s, p);
      p = p -> left;
    } else {
      //这里需要注意的是一个结点如果有右结点被访问后,由于当前结点还在栈中
      //所以会造成死循环,所以这里需要标识,避免死循环
      top(s, p);
      if  (p -> right && p -> right != visitFlag) {
        p = p -> right;
      } else {
        pop(s, p);
        visit(p);
        //出栈后记录一下,防止重复入栈,避免死循环
        visit_flag = p;
        p = NULL;
      }
    }
  }
}

层次遍历

1、顺序遍历

//层次遍历整体比较简单就是借助队列,
//先访问根结点,如果有左孩子就入栈,有右孩子再入栈,一次扫描栈,直至为空
void levelOrder(BiTree root) {
  BiTree p;
  Queue q;
  initQueue(q);
  enQueue(q, root);
  while (!isEmpty(q)) {
    deQueue(q, p);
    if (p -> left) {
      enQueue(p -> left);
    }
    if (p -> right) {
      enQueue(p -> right);
    }
  }
}

2、逆序遍历

void levelOrderReverse (BiTree root) {
  if (NULL == root) {
    return;
  }
  BiTree cur = root;
   //定义栈,将各结点放入栈中,然后遍历
  Stack s;
  //队列用于层序的正向遍历
  Queue q;
  initStack(s);
  initQueue(s);
  //将树的根结点先入栈
  enQueue(q, cur);
  //将顺序入队的数据,放入栈中
  while (!isEmpty(q)) {
    //出栈
    deQueue(q, cur);
    //放入栈
    push(s, cur);
    if (cur  -> left) {
      enQueue(q, cur -> left);
    }
    if (cur -> right) {
      enQueue(q, cur  -> right);
    }
  }
  //将栈中数据出栈分别访问
  while (!isEmpty(s)) {
    pop(s, p);
    visit(p);
  }
}

你可能感兴趣的:(数据结构之二叉树2)