文章目录
- [1. 数据元素的表示](#1. 数据元素的表示)
- [2. 创建二叉树](#2. 创建二叉树)
- [3. 遍历二叉树](#3. 遍历二叉树)
-
- [3.1 先序遍历](#3.1 先序遍历)
-
- [3.1.1 递归遍历](#3.1.1 递归遍历)
- [3.1.2 非递归遍历](#3.1.2 非递归遍历)
- [3.2 中序遍历](#3.2 中序遍历)
-
- [3.2.1 递归遍历](#3.2.1 递归遍历)
- [3.2.2 非递归遍历](#3.2.2 非递归遍历)
- [3.3 后序遍历](#3.3 后序遍历)
-
- [3.3.1 递归遍历](#3.3.1 递归遍历)
- [3.3.2 非递归遍历](#3.3.2 非递归遍历)
- [3.4 层次遍历](#3.4 层次遍历)
1. 数据元素的表示
c
#define ElemType char // 树结点的数据元素类型
typedef struct BiTNode{ // 链式二叉树
ElemType data; // 数据域
struct BiTNode* lchild; // 左孩子指针
struct BiTNode* rchild; // 右孩子指针
}BiTNode,*BiTree;
2. 创建二叉树
c
/* 基于先序遍历递归创建二叉树 */
BiTree PreOrderCreate(BiTree &T) {
ElemType data;
printf("输入当前结点的值:");
scanf("%c", &data);
getchar();
if (data!='#') { // data不为'#',表示要创建新结点
BiTNode* t = (BiTNode*)malloc(sizeof(BiTNode)); // 创建新结点
if (!t) { // 创建结点失败,返回空指针
return NULL;
}
t->data = data;
t->lchild = t->rchild = NULL; // 将新结点的左、右孩子指针置为空
T = t;
T->lchild = PreOrderCreate(T->lchild); // 递归创建左子树
T->rchild = PreOrderCreate(T->rchild); // 递归创建右子树
}
return T;
}
3. 遍历二叉树
3.1 先序遍历
3.1.1 递归遍历
c
/* 先序遍历(NLR) */
void PreOrder(BiTree T) {
if (T) {
Visit(T); // 访问根结点
PreOrder(T->lchild); // 递归遍历左子树
PreOrder(T->rchild); // 递归遍历右子树
}
}
3.1.2 非递归遍历
c
/* 先序遍历(LNR)非递归 */
void PreOrder(BiTree T) {
LinkStack S; // 定义一个链栈
InitStack(S); // 初始化链栈
BiTree p = T; // p是遍历指针
while(p||!StackEmpty(S)){ // 进行遍历,p指针与栈同时为空,结束遍历
if(p){ // 子树的根结点非空
Visit(p); // 访问子树的根结点
Push(S,p); // 当前结点入栈
p=p->lchild; // 一直向左走
}
else{ // 子树的根结点为空,出栈并转向栈结点的右子树
Pop(S,p); // 栈顶元素出栈(子树的根结点)
p=p->rchild; // 向子树根结点的右子树走
}
}
}
3.2 中序遍历
3.2.1 递归遍历
c
/* 中序遍历(LNR) */
void InOrder(BiTree T) {
if (T) {
PreOrder(T->lchild); // 递归遍历左子树
Visit(T); // 访问根结点
PreOrder(T->rchild); // 递归遍历右子树
}
}
3.2.2 非递归遍历
c
/* 中序遍历(LNR)非递归 */
void InOrder(BiTree T) {
LinkStack S; // 定义一个链栈
InitStack(S); // 初始化链栈
BiTree p = T; // p是遍历指针
while(p||!StackEmpty(S)){ // p非空或栈非空循环
if(p){ // 子树的根结点非空
Push(S,p); // 当前结点入栈
p=p->lchild; // 一直向左走
}
else{ // 子树的根结点为空,出栈并转向栈结点的右子树
Pop(S,p); // 栈顶元素出栈(子树的根结点)
Visit(p); // 访问子树的根结点
p=p->rchild; // 向子树根结点的右子树走
}
}
}
3.3 后序遍历
3.3.1 递归遍历
c
/* 后序遍历(LRN) */
void PostOrder(BiTree T) {
if (T) {
PreOrder(T->lchild); // 递归遍历左子树
PreOrder(T->rchild); // 递归遍历右子树
Visit(T); // 访问根结点
}
}
3.3.2 非递归遍历
c
/* 后序遍历(LRN) 非递归*/
void PostOrder(BiTree T){
LinkStack S; // 创建链栈
InitStack(S); // 初始化链栈
BiTNode *p=T; // 遍历结点指针
BiTNode *r=NULL; // 记录上一次访问的结点
while(p||!StackEmpty(S)){ // 遍历树,p指针与链栈同时为空遍历结束
if(p){ // 走到最左边
Push(S,p);
p=p->lchild;
}
else{ // 向右
GetTop(S,p); // 读栈顶元素结点(非出栈)
if(p->rchild&&p->rchild!=r){ // 若右子树存在,且未被访问过
p=p->rchild; // 转向右
}else{ // 否则,弹出结点并访问
Pop(S,p); // 将结点弹出
Visit(p); // 访问该结点
r=p; // 记录上一次访问的结点
p=NULL; // 结点访问完后,重置p指针
}
}
}
}
3.4 层次遍历
c
/* 层次遍历 */
void LevelOrder(BiTree T) {
LinkQueue Q; // 定义一个链队列
InitQueue(Q); // 初始化队列
EnQueue(Q,T); // 根结点入队
BiTNode *p; // 遍历结点指针
while(!(QueueEmpty(Q))){ // 进行遍历,队列为空遍历结束
DeQueue(Q,p); // 队头元素出队
Visit(p); // 访问该结点
if(p->lchild){ // 该结点存在左子树(左孩子),进队
EnQueue(Q,p->lchild);
}
if(p->rchild){ // 该结点存在右子树(右孩子),进队
EnQueue(Q,p->rchild);
}
}
}
.