Java基本查找算法 -- 树的查找

一、树表的查找

树表查找的对象是以二叉树或树作为表的组织形式。树表在进行插入或删除操作时,可以方便地维护表的有序性,不需要移动表中的记录,从而减少因移动记录引起的额外时间开销。常见的树表有二叉树、平衡二叉树、B-树和B+树等。下面将以二叉排序树作为实例进行讲解。

二叉排序树(简称BST)的定义:二叉排序树或者是空树,或者是满足如下性质实例的二叉树:

  • (1)若它的左子树非空,则左子树上所有记录的值均小于根记录的值
  • (2)若它的右子树非空,则右子树上所有记录的值均大于根记录的值。
  • (3)它的左、右子树分别也是二叉排序树。

图1.1所示是一颗二叉排序树。二叉排序树实际上是增加了限制条件的特殊二叉树,限制条件的实质就是二叉排序树中任意一个结点的关键字大于其左子树上所有结点的关键字,且小于其右子树上有结点的关键字。这样的限制给查找操作的实现提供了晰的思路:一颗以二叉链表为存储结构的二叉排序树上要找比某结点x小的结点,只需通过x结点的左指针到它的左子树上去找,若要找比某结点x大的结点,只需通过x结点的右指针到它的右子树上去找。可以证明,二叉排序树的中序遍历的序列是按结点关键字递增排序的有序序列。所以构造一颗二叉排序树就是对数结点关键字进行排序,“排序树”也因此而得名。图1.1的中序遍历结果是:1,2,3,4,5,6,8,10。

在这里插入图片描述

二叉排序树常常采用二叉链表作为存储结构,数据结点的Java代码如下:

class BSTNode { // 二叉排序树节点类
	public int key;
	public BSTNode lchild;
	public BSTNode rchild;
	
	public BSTNode() {
		this.lchild = null;
		this.rchild = null;
	}
}

创建二又排序树,从空二叉树开始,首先读入第一个结点作为二叉排序树的根结点;其次从读入第二个结点起,将读入结点的关键字和根节点的关键字比较;

  • (1)读入的结点关键字等于根结点关键字,则说明树中有此结点,不做处理。
  • (2)读入的结点关键字大于根结点关键字,则将此结点插入根节点的右子树
  • (3)读入的结点关键字小于根结点关键字,则将此结点插入根节点的左子树。
  • (4)在子树中的插入过程和前面的步骤(1),(2),(3)相同。

例:有如下数字构成的序列 A={8,3,6,10,2,5,1},请以序列值为关键建立二叉排序树。
对应数字序列A={8,3,6,10,2,5,1}建立二叉排序树的过程如图1.2所示。

在这里插入图片描述

生成二叉排序树的插入结点,是递归算法,就是从根节点开始逐层向下查找,最终将待插入结点作为叶子结点插入到二叉排序树的对应位置。
除了生成二叉排序树外,为了便于验证插入结点的正确与否,在下面的Java代码里增加了树的中序遍历打印各结点值得代码,树的中序遍历也是递归算法,具体结点插入和打印算法代码如下s示例所示。

二叉排序树上查找的算法描述为:将给定值和二叉排序树的根结点的关键字比较;

  • (1)给定值等于根结点关键字,则根结点就是要查找的结点。
  • (2)给定值大于根结点关键字,则继续在根结点的右子树上查找。
  • (3)给定值小于根结点关键字,则继续在根结点的左子树上查找
  • (4)在子树中的查找过程和前面的步骤(1),(2),(3)相同

例:在图1.2建立的二叉排序树中,查找关键字为2的结点,并输出结果,查找算法是递归算法。

public class BST { //构建二叉排序树
	public BSTNode root;
	public BST() {
		this.root = null;
	}
	
	public void insert(int data) {
		if (this.root == null) {
			root = new BSTNode();
			root.key = data;
		} else {
			bSTInsert(this.root, data);
		}
	}
	
	public void bSTInsert(BSTNode node, int key) {
		if (node==null || node.key==key) {
			return;
		} else if (node.key > key) {
			if (node.lchild == null) {
				BSTNode temp = new BSTNode();
				temp.key = key;
				node.lchild = temp;
			} else {
				bSTInsert(node.lchild, key);
			}
		} else {
			if (node.rchild==null) {
				BSTNode temp = new BSTNode();
				temp.key = key;
				node.rchild = temp;
			} else {
				bSTInsert(node.rchild, key);
			}
		}
	}
	
	public void createBFS(int[] a) { // 创建二叉排序树
		int i = 0;
		while (i<a.length) {
			this.insert(a[i]);
			i++;
		}
	}
	
	public void print() { //打印二叉排序树
		if (this.root == null) {
			System.out.println("树为空");
		} else {
			print(root);
		}
	}
	
	public void print(BSTNode node) { //中序遍历二叉树
		if (node == null) {
			return;
		} else {
			print(node.lchild);
			System.out.print(node.key + " ");
			print(node.rchild);
		}
	}
	
	/** 查找二叉排序树  */
	public BSTNode BSTSearch(int key) {
		if (this.root == null) {
			return null;
		} else {
			if (this.root.key == key) {
				return root;
			} else {
				return this.bSTSearch(root, key);
			}
		}
	}
	
	public BSTNode bSTSearch(BSTNode node, int key) {
		if (node.key == key) {
			return node;
		} else if (node.key > key) {
			if (node.lchild != null) {
				return bSTSearch(node.lchild, key);
			} else {
				return null;
			}
		} else {
			if (node.rchild!=null) {
				return bSTSearch(node.rchild,key);
			} else {
				return null;
			}
		}
	}

}

class BSTNode { // 二叉排序树节点类
	public int key;
	public BSTNode lchild;
	public BSTNode rchild;
	
	public BSTNode() {
		this.lchild = null;
		this.rchild = null;
	}
	
}

算法分析:对于利用二叉排序树法进行查找,其时间复杂度受二叉树的深度影响,假设给定序列为有序的情况,则构造的二叉排序树只有左子树或者是有右子树,其算法将退化为顺序查找,这时的查找长度是(n+1)/2;而当给定序列二又排序树的左右子树分布比较均匀,每次查找可减少一半左右的节点数,则可以提高查找效率。平衡二叉树就是用来平衡二又排序树的,当二又排序树的左右子树的差值的绝对值大于1时就需要平衡。平衡的二又树才是真正的log2n数量级的!因此,建立均匀的平衡二又排序树是提高此算法的重要因素。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

书香水墨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值