您的位置:首页 > 理论基础 > 数据结构算法

<数据结构>二叉树的递归、非递归以及层次遍历算法C语言实现

2013-11-02 17:12 471 查看
二叉树是数据结构中一种非常重要的结构,熟练的掌握二叉树的创建,遍历是打好编程基础的关键。对于遍历,不能仅仅只掌握递归遍历,还应掌握效率更高地非递归遍历。对于非递归的先序、中序、后序遍历要用到栈(在之前的博文中已经提到了具体的实现过程),而在层次遍历中要使用到另一种数据结构——队列,这个在之前博文中没有提到,因此在本篇博文中将会给出简单实现。

在本篇博文中给出的代码实现了:二叉树的创建、二叉树的递归、非递归的先、中、后序以及层次遍历七种遍历算法。话不多说,下面给出代码(仅供参考):

因为要用到栈和队列,因此在这代码一并给出,方便大家运行。

“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;
}


运行结果如下:



与大家分享,共同学习,相互提高,如有疑问或建议,请留言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐