二叉搜索树

本文详细介绍了二叉搜索树的基本概念、查询、插入和删除操作。通过具体的算法实现,帮助读者理解二叉搜索树的工作原理及其维护平衡的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、什么是二叉搜索树

         二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于等于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于等于它的根结点的值; 它的左、右子树也分别为二叉排序树


二、查询

定义树的结点类为

class Node{
		int k;
		Node left = null;
		Node right = null;
		Node p = null;
	}


查找过程,从树的根节点开始查找,输入树的根节点和需要查找的k值,如果结点存在,返回指向关键字k的结点,否则返回null。



public Node TreeSearch(Node root,int k){
		if(root==null||k==root.k)
			return root;
		if(k<root.k){
			return TreeSearch(root.left,k);
		}else{
			return TreeSearch(root.right,k);
		}	
	}



三、插入

插入和删除会引起由二叉搜索树的动态集合的变化。一定要修改数据结果来反映这个变化,但修改要保持二叉树搜索树性质成立。

public void TreeInsert(Node root,Node z){
		Node y = null;
		Node x = root;
		while(x!=null){
			y = x;
			if(z.k<x.k){
				x = x.left;
			}else{
				x = x.right;
			}
		}
		z.p = y;
		if(y==null){
			root = z;
		}else if(z.k<y.k){
			y.left = z;
		}else{
			y.right = z;
		}
		
	}


四、删除

删除分为三种情况

1、如果z没有孩子结点,那么知识简单地将它删除,并修改它的父结点,用null最为孩子了替换z

2、如果z只有一个孩子,那么将这个孩子提升到树中的z的位置,并修改z的父结点,用z的孩子代替z

3、如果z有两个孩子,那么找z的后继y(一定在z的右子树中)并让其占据树中z的位置,z原来额右子树部分称为y的右子树,并且z的左子树称为y的新的左子树。


为了完成删除操作,我们先来做一下准备工作。

最大关键字元素和最下关键字元素

	/**
	 * 获得最小值元素
	 * @param x
	 * @return
	 */
	public Node TreeMiniNum(Node x){
		while(x.left!=null){
			x = x.left;
		}
		return x;
	}
	
	/**
	 * 获得最大值元素
	 * @param x
	 * @return
	 */
	public Node TreeMaxiNum(Node x){
		while(x.right!=null){
			x = x.right;
		}
		return x;
	}


前驱和后继

一个结点的后继是大于x.key的最小关键词的结点,前驱是小于x.key的最大关键字的结点。


	/**
	 * 求后继
	 * @param x
	 * @return
	 */
	public Node TreeSuccessor(Node x){
		if(x.right!=null){
			return TreeMiniNum(x.right);
		}
		Node y = x.p;
		while(y!=null && x == y.right){
			x = y;
			y = y.p;
		}
		
		return y;
	}
	




为了在二叉搜索树内移动子树,定义一个子过程TRANSPLANT,它是用另一颗子树替换一棵子树并成为其双亲的孩子结点。当TRANSPLANT用一颗以v为根的子树来替换一颗以u为根的子树时,结点u的双亲就变为结点v的双亲,并最后v成为u的双亲的相应孩子。


public void Transplant(Node root,Node u,Node v){
		if(u.p==null)
			root = v;
		else if(u==u.p.left)
			u.p.left = v;
		else 
			u.p.right = v;
		if(v!=null){
			v.p = u.p;
		}
	}





下面是二叉搜索树删除结点z的删除过程

public void TreeDelete(Node root,Node z){
		
		//第一种情况
		if(z.left==null)
			Transplant(root, z, z.right);
		else if(z.right == null)
			Transplant(root, z, z.left);
		//第二和第三种情况
		else {
			Node y = TreeMiniNum(z.right);
			if(y.p!=z){//第三种情况
				Transplant(root, y, y.right);
				y.right = z.right;
				y.right.p = y;
			}
			//z的后继恰好为z的有右孩子,第二种情况
			Transplant(root, z, y);
			y.left = z.left;
			y.left.p = y;
		}
	}





在一颗高度为h的二叉搜素树上,实现动态集合操作Insert和Delete的运行时间均为o(h)。



本文为《算法导论》二叉搜索复习笔记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值