数据结构-二叉树-二叉链表-先序遍历-中序遍历-后序遍历-递归-非递归
//代码附有详细注释,完整代码在文章最后。
定义常量
#define stackinitsize 100
#define OK 1
#define ERROR 0
#define OVERFLOW -1
给元素起一个别名,如果需要更换元素类型只需要更改一处地方,并且写代码时ElemType比int更容易理解。
typedef int TElemType ; //元素类型 int
typedef int Status; //状态
二叉树的二叉链表存储表示
//二叉树的二叉链表存储表示
typedef struct BiTNode
{
TElemType data;
struct BiTNode *lchild, *rchild; //左右孩子指针
}BiTnode,*BiTree;
typedef struct{
//该堆栈的元素是指针类型的
//base和top均是指向指针的指针
BiTnode **base; //二级指针
BiTnode **top;
int stacksize;
}sqstack; //堆栈结构
基本操作的函数原型说明(部分)
// 基本操作的函数原型说明(部分)
Status CreateBitree(BiTree &T);
//按先序次序输入二叉树中结点的值(一个字符),#字符表示空树。
//构造二叉链表表示的二叉树T.
Status PreOrderTraverse(BiTree T,Status(*Visit)(TElemType e));
//采用二叉链表存储结构,visit是对结点操作的应用函数。
//先序遍历二叉树T,对每个结点调用函数Visit 一次且仅一次。
//一旦visit()失败,则操作失败。
Status lnorderTraverse(BiTree T,Status(*Visit)(TElemType e));
//采用二叉链表存储结构,Visit是对结点操作的应用函数。
//中序遍历二叉树T,对每个结点调用函数Visit 一次且仅一次。
//一旦visit()失败,则操作失败。
Status PostorderTraverse(BiTree T,Status(*Visit)(TElemType e));
//采用二叉链表存储结构,visit是对结点操作的应用函数。
//后序遍历二叉树T,对每个结点调用函数Visit 一次且仅一次。
//一旦visit()失败,则操作失败。
Status LevellOrderTraverse(BiTree T,Status(*Visit)(TElemType e));
//采用二又链表存储结构,Visit是对结点操作的应用函数。
//层序遍历二叉树T,对每个结点调用函数Visit 一次且仅一次。
//—旦visit()失败,则操作失败
初始化堆栈
//初始化堆栈
void lnitStack(sqstack &s) //形参s为引用
{
s.base=(BiTnode**) malloc (stackinitsize* sizeof (BiTree)); //生成stackinitsize数量内存空间来存放二级指针
if (!s.base) return ;
s.top=s.base; //空栈:栈底和栈顶相等
s.stacksize=100;
return ;
}
压栈,出栈函数以及栈空判别
//将元素压入堆栈
void Push(sqstack &s, BiTnode *e) //形参e为指针变量
{
*s.top++=e;
}
//弹栈
void Pop(sqstack &s, BiTnode **e) //e为二级指针,因为栈中存放的是指针
{
*e=*--s.top;
}
int StackEmpty(sqstack s) //栈空判别
{
return (s.top==s.base);//栈顶和栈底相等时栈为空
}
取栈顶元素
//取栈顶元素
Status GetTop(sqstack s, BiTnode **e)
{
if (s.top==s.base) return ERROR;
*e=*(s.top-1);
return OK;
}
创建二叉树,输入按先序次序输入(一个字符),#表示空字符
//按先序次序输入二叉树中结点的值(一个字符),#字符表示空树。
//构造二叉链表表示的二叉树T.
Status CreateBiTree(BiTree &T)//引用
{
char ch;
ch=getchar();
if ( ch == '#' )T=NULL;
else
{
if (!(T=(BiTnode *) malloc (sizeof(BiTnode)))) return (OVERFLOW);
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //构造左子树
CreateBiTree(T->rchild); //构造右子树
}
return OK;
}
先序遍历二叉树的递归算法
Status PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e) ) //第二个参数为调用函数
//采用二叉链表存储结构,visit是对数据元素操作的应用函数
//先序遍历二叉树T的递归算法,对每个数据元素调用函数visit.
//调用实例:PreOrderTraverse(T,printElement);
{
if(T)
{
if (Visit(T->data)) //访问根节点的数据域
if ( PreOrderTraverse(T->lchild, Visit) ) //前序遍历左子树
if (PreOrderTraverse(T->rchild,Visit)) //前序遍历右子树
return OK; //表示根节点左孩子和右孩子都存在
return ERROR; //碰到叶子结点即终端节点
}else return OK;
}
中序遍历二叉树的递归算法
//中序遍历二叉树T的递归算法
Status lnOrderTraverse(BiTree T, Status(*Visit)(TElemType e) )
{
if (T)
{
if (lnOrderTraverse(T->lchild,Visit)) //遍历左子树
if (Visit(T->data)) //访问根节点的数据域
if (lnOrderTraverse(T->rchild,Visit))//遍历右子树
return OK;
return ERROR;
}
else return OK;
} //preOrderTraVerse
后序遍历二叉树的递归算法
//后序遍历二叉树T的递归算法
Status PostOrderTraverse(BiTree T, Status(*Visit)(TElemType e))
{
if(T){
if (PostOrderTraverse(T->lchild,Visit)) //遍历左子树
if (PostOrderTraverse(T->rchild,Visit)) //遍历右子树
if (Visit(T->data)) //访问根节点的数据域
return OK;
return ERROR;
}else return OK;
}
输出元素的值
//输出元素e的值
Status PrintElement(TElemType e)
{
printf("%c",e);
return OK;
}
中序遍历二叉树T的非递归算法1
//中序遍历二叉树T的非递归算法
Status lnorderTraverseNoRecursion1(BiTree T, Status(*Visit)(TElemType e))
{
sqstack s;
BiTree p;
lnitStack(s); //初始化链表
p=T;
while (p || !StackEmpty(s))
{
if (p)
{
Push(s,p); //根指针进栈
p=p->lchild;//遍历左子树
}
else
{
Pop(s, &p); //根指针退栈
if (!Visit(p->data))//访问根结点
return ERROR;
p=p->rchild; //遍历右子树
}//else
}//while
return OK;
}
中序遍历二叉树的非递归算法2
//中序遍历二叉树T的非递归算法2
Status lnorderTraverseNoRecursion2(BiTree T,Status(*Visit)(TElemType e))
{
sqstack s;
BiTree p;
lnitStack(s);
Push(s, T);
while (!StackEmpty(s))
{
while (GetTop(s, &p) && p)
Push(s, p->lchild); //向左走到尽头
Pop(s, &p); //空指针退栈
if (!StackEmpty(s))
{ //访问结点,向右一步
Pop(s, &p);
if (!Visit(p->data))
return ERROR;
Push(s, p->rchild);
}//if
} //while
return OK;
}
主函数,输入实例:ab##c##
void main()
{
BiTree t;
printf("\n请按先序遍历输入二叉树(当左右子树为空时用#输入)\n");
CreateBiTree(t);
printf ("\n该二叉树的先序遍历为:\n");
PreOrderTraverse(t,PrintElement);
printf ("\n该二叉树的中序遍历为:\n");
lnOrderTraverse(t,PrintElement);
printf ("\n该二叉树的后序遍历为:\n");
PostOrderTraverse(t,PrintElement);
printf ("\n该二叉树的中序遍历为:(用非递归调用l)\n");
lnorderTraverseNoRecursion1(t,PrintElement);
printf ("\n该二叉树的中序遍历为:(用非递归调用2)\n");
lnorderTraverseNoRecursion2(t,PrintElement);
printf("\n");
}
最后,如果觉得这篇博客能帮助到你,请点个小小的赞支持一下我(收藏也行呀,嘻嘻),这是我继续更新的动力呀,关注我可以得到第一时间的更新,更加快人一步哦。
如果有问题请在评论区留言,一起交流进步。
附完整代码:
#include "stdio.h"
#include "stdlib.h"
#define stackinitsize 100
#define OK 1
#define ERROR 0
#define OVERFLOW -1
typedef int TElemType ; //元素类型 int
typedef int Status; //状态
//二叉树的二叉链表存储表示
typedef struct BiTNode
{
TElemType data;
struct BiTNode *lchild, *rchild; //左右孩子指针
}BiTnode,*BiTree;
typedef struct{
//该堆栈的元素是指针类型的
//base和top均是指向指针的指针
BiTnode **base; //二级指针
BiTnode **top;
int stacksize;
}sqstack; //堆栈结构
// 基本操作的函数原型说明(部分)
Status CreateBitree(BiTree &T);
//按先序次序输入二叉树中结点的值(一个字符),#字符表示空树。
//构造二叉链表表示的二叉树T.
Status PreOrderTraverse(BiTree T,Status(*Visit)(TElemType e));
//采用二叉链表存储结构,visit是对结点操作的应用函数。
//先序遍历二叉树T,对每个结点调用函数Visit 一次且仅一次。
//一旦visit()失败,则操作失败。
Status lnorderTraverse(BiTree T,Status(*Visit)(TElemType e));
//采用二叉链表存储结构,Visit是对结点操作的应用函数。
//中序遍历二叉树T,对每个结点调用函数Visit 一次且仅一次。
//一旦visit()失败,则操作失败。
Status PostorderTraverse(BiTree T,Status(*Visit)(TElemType e));
//采用二叉链表存储结构,visit是对结点操作的应用函数。
//后序遍历二叉树T,对每个结点调用函数Visit 一次且仅一次。
//一旦visit()失败,则操作失败。
Status LevellOrderTraverse(BiTree T,Status(*Visit)(TElemType e));
//采用二又链表存储结构,Visit是对结点操作的应用函数。
//层序遍历二叉树T,对每个结点调用函数Visit 一次且仅一次。
//—旦visit()失败,则操作失败
//初始化堆栈
void lnitStack(sqstack &s) //形参s为引用
{
s.base=(BiTnode**) malloc (stackinitsize* sizeof (BiTree)); //生成stackinitsize数量内存空间来存放二级指针
if (!s.base) return ;
s.top=s.base; //空栈:栈底和栈顶相等
s.stacksize=100;
return ;
}
//将元素压入堆栈
void Push(sqstack &s, BiTnode *e) //形参e为指针变量
{
*s.top++=e;
}
//弹栈
void Pop(sqstack &s, BiTnode **e) //e为二级指针,因为栈中存放的是指针
{
*e=*--s.top;
}
int StackEmpty(sqstack s) //栈空判别
{
return (s.top==s.base);//栈顶和栈底相等时栈为空
}
//取栈顶元素,即指针
Status GetTop(sqstack s, BiTnode **e)
{
if (s.top==s.base) return ERROR;
*e=*(s.top-1);
return OK;
}
//按先序次序输入二叉树中结点的值(一个字符),#字符表示空树。
//构造二叉链表表示的二叉树T.
Status CreateBiTree(BiTree &T)//引用
{
char ch;
ch=getchar();
if ( ch == '#' )T=NULL;
else
{
if (!(T=(BiTnode *) malloc (sizeof(BiTnode)))) return (OVERFLOW);
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //构造左子树
CreateBiTree(T->rchild); //构造右子树
}
return OK;
}
Status PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e) ) //第二个参数为调用函数
//采用二叉链表存储结构,visit是对数据元素操作的应用函数
//先序遍历二叉树T的递归算法,对每个数据元素调用函数visit.
//调用实例:PreOrderTraverse(T,printElement);
{
if(T)
{
if (Visit(T->data)) //访问根节点的数据域
if ( PreOrderTraverse(T->lchild, Visit) ) //前序遍历左子树
if (PreOrderTraverse(T->rchild,Visit)) //前序遍历右子树
return OK; //表示根节点左孩子和右孩子都存在
return ERROR; //碰到叶子结点即终端节点
}else return OK;
}
//中序遍历二叉树T的递归算法
Status lnOrderTraverse(BiTree T, Status(*Visit)(TElemType e) )
{
if (T)
{
if (lnOrderTraverse(T->lchild,Visit)) //遍历左子树
if (Visit(T->data)) //访问根节点的数据域
if (lnOrderTraverse(T->rchild,Visit))//遍历右子树
return OK;
return ERROR;
}
else return OK;
} //preOrderTraVerse
//后序遍历二叉树T的递归算法
Status PostOrderTraverse(BiTree T, Status(*Visit)(TElemType e))
{
if(T){
if (PostOrderTraverse(T->lchild,Visit)) //遍历左子树
if (PostOrderTraverse(T->rchild,Visit)) //遍历右子树
if (Visit(T->data)) //访问根节点的数据域
return OK;
return ERROR;
}else return OK;
}
//输出元素e的值
Status PrintElement(TElemType e)
{
printf("%c",e);
return OK;
}
//中序遍历二叉树T的非递归算法
Status lnorderTraverseNoRecursion1(BiTree T, Status(*Visit)(TElemType e))
{
sqstack s;
BiTree p;
lnitStack(s); //初始化链表
p=T;
while (p || !StackEmpty(s))
{
if (p)
{
Push(s,p); //根指针进栈
p=p->lchild;//遍历左子树
}
else
{
Pop(s, &p); //根指针退栈
if (!Visit(p->data))//访问根结点
return ERROR;
p=p->rchild; //遍历右子树
}//else
}//while
return OK;
}
//中序遍历二叉树T的非递归算法2
Status lnorderTraverseNoRecursion2(BiTree T,Status(*Visit)(TElemType e))
{
sqstack s;
BiTree p;
lnitStack(s);
Push(s, T);
while (!StackEmpty(s))
{
while (GetTop(s, &p) && p)
Push(s, p->lchild); //向左走到尽头
Pop(s, &p); //空指针退栈
if (!StackEmpty(s))
{ //访问结点,向右一步
Pop(s, &p);
if (!Visit(p->data))
return ERROR;
Push(s, p->rchild);
}//if
} //while
return OK;
}
void main()
{
BiTree t;
printf("\n请按先序遍历输入二叉树(当左右子树为空时用#输入)\n");
CreateBiTree(t);
printf ("\n该二叉树的先序遍历为:\n");
PreOrderTraverse(t,PrintElement);
printf ("\n该二叉树的中序遍历为:\n");
lnOrderTraverse(t,PrintElement);
printf ("\n该二叉树的后序遍历为:\n");
PostOrderTraverse(t,PrintElement);
printf ("\n该二叉树的中序遍历为:(用非递归调用l)\n");
lnorderTraverseNoRecursion1(t,PrintElement);
printf ("\n该二叉树的中序遍历为:(用非递归调用2)\n");
lnorderTraverseNoRecursion2(t,PrintElement);
printf("\n");
}