二叉树遍历

先序

递归

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语言版)的更多相关文章

  1. 二叉树的建立与递归遍历C语言版

    </pre><pre name="code" class="cpp">#include <stdio.h> #include ...

  2. 二叉树的基本操作(C语言版)

    今天走进数据结构之二叉树 二叉树的基本操作(C 语言版) 1 二叉树的定义 二叉树的图长这样: 二叉树是每个结点最多有两个子树的树结构,常被用于实现二叉查找树和二叉堆.二叉树是链式存储结构,用的是二叉 ...

  3. 二叉树遍历(非递归版)——python

    二叉树的遍历分为广度优先遍历和深度优先遍历 广度优先遍历(breadth first traversal):又称层次遍历,从树的根节点(root)开始,从上到下从从左到右遍历整个树的节点. 深度优先遍 ...

  4. 学习笔记——二叉树相关算法的实现(Java语言版)

    二叉树遍历概念和算法 遍历(Traverse): 所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问. 从二叉树的递归定义可知,一棵非空的二叉树由根结点及左. ...

  5. 数据结构(C语言版)-第5章 树和二叉树

    5.1  树和二叉树的定义 树(Tree)是n(n≥0)个结点的有限集,它或为空树(n = 0):或为非空树,对于非空树T:(1)有且仅有一个称之为根的结点:(2)除根结点以外的其余结点可分为m(m& ...

  6. 数据结构(c语言版)代码

    第1章  绪论       文档中源码及测试数据存放目录:数据结构\▲课本算法实现\▲01 绪论  概述        第一章作为绪论,主要介绍了数据结构与算法中的一些基本概念和术语.对于这些概念术语 ...

  7. c++学习书籍推荐《清华大学计算机系列教材:数据结构(C++语言版)(第3版)》下载

    百度云及其他网盘下载地址:点我 编辑推荐 <清华大学计算机系列教材:数据结构(C++语言版)(第3版)>习题解析涵盖验证型.拓展型.反思型.实践型和研究型习题,总计290余道大题.525道 ...

  8. 数据结构C语言版 有向图的十字链表存储表示和实现

    /*1wangxiaobo@163.com 数据结构C语言版 有向图的十字链表存储表示和实现 P165 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h> ...

  9. 二叉树遍历(flist)(二叉树,已知中序层序,求先序)

    问题 C: 二叉树遍历(flist) 时间限制: 1 Sec  内存限制: 128 MB提交: 76  解决: 53[提交][状态][讨论版][命题人:quanxing][Edit] [TestDat ...

  10. 二叉树遍历(flist)(已知中序和按层遍历,求先序 )

    问题 F: 二叉树遍历(flist) 时间限制: 1 Sec  内存限制: 128 MB提交: 11  解决: 9[提交][状态][讨论版][命题人:quanxing][Edit] [TestData ...

随机推荐

  1. 【转载】 HTTP中的响应协议及302、304的含义

    原文地址: https://www.cnblogs.com/chenyablog/p/9197305.html ============================== 响应协议 HTTP/1.1 ...

  2. 再探 游戏 《 2048 》 —— AI方法—— 缘起、缘灭(5) —— 第一个用于解决2048游戏的Reinforcement learning方法——《Temporal Difference Learning of N-Tuple Networks for the Game 2048》

    <2048>游戏在线试玩地址: https://play2048.co/ 如何解决<2048>游戏源于外网的一个讨论帖子,而这个帖子则是讨论如何解决该游戏的最早开始,可谓是&q ...

  3. java多线程之ReentrantLock详解

    1.背景 2.基本语法 public class Test01 { // 定义锁 static ReentrantLock reentrantLock = new ReentrantLock(); p ...

  4. 多线程之park()与interrupt()的理解

    1.背景 其他不多说,很多时候面试会问 2.代码 package com.ldp.demo01; import com.common.MyThreadUtil; import lombok.exter ...

  5. 2023上海理工大学校内选拔赛A-D题

    前言 不要在意标题,既然是随记,就随性点() 今天参加了2023年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛(同步赛)_ACM/NOI/CSP/CCPC/ICPC算法编程 ...

  6. 第 111 场双周赛 - 力扣(LeetCode)

    第 111 场双周赛 - 力扣(LeetCode) 2824. 统计和小于目标的下标对数目 - 力扣(LeetCode) 枚举即可 class Solution { public: int count ...

  7. 神经网络之卷积篇:详解三维卷积(Convolutions over volumes)

    详解三维卷积 从一个例子开始,假如说不仅想检测灰度图像的特征,也想检测RGB彩色图像的特征.彩色图像如果是6×6×3,这里的3指的是三个颜色通道,可以把它想象成三个6×6图像的堆叠.为了检测图像的边缘 ...

  8. IoTSharp:基于 .NET 8.0 的开源物联网平台

    前言 想要快速了解物联网的世界吗?如果你对物联网(IoT)感兴趣,或者正打算开发自己的物联网项目.可以试试 IoTSharp,一个基于 .NET 的开源平台. 无论你是初学者还是有经验的大佬,IoTS ...

  9. 异源数据同步 → DataX 为什么要支持 kafka?

    开心一刻 昨天发了一条朋友圈:酒吧有什么好去的,上个月在酒吧当服务员兼职,一位大姐看上了我,说一个月给我 10 万,要我陪她去上海,我没同意 朋友评论道:你没同意,为什么在上海? 我回复到:上个月没同 ...

  10. 关于人工智能的思考,写在chatGPT爆火之时

    今天是2023年3月22日,今天思维比较活跃,故作文一篇,以记录当下所想. 先是回家询问了未婚妻的想法,然后记录自己的想法. 未婚妻的想法: 1.在AI领域已经滞后于世界了.因为在墙头上看到过一个加拿 ...