[数据结构基础]链式二叉树及其前序、中序和后序遍历

news/2025/1/15 21:51:34/

一. 链式二叉树的结构和实现

1.1 链式二叉树的结构

链式二叉树,即使用链来表示一颗二叉树。链式二叉树的存储又可分为二叉链和三叉链,其中二叉链存储节点数据、指向左子节点的指针和指向右子节点的指针,三叉链相对于二叉链多存储指向父亲节点的指针,二叉链和三叉链的结构见图1.1。

1.2 链式二叉树的实现

链式二叉树的实现与链表节点的实现类似,要定义一个结构体,其成员包括存储的数据、指向左孩子节点的指针和指向右孩子节点的指针,如果是三叉链要多包含一个指向父亲节点的指针。

typedef int BTDataType;   //重定义节点数据类型//采用二叉链表定义
typedef struct BinaryTreeNode
{BTDataType data;   //节点数据struct BinaryTreeNode* left;  //指向左孩子节点的指针struct BinaryTreeNode* right; //指向右孩子节点的指针
};//采用三叉链表定义
typedef struct BinaryTreeNode
{BTDataType data;   //节点数据struct BinaryTreeNode* parent;  //指向父亲节点的指针 struct BinaryTreeNode* left;    //指向左孩子节点的指针struct BinaryTreeNode* right;   //指向右孩子节点的指针
};

1.3 链式二叉树节点的创建

采用BuyNode函数,创建链式二叉树节点(这里以二叉链表为例)。BuyNode函数有一个参数x,为节点要存储的数据,函数进行的操作有:为节点动态开辟内存空间、将x存入节点空间、将指向左孩子节点的指针和指向右孩子节点的指针均置为NULL。

BuyNode函数代码:

BTNode* BuyNode(BTDataType x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));assert(newnode);newnode->data = x;newnode->left = newnode->right = NULL;return newnode;
}

二.  二叉树的前序、中序和后序遍历

2.1 前序、中序和后序遍历的概念

  1. 前序遍历(Preorder Traversal 亦称先序遍历):在遍历左右子树之前访问根节点。具体遍历顺序为:根节点 -> 左子树 -> 右子树。
  2. 中序遍历(Inorder Traversal):访问根节点发生在遍历左右子树之间。具体遍历顺序为:左子树 -> 根节点 -> 右子树。
  3. 后序遍历(Postorder Traversal):在遍历左右子树之后访问根节点。具体遍历顺序为:左子树 -> 右子树 -> 根节点。
图2.1  二叉树

如图1.2所示的二叉树(\varphi表示空),其前序、中序、后序遍历的访问顺序分别为:

  • 前序遍历:1 -> 2 -> 3 -> NULL -> 4 -> 5 -> 6
  • 中序遍历:3 -> 2 -> NULL -> 1 -> 5 -> 4 -> 6
  • 后序遍历:3 -> NULL -> 2 -> 5 -> 6 -> 4 -> 1
图2.2  图2.1中二叉树的前序、中序、后续遍历图解

 

2.2 链式二叉树的前序、中序、后序遍历的函数实现

无论是对链式二叉树进行前序、中序还是后序遍历,都是采用递归的思想来实现的。

2.2.1 前序遍历函数PreOrder

向函数传入指向根节点的指针作为参数,判断根节点是否为空,如果为空,则函数返回。如果不为空,则先打印该节点的数据,然后先后将指向左孩子节点的指针和指向右孩子节点的指针作为参数传入函数PreOrder进行递归调用即可。

PreOrder函数代码:

void PreOrder(BTNode* root)
{if (NULL == root){return;}printf("%d ", root->data);PreOrder(root->left);PreOrder(root->right);
}

2.2.2 中序遍历函数InOrder

向函数传入指向根节点的指针作为参数,判断根节点是否为空,如果为空,则函数返回。如果不为空,则先将指向左孩子节点的指针作为参数传给函数InOrder递归调用,再打印当前节点数据,最后将指向右孩子节点的指针作为参数传给函数InOrder递归调用即可。

InOrder函数代码:

void InOrder(BTNode* root)
{if (NULL == root){return;}InOrder(root->left);printf("%d ", root->data);InOrder(root->right);
}

2.2.3 后序遍历函数PostOrder

向函数传入指向根节点的指针作为参数,判断根节点是否为空,如果为空,则函数返回。如果不为空,则首先先后将指向左孩子节点的指针和指向右孩子节点的指针作为传入函数进行递归调用,然后打印节点数据即可。

PostOrder函数代码:

void PostOrder(BTNode* root)
{if (NULL == root){return;}PostOrder(root->left);PostOrder(root->right);printf("%d ", root->data);
}


http://www.ppmy.cn/news/12882.html

相关文章

第四十七章 使用 ^SystemPerformance 监视性能 - 自定义 ^SystemPerformance 实用程序

文章目录第四十七章 使用 ^SystemPerformance 监视性能 - 自定义 ^SystemPerformance 实用程序更改输出目录获取版本信息操纵配置文件Create New Profiles第四十七章 使用 ^SystemPerformance 监视性能 - 自定义 ^SystemPerformance 实用程序 本节介绍可以使用 API 完成的任务…

Android Studio 阅读 frameworks/base 下的代码

从网上搜的方案都是生成 android.ipr,但是这个需要整编,整编一次比较费时费劲,所以想了个巧招 首先用 Android Studio 打开 frameworks/base,其文件夹目录大概形如下: ├── Android.bp├── Android.mk├── api …

LeetCode-1814. 统计一个数组中好对子的数目【哈希表】

LeetCode-1814. 统计一个数组中好对子的数目【哈希表】题目描述:解题思路一:由题中nums[i]rev(nums[j])nums[j]rev(nums[i])得到nums[i]-rev(nums[i])nums[j]-rev(nums[j])解题思路二:0解题思路三:0题目描述: 给你一个…

第二类换元法

前置知识:直接积分法 第二类换元法简介 在求∫f(x)dx\int f(x)dx∫f(x)dx时,若不好求,则我们可以令xφ(t)x\varphi(t)xφ(t),则 ∫f(x)dx∫f(φ(t))d(φ(t))∫f(φ(t))φ′(t)dt\int f(x)dx\int f(\varphi(t))d(\varphi(t))\int…

kafka常用命令大全

目录 启动kafka服务 停止kafka服务 创建一个叫demo-topic的主题(topic),有两个分区,每个分区3个副本,同时指定该主题的消息保留时长(72小时) 列出指定主题(topic)的详细信息 查看所有…

C进阶_内存库函数

目录 memcpy 模拟实现memcpy memmove 模拟实现memmove memcmp memcpy 它的函数原型为: void * memcpy ( void * destination, const void * source, size_t num ); 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。 这个函数…

【树莓派4B】搭建HomeAssistant服务端(二)(systemd配置开机自启动,cpolar内网穿透)

设置开机自启动 创建home-assistanthomeassistant.service服务: sudo nano /etc/systemd/system/home-assistanthomeassistant.service复制以下内容,定义服务,其中After定义先行服务,ExecStart执行启动脚本: [Unit]…

HTB打靶(Active Directory 101 Resolute)

nmap扫描 nmap -A -T4 10.10.10.169 Starting Nmap 7.93 ( https://nmap.org ) at 2023-01-16 01:30 EST Stats: 0:00:04 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan SYN Stealth Scan Timing: About 74.65% done; ETC: 01:30 (0:00:01 remaining) St…