二叉树四种遍历的实现

简介: 二叉树四种遍历的实现

前言


二叉树的遍历有:前序/中序/后序的递归结构遍历以及层序遍历。遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。


前序遍历(Preorder Traversal)


深度优先搜索(DFS)通常指的就是前序遍历(也叫先序遍历);

遍历顺序:当前结点(根节点 ), 左子树, 右子树 即访问根结点的操作发生在遍历其左右子树之前

代码实现:

typedef struct BTNode
{
    char _data;
    struct BTNode* _left;
    struct BTNode* _right;
}BTNode;
// 二叉树前序遍历
void Preorder(BTNode* root)
{
  if (root == NULL) //如果为空,直接返回  后两个遍历简化此过程
    return;
  printf("%d", root->_data);
  Preorder(root->_left);
  Preorder(root->_right);
}


图解:


image.png


中序遍历历(Inorder Traversal)


遍历顺序:左子树,根节点,右子树 访问根结点的操作发生在遍历其左右子树之中(间)。

代码实现:

typedef struct BTNode
{
    char _data;
    struct BTNode* _left;
    struct BTNode* _right;
}BTNode;
//二叉树中序遍历
void Inorder(BTNode* root)
{
    if(root)
    {
        Inorder(root->_left);
        printf("%c ", root->_data);
        Inorder(root->_right);
    }
}


后序遍历(Postorder Traversal)


遍历顺序:左子树,右子树,根节点 访问根结点的操作发生在遍历其左右子树之后。

代码实现:

typedef struct BTNode
{
    char _data;
    struct BTNode* _left;
    struct BTNode* _right;
}BTNode;
// 二叉树后序遍历
void PostOrder(BTNode* root)
{
  if (root)
  {
    PostOrder(root->_left);
    PostOrder(root->_right);
    printf("%c", root->_data);
  }
}


由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为

根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。


层序遍历


也叫广度优先搜索(BFS)。遍历顺序:从所在二叉树的根节点出发,从上到下按层遍历,每层从左到右遍历


1c302e2a789b4661b9b186a3bd9fe4db.png


代码实现

这里我们利用队列其先进先出的性质,实现层序遍历

队列:

// Queue.h
#pragma once
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <stdlib.h>
// 前置声明
struct BinaryTreeNode;
typedef struct BinaryTreeNode* QDataType;
typedef struct QueueNode
{
  struct QueueNode* next;
  QDataType data;
}QNode;
typedef struct Queue
{
  QNode* head;
  QNode* tail;
}Queue;
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
// 队尾入
void QueuePush(Queue* pq, QDataType x);
// 队头出
void QueuePop(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
//Queue.c
#include "Queue.h"
void QueueInit(Queue* pq)
{
  assert(pq);
  pq->head = pq->tail = NULL;
}
void QueueDestory(Queue* pq)
{
  assert(pq);
  QNode* cur = pq->head;
  while (cur)
  {
    QNode* next = cur->next;
    free(cur);
    cur = next;
  }
  pq->head = pq->tail = NULL;
}
// 队尾入
void QueuePush(Queue* pq, QDataType x)
{
  assert(pq);
  QNode* newnode = (QNode*)malloc(sizeof(QNode));
  if (newnode == NULL)
  {
    printf("malloc fail\n");
    exit(-1);
  }
  newnode->data = x;
  newnode->next = NULL;
  if (pq->tail == NULL)
  {
    pq->head = pq->tail = newnode;
  }
  else
  {
    pq->tail->next = newnode;
    pq->tail = newnode;
  }
}
// 队头出
void QueuePop(Queue* pq)
{
  assert(pq);
  assert(pq->head);
  // 1、一个
  // 2、多个
  if (pq->head->next == NULL)
  {
    free(pq->head);
    pq->head = pq->tail = NULL;
  }
  else
  {
    QNode* next = pq->head->next;
    free(pq->head);
    pq->head = next;
  }
}
QDataType QueueFront(Queue* pq)
{
  assert(pq);
  assert(pq->head);
  return pq->head->data;
}
QDataType QueueBack(Queue* pq)
{
  assert(pq);
  assert(pq->head);
  return pq->tail->data;
}
int QueueSize(Queue* pq)
{
  assert(pq);
  int size = 0;
  QNode* cur = pq->head;
  while (cur)
  {
    ++size;
    cur = cur->next;
  }
  return size;
}
bool QueueEmpty(Queue* pq)
{
  assert(pq);
  return pq->head == NULL;
}


层序遍历:

typedef int BTDataType;
typedef struct BinaryTreeNode
{
  BTDataType data;
  struct BinaryTreeNode* left;
  struct BinaryTreeNode* right;
}BTNode;
void LevelOrder(BTNode* root)
{
  Queue q;
  QueueInit(&q);
  if (root != NULL)
    QueuePush(&q, root);
  while (!QueueEmpty(&q))  //队列不为空则继续
  {
    BTNode* front = QueueFront(&q);
    QueuePop(&q);
    printf("%c", front->data);
    if (front->left) //if左边不为空
    {
      QueuePush(&q, front->left);
    }
    if (front->right)
    {
      QueuePush(&q, front->right);
    }
  }
  printf("\n");
  QueueDestory(&q);
}
int main()
{
  BTNode* root;
  LevelOrder(root);
}



本节完

相关文章
|
安全 算法 编译器
【C++ 泛型编程 入门篇】 C++ 模板元编程之枚举内嵌 实战教程
【C++ 泛型编程 入门篇】 C++ 模板元编程之枚举内嵌 实战教程
284 0
|
机器学习/深度学习 自然语言处理
文生图模型-Stable Diffusion | AIGC
所谓的生成式模型就是通过文本或者随机采样的方式来得到一张图或者一段话的模型,比如文生图,顾名思义通过文本描述来生成图像的过程。当前流行的文生图模型,如DALE-2, midjourney以及今天要介绍的Stable Diffusion,这3种都是基于Diffusion扩散模型【1月更文挑战第6天】
1516 0
|
Cloud Native 数据可视化 架构师
一文看懂蚂蚁BizStack 云原生开发和治理平台
在数字化转型大背景下,企业如何解决业务敏捷交付、科技持续治理难题?
1710 2
一文看懂蚂蚁BizStack 云原生开发和治理平台
|
传感器 开发框架 物联网
揭开.NET在IoT领域的神秘面纱:如何构建智能设备,让未来生活触手可及?
【8月更文挑战第28天】随着物联网技术的发展,智能设备正深入我们的生活。.NET作为跨平台开源框架,在IoT领域应用广泛。本文介绍如何利用.NET构建智能设备,通过实例展示从环境搭建到项目创建、代码编写及运行的全过程,帮助开发者快速实现IoT解决方案,开启智能设备开发的新篇章。
333 0
|
存储 Ubuntu 算法
KNIME学习记录
KNIME学习记录
1010 0
|
缓存 算法 开发者
【Conan 入门教程 】了解 Conan2.1 中内置部署策略
【Conan 入门教程 】了解 Conan2.1 中内置部署策略
276 1
|
JSON C++ 数据格式
《C++避坑神器·二十二》VS能正常运行程序,但运行exe程序无响应解决办法
《C++避坑神器·二十二》VS能正常运行程序,但运行exe程序无响应解决办法
426 0
子串分值和(蓝桥杯C组)
子串分值和(蓝桥杯C组)
96 0
|
IDE Java 开发工具
【问题记录与解决】启动Jupyter,运行代码时报错【Error】 || 通过 Jupyter 建立的Python文件在哪儿 || Jupyter 中 移动 Python 文件 到 指定文件夹
和大家大部分遇到的问题一样,也是在启动Jupyter时,发现运行不了简单的代码,报错Error。而且对当前文件也执行不了“重命名”。
【问题记录与解决】启动Jupyter,运行代码时报错【Error】 || 通过 Jupyter 建立的Python文件在哪儿 || Jupyter 中 移动 Python 文件 到 指定文件夹