二叉树顺序存储基本思路:
二叉树顺序存储代码:
package com.ws.数据结构.树.顺序存储二叉树;
public class ArrBinaryTreeDemo {
public static void main(String[] args) {
int[] arr={1,2,3,4,5,6,7};
//创建顺序存储二叉树对象
System.out.println("顺序存储二叉树前序遍历:");
ArrBinaryTree arrBinaryTree=new ArrBinaryTree(arr);
arrBinaryTree.qianprintf();//1,2,4,5,3,6,7
System.out.println();
System.out.println("顺序存储二叉树中序遍历:");
arrBinaryTree.zhongprintf();//4,2,5,1,6,3,7
System.out.println();
System.out.println("顺序存储二叉树后序遍历:");
arrBinaryTree.houprintf();//4,5,2,6,7,3,1
System.out.println();
}
}
//顺序存储二叉树
class ArrBinaryTree{
private int[] arr;//存储二叉树节点的数组
public ArrBinaryTree(int[] arr) {
this.arr = arr;
}
//重载遍历,默认从0开始
public void qianprintf(){
this.qianprintf(0);
}
public void zhongprintf(){
this.zhongprintf(0);
}
public void houprintf(){
this.houprintf(0);
}
/**
* 顺序存储二叉树的前序遍历
* @param n 数组下标
*/
public void qianprintf(int n){
//数组为空 或者数组长度为0
if (arr==null||arr.length==0){
System.out.println("数组为空,不能按照二叉树的前序遍历!!");
}
//输出当前元素
System.out.print(arr[n]+" ");
//向左递归遍历
if ((n*2+1)<arr.length){
qianprintf(2*n+1);
}
//向右递归遍历
if ((n*2+2)<arr.length){
qianprintf(n*2+2);
}
}
//中序遍历
public void zhongprintf(int n){
//数组为空 或者数组长度为0
if (arr==null||arr.length==0){
System.out.println("数组为空,不能按照二叉树的前序遍历!!");
}
//向左递归遍历
if ((n*2+1)<arr.length){
zhongprintf(2*n+1);
}
//输出当前元素
System.out.print(arr[n]+" ");
//向右递归遍历
if ((n*2+2)<arr.length){
zhongprintf(n*2+2);
}
}
//后序遍历
public void houprintf(int n){
//数组为空 或者数组长度为0
if (arr==null||arr.length==0){
System.out.println("数组为空,不能按照二叉树的前序遍历!!");
}
//向左递归遍历
if ((n*2+1)<arr.length){
houprintf(2*n+1);
}
//向右递归遍历
if ((n*2+2)<arr.length){
houprintf(n*2+2);
}
//输出当前元素
System.out.print(arr[n]+" ");
}
}
顺序存储二叉树前序遍历:
1 2 4 5 3 6 7
顺序存储二叉树中序遍历:
4 2 5 1 6 3 7
顺序存储二叉树后序遍历:
4 5 2 6 7 3 1
线索化二叉树思路:
线索化二叉树与遍历线索化二叉树代码:
package com.ws.数据结构.树.线索化二叉树;
public class ThreadedBinaryTreeDemo {
public static void main(String[] args) {
//测试中序线索二叉树
HeroNode root=new HeroNode(1,"a");
HeroNode node2=new HeroNode(3,"b");
HeroNode node3=new HeroNode(6,"c");
HeroNode node4=new HeroNode(8,"d");
HeroNode node5=new HeroNode(10,"e");
HeroNode node6=new HeroNode(14,"f");
//二叉树 手动创建
root.setZuo(node2);
root.setYou(node3);
node2.setZuo(node4);
node2.setYou(node5);
node3.setZuo(node6);
//测试线索化
BinaryTree binaryTree=new BinaryTree();
binaryTree.setRoot(root);
System.out.println("中序遍历线索化:");
binaryTree.xianzhongprintf();//中序遍历线索化
// 5 10节点测试
HeroNode zuoNode=node5.getZuo();
HeroNode youNode=node5.getYou();
//线索化后左节点变成前驱节点
System.out.println("线索化后左节点变成前驱节点,10节点的前驱节点是:"+zuoNode);//3
System.out.println("线索化后右节点变成后继节点,10节点的后继节点是:"+youNode);//1
}
}
//创建二叉树节点
class HeroNode{
private int hao;//编号
private String name;//名字
private HeroNode zuo;//左索引 默认null
private HeroNode you;//右索引 默认null
private int zuoType;//==0 表示指向左子树 ==1 表示指向前驱节点
private int youType;//==0 表示指向右子树 ==1 表示指向后继节点
public HeroNode(int hao, String name) {
this.hao = hao;
this.name = name;
}
//前序遍历
public void qianprintf(){
System.out.println(this);//先输出当前(父)节点
//递归向左子树
if (this.zuo!=null){
this.zuo.qianprintf();
}
//递归向右子树遍历
if (this.you!=null){
this.you.qianprintf();
}
}
//中序遍历
public void zhongprintf(){
//递归向左子树
if (this.zuo!=null){
this.zuo.zhongprintf();
}
//输出父节点
System.out.println(this);
//递归向右子树
if (this.you!=null){
this.you.zhongprintf();
}
}
//后序遍历
public void houprintf(){
//递归向左子树
if (this.zuo!=null){
this.zuo.houprintf();
}
//递归向右子树
if (this.you!=null){
this.you.houprintf();
}
//输出父节点
System.out.println(this);
}
//查找
/**
* 前序查找
* @param hao 序号
* @return 找到就返回节点,找不到返回null
*/
public HeroNode qianzhaoNode(int hao){
System.out.println("前序找");
//当前节点是不是
if (this.hao==hao){
return this;
}
//判断当前节点的左节点是否为空,不空就递归
//递归找,找到返回
HeroNode nodes=null;
if (this.zuo!=null){
nodes=this.zuo.qianzhaoNode(hao);//向左前序遍历查找
}
if (nodes!=null){//在左子树找到
//找到了
return nodes;
}
//没有左子树
//判断当前节点的右节点是否为空,不空就递归
if (this.you!=null){
nodes=this.you.qianzhaoNode(hao);//向右前序遍历查找
}
return nodes;//向右找是最后一次找,必须返回结果,可能找到,也可能没找到
}
/**
* 中序查找
* @param hao
* @return
*/
public HeroNode zhongzhaoNode(int hao){
//判断当前节点左节点是否为空,不空就递归
HeroNode nodes=null;
if (this.zuo!=null){
nodes=this.zuo.zhongzhaoNode(hao);//向左中序查找
}
if (nodes!=null){//在左子树找到
//找到了
return nodes;
}
System.out.println("中序找");
//当前节点是不是
if (this.hao==hao){
return this;
}
//不是,向右递归中序查找
if (this.you!=null){
nodes=this.you.zhongzhaoNode(hao);
}
return nodes;
}
/**
* 后序遍历
* @param hao
* @return
*/
public HeroNode houzhaoNode(int hao){
//判断当前节点左节点是否为空,不空就递归
HeroNode nodes=null;
if (this.zuo!=null){
nodes=this.zuo.houzhaoNode(hao);
}
if (nodes!=null){//在左子树找到
//找到了
return nodes;
}
//左子树没找到,向右递归后序查找
if (this.you!=null){
nodes=this.you.houzhaoNode(hao);
}
if (nodes!=null){//在右子树找到
//找到了
return nodes;
}
System.out.println("后序找");
//判断当前节点是不是
if (this.hao==hao){
return this;
}
return nodes;
}
public int getHao() {
return hao;
}
public void setHao(int hao) {
this.hao = hao;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public HeroNode getZuo() {
return zuo;
}
public void setZuo(HeroNode zuo) {
this.zuo = zuo;
}
public HeroNode getYou() {
return you;
}
public void setYou(HeroNode you) {
this.you = you;
}
public int getZuoType() {
return zuoType;
}
public void setZuoType(int zuoType) {
this.zuoType = zuoType;
}
public int getYouType() {
return youType;
}
public void setYouType(int youType) {
this.youType = youType;
}
@Override
public String toString() {
return "HeroNode{" +
"hao=" + hao +
", name='" + name + '\'' +
'}';
}
}
//创建线索化二叉树
class BinaryTree{
private HeroNode root;//根节点
//为了实现线索化,要创建一个指向当前节点前驱节点的指针
private HeroNode qianqu=null;//保留当前节点的前驱节点
public void setRoot(HeroNode root){
this.root=root;
}
//重载 线索化二叉树自动输入根节点
public void xianzhongprintf(){
this.xianzhongprintf(root);
}
//中序遍历线索化二叉树
public void xianzhongprintf(HeroNode node){
//为空,不进行线索化
if (node==null){
return;
}
//一 先线索化左子树
xianzhongprintf(node.getZuo());
//二 线索化当前节点
//1.处理当前节点的前驱节点
if (node.getZuo()==null){
//左指针指向前驱节点
node.setZuo(qianqu);
//修改当前节点左指针类型,标识他是前驱节点
node.setZuoType(1);
}
//2.处理当前节点的后继节点
if (qianqu!=null&&qianqu.getYou()==null){
//前驱节点的右指针指向当前节点
qianqu.setYou(node);
//前驱节点的右指针裂项
qianqu.setYouType(1);
}
//3.处理完当前节点后,把当前节点变成下一个节点的前驱节点
qianqu=node;
//三 线索化右子树
xianzhongprintf(node.getYou());
}
//前序遍历
public void qianprintf(){
if (this.root!=null){
this.root.qianprintf();
}else {
System.out.println("当前二叉树为空,无法前序遍历");
}
}
//中序遍历
public void zhongprintf(){
if (this.root!=null){
this.root.zhongprintf();
}else {
System.out.println("当前二叉树为空,无法中序遍历");
}
}
//后序遍历
public void houprintf(){
if (this.root!=null){
this.root.houprintf();
}else {
System.out.println("当前二叉树为空,无法后序遍历");
}
}
//前序查找
public HeroNode qianzhaoNode(int hao){
if (root!=null){
return root.qianzhaoNode(hao);
}else {
return null;
}
}
//中序查找
public HeroNode zhongzhaoNode(int hao){
if (root!=null){
return root.zhongzhaoNode(hao);
}else {
return null;
}
}
//后序查找
public HeroNode houzhaoNode(int hao){
if (root!=null){
return root.houzhaoNode(hao);
}else {
return null;
}
}
}
中序遍历线索化:
线索化后左节点变成前驱节点,10节点的前驱节点是:HeroNode{hao=3, name='b'}
线索化后右节点变成后继节点,10节点的后继节点是:HeroNode{hao=1, name='a'}
遍历线索化二叉树:
线索化二叉树后,各个节点指向都有变化,不能用原来的遍历方式,可以线性遍历
package com.ws.数据结构.树.遍历线索化二叉树;
public class ThreadedBinaryTreeDemo {
public static void main(String[] args) {
//测试中序线索二叉树
HeroNode root=new HeroNode(1,"a");
HeroNode node2=new HeroNode(3,"b");
HeroNode node3=new HeroNode(6,"c");
HeroNode node4=new HeroNode(8,"d");
HeroNode node5=new HeroNode(10,"e");
HeroNode node6=new HeroNode(14,"f");
//二叉树 手动创建
root.setZuo(node2);
root.setYou(node3);
node2.setZuo(node4);
node2.setYou(node5);
node3.setZuo(node6);
//测试线索化
BinaryTree binaryTree=new BinaryTree();
binaryTree.setRoot(root);
System.out.println("中序遍历线索化:");
binaryTree.xianzhongprintf();//中序遍历线索化
// 5 10节点测试
HeroNode zuoNode=node5.getZuo();
HeroNode youNode=node5.getYou();
//线索化后左节点变成前驱节点
System.out.println("线索化后左节点变成前驱节点,10节点的前驱节点是:"+zuoNode);//3
System.out.println("线索化后右节点变成后继节点,10节点的后继节点是:"+youNode);//1
//测试遍历线索化二叉树
System.out.println("遍历线索化二叉树:");
binaryTree.bianzhongprintf();//8 3 10 1 14 6
}
}
//创建二叉树节点
class HeroNode{
private int hao;//编号
private String name;//名字
private HeroNode zuo;//左索引 默认null
private HeroNode you;//右索引 默认null
private int zuoType;//==0 表示指向左子树 ==1 表示指向前驱节点
private int youType;//==0 表示指向右子树 ==1 表示指向后继节点
public HeroNode(int hao, String name) {
this.hao = hao;
this.name = name;
}
//前序遍历
public void qianprintf(){
System.out.println(this);//先输出当前(父)节点
//递归向左子树
if (this.zuo!=null){
this.zuo.qianprintf();
}
//递归向右子树遍历
if (this.you!=null){
this.you.qianprintf();
}
}
//中序遍历
public void zhongprintf(){
//递归向左子树
if (this.zuo!=null){
this.zuo.zhongprintf();
}
//输出父节点
System.out.println(this);
//递归向右子树
if (this.you!=null){
this.you.zhongprintf();
}
}
//后序遍历
public void houprintf(){
//递归向左子树
if (this.zuo!=null){
this.zuo.houprintf();
}
//递归向右子树
if (this.you!=null){
this.you.houprintf();
}
//输出父节点
System.out.println(this);
}
//查找
/**
* 前序查找
* @param hao 序号
* @return 找到就返回节点,找不到返回null
*/
public HeroNode qianzhaoNode(int hao){
System.out.println("前序找");
//当前节点是不是
if (this.hao==hao){
return this;
}
//判断当前节点的左节点是否为空,不空就递归
//递归找,找到返回
HeroNode nodes=null;
if (this.zuo!=null){
nodes=this.zuo.qianzhaoNode(hao);//向左前序遍历查找
}
if (nodes!=null){//在左子树找到
//找到了
return nodes;
}
//没有左子树
//判断当前节点的右节点是否为空,不空就递归
if (this.you!=null){
nodes=this.you.qianzhaoNode(hao);//向右前序遍历查找
}
return nodes;//向右找是最后一次找,必须返回结果,可能找到,也可能没找到
}
/**
* 中序查找
* @param hao
* @return
*/
public HeroNode zhongzhaoNode(int hao){
//判断当前节点左节点是否为空,不空就递归
HeroNode nodes=null;
if (this.zuo!=null){
nodes=this.zuo.zhongzhaoNode(hao);//向左中序查找
}
if (nodes!=null){//在左子树找到
//找到了
return nodes;
}
System.out.println("中序找");
//当前节点是不是
if (this.hao==hao){
return this;
}
//不是,向右递归中序查找
if (this.you!=null){
nodes=this.you.zhongzhaoNode(hao);
}
return nodes;
}
/**
* 后序遍历
* @param hao
* @return
*/
public HeroNode houzhaoNode(int hao){
//判断当前节点左节点是否为空,不空就递归
HeroNode nodes=null;
if (this.zuo!=null){
nodes=this.zuo.houzhaoNode(hao);
}
if (nodes!=null){//在左子树找到
//找到了
return nodes;
}
//左子树没找到,向右递归后序查找
if (this.you!=null){
nodes=this.you.houzhaoNode(hao);
}
if (nodes!=null){//在右子树找到
//找到了
return nodes;
}
System.out.println("后序找");
//判断当前节点是不是
if (this.hao==hao){
return this;
}
return nodes;
}
public int getHao() {
return hao;
}
public void setHao(int hao) {
this.hao = hao;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public HeroNode getZuo() {
return zuo;
}
public void setZuo(HeroNode zuo) {
this.zuo = zuo;
}
public HeroNode getYou() {
return you;
}
public void setYou(HeroNode you) {
this.you = you;
}
public int getZuoType() {
return zuoType;
}
public void setZuoType(int zuoType) {
this.zuoType = zuoType;
}
public int getYouType() {
return youType;
}
public void setYouType(int youType) {
this.youType = youType;
}
@Override
public String toString() {
return "HeroNode{" +
"hao=" + hao +
", name='" + name + '\'' +
'}';
}
}
//创建线索化二叉树
class BinaryTree{
private HeroNode root;//根节点
//为了实现线索化,要创建一个指向当前节点前驱节点的指针
private HeroNode qianqu=null;//保留当前节点的前驱节点
public void setRoot(HeroNode root){
this.root=root;
}
//重载 线索化二叉树自动输入根节点
public void xianzhongprintf(){
this.xianzhongprintf(root);
}
//中序遍历线索化二叉树
public void xianzhongprintf(HeroNode node){
//为空,不进行线索化
if (node==null){
return;
}
//一 先线索化左子树
xianzhongprintf(node.getZuo());
//二 线索化当前节点
//1.处理当前节点的前驱节点
if (node.getZuo()==null){
//左指针指向前驱节点
node.setZuo(qianqu);
//修改当前节点左指针类型,标识他是前驱节点
node.setZuoType(1);
}
//2.处理当前节点的后继节点
if (qianqu!=null&&qianqu.getYou()==null){
//前驱节点的右指针指向当前节点
qianqu.setYou(node);
//前驱节点的右指针裂项
qianqu.setYouType(1);
}
//3.处理完当前节点后,把当前节点变成下一个节点的前驱节点
qianqu=node;
//三 线索化右子树
xianzhongprintf(node.getYou());
}
//遍历中序线索化二叉树
public void bianzhongprintf(){
//临时存储当前遍历的节点
HeroNode node=root;
while (node!=null){
//找到头 zuo=null
//zuoType=1是按照线索化二叉树有效节点
while (node.getZuoType()==0){
node=node.getZuo();
}
//打印当前节点
System.out.println(node);
//右指针是否指向后继节点 一直输出
while (node.getYouType()==1){
//获取当前节点的后继节点
node=node.getYou();
System.out.println(node);
}
//替换 右节点移动,因为找头的时候已经左递归了
node=node.getYou();
}
}
//前序遍历
public void qianprintf(){
if (this.root!=null){
this.root.qianprintf();
}else {
System.out.println("当前二叉树为空,无法前序遍历");
}
}
//中序遍历
public void zhongprintf(){
if (this.root!=null){
this.root.zhongprintf();
}else {
System.out.println("当前二叉树为空,无法中序遍历");
}
}
//后序遍历
public void houprintf(){
if (this.root!=null){
this.root.houprintf();
}else {
System.out.println("当前二叉树为空,无法后序遍历");
}
}
//前序查找
public HeroNode qianzhaoNode(int hao){
if (root!=null){
return root.qianzhaoNode(hao);
}else {
return null;
}
}
//中序查找
public HeroNode zhongzhaoNode(int hao){
if (root!=null){
return root.zhongzhaoNode(hao);
}else {
return null;
}
}
//后序查找
public HeroNode houzhaoNode(int hao){
if (root!=null){
return root.houzhaoNode(hao);
}else {
return null;
}
}
}
中序遍历线索化:
线索化后左节点变成前驱节点,10节点的前驱节点是:HeroNode{hao=3, name='b'}
线索化后右节点变成后继节点,10节点的后继节点是:HeroNode{hao=1, name='a'}
遍历线索化二叉树:
HeroNode{hao=8, name='d'}
HeroNode{hao=3, name='b'}
HeroNode{hao=10, name='e'}
HeroNode{hao=1, name='a'}
HeroNode{hao=14, name='f'}
HeroNode{hao=6, name='c'}