社区
C语言
帖子详情
求组!!层次遍历二叉树
帅过吴彦祖
2017-07-15 06:40:27
求组,层次遍历二叉树
...全文
224
1
打赏
收藏
求组!!层次遍历二叉树
求组,层次遍历二叉树
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
1 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
帅过吴彦祖
2017-07-15
打赏
举报
回复
# include<stdio.h> # include<stdlib.h> //二叉树结点类型定义 typedef struct btNode { char data; struct btNode * lchild; struct btNode * rchild; }BiTree,*Tree; //队列结点类型定义 typedef struct Node { Tree data; struct Node * next; }Node,*pNode; typedef struct Queue { pNode front; pNode rear; }QUEUE; /*==========队列函数定义==========*/ void InitQueue(QUEUE &); void EnQueue(QUEUE &, Tree); void DeQueue(QUEUE &); bool EmptyQueue(QUEUE); void GetHead(QUEUE, Tree&); /*==========队列函数定义==========*/ /*==========二叉树函数定义==========*/ void CreateTree(Tree &); void Visit(Tree); int Height(Tree); void LevelOrder(Tree); /*==========二叉树函数定义==========*/ int main(void) { Tree T; printf("\n按先序序列输入结点序列,'#'代表空:"); CreateTree(T); printf("二叉树的高度为%d\n",Height(T)); printf("二叉树的层次遍历结果为:"); LevelOrder(T); printf("\n"); return 0; } void init(QUEUE & Q) { Q.front = (pNode)malloc(sizeof(Node)); if(NULL == Q.front) { printf("动态分配内存失败\n"); exit(-1); } Q.rear = Q.front; } //入队 void EnQueue(QUEUE & Q, Tree e) { pNode pNew = (pNode)malloc(sizeof(Node)); if(NULL == pNew) { printf("动态分配内存失败\n"); exit(-1); } pNew->data = e; pNew->next = NULL; Q.rear->next = pNew; Q.rear = pNew; } //出队 void DeQueue(QUEUE & Q) { if(Q.front == Q.rear) return; else { pNode p = Q.front->next; Q.front = p->next; if(Q.rear == p) Q.rear = Q.front; free(p); } } //判断队列是否为空 bool EmptyQueue(QUEUE Q) { if(Q.rear == Q.front) return true; else return false; } //获得对首元素 void GetHead(QUEUE Q, Tree & e) { if(EmptyQueue(Q)) { return; } else { e = Q.front->next->data; } } //创建二叉树 void CreateTree(Tree &T) { char ch; scanf("%c", &ch); if('#' == ch) T = NULL; else { T = (Tree)malloc(sizeof(BiTree)); if(NULL == T) { printf("动态分配内存失败"); exit(-1); } else { T->data = ch; CreateTree(T->lchild); CreateTree(T->rchild); } } } //访问节点 void Visit(Tree T) { printf("%c", T->data); } //求树的高度 int Height(Tree T) { int ld = 0; int rd = 0; if(NULL == T) return 0; else { ld = Height(T->lchild); rd = Height(T->rchild); return 1 + (ld>rd?ld:rd); } } //层次遍历 void LevelOrder(Tree T) { QUEUE Q; init(Q); Tree p; if(NULL != T) { EnQueue(Q, T); while(!EmptyQueue(Q)) { GetHead(Q, p); DeQueue(Q); Visit(p); if(NULL != p->lchild) EnQueue(Q, p->lchild); if(NULL != p->rchild) EnQueue(Q, p->rchild); } } } 输入A##能行输入AB##C##错误
建立
二叉树
,并输出
二叉树
的先序,中序和后序遍历序列,以及
二叉树
的叶子数
二叉树
可执行代码,用了就知道 。
二叉树
的遍历、线索及应用( 用递归或非递归的方法都可以) [问题描述] 建立
二叉树
,并输出
二叉树
的先序,中序和后序遍历序列,以及
二叉树
的叶子数。 [基本要求] 要求根据读取的元素建立
二叉树
,能输出各种遍历。 [实现提示] 可通过输入带空格的前序序列建立二叉链表。
生成平衡
二叉树
设
二叉树
节点值为大写字母,输入
二叉树
的前序遍历和中序遍历序列,生成此
二叉树
,输出该
二叉树
的后续遍历和按
层次遍历
序列。输入某节点值,在
二叉树
中查找该结点,若该结点存在,则输出从根到该结点的路径,否则给出不存在信息。
算法入门教程——
二叉树
循序渐进的讲解
二叉树
的相关知识。其中包括二叉搜索树的插入、删除与查询、
二叉树
的遍历、求一颗
二叉树
的高度等重要且经典的知识。
第五章 树与
二叉树
5.1 数的逻辑结构 5.1.1 1、树的定义 在树中常常将数据元素称为结点 (1)有且仅有一个特定的称为根的结点; (2)当n>1时,除根结点之外的其余结点被分成m(m>0)个互不相交的有限集合T1,T2,•••Tm,其中每个集合又是一棵树,并称为这个节点的子树。 2、树的基本术语: 结点的度、树的度 叶子节点、分支结点 孩子节点、分支结点、兄弟节点 路径、路径长度 祖先、子孙 结点的层数、树的深度(高度) 层序编号 有序树、无序树 森林 5.1.2 树的抽象数据类型定义 5.1.3树的遍历操作 1、前序遍历 树的前序遍历操作定义为: 若树为空,则空操作返回;否则 (1)访问根结点 (2)按照从左向右的顺序前序遍历根结点的每一棵子树。 2、中序遍历 树的中序遍历操作定义为: 若树为空,则空操作返回;否则 (1)按照从左向右的顺序后序遍历根结点的每一棵子树; (2)访问根结点。 3、层序遍历 树的层序遍历也称作树的广泛遍历,其操作定义为树的第一层开始,自上而下逐层遍历,在同一层中,按从左向右的顺序对结点逐个访问。 5.2树的存储结构 5.2.1 双亲表示法 由树的定义可知,树中每个结点都有且仅有一个双亲结点。所以利用这一特性,可以用一维数组来存储各个结点,数组中一个元素对应一个结点,数组元素包括树中结点的数据信息以及该结点的双亲在数组中的下标。 其中: Data为数据域,存储树中结点的数据信息; Parent为指针即游标,存储该结点的双亲在数组中的小标。 5.2.2孩子表示法 1、多重链表表示法 (1)指针域的个数等于该结点的度。 (2)指针域的个数等于树的度。 2、孩子链表表示法 把孩子看成一个线性表,且以单链表存储,称为该结点的孩子链表。则n个结点有n个孩子链表。 孩子节点有两类:孩子节点、表头结点。 5.2.3 双亲孩子表示法 即将双亲表示法和孩子链表表示法相结合的存储方法。仍将各结点的孩子分别组成单链表,同时用一维数组顺序存储树中的各结点,数组元素除了包括结点的数据信息和该结点的孩子链表的头指针之外,还增设一个域存储该结点的双亲在数组的下标。 5.2.4孩子兄弟表示法 又称二链表表示法,其方法是链表中每个结点除数据域外,还设置了两个指针分别指向该结点的第一个孩子和右兄弟链表的结构: Firstchild data rightsib 指针域,存储第一个孩子结点的存储地址 数据域,存储该结点的数据信息 指针域,存储该结点右兄弟结点的存储地址 5.3
二叉树
的逻辑结构 最简单的树结构,特别适合计算机处理,而且任何数都可以简单的转换为
二叉树
。(重点内容) 5.3.1
二叉树
的定义
二叉树
是n(n>=0)个结点的有限集合,该集合或者为空集,或者有一个根节点和两棵互不相交的、分别称为根节点的左子树和右子树的
二叉树
组成。
二叉树
具有五种基本形态: 1、空
二叉树
; 2、只有一个根结点; 3、根结点只有左子树; 4、根结点只有右子树; 5、根结点既有左子树又有右子树 特殊
二叉树
: 1、斜树; 2、满
二叉树
; 3、完全
二叉树
; 5.3.2
二叉树
的基本性质 性质5-1
二叉树
的第i层上最多有2^(i-1)个结点(i>=1)。 性质5-2 在一棵深度为k的
二叉树
中,最多有2^k-1个结点,最少有k个结点。 性质5-3 在一棵
二叉树
中,如果叶子结点的个数为n0,度为2的结点个数为n2,则n0=n2+1. 性质5-4 具有n个结点的完全
二叉树
的深度为【log2^n】+1。 性质5-5 对一棵具有n个结点的完全
二叉树
中的结点从一开始按层序编号,则对于任意的编号为i(1<=i<=n)的结点,有: (1)如果i>1,则结点i的双亲的编号为【i/2】;否则结点i是根结点,无双亲。 (2)如果2i<=n,则 结点i的左孩子的编号为2i;否则结点i无左孩子。 (3)如果2i+1<=n,则结点i的右孩子的编号为2i+1,否则结点i无右孩子。 5.3.3
二叉树
的抽象数据类型定义 同树类似,在不同的应用中,
二叉树
的基本操作不尽相同。 5.3.4
二叉树
的遍历操作
二叉树
的遍历是指从根节点出发,按照某种次序访问
二叉树
是所有结点,使得每个结点被访问一次且仅被访问一次。由于
二叉树
中每个结点都可能有两个子树,因此需要寻找一条合适的搜索路径。 1、前序遍历 前序遍历
二叉树
操作定义为: 若树为空,则空操作返回;否则 (1)访问根结点 (2)前序遍历根结点的左子树 (3)前序遍历根结点的右子树 2、中序遍历 中序遍历
二叉树
操作定义为: 若树为空,则空操作返回;否则 (1)中序遍历根结点的左子树 (2)访问根结点 (3)中序遍历根结点的右子树 3、后序遍历 后序遍历根结点的左子树 后序遍历根结点的右子树 访问根结点 4、层序遍历
二叉树
的层序遍历是指从
二叉树
的第一层开始,从上之下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。 5.4
二叉树
存储结构及实现 5.4.1 顺序存储结构 具体步骤: (1)将
二叉树
按完全
二叉树
编号。 (2)将
二叉树
中的结点一编号顺序存储到一维数组中。 5.4.2 二叉链表 基本思想: 令
二叉树
的每个结点对应一个链表结点,链表结点除了存放于
二叉树
结点有关的数据信息外,还要设置指示左右孩子的指针。 5.4.3 三叉链表 在二叉链表存储方式下,从某个结点出发可以直接访问它的孩子结点,但要找到它的双亲结点,则需要从根节点开始搜索,最坏的情况下,需要遍历整个二叉链表。此时采用三叉树链表储存
二叉树
。 其中,data,lchild,rchild三个域的含义同
二叉树
,parent域为指向该结点的双亲结点指针。 5.4.4 线索链表 按照某种遍历次序对
二叉树
进行遍历,可以把
二叉树
中所有结点排成一个线性序列。在集体应用中,有时需要访问
二叉树
中的结点在某种遍历序列中前驱和后继,此时,在存储结构中应该保存结点在某种遍历序列中的前驱和后继信息。 前驱和后继结点的指针称为线索,加上线索的
二叉树
称为线索
二叉树
,加上线索的二叉链表称为线索链表。 5.5
二叉树
遍历的非递归算法 5.5.1 前序遍历非递归算法 关键:在前序遍历过某个左子树后,如何找到该结点的右子树的根指针。 一般的前序遍历执行过程中,设要遍历
二叉树
的根指针为bt,可能出现两种情况: (1)若bt!=NULL,则表明当前
二叉树
不为空,此时,应输入根结点bt的值并将bt保存到栈中,准备继续遍历bt的左子树。 (2)若bt=NULL,则表明以bt为根指针的
二叉树
遍历完毕,并且bt是栈顶指针所指结点的左子树,若栈不空,则应根据栈顶指针所指结点找到待遍历右子树的根指针并赋予bt,以继续遍历下去;若栈空,则表明整个
二叉树
遍历完毕。 5.5.2 中序遍历非递归算法 此算法只是需要将前序遍历的非递归算法中输出的语句cout<
data移到bt=s[top--]之后即可。 5.5.3 后序遍历非递归算法 后序遍历的不同在于:结点要出入两次栈,出两次栈,这种情况的含义和处理方法为: (1)第一次出栈:只遍历晚左子树,右子树尚未遍历,则该结点不出栈,利用栈顶结点找到它的右子树,准备遍历它的右子树。 (2)第二次出栈:遍历完右子树,该结点出栈,并访问它。 设根指针为bt,则可能有以下两种情况: (1)若bt!=NULL,则bt及标志flag入栈,遍历其左子树。 (2)若bt=NULL,此时栈空,则整个遍历结束;若栈不空,则表明栈顶结点的左子树或右子树已遍历结束。若栈顶点的标志flag=1,则表明栈结点的左子树已遍历完毕,将flag修改为2,修改为2,并遍历栈定点的右子树;若栈顶结点的标志flag=2,则表明栈结点的右子树也遍历完毕,输出栈顶结点。 5.6 树、森林与
二叉树
的转换 1.树转换为
二叉树
将一棵树转换为
二叉树
的方法为: (1)加线——树中所有相邻的兄弟结点之间加一条线; (2)去线——对树中的每个节点,只保留它与第一个孩子结点之间的连线,删去它与其他孩子结点之间的连线。 (3)层次调节——以根结点为轴心,将树顺时针转动一定角度,使之层次分明。 2.森林转换成
二叉树
(1)将森林中的每一棵
二叉树
转化成
二叉树
; (2)从第二课
二叉树
开始,依次把后一棵
二叉树
的根结点作为一棵
二叉树
根节点的右孩子,当所有
二叉树
连起来后,此时所得到的
二叉树
就是由森林转换得到的
二叉树
。 3、
二叉树
转换为树或森林 (1)加线——若某个结点x是其双亲y的左孩子,则把结点x的右孩子、右孩子的右孩子、……,都与结点y用线连起来; (2)去线——删去原
二叉树
中所有的双亲结点与右孩子结点的连线; (3)层次调整——整理由(1)、(2)两步所得到的树或森林,使之层次分明。 (4)森林的遍历 两种遍历方法;前序遍历后续遍历。 5.7 应用举例 5.7.1
二叉树
的应用举例——哈夫曼及哈夫曼编码 1、哈夫曼树也称最优
二叉树
,在实际中有着广泛的应用。 叶子节点的权值 是对叶子结点赋予的一个有意义的数值量。
二叉树
的带权路径长度 设
二叉树
具有n个带权值的叶子节点,从根节点到叶子节点的路径长度与相应的叶子节点权值的乘积之和叫做
二叉树
的带权路径长度,记为: WPL=EWkLk 哈夫曼树 给定一组具有确定权值的叶子结点,可以构造出不同的
二叉树
,将其中带权值路径长度最小的
二叉树
称为哈夫曼树。 哈夫曼算法基本思想: (1)初始化:由给定的n个权值构造n棵只有一个根结点的
二叉树
,从而得到一个
二叉树
集合。 (2)选取与合并:在F中选取根结点的权值最小的两棵
二叉树
分别作为左、右子树构造一棵新的
二叉树
,这棵新的
二叉树
的根结点的权值为其左右子树根结点的权值之和。 (3)删除与加入:在F中删除作为左、右子树的两棵
二叉树
,并将新建的
二叉树
加入到F中。 (4)重复(2)(3)两步的操作,当集合F只剩下一棵
二叉树
时这棵
二叉树
便是哈夫曼树。 2、哈夫曼编码 在进行程序设计时,通常给每一个字符记一个单独的代码来表示一组字符,我们称之为编码。
北京交通大学数据结构上机题10-19
数组与广义表 10、鞍点问题: 若矩阵A中的某一元素A[i,j]是第i行中的最小值,而又是第j列中的最大值,则称A[i,j]是矩阵A中的一个鞍点。写出一个可以确定鞍点位置的程序。 11、稀疏矩阵转置: 输入稀疏矩阵中每个元素的行号、列号、值,建立稀疏矩阵的三元组存储结构,并将此矩阵转置,显示转置前后的三元组结构。 12、用头尾链表存储表示法建立广义表,输出广义表,求广义表的表头、广义表的表尾和广义表的深度。 树和
二叉树
以下问题要求统一在一个大程序里解决。 13、按先序遍历的扩展序列建立
二叉树
的存储结构 14、
二叉树
先序、中序、后序遍历的递归算法 15、
二叉树
中序遍历的非递归算法 16、
二叉树
层次遍历
的非递归算法 17、求
二叉树
的深度(后序遍历) 18、建立树的存储结构 19、求树的深度
C语言
69,371
社区成员
243,080
社区内容
发帖
与我相关
我的任务
C语言
C语言相关问题讨论
复制链接
扫一扫
分享
社区描述
C语言相关问题讨论
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章