二叉树遍历(C语言版)
二叉树遍历
先序
递归
int *res;
void preorder(struct TreeNode *root, int *returnSize) {
if (root == NULL) return;
// 根左右
res[(*returnSize)++] = root->val;
preorder(root->left, returnSize);
preorder(root->right, returnSize);
}
int *preorderTraversal(struct TreeNode *root, int *returnSize) {
res = (int *) malloc(sizeof(int) * 100);
*returnSize = 0;
preorder(root, returnSize);
return res;
}
迭代
int *preorderTraversal(struct TreeNode *root, int *returnSize) {
int *res = (int *) malloc(sizeof(int) * 100);
*returnSize = 0;
struct TreeNode *stack[100];
int top = 0;
while (top != 0 || root != NULL) {
// 左子树入栈
while (root != NULL) {
// 访问
res[(*returnSize)++] = root->val;
stack[top++] = root;
root = root->left;
}
root = stack[--top];
root = root->right;
}
return res;
}
迭代(右子树先入栈)
int *preorderTraversal(struct TreeNode *root, int *returnSize) {
int *res = (int *) malloc(sizeof(int) * 100);
*returnSize = 0;
if (root == NULL) return res;
struct TreeNode *stack[100];
int top = 0;
stack[top++] = root;
while (top != 0) {
root = stack[--top];
res[(*returnSize)++] = root->val;
// 右子树先入栈
if (root->right != NULL) stack[top++] = root->right;
if (root->left != NULL) stack[top++] = root->left;
}
return res;
}
右左根访问,再反转序列
int *res;
void dfs(struct TreeNode *root, int *returnSize) {
if (root == NULL) return;
// 按右左根的顺序访问,再把序列反过来
dfs(root->right, returnSize);
dfs(root->left, returnSize);
res[(*returnSize)++] = root->val;
}
int *preorderTraversal(struct TreeNode *root, int *returnSize) {
res = (int *) malloc(sizeof(int) * 100);
*returnSize = 0;
if (root == NULL) return res;
dfs(root, returnSize);
// 序列反过来
int left = 0, right = *returnSize - 1;
while (left < right) {
int temp = res[left];
res[left] = res[right];
res[right] = temp;
left++;
right--;
}
return res;
}
Morris
int *res;
// Morris
void preorderMorris(struct TreeNode *root, int *returnSize) {
if (root == NULL) return;
struct TreeNode *cur = root;
while (cur != NULL) {
if (cur->left != NULL) {
// 左子树不空,遍历左子树,找到左子树的最右侧节点
struct TreeNode *rightMost = cur->left;
while (rightMost->right != NULL && rightMost->right != cur) {
rightMost = rightMost->right;
}
// 最右侧节点的右指针指向NULL或者cur
if (rightMost->right == NULL) {
// 有左右孩子的节点第一次被访问
res[(*returnSize)++] = cur->val;
// 把最右侧节点的right指向cur
rightMost->right = cur;
// 访问左子树
cur = cur->left;
} else {
// 有左右孩子的节点第二次被访问
// 恢复
rightMost->right = NULL;
// 遍历右子树
cur = cur->right;
}
} else {
// 只有右孩子的节点只会被访问一次
res[(*returnSize)++] = cur->val;
// 遍历右子树
cur = cur->right;
}
}
}
int *preorderTraversal(struct TreeNode *root, int *returnSize) {
res = (int *) malloc(sizeof(int) * 100);
*returnSize = 0;
if (root == NULL) return res;
preorderMorris(root, returnSize);
return res;
}
中序
递归
int *res;
void inorder(struct TreeNode *root, int *returnSize) {
if (root == NULL) return;
// 左根右
inorder(root->left, returnSize);
res[(*returnSize)++] = root->val;
inorder(root->right, returnSize);
}
int *inorderTraversal(struct TreeNode *root, int *returnSize) {
res = (int *) malloc(sizeof(int) * 100);
*returnSize = 0;
inorder(root, returnSize);
return res;
}
迭代
int *inorderTraversal(struct TreeNode *root, int *returnSize) {
int *res = (int *) malloc(sizeof(int) * 100);
*returnSize = 0;
struct TreeNode *stack[100];
int top = 0;
while (top != 0 || root != NULL) {
// 左子树入栈
while (root != NULL) {
stack[top++] = root;
root = root->left;
}
root = stack[--top];
// 访问
res[(*returnSize)++] = root->val;
root = root->right;
}
return res;
}
Morris
int *res;
void inorderMorris(struct TreeNode *root, int *returnSize) {
if (root == NULL) return;
struct TreeNode *cur = root;
while (cur != NULL) {
if (cur->left != NULL) {
struct TreeNode *rightMost = cur->left;
while (rightMost->right != NULL && rightMost->right != cur) {
rightMost = rightMost->right;
}
if (rightMost->right == NULL) {
rightMost->right = cur;
cur = cur->left;
} else {
// 有左右孩子的节点第二次被经过,左子树都遍历完了,访问节点
res[(*returnSize)++] = cur->val;
rightMost->right = NULL;
cur = cur->right;
}
} else {
// 只有右孩子的节点只会被经过一次,直接访问
res[(*returnSize)++] = cur->val;
cur = cur->right;
}
}
}
int *inorderTraversal(struct TreeNode *root, int *returnSize) {
res = (int *) malloc(sizeof(int) * 100);
*returnSize = 0;
if (root == NULL) return res;
inorderMorris(root, returnSize);
return res;
}
后序
递归
int *res;
void postOrder(struct TreeNode *root, int *returnSize) {
if (root == NULL) return;
// 左右根
postOrder(root->left, returnSize);
postOrder(root->right, returnSize);
res[(*returnSize)++] = root->val;
}
int *postorderTraversal(struct TreeNode *root, int *returnSize) {
res = (int *) malloc(sizeof(int) * 100);
*returnSize = 0;
postOrder(root, returnSize);
return res;
}
迭代
int *postorderTraversal(struct TreeNode *root, int *returnSize) {
int *res = (int *) malloc(sizeof(int) * 100);
*returnSize = 0;
struct TreeNode *stack[100];
int top = 0;
// 记录上个访问的节点
struct TreeNode *pre = NULL;
while (top != 0 || root != NULL) {
// 左子树入栈
while (root != NULL) {
stack[top++] = root;
root = root->left;
}
root = stack[--top];
if (root->right == NULL || root->right == pre) {
// 右子树为空或者已经访问完了,可以访问这个节点了
res[(*returnSize)++] = root->val;
pre = root;
root = NULL;
} else {
// 遍历右子树
// 先把当前节点再次压栈
stack[top++] = root;
root = root->right;
}
}
return res;
}
Morris
int *res;
// 把右子树反转
struct TreeNode *reverseRightTree(struct TreeNode *root) {
struct TreeNode *pre = NULL;
struct TreeNode *cur = root;
while (cur != NULL) {
struct TreeNode *nextRight = cur->right;
cur->right = pre;
pre = cur;
cur = nextRight;
}
return pre;
}
// 自底向上访问右节点(访问反转后的右节点)
void visitReversedRightTree(struct TreeNode *root, int *returnSize) {
// 反转右子树
struct TreeNode *reversed = reverseRightTree(root);
struct TreeNode *cur = reversed;
while (cur != NULL) {
res[(*returnSize)++] = cur->val;
cur = cur->right;
}
// 反转回去
reverseRightTree(reversed);
}
void postorderMorris(struct TreeNode *root, int *returnSize) {
struct TreeNode *cur = root;
while (cur != NULL) {
if (cur->left != NULL) {
struct TreeNode *rightMost = cur->left;
while (rightMost->right != NULL && rightMost->right != cur) {
rightMost = rightMost->right;
}
if (rightMost->right == NULL) {
rightMost->right = cur;
cur = cur->left;
} else {
rightMost->right = NULL;
// 一个节点被第二次经过的时候,自底向上访问左子树的所有的右节点
visitReversedRightTree(cur->left, returnSize);
cur = cur->right;
}
} else {
cur = cur->right;
}
}
// 再遍历一次
visitReversedRightTree(root, returnSize);
}
int *postorderTraversal(struct TreeNode *root, int *returnSize) {
res = (int *) malloc(sizeof(int) * 100);
*returnSize = 0;
if (root == NULL) return res;
postorderMorris(root, returnSize);
return res;
}
层序
int **levelOrder(struct TreeNode *root, int *returnSize, int **returnColumnSizes) {
// 一层最多元素个数
const int size = 1002;
// 最多层数
const int leverMax = 2000;
// 返回的二维数组,第一维表示所在层,第二维表示该层的所有元素
int **res = (int **) malloc(sizeof(int *) * leverMax);
// 一维的维度(多少层)
*returnSize = 0;
// 每个二维的维度(每层多少元素)
*returnColumnSizes = (int *) malloc(sizeof(int) * leverMax);
if (root == NULL) return res;
// 循环队列
struct TreeNode *queue[size];
int lever = 0;
// 保存每层元素个数,下标就是所在层,从0开始
int *columnSize = (int *) calloc(leverMax, sizeof(int));
int front = 0, rear = 0;
queue[rear++] = root;
while (front != rear) {
// 当前层元素数
int count = (rear - front + size) % size;
res[lever] = (int *) malloc(sizeof(int) * count);
int temp = 0;
while (count-- > 0) {
root = queue[(front++) % size];
// 记录当前层的元素
res[lever][temp++] = root->val;
// 当前层元素总数加一
columnSize[lever]++;
if (root->left != NULL) queue[(rear++) % size] = root->left;
if (root->right != NULL) queue[(rear++) % size] = root->right;
}
// 加一层
lever++;
}
*returnSize = lever;
for (int i = 0; i < lever; ++i)
(*returnColumnSizes)[i] = columnSize[i];
return res;
}
二叉树遍历(C语言版)的更多相关文章
- 二叉树的建立与递归遍历C语言版
</pre><pre name="code" class="cpp">#include <stdio.h> #include ...
- 二叉树的基本操作(C语言版)
今天走进数据结构之二叉树 二叉树的基本操作(C 语言版) 1 二叉树的定义 二叉树的图长这样: 二叉树是每个结点最多有两个子树的树结构,常被用于实现二叉查找树和二叉堆.二叉树是链式存储结构,用的是二叉 ...
- 二叉树遍历(非递归版)——python
二叉树的遍历分为广度优先遍历和深度优先遍历 广度优先遍历(breadth first traversal):又称层次遍历,从树的根节点(root)开始,从上到下从从左到右遍历整个树的节点. 深度优先遍 ...
- 学习笔记——二叉树相关算法的实现(Java语言版)
二叉树遍历概念和算法 遍历(Traverse): 所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问. 从二叉树的递归定义可知,一棵非空的二叉树由根结点及左. ...
- 数据结构(C语言版)-第5章 树和二叉树
5.1 树和二叉树的定义 树(Tree)是n(n≥0)个结点的有限集,它或为空树(n = 0):或为非空树,对于非空树T:(1)有且仅有一个称之为根的结点:(2)除根结点以外的其余结点可分为m(m& ...
- 数据结构(c语言版)代码
第1章 绪论 文档中源码及测试数据存放目录:数据结构\▲课本算法实现\▲01 绪论 概述 第一章作为绪论,主要介绍了数据结构与算法中的一些基本概念和术语.对于这些概念术语 ...
- c++学习书籍推荐《清华大学计算机系列教材:数据结构(C++语言版)(第3版)》下载
百度云及其他网盘下载地址:点我 编辑推荐 <清华大学计算机系列教材:数据结构(C++语言版)(第3版)>习题解析涵盖验证型.拓展型.反思型.实践型和研究型习题,总计290余道大题.525道 ...
- 数据结构C语言版 有向图的十字链表存储表示和实现
/*1wangxiaobo@163.com 数据结构C语言版 有向图的十字链表存储表示和实现 P165 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h> ...
- 二叉树遍历(flist)(二叉树,已知中序层序,求先序)
问题 C: 二叉树遍历(flist) 时间限制: 1 Sec 内存限制: 128 MB提交: 76 解决: 53[提交][状态][讨论版][命题人:quanxing][Edit] [TestDat ...
- 二叉树遍历(flist)(已知中序和按层遍历,求先序 )
问题 F: 二叉树遍历(flist) 时间限制: 1 Sec 内存限制: 128 MB提交: 11 解决: 9[提交][状态][讨论版][命题人:quanxing][Edit] [TestData ...
随机推荐
- tensorflow1.x——如何在python多线程中调用同一个session会话
如何在python多线程中调用同一个session会话? 这个问题源于我在看的一个强化学习代码: https://gitee.com/devilmaycry812839668/scalable_age ...
- 《最新出炉》系列小成篇-Python+Playwright自动化测试-67 - 模拟手机浏览器兼容性测试
1.简介 在日常工作中,我们会遇到需要使用不同的硬件设备测试兼容性的问题,尤其是现在手机型号基本上是每个厂家每年发布一款新机型,而且手机的屏幕大小分辨率五花八门的,我们基本不可能全部机型都用真机测试一 ...
- JavaScript设计模式样例二十二 —— 访问者模式
访问者模式(Visitor Pattern) 定义:使用一个访问者类,改变元素类的执行算法.通过这种方式,元素的执行算法可以随着访问者改变而改变.目的:将数据结构与数据操作分离.场景:您在朋友家做客, ...
- 快手 内推码:TYORVzmsw 秋招 应届生/实习生 真正本人内推 已有多人在我内推之后,接连顺利通过了HR筛选、用人部门筛选、面试!
内推码:TYORVzmsw 校园招聘岗位列表:https://campus.kuaishou.cn/#/campus/jobs?code=TYORVzmsw 真正的本人内部推荐! 已有多人在我内推之后 ...
- Graphics2D绘图方法总结
一.简介 在开发中可能会遇到这样一类场景,业务复杂度不算太高,技术难度不算太深,但是做起来就很容易把人整破防,伤害很高侮辱性很强的:绘图. 绘图最怕有人挑刺:这里变形,那里不对,全图失真. 最近在处理 ...
- Maven 配置程序入口
配置单个程序入口 Exec Maven Plugin 插件允许你在 Maven 生命周期中的某个阶段直接运行 Java 类. 在你的 pom.xml 文件中添加如下配置: <project> ...
- 工程化Vue使用
目录 环境准备 Vue项目-创建 Vue项目开发流程 API风格 案例 推荐阅读: VUE-局部使用 环境准备 介绍:create-vue是Vue官方提供的最新的脚手架工具,用于快速生成一个工程化的V ...
- mysql 存储结构介绍及执行过程分析
MySQL体系结构介绍 1 mysql 的体系结构 MySQL整体的逻辑结构可以分为4层,客户层.服务层.存储引擎层.数据层 客户层 客户层:进行相关的连接处理.权限控制.安全处理等操作 服务层 服务 ...
- Istio实现sidecar自动注入
Istio实现sidecar自动注入 Sidecar模式 在Sidecar部署方式中,你会为每个应用的容器部署一个伴生容器.对于Service Mesh,Sidecar接管进出应用程序容器的所有网络流 ...
- 一文轻松搞定 tarjan 算法(二)(附带 tarjan 题单)
完结篇:tarjan 求割点.点双连通分量.割边(桥)(附 40 道很好的 tarjan 题目). 上一篇(tarjan 求强连通分量,缩点,求边双) tarjan 求割点 还是求强联通分量的大致思路 ...