<数据结构>二叉树的递归、非递归以及层次遍历算法C语言实现
2013-11-02 17:12
471 查看
二叉树是数据结构中一种非常重要的结构,熟练的掌握二叉树的创建,遍历是打好编程基础的关键。对于遍历,不能仅仅只掌握递归遍历,还应掌握效率更高地非递归遍历。对于非递归的先序、中序、后序遍历要用到栈(在之前的博文中已经提到了具体的实现过程),而在层次遍历中要使用到另一种数据结构——队列,这个在之前博文中没有提到,因此在本篇博文中将会给出简单实现。
在本篇博文中给出的代码实现了:二叉树的创建、二叉树的递归、非递归的先、中、后序以及层次遍历七种遍历算法。话不多说,下面给出代码(仅供参考):
因为要用到栈和队列,因此在这代码一并给出,方便大家运行。
“LinkStack.h”:
[/code]
"LinkQueue.h":
"BiTree.h":
"LinkStack.c":
"LinkQueue.c":
"BiTree.c":
"main.c":
运行结果如下:
与大家分享,共同学习,相互提高,如有疑问或建议,请留言。
在本篇博文中给出的代码实现了:二叉树的创建、二叉树的递归、非递归的先、中、后序以及层次遍历七种遍历算法。话不多说,下面给出代码(仅供参考):
因为要用到栈和队列,因此在这代码一并给出,方便大家运行。
“LinkStack.h”:
#ifndef _LINKSTACK_H #define _LINKSTACK_H #include<stdlib.h> #include<stdio.h> #include"BiTree.h" //定义栈中数据的类型 typedef BiTree LStackElem; //定义栈元素的结构 typedef struct SNode { LStackElem data; struct SNode * next; }SNode, *LinkNode; //定义栈的结构 typedef struct { LinkNode node; //栈顶指针(相当于链表中的头指针) int size; //栈的大小 }LinkStack; //初始化栈 void init_link_stack(LinkStack &S); //进栈 void push(LinkStack &S, LStackElem e); //出栈 void pop(LinkStack &S, LStackElem &e); //判断栈是否为空 int is_stack_empty(LinkStack S); //获得栈顶元素 void get_top(LinkStack S, LStackElem &e); #endif
[/code]
"LinkQueue.h":
#ifndef _LINKQUEUE_H #define _LINKQUEUE_H #include"BiTree.h" typedef BiTree QueueElem; typedef struct QNode { QueueElem data; struct QNode * next; }QNode; typedef struct { QNode * top; //队列头指针 QNode * bottom; //队列尾指针 int size; //队列大小 }LinkQueue; //初始化队列 void init_link_queue(LinkQueue &Q); //入队列 void in_link_queue(LinkQueue &Q, QueueElem e); //出队列 void out_link_queue(LinkQueue &Q, QueueElem &e); //队列是否为空 int is_queue_empty(LinkQueue Q); #endif
"BiTree.h":
#ifndef _BITREE_H #define _BITREE_H //定义二叉树中存储的数据类型 typedef int BiNodeElem; //定义二叉树的结构 typedef struct BiNode { BiNodeElem data; struct BiNode * lchild; struct BiNode * rchild; }BiNode, *BiTree; //初始化一棵仅含根节点的二叉树,根节点的值为e void init_bitree(BiTree &T, BiNodeElem e); //产生树节点 BiNode * creat_bitree_node(BiNodeElem e, BiNode * lchild, BiNode * rchild); //增加左子树 void add_lchild(BiNode * &binode, BiNode * lchild); //增加右子树 void add_rchild(BiNode * &binode, BiNode * rchild); //递归先序遍历 void pro_order_recursion(BiTree T); //递归中序遍历 void infix_order_recursion(BiTree T); //递归后序遍历 void post_order_recursion(BiTree T); //非递归先序遍历 void pro_order_no_recursion(BiTree T); //非递归中序遍历 void infix_order_no_recursion(BiTree T); //非递归后序遍历 void post_order_no_recursion(BiTree T); //层次遍历 void hierarchy_order(BiTree T); #endif
"LinkStack.c":
#include"LinkStack.h" //初始化栈 void init_link_stack(LinkStack &S) { S.node = (SNode *)malloc(sizeof(SNode)); S.node->next = NULL; S.size = 0; } //进栈 void push(LinkStack &S, LStackElem e) { LinkNode p = (LinkNode)malloc(sizeof(SNode)); p->data = e; p->next = S.node->next; S.node->next = p; ++S.size; } //出栈 void pop(LinkStack &S, LStackElem &e) { if(is_stack_empty(S)) { printf("栈为空,不能出栈。\n"); return; } e = S.node->next->data; LinkNode p = S.node->next; S.node->next = S.node->next->next; free(p); --S.size; } //判断栈是否为空 int is_stack_empty(LinkStack S) { if(S.size == 0) return 1; else return 0; } //获得栈顶元素 void get_top(LinkStack S, LStackElem &e) { e = S.node->next->data; }
"LinkQueue.c":
#include"LinkQueue.h" #include<stdio.h> #include<stdlib.h> //初始化队列 void init_link_queue(LinkQueue &Q) { Q.top = Q.bottom = (QNode *)malloc(sizeof(QNode)); Q.top->next = NULL; Q.size = 0; } //入队列(尾插法) void in_link_queue(LinkQueue &Q, QueueElem e) { QNode * p = (QNode *)malloc (sizeof(QNode)); p->data = e; p->next = NULL; Q.bottom->next = p; Q.bottom = p; ++Q.size; } //出队列 void out_link_queue(LinkQueue &Q, QueueElem &e) { if(Q.size > 0) { e = Q.top->next->data; QNode * p = Q.top->next; Q.top->next = Q.top->next->next; if(Q.bottom == p) Q.bottom = Q.top; free(p); --Q.size; } } //队列是否为空 int is_queue_empty(LinkQueue Q) { if(Q.size == 0) return 1; else return 0; }
"BiTree.c":
#include"BiTree.h" #include"LinkStack.h" #include"LinkQueue.h" #include<stdio.h> #include<stdlib.h> //初始化一棵仅含根节点的二叉树,根节点的值为e void init_bitree(BiTree &T, BiNodeElem e) { T = (BiNode *) malloc(sizeof(BiNode)); T->data = e; T->lchild = NULL; T->rchild = NULL; } //产生树节点 BiNode * creat_bitree_node(BiNodeElem e, BiNode * lchild, BiNode * rchild) { BiNode * pTree = (BiNode *)malloc(sizeof(BiNode)); pTree->data = e; pTree->lchild = lchild; pTree->rchild = rchild; return pTree; } //增加左子树 void add_lchild(BiNode * &binode, BiNode * lchild) { if(binode != NULL) binode->lchild = lchild; } //增加右子树 void add_rchild(BiNode * &binode, BiNode * rchild) { if(binode != NULL) binode->rchild = rchild; } //递归先序遍历 void pro_order_recursion(BiTree T) { if(T != NULL) { printf("%d ",T->data); pro_order_recursion(T->lchild); pro_order_recursion(T->rchild); } } //递归中序遍历 void infix_order_recursion(BiTree T) { if(T != NULL) { infix_order_recursion(T->lchild); printf("%d ",T->data); infix_order_recursion(T->rchild); } } //递归后序遍历 void post_order_recursion(BiTree T) { if(T != NULL) { post_order_recursion(T->lchild); post_order_recursion(T->rchild); printf("%d ",T->data); } } //非递归先序遍历 void pro_order_no_recursion(BiTree T) { LinkStack S; init_link_stack(S); //把根节点指针赋值给p BiNode * p = T; while( NULL != p || !is_stack_empty(S)) { //打印当前节点,其左节点依次进栈 while(NULL != p ) { printf("%d ",p->data); push(S,p); p = p->lchild; } if(!is_stack_empty(S)) { pop(S,p); p = p->rchild; } } } //非递归中序遍历 void infix_order_no_recursion(BiTree T) { LinkStack S; init_link_stack(S); //把根节点指针赋值给p BiNode * p = T; while( NULL != p || !is_stack_empty(S)) { //左节点依次进栈 while(NULL != p) { push(S,p); p = p->lchild; } if(!is_stack_empty(S)) { pop(S,p); printf("%d ",p->data); p = p->rchild; } } } //非递归后序遍历 void post_order_no_recursion(BiTree T) { LinkStack S; init_link_stack(S); BiNode * p = T; //存储最近一次访问的节点 BiNode * visited =NULL; while(NULL != p || !is_stack_empty(S)) { //直接写p 更为简单,不需要写NULL !=p while(p) { push(S,p); p = p->lchild; } if(!is_stack_empty(S)) { pop(S,p); //如果不存在右子树,或右子树被访问 /* 解析一下:根据上面的while循环,栈顶元素必然不存在左子树;如何存在右子树,又根据后序遍历的特点, 最近一次被访问的节点,必然是该节点的右子树 */ if( !p->rchild || p->rchild == visited) { printf("%d ",p->data); visited = p; p = NULL; } else { push(S,p); p = p->rchild; } } } } //层次遍历 void hierarchy_order(BiTree T) { LinkQueue Q; init_link_queue(Q); BiNode * p; if(T) { in_link_queue(Q,T); while(!is_queue_empty(Q)) { out_link_queue(Q,p); printf("%d ",p->data); if(p->lchild) in_link_queue(Q,p->lchild); if(p->rchild) in_link_queue(Q,p->rchild); } } }
"main.c":
#include"LinkStack.h" #include"LinkQueue.h" #include"BiTree.h" int main() { BiTree T; init_bitree(T,10); BiNode * lchild = creat_bitree_node(20,NULL,creat_bitree_node(40,NULL,NULL)); add_lchild(T, lchild); BiNode * rchild1 = creat_bitree_node(50,creat_bitree_node(60,NULL,NULL),creat_bitree_node(70,NULL,NULL)); BiNode * rchild = creat_bitree_node(30, NULL, rchild1); add_rchild(T,rchild); printf("构造的树的结果如下:\n"); printf(" 10\n"); printf(" / \\\n"); printf(" 20 30\n"); printf(" \\ \\ \n"); printf(" 40 50\n"); printf(" /\\\n"); printf(" 60 70\n\n"); printf("递归先序遍历的结果:\n"); pro_order_recursion(T); printf("\n"); printf("递归中序遍历的结果:\n"); infix_order_recursion(T); printf("\n"); printf("递归后序遍历的结果:\n"); post_order_recursion(T); printf("\n"); printf("\n===============================================\n\n"); printf("非递归先序遍历的结果:\n"); pro_order_no_recursion(T); printf("\n"); printf("非递归中序遍历的结果:\n"); infix_order_no_recursion(T); printf("\n"); printf("非递归后序遍历的结果:\n"); post_order_no_recursion(T); printf("\n"); printf("非递归层次遍历的结果:\n"); hierarchy_order(T); printf("\n"); return 0; }
运行结果如下:
与大家分享,共同学习,相互提高,如有疑问或建议,请留言。
相关文章推荐
- <二叉树 前中后 层序 非递归遍历 c语言实现>
- python实现二叉树的建立以及遍历(递归前序、中序、后序遍历,队栈前序、中序、后序、层次遍历)
- <数据结构>单链表元素按插入方法排序实现
- <数据结构>顺序列表的C语言实现
- <数据结构>顺序栈的C语言实现
- <数据结构>链栈的C语言实现
- <数据结构>各种排序算法的实现与总结(一)
- <leetcode系列> String to Integer (atoi) 以及atoi源码实现
- 二叉树的先序、中序、后序的递归及非递归实现,以及层次遍历的实现:
- 实现二叉树的先序遍历、中序遍历、后序遍历的递归非递归算法以及层次遍历算法
- <数据结构>单链表的C语言实现
- 二叉树创建、前序遍历、中序遍历、后序遍历 的 递归与非递归实现 以及 层次遍历
- <有道笔试题>链表加法的递归实现
- <数据结构> 第二章 线性表之循环链表的代码粗实现
- <数据结构学习与实验指导>3-1一元多项式求导/3-2汉诺塔的非递归实现
- <Unity UGUI>使用c#反射实现UGUI文本显示的国际化
- <Unity 3D工作笔记>脚本中勾选与取消勾选脚本,代码中的实现!
- 《C++第九周实验报告2-1》---接第8周任务2,定义Time类中的<<和>>运算符重载,实现时间的输入输出
- <数据结构> ——迟来的课程设计__04
- <!DOCTYPE> 标签的深度剖析以及使用选择