数据结构笔记_24 二叉树的前序、中序、后序查找

这一节,完成以下任务:

  1. 编写前序、中序、后序查找的方法。
  2. 使用三种方式,查找no为5的结点。
  3. 分析每种查找方式,分别比较了几次。

一、思路

与前面遍历的思路类似,直接上思路图解:
在这里插入图片描述
以 5号节点为例,不同顺序的查找方式,比较次数是不一样的。

前序需要4次比较才能找到5号节点,中序3次,后序2次。

二、代码

1、三种查找底层代码

// 前序遍历查找
	/**
	 * @param no 查找no
	 * @return 找到就返回该Node,否则返回null
	 */
	public HeroNode preOrderSearch(int no) {
    
    
		System.out.println("进入前序查找~");
		// 比较当前结点是不是
		if (this.no == no) {
    
    
			return this;
		}
		// 1.判断当前结点的左子节点是否为空,若不为空,则递归前序查找
		// 2.如果左递归前序查找,找到结点,则返回
		HeroNode resNode = null;
		if (this.left != null) {
    
    
			resNode = this.left.preOrderSearch(no);
		}
		if (resNode != null) {
    
    // 说明我们左子树找到
			return resNode;
		}
		// 1.左递归前序查找,找到结点,则返回,否则继续判断,
		// 2.当前结点的右子节点是否为空,如果不为空,则继续向右递归前序查找。
		if (this.right != null) {
    
    
			resNode = this.right.preOrderSearch(no);
		}
		return resNode;
	}

	// 中序遍历查找
	public HeroNode midOrderSearch(int no) {
    
    
		// 判断当前结点的左子节点是否为空,如果不为空,则递归中序查找。
		HeroNode resNode = null;
		if (this.left != null) {
    
    
			resNode = this.left.midOrderSearch(no);
		}
		if (resNode != null) {
    
    
			return resNode;
		}
		System.out.println("进入中序查找~");
		// 如果找到,则返回,如果没找到,就和当前结点比较,如果是则返回当前结点
		if (this.no == no) {
    
    
			return this;
		}
		// 否则,向右进行右递归的中序查找
		if (this.right != null) {
    
    
			resNode = this.right.midOrderSearch(no);
		}
		return resNode;
	}

	// 后序遍历查找
	public HeroNode postOrderSearch(int no) {
    
    
		// 判断当前节点的左子节点是否为空,如果不为空,则递归后序查找
		HeroNode resNode = null;
		if (this.left != null) {
    
    
			resNode = this.left.postOrderSearch(no);
		}
		if (resNode != null) {
    
    // 说明在左子树找到
			return resNode;
		}
		// 如果左子树没有找到,就向右子树递归进行后序遍历查找
		if (this.right != null) {
    
    
			resNode = this.right.postOrderSearch(no);
		}
		if (resNode != null) {
    
    // 说明在右子树找到
			return resNode;
		}
		System.out.println("进入后序查找~");
		// 如果左右子树都没有找到,就比较当前结点是不是
		if (this.no == no) {
    
    
			return this;
		}
		return resNode;

	}

2、BinaryTree类中调用代码

	// 前序遍历查找
	public HeroNode preOrderSearch(int no) {
    
    
		if (root != null) {
    
    // 至少有一个结点
			return root.preOrderSearch(no);
		} else {
    
    
			return null;
		}
	}

	// 中序遍历查找
	public HeroNode midOrderSearch(int no) {
    
    
		if (root != null) {
    
    
			return root.midOrderSearch(no);
		} else {
    
    
			return null;
		}
	}

	// 后序遍历查找
	public HeroNode postOrderSearch(int no) {
    
    
		if (root != null) {
    
    
			return root.postOrderSearch(no);
		} else {
    
    
			return null;
		}
	}

3、测试代码

		// 测试前序遍历查找
		// 前序遍历为5的次数: 4
		System.out.println("这是前序查找方式~~");
		HeroNode resNode = binaryTree.preOrderSearch(5);
		if (resNode != null) {
    
    
			System.out.printf("找到了,信息为no=%d name=%s\n", resNode.getNo(), resNode.getName());
		} else {
    
    
			System.out.printf("没有找到 no = %d 的英雄", 5);
		}

		// 测试中序遍历查找
		// 中序遍历为5的次数: 3
		System.out.println("这是中序查找方式~~");
		HeroNode resNode1 = binaryTree.midOrderSearch(5);
		if (resNode1 != null) {
    
    
			System.out.printf("找到了,信息为no=%d name=%s\n", resNode1.getNo(), resNode1.getName());
		} else {
    
    
			System.out.printf("没有找到 no = %d 的英雄", 5);
		}

		// 测试后序遍历查找
		// 后序遍历为5的次数: 2
		System.out.println("这是后序查找方式~~");
		HeroNode resNode2 = binaryTree.postOrderSearch(5);
		if (resNode2 != null) {
    
    
			System.out.printf("找到了,信息为no=%d name=%s\n", resNode2.getNo(), resNode2.getName());
		} else {
    
    
			System.out.printf("没有找到 no = %d 的英雄", 5);
		}

输出结果:

在这里插入图片描述

值得注意的是,测试进行了几次比较时,需要在进行比较的语句前加上输出测试语句,因为用到了递归,例如后序遍历查找:前面都是判断是否为空,后面才是判断是否相等。

后序比较流程:1 的左子节点是否为空,不为空,进入左递归。再判断左子是否为空,为空,退出;判断右子是否为空,为空,退出。开始进行比较2和5(比较次数+1)。

左子树遍历结束,没有找到。结束比较,返回上一个栈,右子树不为空,调用后序递归,又开始比较3的左子树是否为空,不为空,进入后序递归,比较5的左子树是否为空,为空,退出;判断右子树是否为空,为空,退出。开始进行比较5和5(比较次数+1)

小结:不难看出,判断为空有多次,而判断是否相等只有2次。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45909299/article/details/114197871
今日推荐