二叉树遍历之前序遍历(递归与非递归)

一、前序遍历简介
二叉树的遍历方法一共有很多,今天我们先来了解一下二叉树的前序遍历。
前序遍历的顺序:根、左子树、右子树。
在这里插入图片描述
如图中这棵树前序的遍历结果应该是1、2、4、8、9、5、3、6、7。
先根1 ,然后左子树(我们要先处理完这整棵左子树再去看1的右子树),左子树在根2,然后又是左子树,根4,然后又是左子树,8,8在没有左边,所以接下来是4的右边9,然后是2的右边5,然后是1的整棵右子树,也遵循同样的规律根3,左子树6,6在没有左,则是右7,结束。

二、二叉树前序遍历递归与非递归
(我觉得我文字叙述的真的非常的啰嗦,但是我想用文字来描述出我的理解和思路,建议大家可以用笔跟着代码画一画,画出一棵树走一走,可以直接看代码,文字我自己都觉得啰嗦,😔)
1、非递归遍历
前序遍历的顺序是根,左子树,右子树,我们通过根可以找到左孩子,然后如果根的左孩子非叶子结点,我们要让它成为新根,打印,在找左子树,那么现在问题来了,如果最开始的根有右孩子,如何才能够找到呢,一定是要通过根才能找到右孩子,我们在向下走,继续打印的时候已经把根改变了,所以现在的问题变成了如何可以找到一路走来的根呢?当然是要把这些根保存起来,先路过的根的右子树一定是后被处理,所以先路过的根要先保存后处理,那么我们学过的哪种数据结构既可以保存元素,还可以实现这种先保存后用的特性呢?当然就是我们学过的栈啦!先进后出的特性使它成为我们这次代码实现的得力助手。不过我们要把栈里面保存的元素类型换一下,以前一般都是数据类型,现在是二叉树的结点类型。
2、非递归代码实现分析
首先我们要定义一个辅助栈,并对它初始化,接着就要开始遍历,这显然是一个循环过程。然后进行遍历,根,打印,保存入栈,找左孩子,成为新根,在打印、保存,这个过程就是一直向左,那么什么时候结束呢?那就是根的左面是空,(不能在向左走)也就是再次赋值的新根为空,接着就要弹出上面的根,通过这些根来找右,让根的右孩子成为新根,因为我们还在一个遍历整棵树的大循环里,让新根再次进入打印,保存,向左走的过程,其实每一棵树都是重复上述过程,那么什么时候可以结束最大的循环,遍历完成呢?我们每弹出一个根,是不是就证明他已经被处理完左孩子,马上要被处理右孩子,等到栈里的每一个根都被弹出,每一个根都处理完左孩子和右孩子的时候,我们的任务就完成了。所以在弹出以前,我们要先判断一下,栈内元素个数是否为0,是0则结束循环。
3、非递归代码实现

void UnRecPreTravresal(BinaryTree* pTree)
  {
      if(pTree == NULL) return;
      //辅助栈
      Stack *pStack = NULL;
      s_Init(&pStack);
  
      //遍历
      while(1)
      {
          while(pTree)
          {
              //打印
			  printf("%d ",pTree->nVaule);
             //保存
             s_Push(pStack,pTree);
             //向左走
             pTree = pTree->pLeft;
         }
         if(pStack->nCount == 0) break;
         //弹出
         pTree = s_Pop(pStack);
         // 找右
         pTree = pTree->pRight;
     }
     printf("\n");
 }

4、递归遍历与代码实现
递归就是自己调用自己,每结束当前所处的函数,都会跳回到上一次的函数里,先打印根,然后是根的左孩子,打印,是不是就相当于根的左孩子进入到当前的这个函数,然后根的左孩子又进入,根的左孩子为空结束,跳到上一层函数根的左孩子走完了,到根右孩子,成为新根又进入到函数中,打印,在左孩子 … …

void PreorderTraversal(BinaryTree *pTree)
   {
       if(pTree == NULL) return;
  
       printf("%d ",pTree->nVaule);
  
       PreorderTraversal(pTree->pLeft);
  
       PreorderTraversal(pTree->pRight);
  
  }

三、全部代码及结果

#include<stdio.h>
#include<stdlib.h>
 typedef struct node
 {
       int nVaule;
       struct node *pRight;
       struct node *pLeft;

  }BinaryTree;
//手动造一棵僵硬的树,5个结点,用来测试代码
BinaryTree *CreateBinarytree()
 {   
     BinaryTree* pRoot = NULL;
     //根
     pRoot = (BinaryTree*)malloc(sizeof(BinaryTree));
     pRoot->nVaule = 1;
     //根的左
     pRoot->pLeft = (BinaryTree*)malloc(sizeof(BinaryTree));
     pRoot->pLeft->nVaule = 2;
     //根的左的左
     pRoot->pLeft->pLeft = (BinaryTree*)malloc(sizeof(BinaryTree));
     pRoot->pLeft->pLeft->nVaule = 4;
     pRoot->pLeft->pLeft->pLeft = NULL;
     pRoot->pLeft->pLeft->pRight = NULL;
     //根的左的右
     pRoot->pLeft->pRight = (BinaryTree*)malloc(sizeof(BinaryTree));
     pRoot->pLeft->pRight->nVaule = 5;
     pRoot->pLeft->pRight->pLeft = NULL;
     pRoot->pLeft->pRight->pRight = NULL;
     //根的右
     pRoot->pRight = (BinaryTree*)malloc(sizeof(BinaryTree));
     pRoot->pRight->nVaule = 3;
     pRoot->pRight->pLeft = NULL;
     pRoot->pRight->pRight = NULL;

      return pRoot;
  }
typedef struct data
 {   
     BinaryTree* nValue;
     struct data *pNext;
 }MyStack;
 
 typedef struct stack
 {   
     int nCount;
     MyStack *pTop;
 }Stack;
 
 void s_Init(Stack **pStack)
 {   
     *pStack=(Stack*)malloc(sizeof(Stack));
     (*pStack)->nCount=0;
     (*pStack)->pTop=NULL;
 
 }
 void s_Push(Stack *pStack,BinaryTree* nNum)
 {   
     if(pStack==NULL)
     {
         printf("不存在\n");
         return;
     }
      
      MyStack *pTemp=NULL;
      pTemp=(MyStack*)malloc(sizeof(MyStack));
      pTemp->nValue=nNum;
      pTemp->pNext=pStack->pTop;
      pStack->pTop=pTemp;
      pStack->nCount++;
  }
 BinaryTree* s_Pop(Stack *pStack)
  {   
      if(pStack==NULL) exit(1);
      if(pStack->pTop==NULL) return NULL;
      
      MyStack *pDel=pStack->pTop;
      BinaryTree* nNum=pDel->nValue;
  
      pStack->pTop=pStack->pTop->pNext;
      free(pDel);
      pDel=NULL;
      pStack->nCount--;
      return nNum;
  
  }
  void UnRecPreTravresal(BinaryTree* pTree)
  {
      if(pTree==NULL) return;
      //辅助栈
      Stack *pStack =NULL;
      s_Init(&pStack);
  
      //遍历
      while(1)
      {
          while(pTree)
          {
              //打印
			  printf("%d ",pTree->nVaule);
             //保存
             s_Push(pStack,pTree);
             //向左走
             pTree=pTree->pLeft;
         }
         if(pStack->nCount==0) break;
         //弹出
         pTree=s_Pop(pStack);
         // 找右
         pTree=pTree->pRight;
     }
     printf("\n");
 }


//前序的递归遍历
   void PreorderTraversal(BinaryTree *pTree)
   {
       if(pTree == NULL) return;
  
       printf("%d ",pTree->nVaule);
  
       PreorderTraversal(pTree->pLeft);
  
       PreorderTraversal(pTree->pRight);
  
  }


int main()
{
	BinaryTree* pTree = NULL;
	pTree=CreateBinarytree();
	PreorderTraversal(pTree);
	printf("\n");
	UnRecPreTravresal(pTree);
	printf("\n");


	return 0;

}

在这里插入图片描述

在这里插入图片描述

  • 11
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值