二叉树的遍历,顺序存储,线索化

定义

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分 。

结论:
前序:先根,再左,再右
中序:先在,再根,再右
后序:先在,再右,再根

在这里插入图片描述

遍历

前序


 public void preOrder() {
 	System.out.println(this.name); 
	//递归向左子树前序遍历
	if (this.left != null) {
	    this.left.preOrder();
	}
	//递归向右子树前序遍历
	if (this.right != null) {
	    this.right.preOrder();
	}
  }

1 2 4 5 3 6 7

中序

 public void infixOrder() {

  //递归向左子树中序遍历
     if (this.left != null) {
         this.left.infixOrder();
     }
     //输出父结点
     System.out.println(this);
     //递归向右子树中序遍历
     if (this.right != null) {
         this.right.infixOrder();
     }
 }

84251637

后序

public void postOrder() {
     if (this.left != null) {
         this.left.postOrder();
     }
     if (this.right != null) {
         this.right.postOrder();
     }
     System.out.println(this.name);
 }

8 4 5 2 6 7 3 1

小结

前序,中,后序只是过程操作有所改动,基本遍历方式一致

查找

在这里插入图片描述

前序查找


 public void preOrder(HeroNode node) {
 	if (this.id == node.id){
 		//找到了
 		return 
 	}
	//递归向左子树前序遍历
	if (this.left != null) {
	    this.left.preOrder();
	}
	//递归向右子树前序遍历
	if (this.right != null) {
	    this.right.preOrder();
	}
  }

中,后序也是如此就不列举了

顺序存储

上图的二叉树的结点,要求以数组的方式来存放arr : [1,2,3,4,5,6,7,8]

特点

特点:

  1. 顺序二叉树通常只考虑完全二叉树2)
  2. 第n个元素的左子节点为惇2*n+13)
  3. 第n个元素的右子节点为2*n+24)
  4. 第n个元素的父节点为(n-1)/ 2
  5. n:表示二叉树中的第几个元素(按О开始编号如图所示)

代码实现

  public static void preOrderStorage(int index, HeroNode heroNode) {
        if (arr == null || arr.length == 0) {
           return;
        }
        System.out.println(heroNode);

        if (index * 2 + 1 < arr.length) {
            
            HeroNode heroNode1 = new HeroNode(2 * index + 1,arr[2 * index + 1] + "");
            heroNode.setLeft(heroNode1);
            preOrderStorage(2 * index + 1,heroNode1);
        }
        
        if (index * 2 + 2 < arr.length) {
            HeroNode heroNode2 = new HeroNode(2 * index + 2,arr[2 * index + 2] + "");
            heroNode.setRight(heroNode2);
            preOrderStorage(2 * index + 2,heroNode2);
        }
    }

在这里插入图片描述

线索化二叉树

优势
(1)利用线索二叉树进行中序遍历时,不必采用堆栈处理,速度较一般二叉树的遍历速度快,且节约存储空间。
(2)任意一个结点都能直接找到它的前驱和后继结点。 [2]
不足
(1)结点的插入和删除麻烦,且速度也较慢。
(2)线索子树不能共用。 [2]

我们先把分析一下二叉树,其中的 8,7,5,6,7的一部分指针没有用上

在这里插入图片描述
前驱后继,定义规则如下:

若结点的左子树为空,则该结点的左孩子指针指向其前驱结点。
若结点的右子树为空,则该结点的右孩子指针指向其后继结点。

  1. n个结点的二叉链表中含有n+1【公式2n-(n-1)=n+1】个空指针域。利用二叉链表中的空指针域,存放指向
  2. 这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。

线索化如下

  1. 左子树线索化

  2. 对空指针线索化:

    ①如果p的左孩子为空,则给p加上左线索,将其leftType置为1,让p的左孩子指针指向pre(前驱);

    ②如果pre的右孩子为空,则给pre加上右线索,将其rightType置为1,让pre的右孩子指针指向p(后继);

  3. 将pre指向刚访问过的结点p,即pre = p;

在这里插入图片描述

public void threadedNodes(HeroNode1 node) {
		
		//如果node==null, 不能线索化
		if(node == null) {
			return;
		}
		
		//1.先线索化左子树
		threadedNodes(node.getLeft());
		//处理前驱结点
		if(node.getLeft() == null) {
			//让当前结点的左指针指向前驱结点 
			node.setLeft(pre); 
			//修改当前结点的左指针的类型,指向前驱结点
			node.setLeftType(1);
		}
		
		//处理后继结点
		if (pre != null && pre.getRight() == null) {
			//让前驱结点的右指针指向当前结点
			pre.setRight(node);
			//修改前驱结点的右指针类型
			pre.setRightType(1);
		}
		//让当前结点是下一个结点的前驱结点
		pre = node;
		
		//3.在线索化右子树
		threadedNodes(node.getRight());
		
		
	}

我们结合上面的顺序存储来测试一下

HeroNode1 leftNode = root.getLeft().getLeft().getLeft(); // 8
		HeroNode1 rightNode = root.getLeft().getRight(); // 5
		System.out.println(leftNode.getName() +" left = " + leftNode.getLeft());
		System.out.println(rightNode.getName()+" right = "  + rightNode.getRight());

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值