二叉平衡搜索树的另一种方法——构建两棵子树

目录

内容

相关算法实现

构建的数据结构(Java类形式给出)

Insert函数

buildTree():

getWhichInsert():

总结


想法来源于学院的算法与数据结构实践题。

内容

  1. 构造规则:维持二叉平衡搜索树的一个诱人方法是维持两个二叉搜索子树 。操作的关键在于构建两棵树,若要添加新的key值,将其插入可以让该结点所在层次较小的树,如果待插入结点在两棵树中的高度相同,就将其插入第一棵树。
  2. 针对上述规则修改的二叉搜索树规则:

    该二叉搜索树是一颗空二叉树,或者是一颗满足一下要求的树:

         (1)二叉树中所有结点的关键字的值可以相同;

        (2)根结点如果存在左子树,那么左子树中所有结点关键字值都小于等于根结点关键字的值;

        (3) 根结点如果存在右子树,那么右子树中所有结点关键字值都大于根结点关键字的值;

        (4)根结点的左右子树都应是一颗满足上述要求的二叉搜索树。

相关算法实现

  • 构建的数据结构(Java类形式给出)

class BSTNode{						//内部类,结点类
	char key;						//关键字
	public int height;				//当前阶段所在层次
	BSTNode left;				//左孩
	BSTNode right;				//右孩
}		
	
public class BSTree {
	private BSTNode firstRoot ;			//第一棵树的根节点
	private BSTNode secondRoot;		//第二棵树的根节点
}
  • Insert函数

  1. private void InsertFirst(char ch) {
    	if(this.firstRoot == null) {					//如果树根为空,就直接插到根结点
    		this.firstRoot = new BSTNode(ch,null,null);
    		return ;								//插完,返回
    	}
    	BSTNode currentNode = this.firstRoot ;
    	BSTNode parentNode = null ;
    	int tmpHeight = 0;							//记录parentNode的层数
    	boolean isLeft = true;						//标志量
    	while(currentNode != null) {					//当前结点不为空,就一直循环
    		parentNode = currentNode;				//更新父节点值,当前结点准备下降
    		if(ch > currentNode.key ) {				//根据搜索树定义来判断待插结点位置
    			tmpHeight ++ ;					//更新父节点层次
    			currentNode = currentNode.right ;		//向当前结点的右子树下降
    			isLeft = false;						//由于向右下降,标志量为false
    		}
    		else {
    			tmpHeight ++;
    			currentNode = currentNode.left ;		//否则向左子树下降
    			isLeft = true;
    		}
    	}
    		
    	BSTNode newNode = new BSTNode(ch,null,null);	//构造关键字为key的结点
    	if(isLeft) {								//根据标志量插入到正确位置
    		parentNode.left = newNode;				//插入左树
    		newNode.height = tmpHeight + 1;			//更新新建结点的层次
    	}
    	else {
    		parentNode.right = newNode;				//插入右树
            newNode.height = tmpHeight + 1;	
    	}
    }
    

    其实Insert函数的原型可以写为void Insert(char ch, BSTNode root); 但是在运行过程中我发现给参数表里的root传入firstRoot或是secondRoot,都不能真正实现插入。根据分析应该是传入变量时,root并未真正指向树根。所以简单地我就写成两个函数,分别处理两个子树的插入操作。secondRoot对应的插入操作类似上面。

  • buildTree():

根据构造规则,将结点插入正确的子树

public void buildBSTree(String str1 ) {
	String str = str1;
	int index = 0;								//字符串的下标,0~length
	while(index < str.length()) {
		int choice = this.getWhichInsert(str.charAt(index));	//获取返回结果
		if ( choice == 1) {						//如果返回结果是1就插入左树
			this.InsertFirst(str.charAt(index));
				index++;
		}
		else if (choice == 2) {					//如果是2就插入右树
			this.InsertSecond(str.charAt(index));
			index++;
		}	
	}
}
  • getWhichInsert():

判断结点插入哪棵子树会获得更小的深度

  • private int getWhichInsert(char ch) {
    	int firstHeight = 0;
    	BSTNode currentNode = this.firstRoot;			//当前节点初始化为树根
    	while (currentNode != null) {					//当当前节点不为空是循环执行
    		firstHeight ++;
    		if ( ch > currentNode.key) {				//如果待插入节点的值大于当前节点值
    			currentNode = currentNode.right;		//则要插入右子树,当前节点更改为右子树
    		} else {								//小于等于插入左子树
    			currentNode = currentNode.left;		//插入当前节点的左子树
    		}
    	}
    
    	int secondHeight = 0;
    	currentNode = this.secondRoot ;
    	while (currentNode != null) {					//当当前节点不为空是循环执行
    		secondHeight ++;
    		if ( ch > currentNode.key) {				//如果待插入节点的值大于当前节点值
    			currentNode = currentNode.right;		//则要插入右子树,当前节点更改为右子树
    		} else {								//小于等于插入左子树
    			currentNode = currentNode.left;		//插入当前节点的左子树
    		}
    	}
    	if(firstHeight <=secondHeight)				//如果插入左树结点深度更小
    		return 1;								//返回1
    	else 
    		return 2;								//否则返回2
    }
    

    可以看出,实现原理就是插入中的定位带插入结点位置的那部分,没什么难度。

总结

其实,使用两棵子树来维持搜索树的平衡的做法实现起来并不难。而且这也提供了另一种实现搜索树平衡的思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值