数据结构二叉树遍历及线索化后各种操作(绝对无错)

合集下载

二叉树遍历前序中序后序算法

二叉树遍历前序中序后序算法

二叉树遍历前序中序后序算法嘿,朋友,今天咱们聊聊二叉树的遍历,听上去有点复杂,其实一点都不难,就像吃瓜一样轻松!先来简单介绍一下,二叉树就像家里的家谱树,每个节点代表一个家庭成员,左右两个孩子代表着它的“后代”。

而遍历嘛,就是咱们要找出树上的每一个成员,看看他们在干啥。

首先是前序遍历,听这个名字就知道,它是先看爸爸,然后看左边的孩子,最后再看右边的。

这就像咱们去亲戚家串门,进门先跟长辈打招呼,再去找小朋友玩,先礼后兵,懂不懂?这样一来,整个树就都在咱的掌控之中,简直是如虎添翼。

再说这中序遍历,简单得很,就是先看左边,再看爸爸,最后再看右边。

就像咱们吃饭,先把青菜吃了,接着吃主食,最后来个甜点,吃得心满意足。

通过这种方式,咱们能得到一个排好序的结果,简直是个小吃货的心愿。

然后就是后序遍历,听名字就觉得有点神秘。

它的顺序是先看左边的孩子,再看右边的,最后才是爸爸。

这个遍历方式就像是收拾家,先把玩具放回去,再把书整理好,最后再把桌子擦一擦,整个过程干净利落,谁看了都得点赞!这样一来,不论是前、中、后,咱都能把树上的每一个节点清清楚楚地遍历一遍,真是爽快!可能会遇到一些难缠的树,比如不平衡的二叉树,这时候就像是一个在打怪的游戏,咱们得运用聪明才智,找到最优解。

你要是用前序遍历的话,能迅速找到每个节点,可是要是用后序遍历,那可就需要更多的耐心和时间。

每一种遍历方法都有它独特的魅力,就像每个人的性格,各有千秋,谁也不能小看谁!说到这里,咱们还得提提递归和非递归的方法。

递归就像是个循环的故事,永远在重复,直到找到结果;而非递归呢,就是更为直接,像一刀切的方式,让人省心省力。

每种方式都有它的优缺点,选哪个好,得看你自己的情况,真是一个聪明的选择题呢!哎,提到遍历,大家最关心的就是效率问题了。

前序、中序、后序,各有高低,性能的差异就像爬山,谁能跑得快,谁就能早到山顶。

不过别担心,只要有方法,效率就会提高,想要在这棵树上玩得开心,最重要的就是要选择合适的遍历策略。

二叉树的遍历方法

二叉树的遍历方法

二叉树的遍历方法1. 前序遍历:先访问根节点,再遍历左子树,最后遍历右子树。

详细描述:从根节点开始,首先访问根节点并打印它的值。

接着,递归地遍历左子树,然后递归地遍历右子树。

2. 中序遍历:先遍历左子树,再访问根节点,最后遍历右子树。

详细描述:从根节点开始,首先递归地遍历左子树。

然后,访问根节点并打印它的值。

递归地遍历右子树。

3. 后序遍历:先遍历左子树,再遍历右子树,最后访问根节点。

详细描述:从根节点开始,首先递归地遍历左子树。

然后,递归地遍历右子树。

访问根节点并打印它的值。

4. 层序遍历:按照层级顺序从上往下逐层遍历二叉树。

详细描述:从根节点开始,将其放入队列中。

然后,循环执行以下步骤直到队列为空:取出队列头部的节点,访问该节点并打印它的值,将其左子节点和右子节点(如果存在)依次放入队列尾部。

5. 深度优先遍历(DFS):按照深度优先的顺序遍历二叉树。

详细描述:深度优先遍历可以使用递归或者栈来实现。

从根节点开始,首先访问根节点并打印它的值。

接着,递归地遍历左子树,并递归地遍历右子树。

6. 广度优先遍历(BFS):按照广度优先的顺序遍历二叉树。

详细描述:广度优先遍历使用队列来实现。

从根节点开始,首先将根节点放入队列中。

然后,开始循环,直到队列为空:取出队列头部的节点,访问该节点并打印它的值,将其左子节点和右子节点(如果存在)依次放入队列尾部。

7. 反序前序遍历:先访问右子树,再访问左子树,最后访问根节点。

详细描述:从根节点开始,首先递归遍历右子树。

然后,递归遍历左子树。

访问根节点并打印它的值。

8. 反序中序遍历:先遍历右子树,再访问根节点,最后遍历左子树。

详细描述:从根节点开始,首先递归遍历右子树。

然后,访问根节点并打印它的值。

递归遍历左子树。

9. 反序后序遍历:先访问根节点,再遍历右子树,最后遍历左子树。

详细描述:从根节点开始,首先访问根节点并打印它的值。

接着,递归地遍历右子树。

递归地遍历左子树。

二叉树遍历方法

二叉树遍历方法

二叉树遍历方法一、概述二叉树是一种重要的数据结构,它由节点(Node)组成,每个节点最多有两个孩子节点,分别称为左孩子和右孩子。

遍历二叉树是一种重要的操作,可以用于搜索或处理节点的数据。

本文主要介绍四种二叉树遍历方法:前序遍历、中序遍历、后序遍历和层次遍历,并对它们的特点、时间复杂度、以及实际应用做一个详细介绍。

二、前序遍历前序遍历是指,先访问根节点,再访问根节点的左子树,最后访问根节点的右子树。

具体步骤如下:1.访问根节点2.递归遍历左子树3.递归遍历右子树下面是前序遍历的时间复杂度:O(n),其中n表示节点的个数。

因为需要遍历每个节点一次。

前序遍历的应用场景比较广泛,主要用来复制一棵树。

例如我们需要复制一棵二叉树,只需要先创建一个新的节点,将原树的根节点值赋给新节点,再递归复制左子树和右子树即可。

三、中序遍历中序遍历是指,先访问根节点的左子树,再访问根节点,最后访问根节点的右子树。

具体步骤如下:1.递归遍历左子树2.访问根节点3.递归遍历右子树下面是中序遍历的时间复杂度:O(n),其中n表示节点的个数。

因为需要遍历每个节点一次。

中序遍历的应用场景比较少,但也有一些有用的应用。

例如我们有一棵二叉查找树,需要将它转化为排序后的数组。

只需要使用中序遍历,访问每个节点时将节点值存入数组,就可以得到一个排序后的数组。

四、后序遍历后序遍历是指,先访问根节点的左子树,再访问根节点的右子树,最后访问根节点。

具体步骤如下:1.递归遍历左子树2.递归遍历右子树3.访问根节点下面是后序遍历的时间复杂度:O(n),其中n表示节点的个数。

因为需要遍历每个节点一次。

后序遍历的应用场景比较少,但在树的某些操作中比如判断二叉树是否为平衡树时经常用到。

只有按照后序遍历来遍历二叉树,才能判断它是否为平衡树。

五、层次遍历层次遍历是指,从上到下,从左到右依次访问每个节点。

具体步骤如下:1.将根节点入队2.当队列不为空时,取出队头节点并访问3.将队头节点的左子树、右子树入队下面是层次遍历的时间复杂度:O(n),其中n表示节点的个数。

数据结构—树二叉树前序遍历、中序遍历、后序遍历【图解实现】

数据结构—树二叉树前序遍历、中序遍历、后序遍历【图解实现】

数据结构—树二叉树前序遍历、中序遍历、后序遍历【图解实现】AI研习图书馆,发现不一样的精彩世界数据结构二叉树的遍历一、树在谈二叉树的知识点之前,我们首先来看一下树和图的基本概念。

树:不包含回路的连通无向图,树是一种简单的非线性结构。

由于树有一个不包含回路的特点,因此树被赋予了许多特性,如下所示:1、一棵树中任意的两个结点有且仅有唯一的一条路径连通2、一棵树如果有n个结点,那么它一定恰好有n-1条边3、在一棵树中加上一条边,将会构成一个回路4、一棵树中有且仅有一个没有前驱的结点,即为根结点通常情况下,我们在对树进行讨论的时候,将一棵树中的每个点称为结点:根结点:没有父结点的结点叶结点:没有子结点的结点内部结点:一个结点既不是根结点也不是叶结点每个结点有一个深度的概念,例如上图左边的树,4号结点深度是3。

二、二叉树1. 基本概念二叉树是一种非线性结构,二叉树是由递归定义的,其结点有左右子树之分。

2. 二叉树的存储结构二叉树一般采用链式存储结构,存储结点由数据域和指针域组成,二叉树的链式存储结构也称为二叉链表。

指针域:左指针域和右指针域特点:1、每个结点最多有两颗子树2、左子树和右子树是有顺序的,次序不能颠倒3、即使某个结点只有一颗子树,也要区分左右子树4、二叉树可为空,空的二叉树没有结点,非空二叉树有且仅有一个根节点二叉树中有两种比较特殊的二叉树:满二叉树、完全二叉树,对于满二叉树和完全二叉树可以按照层次进行顺序存储。

满二叉树:二叉树中每个内部结点都存在左子树和右子树满二叉树一定是完全二叉树,但完全二叉树不一定是满二叉树。

满二叉树的严格定义:一颗深度为h且具有2h-1个结点的二叉树。

完全二叉树:解释一:如果一颗二叉树除了最右边位置上有一个或几个叶结点缺少外,其他都是丰满的,那么这样的二叉树就是完全二叉树。

解释二:除第h层外,其他各层(1到h-1)的结点数都达到最大个数,第h层从右向左连续缺若干结点,则这个二叉树就是完全二叉树。

二叉树遍历的递归实现详解(先序、中序、后序和层次遍历)

二叉树遍历的递归实现详解(先序、中序、后序和层次遍历)

⼆叉树遍历的递归实现详解(先序、中序、后序和层次遍历)由⼆叉树的定义可知,⼀棵⼆叉树由根结点、左⼦树和右⼦树三部分组成。

因此,只要遍历了这三个部分,就可以实现遍历整个⼆叉树。

若以D、L、R分别表⽰遍历根结点、左⼦树、右⼦树,则⼆叉树的递归遍历可以有⼀下四种⽅式:先序遍历(DLR)先序遍历的递归过程为(1)访问根结点(2)先序遍历根结点的左⼦树(3)先序遍历根结点的右⼦树举例:代码:void PreOrder(BiTree bt){if(bt ==NULL)return; //递归的结束条件----某结点为空时printf("%d",bt->data); //这⾥⽤printf data表⽰访问结点的数据域PreOrder(bt->lchild); //递归遍历左孩⼦PreOrder(bt->rclild); //递归遍历右孩⼦}中序遍历(LDR)(1)中序遍历根结点的左⼦树(2)访问根结点(3)中序遍历根结点的右⼦树举例:代码:void InOrder(BiTree bt){if(bt ==NULL)return; //递归的结束条件----某结点为空时InOrder(bt->lchild); //递归遍历左孩⼦printf("%d",bt->data); //这⾥⽤printf data表⽰访问结点的数据域InOrder(bt->rclild); //递归遍历右孩⼦}后序遍历(LRD)(1)后序遍历⼆叉树的左⼦树(2)后序遍历⼆叉树的右⼦树(3)访问根结点。

举例:代码:void PostOrder(BiTree bt){if(bt ==NULL)return; //递归的结束条件----某结点为空时PostOrder(bt->lchild); //递归遍历左孩⼦PostOrder(bt->rclild); //递归遍历右孩⼦printf("%d",bt->data); //这⾥⽤printf data表⽰访问结点的数据域}层次遍历(1)根结点⼊队列(2)根结点出队列,根结点的左⼦树、右⼦树相继⼊队列(3)根结点的左⼦树结点出队列,左⼦树结点的左⼦树、右⼦树相继⼊队列(4).......举例:代码://层次遍历⼆叉树void LevelOrder(BiTree T){BiTree Queue[MAX],b; //⽤⼀维数组表⽰队列,front和rear表⽰队⾸和队尾的指针int front,rear;front=rear=0;if(T)//若树为空{Queue[rear++]=T; //根节点⼊队列while(front!=rear) //当队列⾮空{b=Queue[front++]; //队⾸元素出队列,并访问这个节点printf("%2c",b->data);if(b->lchild!=NULL) Queue[rear++]=b->lchild ; //若左⼦树⾮空,则⼊队列if(b->rchild!=NULL) Queue[rear++]=b->rchild ; //若右⼦树⾮空,则⼊队列}}}最终代码:#include<stdio.h>#include<stdlib.h>#define MAX 20typedef char TElemType;typedef int Status;typedef struct BiTNode{TElemType data;struct BiTNode *lchild,*rchild; //左右孩⼦的指针} BiTNode,*BiTree;//先序创建⼆叉树void CreateBiTree(BiTree *T){char ch;ch=getchar();if(ch=='#')(*T)=NULL; //#代表空指针else{(*T)=(BiTree)malloc(sizeof(BiTNode)); //申请节点(*T)->data=ch; //⽣成跟节点CreateBiTree(&(*T)->lchild);CreateBiTree(&(*T)->rchild);}}//先序输出⼆叉树void PreOrder(BiTree T){if(T){printf("%2c",T->data); //访问根节点,此处为输出根节点的数据值PreOrder(T->lchild); //先序遍历左⼦树PreOrder(T->rchild); //先序遍历右⼦树}}//中序输出⼆叉树void InOrder(BiTree T){if(T){InOrder(T->lchild);printf("%2c",T->data);InOrder(T->rchild);}}//后序输出⼆叉树void PostOrder(BiTree T){if(T){PostOrder(T->lchild);PostOrder(T->rchild);printf("%2c",T->data);}}//层次遍历⼆叉树void LevelOrder(BiTree T){BiTree Queue[MAX],b; //⽤⼀维数组表⽰队列,front和rear表⽰队⾸和队尾的指针 int front,rear;front=rear=0;if(T)//若树为空{Queue[rear++]=T; //根节点⼊队列while(front!=rear) //当队列⾮空{b=Queue[front++]; //队⾸元素出队列,并访问这个节点printf("%2c",b->data);if(b->lchild!=NULL) Queue[rear++]=b->lchild ; //若左⼦树⾮空,则⼊队列if(b->rchild!=NULL) Queue[rear++]=b->rchild ; //若右⼦树⾮空,则⼊队列}}}//求树的深度int depth(BiTree T){int dep1,dep2;if(T==NULL) return 0;else{dep1=depth(T->lchild);dep2=depth(T->rchild);return dep1>dep2?dep1+1:dep2+1;}}int main(){BiTree T=NULL;printf("\n 创建⼀棵⼆叉树: \n");CreateBiTree(&T); //创建⼆叉树printf("\n先序遍历的结果为:\n");PreOrder(T); //先序遍历printf("\n中序遍历的结果为:\n");InOrder(T); //中序遍历printf("\n 后序遍历的结果为: \n");PostOrder(T);printf("\n 层次遍历的结果为: \n");LevelOrder(T); //层次遍历printf("\n 树的深度为:%d\n",depth(T));}结果⽰例:⼤家喜欢的话可以点个赞,有错误的地⽅请务必在评论区指出哟。

二叉树遍历大全

二叉树遍历大全

二叉树的前序遍历、中序遍历、后续遍历(包括递归、非递归,共六种)1、前序遍历(递归):算法实现一:#include <stdio.h>#include <stdlib.h>typedef struct BiTNode//定义结构体{char data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;void CreateBiTree(BiTree &T) //前序创建树{char ch;scanf("%c",&ch);if(ch==' ') T=NULL;else{T=(struct BiTNode *)malloc(sizeof(struct BiTNode));T->data=ch;CreateBiTree(T->lchild);CreateBiTree(T->rchild);}}int print(BiTree T)//前序遍历(输出二叉树){if(T==NULL)return 0;else if(T->lchild==NULL && T->rchild==NULL)return 1;else return print(T->lchild)+print(T->rchild);}void main()//主函数{BiTree T;CreateBiTree(T);printf("%d\n",print(T));}算法实现二:#include<stdio.h>#include<stdlib.h>struct BiTNode//定义结构体{char data;struct BiTNode *lchild,*rchild;};int num=0;void CreatBiTree(struct BiTNode *&p) //前序创建树{char ch;scanf("%c",&ch);if(ch==' ') p=NULL;else{p=(struct BiTNode *)malloc(sizeof(struct BiTNode));p->data=ch;CreatBiTree(p->lchild);CreatBiTree(p->rchild);}}void print(struct BiTNode *p) //前序遍历(输出二叉树){if(p!=NULL){if(p->lchild==NULL&&p->rchild==NULL)else{print(p->lchild);print(p->rchild);}}}void main()//主函数{struct BiTNode *p;CreatBiTree(p);print(p);printf("%d\n",num);}#include<stdio.h>#include<stdlib.h>struct BiTNode//定义结构体{char data;struct BiTNode *lchild,*rchild;};void later(struct BiTNode *&p) //前序创建树{char ch;scanf("%c",&ch);if(ch==' ')p=NULL;else{p=(struct BiTNode *)malloc(sizeof(struct BiTNode));p->data=ch;later(p->lchild);later(p->rchild);}}void print(struct BiTNode *p) //中序遍历(输出二叉树){if(p!=NULL){print(p->lchild);printf("%c",p->data);print(p->rchild);}elseprintf(" ");}void main()//主函数{struct BiTNode *p;later(p);print(p);}#include<stdio.h>#include<stdlib.h>struct BiTNode//定义结构体{char data;struct BiTNode *lchild,*rchild;};void later(struct BiTNode *&p) //前序创建树{char ch;scanf("%c",&ch);if(ch==' ')p=NULL;else{p=(struct BiTNode *)malloc(sizeof(struct BiTNode));p->data=ch;later(p->lchild);later(p->rchild);}}void print(struct BiTNode *p) //后序遍历(输出二叉树){if(p!=NULL){print(p->lchild);print(p->rchild);printf("%c",p->data);}elseprintf(" ");}void main()//主函数{/*检测:printf("到了吗");*/struct BiTNode *p;later(p);print(p);}#include<stdio.h>#include<stdlib.h>struct BiTNode *stack[100];struct BiTNode//定义结构体{char data;struct BiTNode *lchild,*rchild;};void later(struct BiTNode *&p) //前序创建树{char ch;scanf("%c",&ch);if(ch==' ')p=NULL;else{p=(struct BiTNode *)malloc(sizeof(struct BiTNode));p->data=ch;later(p->lchild);later(p->rchild);}}void print(struct BiTNode *p) //前序遍历(输出二叉树){int i=-1;while(1){while(p!=NULL){stack[++i]=p->rchild;/*printf("ok?\n");*/printf("%c",p->data);p=p->lchild;}if(i!=-1){p=stack[i];i--;}elsereturn;}}void main()//主函数{struct BiTNode *p,*t;later(p);print(p);}5、中序遍历(非递归)#include<stdio.h>#include<stdlib.h>struct BiTNode *stack[100];struct BiTNode//定义结构体{char data;struct BiTNode *lchild,*rchild;};void later(struct BiTNode *&p) //前序创建树{char ch;scanf("%c",&ch);if(ch==' ')p=NULL;else{p=(struct BiTNode *)malloc(sizeof(struct BiTNode));p->data=ch;later(p->lchild);later(p->rchild);}}void print(struct BiTNode *p) //中序遍历(输出二叉树){int i=-1;while(1){while(p!=NULL){i++;stack[i]=p;p=p->lchild;}if(i!=-1){p=stack[i];i--;printf("%c",p->data);p=p->rchild;}}}void main()//主函数{struct BiTNode *p;later(p);print(p);}6、后续遍历(非递归):#include<stdio.h>#include<stdlib.h>struct BiTNode *stack[100];struct BiTNode//定义结构体{char data;struct BiTNode *lchild,*rchild;};void later(struct BiTNode *&p) //前序创建树{char ch;scanf("%c",&ch);if(ch==' ')p=NULL;else{p=(struct BiTNode *)malloc(sizeof(struct BiTNode));p->data=ch;later(p->lchild);later(p->rchild);}}void print(struct BiTNode *p) //后序遍历(输出二叉树){int i=-1;while(1){while(p!=NULL){stack[++i]=p;/*printf.0("ok?\n");*/p=p->lchild;}if(i!=-1){while(p==stack[i]->rchild||(p==stack[i]->lchild&&stack[i]->rchild==NULL)) {p=stack[i--];printf("%c",p->data);if(i==-1)return;}p=stack[i]->rchild;}elsereturn;}}int main()//主函数{struct BiTNode *p,*t;later(p);print(p);printf("\n");system("pause");return 0;}供测试使用的数据。

二叉树遍历(前中后序遍历,三种方式)

二叉树遍历(前中后序遍历,三种方式)

⼆叉树遍历(前中后序遍历,三种⽅式)⽬录刷题中碰到⼆叉树的遍历,就查找了⼆叉树遍历的⼏种思路,在此做个总结。

对应的LeetCode题⽬如下:,,,接下来以前序遍历来说明三种解法的思想,后⾯中序和后续直接给出代码。

⾸先定义⼆叉树的数据结构如下://Definition for a binary tree node.struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}};前序遍历,顺序是“根-左-右”。

使⽤递归实现:递归的思想很简单就是我们每次访问根节点后就递归访问其左节点,左节点访问结束后再递归的访问右节点。

代码如下:class Solution {public:vector<int> preorderTraversal(TreeNode* root) {if(root == NULL) return {};vector<int> res;helper(root,res);return res;}void helper(TreeNode *root, vector<int> &res){res.push_back(root->val);if(root->left) helper(root->left, res);if(root->right) helper(root->right, res);}};使⽤辅助栈迭代实现:算法为:先把根节点push到辅助栈中,然后循环检测栈是否为空,若不空,则取出栈顶元素,保存值到vector中,之后由于需要想访问左⼦节点,所以我们在将根节点的⼦节点⼊栈时要先经右节点⼊栈,再将左节点⼊栈,这样出栈时就会先判断左⼦节点。

代码如下:class Solution {public:vector<int> preorderTraversal(TreeNode* root) {if(root == NULL) return {};vector<int> res;stack<TreeNode*> st;st.push(root);while(!st.empty()){//将根节点出栈放⼊结果集中TreeNode *t = st.top();st.pop();res.push_back(t->val);//先⼊栈右节点,后左节点if(t->right) st.push(t->right);if(t->left) st.push(t->left);}return res;}};Morris Traversal⽅法具体的详细解释可以参考如下链接:这种解法可以实现O(N)的时间复杂度和O(1)的空间复杂度。

二叉树的遍历详解及实现

二叉树的遍历详解及实现

⼆叉树的遍历详解及实现在之前的博⽂中我们讲解了⼆叉树的使⽤——《哈夫曼压缩》,那么,我们对于⼆叉树的操作不仅仅局限于创造,⼆叉树是⼀种储存处理⽅式,但是,我们不能仅仅是存储数据,那么,我们今天就来讲解⼀下从⼆叉树中读取数据的⽅法及操作。

⼆叉树的遍历⽅式有三种:1.先根序:根、左⼦树、右⼦树2.中根序:左⼦树、根、右孩⼦3.后根序:左⼦树、右⼦树、根现在通过⼀个例⼦来为,我让⼤家清晰了解们这三种遍历⽅法:对于这个⼆叉树来说:先根序遍历结果:A B D F G J C E H I中根序遍历结果:F D J G B A H E I C后根序遍历结果:F J G D B H I E C A现在我们来构造⼀个⼆叉树,然后对这个⼆叉树进⾏遍历操作:⾸先,我们按照我们之前博⽂中⼀直有的惯例,上⼿先编写"mec.h":#ifndef _MEC_H_#define _MEC_H_typedef unsigned char boolean;typedef boolean u8;#define TRUE 1#define FALSE 0#define NOT_FOUND -1#define SET(v, i) (v |= (1 << ((i) ^ 7)))#define CLR(v, i) (v &= ~(1 << ((i) ^ 7)))#define GET(v, i) (((v) & (1 << ((i) ^ 7))) != 0)#endif之后,我们再来构建⼆叉树“单节点”结构体:typedef struct BTREE {int data;struct BTREE *left;struct BTREE *right;}BTREE;那么,我们要构建⼆叉树,就要从键盘输⼊⼀个字符串,再读取字符串判断字符串输⼊是否合理,再根据正确的字符串构建⼆叉树。

第6章 树和二叉树2-遍历二叉树

第6章 树和二叉树2-遍历二叉树
数据结构讲义 第6章 树和二叉树
— 遍历二叉树
6.3 遍历二叉树
Hale Waihona Puke 二叉树的遍历– 方法
D L R
LDR、LRD、DLR RDL、RLD、DRL
先序遍历:先访问根结点,然后分别先 序遍历左子树、右子树。 中序遍历:先中序遍历左子树,然后 访问根结点,最后中序遍历右子树。 后序遍历:先后序遍历左、右子树, 然后访问根结点。 按层次遍历:从上到下、从左到右访 问各结点。
A
B D i C P->A 访问:C B E (6)
A p D F G i
F
G
P->D P->A
访问:C B
(5)
A B C p (7) E G D
A
i F
P->E P->D P->A 访问:C B C
B P->D F E P->A 访问:C B G (8) E p D i
A
A i B P->G P->D P->A 访问:C B E (9) p A C E G D F i

示例代码
作业
A
当用栈非递归实现树 的先序遍历时,写出 遍历右边所表示的树 的全过程。像讲义中 那样,写出遍历每一 步栈中的数据。不是 写具体的实现代码。
B C E D
F
G
– 按先序遍历序列建立二叉树的二叉链表,已知先序
序列为: A B C D E G F
A B C E G D F B ^ C ^ ^ E ^ G D ^ ^ F ^
A ^
二叉树的建立演示
用队列实现层次遍历
可使用一个顺序存储的队列q[100],存放 还没有处理的子树的根结点的地址。注 意,队首和队尾指针分别指向队首结点 和下次进队结点的存放位置。 1) 首先把根节点入队。 2) 然后访问队头的一个结点,再把该结点 非空的左右子树入队。 3) 如果队列不空,重复2)。

图解中序遍历线索化二叉树,中序线索二叉树遍历,CC++描述

图解中序遍历线索化二叉树,中序线索二叉树遍历,CC++描述

图解中序遍历线索化⼆叉树,中序线索⼆叉树遍历,CC++描述对于⼀个有n个结点的⼆叉链表,每个结点有指向左右孩⼦的两个指针域,所以⼀共是2n个指针域,⽽n个结点的⼆叉树⼀共有n-1条分⽀线路,也就是说,存在2n-(n-1)= n+1个空指针域。

中序遍历:HDIBJEFCG,通过遍历可以知道,结点I的前驱是D,后继是B考虑利⽤那些空地址,存放指向结点在某种遍历次序下的前驱和后继结点的地址。

我们把这种指向前驱和后继的指针称指向前驱和后继的指针称为线索,加上线索的⼆叉链表称为线索链表,相应的⼆叉树就称为线索⼆叉树(Threaded Binary Tree)对⼆叉树进⾏中序遍历后,将所有空指针域中的rchild改为指向它们的后继结点。

① H的后继是D ... ⑥ G的后继是NULL,中序遍历最后⼀个节点此时共有6个空指针域被利⽤将所有空指针域中的lchild改为指向当前节点的前驱。

① H的前驱是NULL,中序遍历的第⼀个结点 ... ⑥ G的前驱是C此时共有5个空指针被利⽤最终,空⼼箭头实线为前驱,虚线⿊箭头为后继。

线索⼆叉树,等于是把⼀棵⼆叉树变成了⼀个双向链表,这样插⼊⼀个结点、查找⼀个结点都很⽅便。

对⼆叉树以某种次序遍历使其变为线索⼆叉树的过程称为是线索化。

为了区分lchild是指向左孩⼦还是前驱,rchild是指向右孩⼦还是后继,需要⽤⼀个标志位来区分■ ltag为0时指向该结点的左孩⼦,为1时指向该结点的前驱■ rtag为0时指向该结点的右孩⼦,为1时指向该结点的后继//红⾊部分表⽰前驱和后继⼆叉树输⼊过程:ABDH##I##EJ###CF##G##中序遍历:HDIBJEAFCG输⼊过程就是 ab##c## 中序遍历: bac输⼊过程就是 ABC###DE##F# #中序遍历:CBAEDF#include<iostream>using namespace std;enum TBT{child=0,thread}; //线索⼆叉树结点的指针是指向孩⼦还是前驱后继int createThreadedBinaryTree(pTBTree& root){char data;if(cin>>data){if('#'==data){root = nullptr;return -1;}else{ //⽤data数据来初始化root结点,然后递归建⽴左⼦树和右⼦树root = new TBTreeNode(); //创建结点的时候就把结点全部赋值为空root->data = data;createThreadedBinaryTree(root->lchild);createThreadedBinaryTree(root->rchild);}}return 0;}static TBTreeNode* pre = nullptr; //定义⼀个指针指向中序遍历当前访问结点的前⼀个访问结点前驱后继typedef struct tbt{struct tbt* lchild;enum TBT ltag;char data;enum TBT rtag;struct tbt* rchild;}TBTreeNode,*pTBTree;int createThreadedBinaryTree(pTBTree& root);void inorderThreadingBinaryTree(const pTBTree& root); //中序线索化⼆叉树//在中序遍历的同时就线索化⼆叉树void inorderThreadedBinaryTreeTraversal(pTBTree root); //中序线索化⼆叉树遍历int main(){TBTreeNode* root = nullptr;int ret = createThreadedBinaryTree(root);{if(0==ret){inorderThreadingBinaryTree(root);cout<<endl;inorderThreadingBinaryTreeTraversal(root);cout<<endl;}}system("pause");}访问结点的前⼀个访问结点//线索化结点的后继要⽤到,因为中序遍历顺序:左⼦树,根结点,右⼦树//前驱可以⽤刚刚访问过的结点直接赋值,后继还没有访问,这时候当前结点就是上⼀个访问结点pre的后继//当然,前提条件是pre的右⼦树为空//pre初始值为nullptr,因为从根结点开始访问,前⼀个访问结点就只能是空了void inorderThreadingBinaryTree(const pTBTree& root){if(nullptr==root)return ;/* 参考中序遍历inorderTraversal(root->lchild);cout<<root->data<<" ";inorderTraversal(root->rchild);*/inorderThreadingBinaryTree(root->lchild); //中序遍历左⼦树//判断结点指针域可不可以线索化if(nullptr==root->lchild) //如果左⼦树为空,就可以把指针域拿来线索化,指向前驱{root->lchild = pre;root->ltag = thread;}if(nullptr!=pre&&nullptr==pre->rchild) //如果当前访问的根结点不为空,并且前⾯访问的结点pre右⼦树为空,线索化前⼀个结点的后继{pre->rchild = root;pre->rtag = thread;}//访问根结点就变成修改前⼀个访问结点指针prepre = root; //之后要访问右⼦树,当前结点⾃然就是preinorderThreadingBinaryTree(root->rchild); //中序遍历右⼦树}void inorderThreadedBinaryTreeTraversal(pTBTree root){if(nullptr==root)return;while(nullptr!=root){while(nullptr!=root->lchild&&child==root->ltag) //两个条件,区别中序遍历第⼀个结点的前驱是nullptr{//搜寻从根结点开始的左⼦树的最后⼀个节点root = root->lchild;}cout<<root->data<<" "; //输出根结点while(thread==root->rtag) //该结点有后继,意味着没有右⼦树{cout<<root->rchild->data<<" "; //直接输出后继,也就是中序遍历当前结点下⼀个要访问的结点的值root = root->rchild; //根结点回溯到后继}//该结点有右⼦树,root->rtag==child,左⼦树已经遍历完了,这⾥进⼊右⼦树root = root->rchild; //重复上⾯的操作}}。

二叉树的5种遍历方式

二叉树的5种遍历方式

二叉树的5种遍历方式一、前序遍历前序遍历是指在二叉树中,先访问根节点,然后按照先左后右的顺序遍历左右子树。

具体步骤如下:1. 访问根节点;2. 递归遍历左子树;3. 递归遍历右子树。

前序遍历的应用场景非常广泛。

例如,在二叉搜索树中,前序遍历可以用来实现树的查找操作;在表达式树中,前序遍历可以用来将表达式转换为前缀表达式。

二、中序遍历中序遍历是指在二叉树中,先按照中序遍历左子树,然后访问根节点,最后按照中序遍历右子树的顺序遍历整个二叉树。

具体步骤如下:1. 递归遍历左子树;2. 访问根节点;3. 递归遍历右子树。

中序遍历的一个重要应用是对二叉搜索树进行排序,因为中序遍历可以按照升序输出二叉搜索树中的节点值。

三、后序遍历后序遍历是指在二叉树中,先按照后序遍历左子树,然后按照后序遍历右子树,最后访问根节点的顺序遍历整个二叉树。

具体步骤如下:1. 递归遍历左子树;2. 递归遍历右子树;3. 访问根节点。

后序遍历的一个常见应用是计算表达式树的值,因为后序遍历可以按照逆波兰表达式的顺序遍历表达式树。

四、层序遍历层序遍历是指按照从上到下、从左到右的顺序逐层遍历二叉树的节点。

具体步骤如下:1. 将根节点入队;2. 循环执行以下步骤,直到队列为空:a. 出队一个节点,访问该节点;b. 将该节点的左子节点入队(如果存在);c. 将该节点的右子节点入队(如果存在)。

层序遍历可以用来按层打印二叉树的节点值,也可以用来判断二叉树的深度。

五、深度优先遍历深度优先遍历是指在二叉树中,先访问根节点,然后按照深度优先的顺序遍历左右子树。

具体步骤如下:1. 访问根节点;2. 递归遍历左子树;3. 递归遍历右子树。

深度优先遍历的一个常见应用是判断二叉树是否对称。

通过比较左子树和右子树的节点值,可以判断二叉树是否对称。

深度优先遍历还可以用来解决一些搜索问题,例如在二叉树中查找路径等。

在实际应用中,根据具体的问题场景和需求,选择合适的遍历方式非常重要。

数据结构实验报告-线索二叉树的遍历

数据结构实验报告-线索二叉树的遍历

线索二叉树的遍历--《数据结构实验报告》1.基本思想对于n个结点的二叉树,在二叉链存储结构中有n+1个空链域,利用这些空链域存放在某种遍历次序下该结点的前驱结点和后继结点的指针,这些指针称为线索,加上线索的二叉树称为线索二叉树。

线索二叉树的建立就是在二叉树的基础上进行线索化。

本次实验建立了前序线索二叉树,中序线索二叉树,和后序线索二叉树,并分别对前中序线索二叉树进行了前序,中序,后序遍历,对后序线索二叉树进行了后序遍历。

2.用到的数据结构定义节点元素:Left, right为普通二叉树的左右孩子,value为该节点元素的值,Ltag, Rtag为左右线索化指向节点。

在某些遍历中会用到栈结构,用来存储当前可以路过,但是在以后却访问不到的点。

3.基本操作实现1.前,中,后序二叉树的线索化:线索化的实质是将二叉链表中的空指针改为指向前驱或后继的线索,前驱和后继的信息是在遍历过程中才能得到,故线索化的过程即为在遍历过程中修改空指针的过程。

前,中,序线索化的过程相似,只是修改NULL和递归遍历左右孩子的顺序导致产生不同。

2.前序线索二叉树的前序遍历:因为前序线索二叉树建立的过程就是按照前序遍历的思想线索化的,所以按照一直向左走,直到左边的指向为线索时停止,开始向右指(不管是线索还是树枝),依次递归得到答案。

3.前序线索二叉树的中序遍历:根据前序线索化的二叉树在中序遍历时如果按照前序遍历的方式会出现上面的一些点永远无法被访问到,所以,增加一个数据结构—栈。

在一直向左遍历的时候,将这些节点入栈,在回访时,依次取出这些点,在进入到取出点的右孩子,实现中序遍历。

4.前序线索二叉树的后序遍历:思想和中序遍历差不多,但是是将栈中元素的右孩子遍历完成后在输出该元素的值,实现后序遍历。

5.中序线索二叉树的前序遍历:中序的前序遍历比较简单,和前序线索的前序遍历很像,但是在判断左右孩子是否是线索时,需进行循环遍历判断,不是简单的if。

二叉树遍历方式详解

二叉树遍历方式详解

二叉树遍历方式详解1. 引言1.1 介绍二叉树遍历的重要性二叉树是一种重要的数据结构,在计算机科学领域有着广泛的应用。

二叉树的遍历是对树中所有节点进行访问的一种操作,可以帮助我们更好地理解和操作二叉树。

二叉树的遍历有三种主要方式:前序遍历、中序遍历和后序遍历。

通过对二叉树进行遍历,我们可以按照一定的顺序访问树中的所有节点,从而能够更有效地处理树中的数据。

在实际编程中,我们经常需要对二叉树进行遍历操作,因此掌握各种遍历方式是非常重要的。

1.2 说明本文的主要内容本文将对二叉树遍历方式进行详细解释,主要包括递归遍历和迭代遍历两种方法。

在递归遍历二叉树部分,我们将深入讨论前序遍历、中序遍历和后序遍历的实现原理和步骤。

在迭代遍历二叉树部分,我们将介绍如何使用栈或队列来模拟递归遍历的过程,以及解决实际问题时的应用场景。

结合实际例子,我们将总结各种遍历方式的特点,比较它们之间的区别和优缺点。

我们将讨论如何根据问题的特点和需求选择合适的遍历方式,以及如何优化算法以提高程序的效率和性能。

通过本文的阐述,读者将深入了解二叉树遍历的方法和技巧,为解决实际问题提供更加有效的思路和方法。

2. 正文2.1 递归遍历二叉树递归遍历二叉树是一种常见的遍历方式,它通过递归的方式深度优先地访问二叉树的所有节点。

在递归遍历二叉树时,我们需要遵循以下步骤:1. 判断当前节点是否为空,如果为空则返回。

2. 遍历当前节点的左子树,即递归调用遍历左子树的函数。

3. 访问当前节点。

4. 遍历当前节点的右子树,即递归调用遍历右子树的函数。

递归遍历二叉树的优点在于代码简洁清晰,易于理解和实现。

但是在遇到深度较大的二叉树时,可能会导致栈溢出的问题,因为每次递归调用都会占用一定的栈空间。

递归遍历二叉树的时间复杂度为O(n),其中n为二叉树的节点数。

在实际应用中,递归遍历二叉树常用于解决一些简单的问题,如二叉树的求和,查找特定节点等。

对于深度较大的二叉树或者需要较高性能的情况,通常会选择其他遍历方式,如迭代遍历二叉树。

数据结构二叉树的遍历及其他操作

数据结构二叉树的遍历及其他操作

递归算法实现
void change(BinTree &T){ if( !T ) return T; else{ t=T->lchild; T->lchild=T->rchild; T ->rchild=t; change( T->lchild ); change( T->rchild ); } }
第六章 二叉树的遍历及应用
本讲内容
6.3 遍历二叉树
1.遍历二叉树的概念 2.遍历算法实现(递归算法和非递归算法)
先序、中序、后序和层次遍历
3.遍历算法的应用举例
遍历二叉树
遍历二叉树的概念
遍历二叉树就是如何按某条搜索路径巡访二叉树中 的每个结点,使得每个结点均被访问一次,而且仅 被访问一次。
如何确定搜索路径
遍历算法的应用举例
1.统计二叉树中叶子结点的个数 2.统计二叉树中总结点的个数 3.求二叉树的深度 4.建立二叉树的存储结构 5.交换二叉树的左右子树 6.根据遍历序列画对应二叉树
统计二叉树中叶子结点的个数
算法思想
分别求出左子树、右子树的叶子数,然后相加。
根据二叉树的五种基本形态知:
空二叉树,叶子结点数为0;
左子树 右子树
求二叉树的深度
算法思想
二叉树的深度应为其左、右子树深度的最大值加1。 根据二叉树的五种基本形态知:
空二叉树,深度为0;
只有根的二叉树,深度为1;
只有左子树的二叉树,深度为左子树的深度加1;
只有右子树的二叉树,深度为右子树的深度加1; 具有左右子树的二叉树,深度等于左子树的深度与右子树的深 度的最大值加1。
递归算法实现
void CreateBiTree( BiTree &T ) { scanf(“%c”,&ch); if (ch==„‟ ) T = NULL; else{ if (!(T = (BiTree)malloc(sizeof(BiTNode)))) exit(overflow); T->data = ch; // 生成根结点 CreateBiTree( T->lchild ); // 构造左子树 CreateBiTree( T->rchild ); // 构造右子树 } } // CreateBiTree

二叉树的先序,中序,后序遍历的递归写法

二叉树的先序,中序,后序遍历的递归写法

二叉树的先序,中序,后序遍历的递归写法一、前言二叉树是数据结构中最基础、最重要的一种数据结构之一,如何遍历二叉树是每一个数据结构学习者需要掌握的技能。

本文将介绍二叉树的三种遍历方式:前序遍历、中序遍历和后序遍历,以及它们的递归写法。

二、先序遍历二叉树的先序遍历顺序是:根节点→ 左子树→ 右子树。

1.递归写法(1)基本思路先访问根节点,然后递归遍历左子树,最后递归遍历右子树。

(2)代码实现public void preOrderTraversal(TreeNode root) {if (root == null) return;System.out.println(root.val);preOrderTraversal(root.left);preOrderTraversal(root.right);}2.中序遍历二叉树的中序遍历顺序是:左子树→ 根节点→ 右子树。

1.递归写法(1)基本思路递归遍历左子树,然后访问根节点,最后递归遍历右子树。

(2)代码实现public void inOrderTraversal(TreeNode root) {if (root == null) return;inOrderTraversal(root.left);System.out.println(root.val);inOrderTraversal(root.right);}3.后序遍历二叉树的后序遍历顺序是:左子树→ 右子树→ 根节点。

1.递归写法(1)基本思路递归遍历左子树,然后递归遍历右子树,最后访问根节点。

(2)代码实现public void postOrderTraversal(TreeNode root) {if (root == null) return;postOrderTraversal(root.left);postOrderTraversal(root.right);System.out.println(root.val);}三、总结本文介绍了二叉树的三种遍历方式以及它们的递归写法。

数据结构二叉树遍历及线索化后各种操作(绝对无错)

数据结构二叉树遍历及线索化后各种操作(绝对无错)

实验二二叉树的存储结构及各种运算的实现第一题:#include "stdio.h"#include "malloc.h"#define maxsize 66typedef int datatype;typedef struct node{datatype data ;struct node *lchild,*rchild;} bitree;bitree *Q[maxsize];bitree *creatree(){char ch;int front,rear;bitree *root,*s;root=NULL;front=1;rear=0;ch=getchar();while (ch!='#'){s=NULL;if(ch!='@'){s=malloc(sizeof(bitree));s->data=ch;s->lchild=NULL;s->rchild=NULL;}rear++;Q[rear]=s;if(rear==1)root=s;else{if (s&&Q[front])if(rear%2==0)Q[front]->lchild=s;elseQ[front]->rchild=s;if(rear%2==1)front++;。

}ch=getchar();}return root;}preorder(bitree *t) //前{if (t){printf(" %c ",t->data);preorder(t->lchild);preorder(t->rchild);}}inorder(bitree *t) //中{if (t){inorder(t->lchild);printf(" %c ",t->data);inorder(t->rchild);}postorder(bitree *t) //后{if (t){postorder(t->lchild);postorder(t->rchild);printf(" %c ",t->data);}}int height(bitree *t) //高度{int hl,hr;if(!t) return 0;else{hl=height(t->lchild);hr=height(t->rchild);return ((hl>hr?hl:hr)+1);}}int leaf(bitree *t) //叶子static int s;if(t){leaf(t->lchild);leaf(t->rchild);if(t->lchild==NULL&&t->rchild==NULL) s=s+1;}return s;}main(){bitree *t;int x,y;printf("输入数据,以#做结尾:\n");t=creatree();printf("preorder:\t");preorder(t);printf("\ninorder:\t");inorder(t);printf("\npostorder:\t");postorder(t);x=height(t);y=leaf(t);。

二叉树的中序线索化以及遍历

二叉树的中序线索化以及遍历

⼆叉树的中序线索化以及遍历#include <stdio.h>#include <stdlib.h>typedef struct Node {char data;int Ltag;struct Node* LChild;int Rtag;struct Node* RChild;}BitNode, * BiTree;//先序创建⼆叉树void CreatBiTree(BiTree* root) {char ch;ch = getchar();if (ch == '.')*root = NULL;else {*root = (BitNode*)malloc(sizeof(BitNode));(*root)->data = ch;(*root)->Ltag = 0;(*root)->Rtag = 0;CreatBiTree(&((*root)->LChild));CreatBiTree(&((*root)->RChild));}}//建⽴中序线索树void InThread(BiTree root, BitNode** pre) {if (root != NULL) {InThread(root->LChild, pre);/***********以中序遍历的⽅式添加线索***********///如果该节点没有左孩⼦,则将该节点的左指针指向其中序前驱if (root->LChild == NULL) {root->Ltag = 1;root->LChild = *pre;}//如果该节点的中序前驱没有右孩⼦,则将该节点的右指针指向该节点if (*pre != NULL && (*pre)->RChild == NULL) {(*pre)->RChild = root;(*pre)->Rtag = 1;}//将当前节点设为中序前驱*pre = root;//这本质上还是中序遍历,因此每个节点都会成为前驱//每⼀个节点都检查了其前驱与它⾃⼰的双向关系//但是并未考虑到中序最后⼀个节点的右孩⼦指针域(所以在main函数中处理)InThread(root->RChild, pre);}}//找到中序遍历第⼀个节点的指针BitNode* FindFirstNode(BiTree root) {BitNode* p;//寻找root的右⼦树中“最左下”的节点//⽽其最左下的节点的中序前驱⼀定是NULL,所以可以这样判断while (root != NULL) {p = root;root = root->LChild;}return p;}//在中序⼆叉树中寻找p的中序后继(返回指针)BitNode* InNext(BitNode* p) {BitNode* next;BitNode* q;if (p->Rtag == 1)//若该节点的右孩⼦指针指向了其中序后继return p->RChild;//直接返回其右孩⼦指针else {q = p->RChild;//q为p的右⼦树while (q->Ltag == 0)//当q的左孩⼦是q的中序前驱(q没有左孩⼦了)q = q->LChild; //说明找到了q的右⼦树中最左下的节点next = q;return next;}}//遍历中序线索⼆叉树void InOrder(BiTree root) {BitNode* p = FindFirstNode(root);//找到中序第⼀个节点while (p) {printf("%c", p->data);//输出p = InNext(p);//找下⼀个节点}}int main(){BiTree bt;BitNode* pre = NULL;printf("请输⼊⼀棵⼆叉树:\n");CreatBiTree(&bt);InThread(bt, &pre);//线索化pre->Rtag = 1;//处理最后⼀个节点printf("中序遍历⼆叉树:");InOrder(bt);return 0;}刚讲完线索⼆叉树,模仿课本上的程序写的。

二叉树的遍历与线索化

二叉树的遍历与线索化

▪ 中根遍历算法 void InOrder(Btree root) { if(root!=NULL) { InOrder(root->Lchild); Visit(root->data); InOrder(root->Rchild); } }
▪ 后根遍历算法 void PostOrder(Btree root) { if(root!=NULL) { PostOrder(root->Lchild); PostOrder(root->Rchild); Visit(root ->data); } }
数据结构
二叉树的遍历与线索化
二叉树的遍历:是按某条搜索路径访问树 中的每一个结点,使得每一个结点均被访 问一次,而且仅被访问一次。
▪ 先根遍历二叉树 (1)访问根结点; (2)先根遍历左子树; (3)先根遍历右子树。
▪ 中根遍历二叉树 (1)中根遍历左子树; (2)访问根结点; (3)中根遍历右子树。 ▪ 后根遍历二叉树 (1)后根遍历左子树; (2)后根遍历右子树; (3)访问根结点。
▪ 求二叉树的高度
采用递归的方法定义二叉树的高度: (1)若二叉树为空,则高度为0; (2)若二叉树非空,其高度应为其左右子树高度的最 大值加1。
int TreeDepth(Btree bt) {
int hl,hr,max; if(bt!=NULL) { hl=TreeDepth(bt->Lchild); hr=TreeDepth(bt->Rchild);
max=(hl,hr); return(max+1); } else return(0);
}
▪ 在中根遍历的线索树中查找前驱结点
对于二叉树中任意结点p,要找其前驱结点,当p->Ltag=1 时,p->Lchild即为p的前驱结点;当p->Ltag=0时,说 明p有左子树,此时p的中根遍历下的前驱结点即为其左 子树右链下的最后一个结点。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验二二叉树的存储结构及各种运算的实现第一题:
#include "stdio.h"
#include "malloc.h"
#define maxsize 66
typedef int datatype;
typedef struct node
{
datatype data ;
struct node *lchild,*rchild;
} bitree;
bitree *Q[maxsize];
bitree *creatree()
{
char ch;
int front,rear;
bitree *root,*s;
root=NULL;
front=1;rear=0;
ch=getchar();
while (ch!='#')
{
s=NULL;
if(ch!='@')
{
s=malloc(sizeof(bitree));
s->data=ch;
s->lchild=NULL;
s->rchild=NULL;
}
rear++;
Q[rear]=s;
if(rear==1)
root=s;
else
{
if (s&&Q[front])
if(rear%2==0)
Q[front]->lchild=s;
else
Q[front]->rchild=s;
if(rear%2==1)
front++;
}
ch=getchar();
}
return root;
}
preorder(bitree *t) //前{
if (t)
{
printf(" %c ",t->data);
preorder(t->lchild);
preorder(t->rchild);
}
}
inorder(bitree *t) //中{
if (t)
{
inorder(t->lchild);
printf(" %c ",t->data);
inorder(t->rchild);
}
}
postorder(bitree *t) //后{
if (t)
{
postorder(t->lchild);
postorder(t->rchild);
printf(" %c ",t->data);
}
}
int height(bitree *t) //高度{
int hl,hr;
if(!t) return 0;
else
{
hl=height(t->lchild);
hr=height(t->rchild);
return ((hl>hr?hl:hr)+1);
}
}
int leaf(bitree *t) //叶子{
static int s;
if(t)
{
leaf(t->lchild);
leaf(t->rchild);
if(t->lchild==NULL&&t->rchild==NULL)
s=s+1;
}
return s;
}
main()
{
bitree *t;
int x,y;
printf("输入数据,以#做结尾:\n");
t=creatree();
printf("preorder:\t");preorder(t);
printf("\ninorder:\t");inorder(t);
printf("\npostorder:\t");postorder(t);
x=height(t);
y=leaf(t);
printf("\n高度:%d",x);
printf("\n叶子:%d",y);
printf("\n");
}
第二题:
#include <stdio.h>
#include <malloc.h>
#define maxsize 40
typedef struct node{
char data;
struct node *lchild,*rchild;
int ltag,rtag;
} bitree;
bitree *Q[maxsize]; /*队列*/
bitree *pre=NULL;
bitree *creatree()
{ char ch;
int front,rear; /*队头、队尾*/
bitree *root,*s;
root=NULL; /*空树*/
front=1; rear=0; /*空队*/
ch=getchar();
while(ch!='#')
{ s=NULL;
if(ch!='@') /*建立新结点*/
{ s=(bitree *)malloc(sizeof(bitree));
s->data=ch;
s->lchild=s->rchild=NULL;
s->ltag=s->rtag=0;
}
rear++;
Q[rear]=s; /*入队*/
if(rear==1) root=s;
else
{ if(s && Q[front]) /*孩子、双亲均非空*/
if(rear%2==0) Q[front]->lchild=s;
else Q[front]->rchild=s;
if(rear%2==1) front++; /*出队*/
}
ch=getchar();
}
return root;
}
//中序遍历;
void inorder(bitree *t)
{ if(t)
{ inorder(t->lchild);
printf("%c",t->data);
inorder(t->rchild);
}
}
//中序线索划;
void INTHREAD(bitree *p)
{if(p!=NULL)
{INTHREAD(p->lchild);
if(p->lchild==NULL) p->ltag=1;
if(p->rchild==NULL) p->rtag=1;
if(pre!=NULL)
{ if(pre->rtag==1) pre->rchild=p;
if(p->ltag==1) p->lchild=pre; } pre=p;
INTHREAD(p->rchild);
}
}
//中序线索二叉树中求中序后继结点;
bitree * inordernext (bitree *p)
{
bitree *q;
if(p->rtag==1) return p->rchild;
else
{ q=p->rchild;
while(q->ltag==0) q=q->lchild;
return q;
}
}
//中序遍历;
void traverseinthread(bitree *p)
{
if(p!=NULL)
{while (p->ltag==0 )
p=p->lchild;
do {printf("%c",p->data);
p=inordernext(p);
}while(p!=NULL);
}
}
void main()
{ bitree *t;
t=creatree();
printf("中序遍历结果是:\n:");
inorder(t);
printf("\n");
INTHREAD(t);
printf("线索化中序遍历的结果是:\n");
printf("\n");
traverseinthread(t);
printf("\n");}
输入数据为:abfcd@g@@e#。

相关文档
最新文档