二叉树-------前,中,后序遍历 + 前,中,后序查找+删除节点 (java详解)

目录

提要:

 创建一个简单的二叉树:

二叉树的前中后序遍历:

二叉树的前序遍历:

二叉树的中序遍历: 

二叉树的后续遍历:

小结: 

二叉树的前中后续查找:

二叉树的前序查找:

二叉树的中序查找:

二叉树的后续查找: 

代码实现:

二叉树节点删除操作:

思路与约定:

代码实现:

最后,完整代码:


提要:

 二叉树的遍历是指按某条搜索路径访问树中的每个结点,使得每个结点均被访问一次,而且仅能访问一次(说明不可二次访问,一遍而过)。遍历一颗二叉树便要决定对根结点N、左子树L和右子树的访问顺序。 二叉树常的的遍历方法有前序遍历(NLR)、中序遍历(LNR)和后序遍历(LRN)三种遍历算法,其中 “序” 指的是根结点在何时被访问。

遍历大致过程:

前序遍历:根结点 ---> 左子树 ---> 右子树

中序遍历:左子树---> 根结点 ---> 右子树

后序遍历:左子树 ---> 右子树 ---> 根结点

--------------------------------------------------------------------------------------------------------------------------------

 创建一个简单的二叉树:

二叉树的存储结构分为:顺序存储和类似于链表的链式存储,这里我们学习链式存储的方式, 简单枚举一棵二叉树。

用孩子表示法创建一颗二叉树:

//孩子表示法
class KunBinaryTree{//数据域public int no;//序号public String name;//姓名public KunBinaryTree left;//左孩子的引用,常常代表左孩子为根的整棵左子树public KunBinaryTree right;//右孩子的引用,常常代表右孩子为根的整棵右子树//构造方法public KunBinaryTree(int no,String name){super();this.no = no;this.name = name;}
}
public class TestBinaryTree {public static void main(String[] args){//对象实例化KunBinaryTree root = new KunBinaryTree(1,"唱");KunBinaryTree node1 = new KunBinaryTree(2,"跳");KunBinaryTree node2 = new KunBinaryTree(3,"rap");KunBinaryTree node3 = new KunBinaryTree(4,"篮球");KunBinaryTree node4 = new KunBinaryTree(5,"music");KunBinaryTree node5 = new KunBinaryTree(6,"坤坤");//链接各个节点,使其构成一颗二叉树root.left = node1;root.right = node2;node2.left = node3;node2.right = node4;node4.left = node5;}
}

创建了一颗如图所示的二叉树(一共有6个节点,其中root节点为 “唱”):

 

-------------------------------------------------------------------------------------------------------------------------------- 

二叉树的前中后序遍历:

通过上面的简单介绍,我们可以开始正式学习接下来的操作了

二叉树的前序遍历:

基本思路:

若二叉树为空,什么都不做,否则:

        i、先访问根结点;

        ii、再前序遍历左子树;

        iii、最后前序遍历右子树;

代码实现:

//前序遍历public static void preOrder(KunBinaryTree root){if(root == null){return ;}System.out.print(root.no+" "+root.name+" ");//先访问根preOrder(root.left);//接着左右子树preOrder(root.right);}

函数递归展开图解:

首先,我们从蓝色出发,也就是途中的①,按照先根节点后左右子树的过程进行依次遍历,这里相当于先打印根节点所对应的数据域中的信息后,在接着递归调用左子树,直到为空,回溯后递归调用右子树,直到为空。该树的左子树(总的)调用完后, 开始调用右子树,来到②过程,按照(根-----》左子树---》右子树)的规则继续递归。直到左右子树都为空,返回,也就是③,④过程。从途中可以看出,打印的顺序为:1 唱 2 跳 3 rap 4 篮球 5 music 6 坤坤 

 通过遍历的测试结果也显示,上述过程正确:

 或则用更明了直观的动图解释(图中栗子不为上述栗子,仅做参考,便于理解):

二叉树的中序遍历: 

 基本思路:

二叉树为空,什么也不做,否则:

        i、中序遍历左子树;

        ii、访问根结点;

        iii、中序遍历右子树

代码实现:

 //中序遍历public static void infixOrder(KunBinaryTree root){if(root == null){return ;}infixOrder(root.left);System.out.print(root.no +" "+root.name+" ");infixOrder(root.right);}

 函数递归展开图:

 首先,我们先从红色出发,也就是①,按照(左子树---》根---》右子树)的规则依次遍历,这里相当于从不可在分割的左子树开始从后往前进行打印输出对应信息,与前序遍历基本一致,就是中间根节点的位置变化导致输出顺序的不同。

最终递归结果为(打印顺序为):2 跳 1 唱 4 篮球 3 rap 6 坤坤 5 music 

通过测试也可已看出确实是这样:

 用更直观的动图展示(栗子与上述不同,主要是便于理解其过程):

二叉树的后续遍历:

 基本思路:

若二叉树为空,什么也不做,否则:

        i、后序遍历左子树

        ii、后序遍历右子树

        iii、访问根结点

代码实现:

 //后续遍历public static void postOrder(KunBinaryTree root){if(root == null){return ;}postOrder(root.left);postOrder(root.right);System.out.print(root.no +" "+root.name+" ");}

 函数递归展开图:

首先从①开始,按照(左子树---》右子树---》根)的规则依次遍历,过程与上述类似,不在赘述。递归结果为:2 跳 4 篮球 6 坤坤 5 music 3 rap 1 唱  

测试结果也表明上述结果正确: 

 用更直观的动图演示该过程(栗子与上述不同,主要是便于理解其过程):

小结: 

比较各个遍历的过程 

前序遍历:根结点 ---> 左子树 ---> 右子树

中序遍历:左子树---> 根结点 ---> 右子树

后序遍历:左子树 ---> 右子树 ---> 根结点

我们不难发现,前序遍历的root节点(栗子中也就是"1.唱")一定在遍历结果的首部,二中序遍历的root节点在整个树的中部,在遍历的结果中随树的变化二变化,后续遍历的root节点一定在尾部,利用这个特性,我们可以只知道(前序+中序)或者(后续+中序)或则(前序+后续)的遍历结果还原出该二叉树。

二叉树的前中后续查找:

 有了前中后续遍历的实现,我们接着就能实现查找过程,这是基于遍历来实现的

二叉树的前序查找:

基本思路:

1.先判断当前节点的no(序号)是否等于要查找的

2.如果是相等的,则返回当前节点

3.如果不等,则判断当前节点的左右子节点是否为空,如果不为空,则递归前序查找

4.如果左递归前序查找找到节点,则返回,否则继续判断当前节点的左右子节点是否为空,如果不为空,则继续右递归前序查找

代码实现:

//前序查找public static int count1 = 0;//用于记录递归查找的次数public static KunBinaryTree preOrderSearch(KunBinaryTree root,int no){++count1;if(root.no == no){return root;}KunBinaryTree resNode = null;if(root.left != null){resNode = preOrderSearch(root.left,no);}if(resNode != null){return resNode;}if(root.right != null){resNode = preOrderSearch(root.right,no);}return resNode;}

按照上述的遍历结果我们可以知道,一共进行了6次遍历,(咱们这里查找数字6)那么前序查找遍历的次数为6(即count1=6):

测试结果:

 

二叉树的中序查找:

 基本思路:

1.判断当前节点的左右子节点是否为空,如果不为空,则递归中序查找

2.如果找到,则返回,若果没有找到,就和当前节点比较,如果是则返回当前节点,否则继续进行右递归的中序查找

3.右递归中序查找,找到就返回,否则返回null

代码实现:

//中序查找public static int count2 = 0;//记录中序查找次数public static KunBinaryTree infixOrderSearch(KunBinaryTree root,int no){KunBinaryTree resNode = null;if(root.left != null){resNode = infixOrderSearch(root.left,no);}if(resNode != null){return resNode;}++count2;if(root.no == no){return root;}if(root.right != null){resNode = infixOrderSearch(root.right,no);}return resNode;}

按照上述的遍历结果我们可以知道,一共进行了6次遍历,(咱们这里查找数字6)那么中序查找的遍历次数为5(count2=5):

测试结果:

二叉树的后续查找: 

 基本思路:

1.判断当前节点的左子节点是否为空,如果不为空,则递归后序查找

2.如果找到,就返回,如果没有找到,就判断当前节点的有子节点是否为空,如果不为空,则右递归进行后序查找,如果找到,就返回

3.接着和当前节点进行比较,找到则返回,否则返回null

代码实现:

   //后序查找public static int count3 = 0;//记录后序查找遍历次数public static KunBinaryTree postOrderSearch(KunBinaryTree root,int no){KunBinaryTree resNode = null;if(root.left != null){resNode = postOrderSearch(root.left,no);}if(resNode != null){return resNode;}if(root.right != null){resNode = postOrderSearch(root.right,no);}if(resNode != null){return resNode;}++count3;if(root.no == no){return root;}return resNode;}

按照上述的遍历结果我们可以知道,一共进行了6次遍历,(咱们这里查找数字6)那么后序查找的次数为3(count3=3):

测试结果:

 

二叉树节点删除操作:

 最后,咱么来进行二叉树节点删除的操作

思路与约定:

代码实现:

 //删除节点public static void delTreeNode(KunBinaryTree root,int no){if(root.no == no){root = null;}else{if(root.left != null && root.left.no == no){root.left = null;return ;}if(root.right != null && root.right.no == no){root.right = null;return ;}if(root.left != null){delTreeNode(root.left,no);}if(root.right != null){delTreeNode(root.right,no);}}}

 

这里我们删除4子节点,也就是篮球 

测试结果:

当我们删除3这个子节点时,后面的节点也一并删除了:

 

最后,完整代码:

import java.util.*;class KunBinaryTree{public int no;public String name;public KunBinaryTree left;public KunBinaryTree right;public KunBinaryTree(int no,String name){super();this.no = no;this.name = name;}
}public class BinaryTree {
//前中后序遍历//前序遍历public static void preOrder(KunBinaryTree root){if(root == null){return ;}System.out.print(root.no+" "+root.name+" ");preOrder(root.left);preOrder(root.right);}//中序遍历public static void infixOrder(KunBinaryTree root){if(root == null){return ;}infixOrder(root.left);System.out.print(root.no +" "+root.name+" ");infixOrder(root.right);}//后续遍历public static void postOrder(KunBinaryTree root){if(root == null){return ;}postOrder(root.left);postOrder(root.right);System.out.print(root.no +" "+root.name+" ");}
//前中后序查找//前序查找public static int count1 = 0;//用于记录递归查找的次数public static KunBinaryTree preOrderSearch(KunBinaryTree root,int no){++count1;if(root.no == no){return root;}KunBinaryTree resNode = null;if(root.left != null){resNode = preOrderSearch(root.left,no);}if(resNode != null){return resNode;}if(root.right != null){resNode = preOrderSearch(root.right,no);}return resNode;}//中序查找public static int count2 = 0;//记录中序查找次数public static KunBinaryTree infixOrderSearch(KunBinaryTree root,int no){KunBinaryTree resNode = null;if(root.left != null){resNode = infixOrderSearch(root.left,no);}if(resNode != null){return resNode;}++count2;if(root.no == no){return root;}if(root.right != null){resNode = infixOrderSearch(root.right,no);}return resNode;}//后序查找public static int count3 = 0;//记录后序查找遍历次数public static KunBinaryTree postOrderSearch(KunBinaryTree root,int no){KunBinaryTree resNode = null;if(root.left != null){resNode = postOrderSearch(root.left,no);}if(resNode != null){return resNode;}if(root.right != null){resNode = postOrderSearch(root.right,no);}if(resNode != null){return resNode;}++count3;if(root.no == no){return root;}return resNode;}//删除节点public static void delTreeNode(KunBinaryTree root,int no){if(root.no == no){root = null;}else{if(root.left != null && root.left.no == no){root.left = null;return ;}if(root.right != null && root.right.no == no){root.right = null;return ;}if(root.left != null){delTreeNode(root.left,no);}if(root.right != null){delTreeNode(root.right,no);}}}//测试public static void main(String[] args){Scanner sc = new Scanner(System.in);KunBinaryTree root = new KunBinaryTree(1,"唱");KunBinaryTree node1 = new KunBinaryTree(2,"跳");KunBinaryTree node2 = new KunBinaryTree(3,"rap");KunBinaryTree node3 = new KunBinaryTree(4,"篮球");KunBinaryTree node4 = new KunBinaryTree(5,"music");KunBinaryTree node5 = new KunBinaryTree(6,"坤坤");root.left = node1;root.right = node2;node2.left = node3;node2.right = node4;node4.left = node5;preOrder(root);System.out.println();infixOrder(root);System.out.println();postOrder(root);System.out.println();System.out.print("请输入要查找的数字:");int n = sc.nextInt();KunBinaryTree resNode = postOrderSearch(root,n);System.out.println("一共查找的次数count3:"+count3);if(resNode != null){System.out.printf("找到了,Kun节点 no=%d name=%s",resNode.no,resNode.name);}else{System.out.printf("没有找到Kun节点%d的信息",n);}System.out.println();System.out.print("请输入要删除的子节点:");int n2 = sc.nextInt();System.out.println("删除前:");preOrder(root);System.out.println();System.out.println("删除后:");delTreeNode(root,n2);preOrder(root);}
}

博客到这里也是结束了,制作不易,喜欢的小伙伴可以点赞加关注支持下博主,这对我真的很重要~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/468596.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

揭秘某电商公司最新面试流程

🏃‍♂️ 微信公众号: 朕在debugger© 版权: 本文由【朕在debugger】原创、需要转载请联系博主📕 如果文章对您有所帮助,欢迎关注、点赞、转发和订阅专栏! 记录近期某电商公司面试流程及问题,分为三面:…

【教3妹学编程-算法题】捕获黑皇后需要的最少移动次数

3妹:2哥,新年好鸭~ 2哥 : 新年好,3妹这么早啊 3妹:是啊,新年第一天要起早,这样就可以起早一整年 2哥 :得,我还不了解你,每天晒到日上三竿 3妹:嘿嘿嘿嘿,一年是…

Jenkins实战:docker compose 搭建Jenkins

目录 一、文件准备二、安装三、访问与效果展示 一、文件准备 进入/home/docker目录,新建docker-compose-jenkins.yml文件,内容如下: version: 3.0 services:jenkins:image: jenkins/jenkinscontainer_name: jenkinsports:- "8090:8080…

【计算机网络】FTP 文件传输协议

同样使用TCP 但使用了两个并行的TCP 控制链接 control connection 带外 out-of-band 传送的数据链接 data connection 对于FTP而言,控制链接贯穿了整个用户会话期间,数据链接每传输一个文件就有一次建立FTP是有状态(state)的&…

华为机考入门python3--(12)牛客12-字符串反转

分类:字符串 知识点: 字符串是否为空 if not my_str 字符串逆序 my_str[::-1] 题目来自【牛客】 def reverse_string(s): # 判断字符串是否为空或只包含空格 if not s.strip(): return "" # 使用Python的切片语法反转字符串 re…

Vue.js2+Cesium1.103.0 十五、计算方位角

Vue.js2Cesium1.103.0 十五、计算方位角 Demo <template><divid"cesium-container"style"width: 100%; height: 100%;"/> </template><script> /* eslint-disable no-undef */ /* eslint-disable new-cap */ /* eslint-disable n…

VueCLI核心知识3:全局事件总线、消息订阅与发布

这两种方式都可以实现任意两个组件之间的通信 1 全局事件总线 1.安装全局事件总线 import Vue from vue import App from ./App.vueVue.config.productionTip false/* 1.第一种写法 */ // const Demo Vue.extend({}) // const d new Demo()// Vue.prototype.x d // 把Dem…

【数据结构】二叉树根节点到特定节点路径(C语言版)

二叉树——根节点到特定节点路径查找 一、思路二、代码实现 一、思路 使用二叉链表创建的二叉树&#xff0c;这里我的思路是用链栈来存放找寻二叉树特定节点中&#xff0c;用来存放节点元素 个人思路&#xff1a;创建链栈&#xff0c;遍历二叉树并把路径中节点元素存放到栈中&…

华为机考入门python3--(13)牛客13-句子逆序

分类&#xff1a;列表 知识点&#xff1a; 列表逆序&#xff08;和字符串逆序是一样的&#xff09; my_list[::-1] 题目来自【牛客】 def reverse_sentence(sentence): # 将输入的句子分割words sentence.split() # 将单词逆序排列 words words[::-1] # 将单词用空…

python小项目----多重剪切板

代码&#xff1a; import shelve,pyperclip,sysimport mcbmcbShelfshelve.open(mcb)# 保存剪切板内容 if len(sys.argv)3 and sys.argv[1].lower()save:#剪切板的内容保存到第三个参数中mcbShelf[sys.argv[2]]pyperclip.paste()print("你的剪切板中的内容将被保存到mcbSh…

[Doris] Doris的安装和部署 (二)

文章目录 1.安装要求1.1 Linux操作系统要求1.2 软件需求1.3 注意事项1.4 内部端口 2.集群部署2.1 操作系统安装要求2.2 下载安装包2.3 解压2.4 配置FE2.5 配置BE2.6 添加BE2.7 FE 扩容和缩容2.8 Doris 集群群起脚本 3.图形化 1.安装要求 1.1 Linux操作系统要求 1.2 软件需求 1…

【MySQL】学习约束和使用图形化界面创建表

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-iqtbME2KmWpQFQSt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…