数据结构 二叉搜索树

本文详细介绍了二叉搜索树的基本概念、操作实现及其在Java中的具体应用。通过定义、插入、删除、查找等核心功能的讲解,展示了二叉搜索树作为一种高效数据结构的优势。

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

在实际生活中,我们需要字典来查找字词,字典具有能够快速的在一个大的集合内寻找到一个元素的特征。在程序设计中我们也常常需要在一个大的集合中快速找到需要的元素,因此我们引入二叉搜索树,它可以在大小为n的集合中使得查找平均时间为logn,这大大提高了查询的效率。


1、二叉搜索树的定义

二叉搜索树是一棵二叉树,可能为空;每一个元素有一个关键字,并且任意两个元素的关键字都不同;在根节点的左子树中,元素的关键字都小于根节点的关键字;在根节点的右子树中,元素的关键字都大于根节点的关键字;根节点左子树、右子树都是二叉搜索树。


2、二叉搜索树的的操作和实现

二叉搜索树是一棵二叉树,因此它可以含有二叉树的前序、中序、后序和层次遍历方法,另外可以含有计算高度、返回树的节点数等方法。二叉搜索树的关键在于它的插入和删除函数,这是构建并维持二叉搜索树的实现方法,另外二叉搜索树的最重要作用就是查找,因此含有查找关键字函数。


插入:二叉搜索树的插入很简单。当向一棵二叉搜索树插入元素时,就插入到根节点的位置。而向一棵非空二叉搜索树插入一个元素时,对比根节点的关键字与插入元素的关键字,如果大于则走右子树,若小于则走左子树,若等于直接返回,直到没有子树时将新元素插入到对应的孔子树上就完成了插入。例如:


删除:二叉搜索树的删除有一些麻烦。当树为空时直接返回;假设要删除的节点是p,会遇到以下三种情况:1、p是树叶;2、p只有一棵非空子树;3、p有两棵非空子树,分别对这三种情况进行讨论。

当p是树叶则直接将p删除,并把p父节点指向该节点的指针设为null。

当p只有一棵非空子树时,删除节点p,并将p的父节点指向该节点的指针指向p的非空子树的根节点。

当p含有两棵非空子树时,使用左子树的最大元素或右子树中的最小元素替换掉p元素,然后删除替换元素节点。左子树中最大元素的位置就在左子树一直走右子树直到右子树为空的位置,右子树中最小元素的位置就在右子树中一直走左子树直到左子树为空的位置。


查找:查找就更简单了。使用一个关键字进行查找,当关键字比根节点关键字大时走右子树,当关键字小于根节点关键字时走左子树,当关键字等于时找到元素,直到空为止,空时没有该关键字的元素。


性质:根据二叉搜索树的定义,二叉搜索树的中序遍历是一个由小到大的有序序列,因此二叉搜索树也可以应用于排序。


3、java实现二叉搜索树

建立二叉树节点:

package Structure;

//定义树节点
public class treeNode{
	
	protected int element;//节点域
	protected treeNode leftChild,//左子树指针和右子树指针
	         rightChild;
	
	//无参构造函数,构建空树
	public treeNode(){
		leftChild=rightChild=null;
	}
	
	//新建节点,插入末尾
	public treeNode(int theElement){
		element=theElement;
		leftChild=rightChild=null;
	}
	
	//赋值构造函数,替换节点
	public treeNode(int theElement,treeNode theleftchild,
	         treeNode therightchild){
	    element=theElement;
	    leftChild=theleftchild;
	    rightChild=therightchild;}
};


建立二叉搜索树:

package Structure;

import java.util.LinkedList;

public class SearchTree {
	//根节点
	private treeNode root;
	//大小
	private int size;
	
	//无参构造函数,构建空的二叉搜索树
	public SearchTree (){
		root=null;
		size=0;
	}
	
	//复制构造函数,复制相同的二叉搜索树
	public SearchTree(SearchTree tree){
		
	}
	
	//返回根
	public treeNode getRoot(){
		return root;
	}
	
	//寻找函数
	public boolean find(int theElement){
		treeNode p=root;
		boolean have=false;
		while(p!=null){
			if(theElement<p.element)
			   p=p.leftChild;
			else
				if(theElement>p.element)
				   p=p.rightChild;
				else{
					have=true;
					break;
				}
		}
		return have;
	}
	
	//插入函数
	public void insert(int theElement){
		treeNode p=root,pp=null;
		while(p!=null){
			pp=p;
			if(theElement>p.element)
				p=p.rightChild;
			else{
				if(theElement<p.element)
					p=p.leftChild;
				else
					return;
			}
		}
		treeNode newnode=new treeNode(theElement);
		if(root!=null)
		   if(theElement<pp.element)
		     pp.leftChild=newnode;
		   else
		     pp.rightChild=newnode;
		else
		   root=newnode;
		size++;	
	}
	
	//删除函数
	public void delete(int theElement){
		treeNode p=root, pp=null;
		while(p!=null&&p.element!=theElement){
			pp=p;
			if(theElement<p.element)
		      p=p.leftChild;
		    else
		      p=p.rightChild;
		}
		if(p==null)
		  return;
		if(p.leftChild!=null&&p.rightChild!=null){
			treeNode s=p.leftChild,ps=p;
			while(s.rightChild!=null){
				ps=s;
				s=s.rightChild;
			}
			treeNode q=new treeNode(s.element,p.leftChild,p.rightChild);
			if(pp==null)
			  root=q;
			else if(p==pp.leftChild)
			        pp.leftChild=q;
			     else
			        pp.rightChild=q;
			if(ps==p) pp=q;
			else pp=ps;
			p=s;
		}
		treeNode c;
		if(p.leftChild!=null)
		  c=p.leftChild;
		else
		  c=p.rightChild;
		if(p==root)
		  root=c;
		else{
			if(p==pp.leftChild)
			  pp.leftChild=c;
			else 
			  pp.rightChild=c;
		} 
		size--;
	}
	
	
	//返回树的大小
	public int size(){
		return size;
	}
	
	//打印访问特定节点域
		public void visit(treeNode t) {
			System.out.print(t.element + "   ");
		}
		
		//前序遍历
		public void preOrder(treeNode t) {
			if (t != null) {
				visit(t);
				preOrder(t.leftChild);
				preOrder(t.rightChild);
			}
		}
		
		//中序遍历
		public void inOrder(treeNode t) {
			if (t != null) {
				inOrder(t.leftChild);
				visit(t);
				inOrder(t.rightChild);
			}
		}
		
		//后序遍历
		public void postOrder(treeNode t) {
			if (t != null) {
				postOrder(t.leftChild);
				postOrder(t.rightChild);
				visit(t);
			}
		}
		
		//层次遍历
		public void levelOrder(treeNode t){
			LinkedList<treeNode> q=new LinkedList<>();

			while(t!=null){
				visit(t);
				
				if(t.leftChild!=null)
					q.add(t.leftChild);
				if(t.rightChild!=null)
					q.add(t.rightChild);
				
				if(q.size()!=0)
					t=q.getFirst();
				else
					return;
				
				q.removeFirst();
				
			}
		}
		
		//高度函数
		public int height(treeNode t){
			if(t==null)
				return 0;
			int hl=height(t.leftChild);
			int hr=height(t.rightChild);
			
			if(hl>hr)
				return ++hl;
			else
				return ++hr;
		}
	
	
}


测试:

package Test;

import Structure.SearchTree;
import Structure.treeNode;

public class SearchTreeTest {

	public static void main(String[] args) {
		SearchTree tree=new SearchTree();
		
		tree.insert(5);
		tree.insert(4);
		tree.insert(7);
		tree.insert(3);
		tree.insert(5);
		tree.insert(9);
		tree.delete(5);
		tree.insert(1);
		
		treeNode t=tree.getRoot();
		tree.inOrder(t);
		if(tree.find(3))
			System.out.print("\n找到元素3");
		else
			System.out.print("\n未找到元素3");
	}

}


输出:

1   3   4   7   9   
找到元素3


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值