目录
二叉树是树形结构的一种特殊形式,它的特点是每个结点至多只有两颗子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒。如图1所示:
另外还有完全二叉树,满二叉树等,它们只是二叉树的特例。这里不作重点介绍,想了解的读者可以翻阅相关资料。
若要深入了解如何建立二叉树,则我们首先需要了解二叉树的几种遍历方式,它们分别为先序遍历、中序遍历,后续遍历以及层序遍历。我们知道二叉树是由根结点、左子树和右子树三个基本单元组成。因此若能依次遍历这三部分,便是遍历了整个二叉树。对于创建二叉树亦是如此,我们可以采用递归的方式,按照这几种的遍历方式,依次对这三部分开辟结点,并初始化,最终完成二叉树的创建。对于几种遍历方式在后面将进行介绍。
按照先序遍历顺序创建二叉树:
代码实现:
status createBiTree(BiTree &T)
{
char ch;
scanf("%c",&ch);
if(ch == ' ')
{T = nullptr;}
else
{
T = (BiTNode*)malloc(sizeof(BiTNode));
if(nullptr == T)
{return ERROR;}
T->_mdata = ch; //生成根节点
createBiTree(T->_mplchild); //构造左子树
createBiTree(T->_mprchild); //构造右子树
}
return OK;
}
先序遍历的基本操作是:
若二叉树为空,则空操作;否则
<1>访问根节点;
<2>先序遍历左子树;
<3>先序遍历右子树。
代码实现(递归版本):
status preOrderTraverse(BiTree T,status (*visit)(ElemType)) //前序递归遍历
{
if(NULL == T)
return ERROR;
(*visit)(T->_mdata);
preOrderTraverse(T->_mplchild,visit);
preOrderTraverse(T->_mprchild,visit);
}
代码实现(非递归版本)
status preOrderTraverses(BiTree T,status (*visit)(ElemType)) //前序非递归遍历
{
BiTree p = T;
std::stack<BiTree> stack;
while(p != nullptr || !stack.empty())
{
while(p != nullptr)
{
if(!(*visit)(p->_mdata))
return ERROR;
stack.push(p);
p = p->_mplchild;
}
if(!stack.empty())
{
p = stack.top();
stack.pop();
p = p->_mprchild;
}
}
return OK;
}
中序遍历的基本操作是:
若二叉树为空,则空操作;否则
<1>中序遍历左子树;
<2>访问根节点;
<3>中序遍历右子树。
代码实现(递归版本):
status inOrderTraverse(BiTree T,status (*visit)(ElemType)) //中序递归遍历
{
if(NULL == T)
return ERROR;
inOrderTraverse(T->_mplchild,visit);
(*visit)(T->_mdata);
inOrderTraverse(T->_mprchild,visit);
}
代码实现(非递归版本)
status inOrderTraverses(BiTree T,status (*visit)(ElemType)) //中序非递归遍历
{
BiTree p = T;
std::stack<BiTree> stack;
while(p != nullptr || !stack.empty())
{
if(p != nullptr)
{
stack.push(p);
p = p->_mplchild;
}
else
{
p = stack.top();
stack.pop();
if(!(*visit)(p->_mdata))
return ERROR;
p = p->_mprchild;
}
}
return OK;
}
后序遍历的基本操作是:
若二叉树为空,则空操作;否则
<1>后序遍历左子树;
<2>后序遍历右子树
<3>访问根节点。
代码实现(递归版本):
status postOrderTraverse(BiTree T,status (*visit)(ElemType)) //后序递归遍历
{
if(NULL == T)
return ERROR;
postOrderTraverse(T->_mplchild,visit);
postOrderTraverse(T->_mprchild,visit);
(*visit)(T->_mdata);
}
代码实现(非递归版本)
status postOrderTraverses(BiTree T,status (*visit)(ElemType)) //后序非递归遍历
{
BiTree p = T;
std::stack<BiTree> stack;
while(p != NULL || !stack.empty())
{
while(p != nullptr)
{
p->count = 1;
stack.push(p);
p = p->_mplchild;
}
if(!stack.empty())
{
p = stack.top();
stack.pop();
if(p->count == 1)
{
p->count++;
stack.push(p);
p = p->_mprchild;
}
else if(p->count == 2)
{
if(!(*visit)(p->_mdata))
return ERROR;
p = nullptr;
}
}
}
return OK;
}
除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
代码实现:
status levelTraverses(BiTree T,status (*visit)(ElemType))
{
BiTree p = T;
std::queue<BiTree> queue;
queue.push(p);
while(!queue.empty())
{
p = queue.front();
queue.pop();
if(!(*visit)(p->_mdata))
return ERROR;
if(p->_mplchild != nullptr)
{
queue.push(p->_mplchild);
}
if(p->_mprchild != nullptr)
{
queue.push(p->_mprchild);
}
}
return OK;
}
完整代码实现:
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<stack>
#include<queue>
#include<assert.h>
#define STACK_SIZE 20
typedef char ElemType;
enum status {OK = 1,ERROR = 0,TRUE = 1,FALSE = 0};
typedef struct BiTNode
{
int count; //存储结点被访问的次数
ElemType _mdata;
struct BiTNode *_mplchild;
struct BiTNode *_mprchild;
}BiTNode,*BiTree;
typedef struct
{
BiTree base[STACK_SIZE];
int top;
}Stack;
status createBiTree(BiTree &T)
{
char ch;
scanf("%c",&ch);
if(ch == ' ')
{T = nullptr;}
else
{
T = (BiTNode*)malloc(sizeof(BiTNode));
if(nullptr == T)
{return ERROR;}
T->_mdata = ch; //生成根节点
createBiTree(T->_mplchild); //构造左子树
createBiTree(T->_mprchild); //构造右子树
}
return OK;
}
status show_node(ElemType e)
{
printf("%c ",e);
return OK;
}
status preOrderTraverse(BiTree T,status (*visit)(ElemType)) //前序递归遍历
{
if(NULL == T)
return ERROR;
(*visit)(T->_mdata);
preOrderTraverse(T->_mplchild,visit);
preOrderTraverse(T->_mprchild,visit);
}
status preOrderTraverses(BiTree T,status (*visit)(ElemType)) //前序非递归遍历
{
BiTree p = T;
std::stack<BiTree> stack;
while(p != nullptr || !stack.empty())
{
while(p != nullptr)
{
if(!(*visit)(p->_mdata))
return ERROR;
stack.push(p);
p = p->_mplchild;
}
if(!stack.empty())
{
p = stack.top();
stack.pop();
p = p->_mprchild;
}
}
return OK;
}
status inOrderTraverse(BiTree T,status (*visit)(ElemType)) //中序递归遍历
{
if(NULL == T)
return ERROR;
inOrderTraverse(T->_mplchild,visit);
(*visit)(T->_mdata);
inOrderTraverse(T->_mprchild,visit);
}
status inOrderTraverses(BiTree T,status (*visit)(ElemType)) //中序非递归遍历
{
BiTree p = T;
std::stack<BiTree> stack;
while(p != nullptr || !stack.empty())
{
if(p != nullptr)
{
stack.push(p);
p = p->_mplchild;
}
else
{
p = stack.top();
stack.pop();
if(!(*visit)(p->_mdata))
return ERROR;
p = p->_mprchild;
}
}
return OK;
}
status postOrderTraverse(BiTree T,status (*visit)(ElemType)) //后序递归遍历
{
if(NULL == T)
return ERROR;
postOrderTraverse(T->_mplchild,visit);
postOrderTraverse(T->_mprchild,visit);
(*visit)(T->_mdata);
}
status postOrderTraverses(BiTree T,status (*visit)(ElemType)) //后序非递归遍历
{
BiTree p = T;
std::stack<BiTree> stack;
while(p != NULL || !stack.empty())
{
while(p != nullptr)
{
p->count = 1;
stack.push(p);
p = p->_mplchild;
}
if(!stack.empty())
{
p = stack.top();
stack.pop();
if(p->count == 1)
{
p->count++;
stack.push(p);
p = p->_mprchild;
}
else if(p->count == 2)
{
if(!(*visit)(p->_mdata))
return ERROR;
p = nullptr;
}
}
}
return OK;
}
status levelTraverses(BiTree T,status (*visit)(ElemType))
{
BiTree p = T;
std::queue<BiTree> queue;
queue.push(p);
while(!queue.empty())
{
p = queue.front();
queue.pop();
if(!(*visit)(p->_mdata))
return ERROR;
if(p->_mplchild != nullptr)
{
queue.push(p->_mplchild);
}
if(p->_mprchild != nullptr)
{
queue.push(p->_mprchild);
}
}
return OK;
}
int main()
{
BiTree tree;
createBiTree(tree);
printf("先序遍历:\n");
preOrderTraverse(tree,show_node);
printf("\n");
preOrderTraverses(tree,show_node);
printf("\n");
printf("中序遍历:\n");
inOrderTraverse(tree,show_node);
printf("\n");
inOrderTraverses(tree,show_node);
printf("\n");
printf("后序遍历:\n");
postOrderTraverse(tree,show_node);
printf("\n");
postOrderTraverses(tree,show_node);
printf("\n");
printf("层序遍历:\n");
levelTraverses(tree,show_node);
printf("\n");
return 0;
}