数据结构与算法基础(王卓)(19):遍历二叉树算法的实现
目录
二叉链表、三叉链表定义:
遍历二叉树具体实操:
最终结果:
遍历的实现:
递归遍历程序实现:
三种遍历算法的代码模块
为了文档的简洁性,避免赘述,我们这里只写先序遍历的算法:(中序后序调换语句顺序即可)
非递归遍历程序算法实现:
前置条件(二叉树和顺序栈的):
递归遍历程序算法实现:
以中序遍历为例:
思路:
ISSUES:
不构造新变量的最终程序成品:
构造新变量的最终程序成品:(标准答案)
二叉树层次遍历算法:
核心思路:
前置条件:(原创版本)
函数实现:(原创)
ISSUES:
二叉链表、三叉链表定义:
#include<iostream>
using namespace std;typedef int Status;
#define MAXTSIZE 100typedef char TElemtype;//Tree Elemtype
//根据需求情况修改
typedef TElemtype SqBiTree;//sequence binary tree
//binary:二进制的; 二元的; 由两部分组成的;
SqBiTree bt;//binary treestruct BiNode//二叉链表存储结构
{TElemtype data;structBiNode* lchild, * rchild;//左右孩子指针
};
typedef BiNode * BiTree;struct TriNode//trinary:三元的
{TElemtype data;structBiNode* lchild, * rchild,* parent;
};
typedef TriNode* TriTree;int main()
{}
遍历二叉树具体实操:
最终结果:
遍历的实现:
递归遍历程序实现:
三种遍历算法的代码模块
为了文档的简洁性,避免赘述,我们这里只写先序遍历的算法:(中序后序调换语句顺序即可)
void Pre(BiTree& T)
{if (T != NULL) {cout << T->data;//printf("%d\t{,T->data);Pre(T->lchild);Pre(T->rchild);}
}//注意Pre函数必须要写在遍历函数前面Status PreOrderTraverse(BiTree T)
{if (T == NULL)return 0;//空二叉树else{Pre(T);//visit(T);//访问根结点PreOrderTraverse(T->lchild);//递归遍历左子树PreOrderTraverse(T->rchild); //递归遍历右子树}
}
注:
//PPT上写的是
//void Pre(BiTree* T)
//但是我们的BiTree已经是一个指针类型,所以没必要再画蛇添足这里:
void Pre(BiTree& T)void Pre(BiTree T)
都可以
非递归遍历程序算法实现:
前置条件(二叉树和顺序栈的):
//顺序栈
#include<iostream>
using namespace std;
#include<stdlib.h>//存放exit
#include<math.h>//OVERFLOW,exit#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
//#define OVERFLOW -2 #define MAXlength 100
//可按需修改,PPT中写的是MAXlengthtypedef int Status;
typedef char SElemType;
typedef char TElemtype;//根据需求情况修改struct SqStack
{SElemType* base; //栈底指针 SElemType* top;//栈顶指针int stacksize; //栈可用最大容量
};//二叉树
#define MAXTSIZE 100typedef TElemtype SqBiTree;//sequence binary tree
//binary:二进制的; 二元的; 由两部分组成的;
SqBiTree bt;//binary treestruct BiNode//二叉链表存储结构
{TElemtype data;structBiNode* lchild, * rchild;//左右孩子指针
};
typedef BiNode* BiTree;//函数
Status InitStack(SqStack& S)//构造一个空栈
{S.base = new SElemType[MAXlength];//或//S.base = (SElemType*)malloc(MAXlength * sizeof(SElemType));if (!S.base) exit(OVERFLOW);// 存储分配失败S.top = S.base;//栈顶指针等于栈底指针S.stacksize = MAXlength;return true;
}Status StackEmpty(SqStack S)
{// 若栈为空,返回TRUE;否则返回FALSE if (S.top == S.base)return TRUE;elsereturn FALSE;
}int StackLength(SqStack S)
{return S.top - S.base;
}Status ClearStack(SqStack S)//清空顺序栈
{if (S.base)S.top = S.base;return OK;
}Status DestroyStack(SqStack& S)//销毁
{if (S.base){delete S.base;S.stacksize = 0;S.base = S.top = NULL;}return OK;
}Status Push(SqStack& S, SElemType e)
{if (S.top - S.base == S.stacksize)//不是MAXlengthreturn OVERFLOW;*S.top = e;S.top++;//也可以写成://*S.top++ = e;return true;
}Status Pop(SqStack& S, SElemType& e)
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK; 否则返回ERROR
{if (S.top == S.base) // 等价于 if(StackEmpty(S))return UNDERFLOW;//ERROR;e = *S.top;S.top--;//e = *--S.top;return true;
}
递归遍历程序算法实现:
以中序遍历为例:
思路:
有(根)结点:
- 把根结点存到栈里
- 访问(指针指向)左子树
- 输出左子树(后面想了想又觉得不对,如果这样的话无论如何第一个输出的都是第二层的左孩子)
(根)结点为空:
- 输出上一层的根结点(位于栈顶)
- 指针指向根结点的右子树
Project 1:
Status InOrderTraverse(BiTree T)
{BiTree p=T;//用于访问结点的指针SqStack S;InitStack(S);if (p)//p不为空,有(根)结点//另外这里注意,我们无法构造定义出“空结点/空树”,不要浪费力气了{Push(S, p->data);// 把根结点存到栈里p->lchild;// 访问(指针指向)左子树}else//(根)结点为空{Pop(S, p->data);cout << p->data;// 输出上一层的根节点(位于栈顶)p = p->rchild;//指针指向根节点的右子树}return true;
}
ISSUES:
一、还需要在:
最后加上一个限定条件,判定程序结束(停止退出循环):
所有节点都输出完毕了,程序即停止运行,也就是说:
栈为空,且指针为空
二、是否有必要再构造新变量q,存放出栈的根结点?
是否必须如同(和)PPT答案一样,再构造一个变量来存放出栈时的那个根结点?
如果不这样像上述Project 1一样的话:
我感觉好像没什么问题:
Pop的过程中p原来的值被覆盖掉了,但是两种写法最终结果好像都是p指向右子树
但是这种都是自己的猜测,存疑,希望大家看看有没有问题
不过(另外)值得一提的是:
不构造新变量q会出现以下警告:【但是如果构造新变量q,也会出现以下警告,所以没什么用哈哈哈】
不构造新变量的最终程序成品:
Status InOrderTraverse(BiTree T)
{BiTree p = T;//用于访问结点的指针SqStack S;InitStack(S);while (p || StackEmpty(S)){if (p)//p不为空,有(根)结点//另外这里注意,我们无法构造定义出“空结点/空树”,不要浪费力气了{Push(S, p->data);// 把根结点存到栈里p->lchild;// 访问(指针指向)左子树}else//(根)结点为空{Pop(S, p->data);cout << p->data;// 输出上一层的根节点(位于栈顶)p = p->rchild;//指针指向根节点的右子树}} return true;
}
构造新变量的最终程序成品:(标准答案)
Status InOrderTraverse(BiTree T)
{BiTree p = T;SqStack S;InitStack(S);while (p || StackEmpty(S)){if (p){Push(S, p->data);p->lchild;}else{BiTree q = NULL;Pop(S, q->data);cout << q->data;p = q->rchild;}} return true;
}
注释版本:
Status InOrderTraverse(BiTree T)
{BiTree p = T;//用于访问结点的指针SqStack S;InitStack(S);while (p || StackEmpty(S)){if (p)//p不为空,有(根)结点//另外这里注意,我们无法构造定义出“空结点/空树”,不要浪费力气了{Push(S, p->data);// 把根结点存到栈里p->lchild;// 访问(指针指向)左子树}else//(根)结点为空{BiTree q = NULL;//用于访问结点的指针Pop(S, q->data);cout << q->data;// 输出上一层的根节点(位于栈顶)p = q->rchild;//指针指向根节点的右子树}} return true;
}
二叉树层次遍历算法:
核心思路:
我们这里写层次遍历算法,和前面写的中序遍历不一样
不是通过:
- 存储根节点
- 让指针不断循环
- 访问左子树,输出左子树
以及
- 输出根节点
- 访问并输出右子树
来实现访问遍历整棵树的所有节点,而是通过不断地循环进行:
出队(队头结点)
注意:在每次循环第一步出队的过程中
与此同时(在我们进行出队的操作的过程中)我们也将队列的头结点赋给指针(a)也即是说,在每次循环的过程中,a都会不断变化,不断指向循环开始时的队头结点(队列的第一个节点)
输出队头结点(根节点)
入队左孩子(如果有的话)
入队右孩子(如果有的话)
前置条件:(原创版本)
#include<iostream>
using namespace std;
#include<stdlib.h>//存放exit#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2 typedef char QElemType;
typedef int Status; //函数调用状态
#define MAXQSIZE 100 //初始大小为100,可按需修改struct QNode
{QElemType data;QNode* next;
};
typedef QNode* QuenePtr;//Pointerstruct LinkQueue
{QuenePtr front; // 队头指针QuenePtr rear; // 队尾指针// QNode* front; // 队头指针//QNode* rear; // 队尾指针
};typedef QElemType TElemtype;//根据需求情况修改
typedef TElemtype SqBiTree;//sequence binary tree
//binary:二进制的; 二元的; 由两部分组成的;
SqBiTree bt;//binary treestruct BiNode//二叉链表存储结构
{TElemtype data;structBiNode* lchild, * rchild;//左右孩子指针
};
typedef BiNode* BiTree;struct TriNode//trinary:三元的
{TElemtype data;structBiNode* lchild, * rchild, * parent;
};
typedef TriNode* TriTree;Status InitQueue(LinkQueue& Q)//初始化
{Q.front = Q.rear = new QNode;if (!Q.front)return false;Q.rear->next = NULL;return true;
}Status DesQueue(LinkQueue& Q)//销毁
{while (Q.front){QNode* p = Q.front->next;delete (Q.front);Q.front = p;}//也可以直接指定指针rear暂时储存Q.front->next的地址,反正他放在这闲着也没事//Q.rear=Q.front->next; free(Q.front); Q.front=Q.rear;return OK;
}Status EnQueue(LinkQueue& Q, QElemType e)//入队
{QNode* p = new QNode;//QNode* p = (QuenePtr)malloc(sizeof(QNode));p->data = e;p->next = NULL;Q.rear->next = p;Q.rear = p;return OK;
}Status DeQueue(LinkQueue& Q, QElemType e)//出队
{if (Q.front == Q.rear) return ERROR;QNode* p = Q.front->next;e = p->data;//保存删除的信息Q.front->next = p->next;if (Q.rear == p)Q.rear = Q.front;delete p;return true;
}Status GetHead(LinkQueue Q, QElemType& e)
{if (Q.front == Q.rear) return ERROR;e = Q.front->next->data;return OK;
}Status QueneEmpty(LinkQueue& Q)
{if (Q.front == Q.rear)return true;elsereturn false;}
函数实现:(原创)
void LevelOrder(BiNode* b)//层次遍历
{BiNode* a = b;LinkQueue Q;InitQueue(Q);EnQueue(Q, b->data);//注意:不是 EnQueue(Q, a->data); !!!!!!//把头结点放进队列(入队)while (!QueneEmpty(Q)){DeQueue(Q,a->data);cout << a->data;if(a->lchild)EnQueue(Q, a->lchild->data);if (a->rchild)EnQueue(Q, a->rchild->data);}
}
ISSUES:
(1): BiNode* a = b;
其实这里我没想给他赋初值,但是不弄就会报错。而如果我写成
BiTree a = NULL;
格式虽然不会报错,但是也会出现如下预警:
至于PPT上的标准答案,我觉得是一坨大便,大可不必看,直接看我这个版本的就行/即可
数据结构与算法基础(王卓)(19):遍历二叉树算法的实现相关推荐
- 数据结构与算法基础-王卓
文章预览: 数据结构与算法基础-王卓 第一章绪论 **1.1.1基本概念和术语** 数据 数据元素 数据项 数据对象 1.1.2基本概念和术语 1.数据结构解释 2.数据结构包括三方面内容 3.数据结 ...
- 【数据结构与算法基础】树与二叉树的互化
前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...
- 数据结构与算法基础--王卓
第02周07--类C语言有关操作补充02 函数调用时传送给形参表的实参必须有三个一致:类型 个数 顺序 参数传递两种方式 传值方式(参数为整型.实型.字符型) 传地址 参数为指针变量 参数为引用类型 ...
- 数据结构与算法基础-青岛大学-王卓
数据结构与算法基础(青岛大学-王卓)_哔哩哔哩_bilibili 文章目录: 第一章:数据结构的基本概念 1.逻辑结构的种类 2.存储结构的种类 3.抽象数据类型的形式定义 4.Complex抽象书 ...
- 数据结构与算法基础——重要知识点截图【青岛大学-王卓版】
文章目录: 第一章:数据结构的基本概念 1.逻辑结构的种类 2.存储结构的种类 3.抽象数据类型的形式定义 4.Complex抽象书籍类型中的基本操作 5.概念小结 6.时间复杂度 7.空间复杂度 ...
- 数据结构与算法基础(青岛大学-王卓)(1)
士别三日当刮目相待,不好意思鸽了好久了,因为学习的时间不连续,所以我一直攒着,我又回来继续更新了 没有继续学习浙大的数据结构了,对比了青岛大学的王老师的这个教程我觉得更适合我一些,更入门,更详细. 课 ...
- 青岛大学-王卓 数据结构与算法基础
青岛大学-王卓 数据结构与算法基础 内容目录 文章目录 青岛大学-王卓 数据结构与算法基础 内容目录 第一周 1.0前言 1.1数据结构的研究内容 1.2基本概念和术语1 逻辑结构的种类 存储结构的种 ...
- 数据结构与算法 | 青岛大学 | 王卓
来源链接:https://space.bilibili.com/40323036/video?tid=0&page=6&keyword=&order=pubdate https ...
- 数据结构与算法基础(java版)
目录 数据结构与算法基础(java版) 1.1数据结构概述 1.2算法概述 2.1数组的基本使用 2.2 数组元素的添加 2.3数组元素的删除 2.4面向对象的数组 2.5查找算法之线性查找 2.6查 ...
最新文章
- 酷狗音乐QQ显示(VC源代码)
- Web应用程序信息收集工具wig
- iOS开发能用mysql吗_iOS开发之数据库的简单使用
- 盘点:2020年PMCAFF最受欢迎的文章!
- 技巧速看!如何帮助“表哥”快速玩转报告美化?
- webbrowser设置为相应的IE版本
- 秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量
- Java中UDP协议的基本原理和简单用法
- SpringCloud Config 分布式配置
- 学生档案c语言编程,学生档案管理问题
- DyFPN:浙大华为诺亚西湖大学等提出用于目标检测的动态特征金字塔,减少40%的FLOPs!...
- SCOM 2016 配置报警邮件 (下)
- you need python_Life is short,you need python!(1)
- 将 url query参数 字符串转换为JSON 对象
- Rust:Fn,FnMut,FnOnce
- elasticsearch批量数据导入和导出
- Centos7.8系统安装dkms
- java big5_BIG5编码表
- RGB与CMYK几其他颜色模式的区别
- 25W三星快充协议芯片,支持支持USB PD 3.0
热门文章
- matlab反函数求不出来,求反函数,得到的结果不太明白
- 一个测试工程师的职业生涯感悟
- 指定DIV局部刷新的简单实现,很简单,但是网上搜到的大部分都很复杂
- Javassist使用指南1
- 创建西游记类,实例化猪八戒和孙悟空
- 论文阅读“Robust multi-view clustering with incomplete information”
- 论文阅读:EfficientDet: Scalable and Efficient Object Detection
- Docker Desktop requires a newer WSL kernel version.
- 2021语言与智能技术竞赛:机器阅读理解任务 实验报告
- 权限角色管理模块_界面