二叉树的常见算法
二叉树的遍历
- 先序遍历指的就是先访问本节点,再访问该节点的左孩子和右孩子;
- 中序遍历指的就是:先访问左孩子,再访问本节点,最后访问右孩子;
- 后序遍历指的就是:先访问左右孩子,最后访问本节点。
- 层次遍历:按照树的每一层(高度)进行遍历。
深度遍历
- 递归实现:先序、中序、后序
- 非递归实现:先序、中序、后序
层次遍历
深度遍历
递归实现先序、中序、后序
#include <stdio.h> //声明树类型 typedef struct TREEtag TREEtagNode; struct TREEtag { int val; TREEtagNode *left; TREEtagNode *right; }; //访问 void get(TREEtagNode *node){ printf("%d\n",node->val); } //先序遍历 void r1(TREEtagNode *node){ if(node != NULL) { // get(node); // r1(node->left); // r1(node->right); } } //中序遍历 void r2(TREEtagNode *node){ if(node != NULL) { // r2(node->left); // get(node); // r2(node->right); } } //后序遍历 void r3(TREEtagNode *node){ if(node != NULL) { // r3(node->left); // r3(node->right); // get(node); } } int main () { TREEtagNode A0,A1,A2,A3,A4; A0.left = &A1; A0.right = &A2; A0.val = 10; A1.left = &A3; A1.right = NULL; A1.val = 2; A2.left = &A4; A2.right = NULL; A2.val = 7; A3.left = NULL; A3.right = NULL; A3.val = 5; A4.left = NULL; A4.right = NULL; A4.val = 9; printf("初始化成功\n"); printf("先序遍历:\n"); r1(&A0); printf("中序遍历:\n"); r2(&A0); printf("后序遍历:\n"); r3(&A0); return 0; }

初始化成功 先序遍历: 10 2 5 7 9 中序遍历: 5 2 10 9 7 后序遍历: 5 2 9 7 10
非递归实现:先序、中序、后序
#include <stdio.h> //声明树类型 typedef struct TREEtag TREEtagNode; struct TREEtag { int val; TREEtagNode *left; TREEtagNode *right; }; //访问 void get(TREEtagNode *node){ printf("%d\n",node->val); } #define Size 10 typedef struct stacktag { TREEtagNode *a[Size]; int top; }stack; //先序遍历 void r4(TREEtagNode *node){ if(node != NULL) { //初始化栈 stack Stack; Stack.top = -1; //初始化临时节点 TREEtagNode *p; //把根节点插入栈 Stack.a[++Stack.top] = node; //开始遍历 while(Stack.top != -1) { //取出元素 p = Stack.a[Stack.top--]; //操作 get(p); //存储元素:判断当前节点的左右节点是否存在,如果存在,则先存右元素,后存左元素 if(p->right != NULL) Stack.a[++Stack.top] = p->right; if(p->left != NULL) Stack.a[++Stack.top] = p->left; } } } //中序遍历 void r5(TREEtagNode *node){ if(node != NULL) { //初始化栈 stack Stack; Stack.top = -1; //初始化临时节点 TREEtagNode *p = NULL; p = node; //开始遍历 while(Stack.top != -1 || p != NULL) { while(p != NULL) { Stack.a[++Stack.top] = p; p = p->left; } if(Stack.top != -1) { p = Stack.a[Stack.top--]; //操作 get(p); p = p->right; } } } } //双栈法后序遍历 void r6(TREEtagNode *node){ if(node != NULL) { //初始化栈 stack Stack1; Stack1.top = -1; stack Stack2; Stack2.top = -1; //初始化临时节点 TREEtagNode *p; //把根节点插入栈 Stack1.a[++Stack1.top] = node; //开始遍历 while(Stack1.top != -1) { //取出元素 p = Stack1.a[Stack1.top--]; Stack2.a[++Stack2.top] = p; //存储元素:判断当前节点的左右节点是否存在,如果存在,则先存右元素,后存左元素 if(p->left != NULL) Stack1.a[++Stack1.top] = p->left; if(p->right != NULL) Stack1.a[++Stack1.top] = p->right; } while(Stack2.top != -1) { p = Stack2.a[Stack2.top--]; //操作 get(p); } } } int main () { TREEtagNode A0,A1,A2,A3,A4; A0.left = &A1; A0.right = &A2; A0.val = 10; A1.left = &A3; A1.right = NULL; A1.val = 2; A2.left = &A4; A2.right = NULL; A2.val = 7; A3.left = NULL; A3.right = NULL; A3.val = 5; A4.left = NULL; A4.right = NULL; A4.val = 9; printf("初始化成功\n"); printf("先序遍历:\n"); r4(&A0); printf("中序遍历:\n"); r5(&A0); printf("后序遍历:\n"); r6(&A0); return 0; }

初始化成功 先序遍历: 10 2 5 7 9 中序遍历: 5 2 10 9 7 后序遍历: 5 2 9 7 10
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?