二分搜索树的一些总结以及代码实现(java实现)

概念


  • 二分搜索树:对有一个树的任何结点,其右子树的值总是大于当前结点的值,
  • 其左子树的值总是小于当前结点的值。
  • 注意:线性表,队列,栈都可以存重复元素,树最好不要存。
  • 功能实现
  • 1.判断当前树的长度
  • 2.判断当前树是否为空
  • 3.给树添加元素,两种实现方法,一种是迭代法,一种是递归。
  • 4.查找元素是否包含在树种
  • 5.中序遍历
  • 6.广度优先遍历(队列实现)
  • 7.获取最小值
  • 8.获取最大值
  • 9.删除最小值结点
  • 10。删除最大值结点
  • 11.删除指定元素。
  • 12.打印这个树。重写tostring
  • 13.二叉搜索树迭代器

代码实现

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/*
 * 二分搜索树:对有一个树的任何结点,其右子树的值总是大于当前结点的值,
 * 其左子树的值总是小于当前结点的值。
 * 注意:线性表,队列,栈都可以存重复元素,树最好不要存。
 * 功能实现 1.判断当前树的长度 
 * 2.判断当前树是否为空 
 * 3.给树添加元素,两种实现方法,一种是迭代法,一种是递归。 
 * 4.查找元素是否包含在树种
 * 5.中序遍历
 * 6.广度优先遍历(队列实现)
 * 7.获取最小值
 * 8.获取最大值
 * 9.删除最小值结点
 * 10。删除最大值结点
 * 11.删除指定元素。
 * 12.打印这个树。重写tostring
 */
public class BinarySearchTree<E extends Comparable<E>> {
	/*
	 * 定义结点
	 */
	private class Node {
		public E e;
		public Node left, right;

		public Node(E e) {// 初始化Node
			this.e = e;
			this.left = null;
			this.right = null;
		}
	}

	/*
	 * 定义二叉树的根结点和长度
	 */
	public Node root;
	public int size;

	public BinarySearchTree() {
		this.root = null;
		size = 0;
	}

	/*
	 * 功能实现 1.判断当前树的长度 2.判断当前树是否为空 3.给树添加元素,两种实现方法,一种是迭代法,一种是递归。 4.查找元素是否包含在树种
	 */
	public int size() {// 1.
		return size;
	}

	public boolean isempty() {// 2.
		return size() == 0;
	}

	public void add(E e) {//3.
		// 迭代实现
		/*
		 * if(root==null) { Node n=new Node(e); root=n; size++; } Node p=root;//
		 * while(true) { //先判断重复元素 if(e.compareTo(p.e)==0) {//树种的结点依次和传入的e进行比较 return;
		 * }else if(e.compareTo(p.e)>0) { if(p.right!=null) { p=p.right; }else {
		 * p.right=new Node(e); size++; return; } }else { if(p.left!=null) { p=p.left;
		 * }else { p.left=new Node(e); size++; return; } } }
		 */
		// 递归实现
		root = add(root, e);
	}

	private BinarySearchTree<E>.Node add(BinarySearchTree<E>.Node node, E e) {
		// TODO Auto-generated method stub
		if(node==null) {
			size++;
			return new Node(e);
		}
		if (e.compareTo(node.e) > 0) {
			node.right = add(node.right, e);
		} else if (e.compareTo(node.e) < 0) {
			node.left = add(node.left, e);
		}
		return node;
	}
	public boolean contains(E e) {//4.
		//迭代
		/*if(root==null) {
			return false;
		}
		Node p=root;
		while(true) {
			if(p==null) {
				break;
			}
			if(e.compareTo(p.e)>0) {
				p=p.right;
			}else if(e.compareTo(p.e)<0) {
				p=p.left;
			}else {
				return true;
			}
		}
		return false;
	}*/
		//递归
		return contains(root,e);
}

	private boolean contains(BinarySearchTree<E>.Node node, E e) {
		// TODO Auto-generated method stub
		if(node==null) {
			return false;
		}
		if(e.compareTo(node.e)>0) {
			return contains(node.right,e);
		}else if(e.compareTo(node.e)<0){
			return contains(node.left,e);
		}else {
			return true;
		}
	}
	public void inOrder() {//左右中
		/*
		 * 将遍历的结果存到List中
		 *
		 */
		List list=new ArrayList<E>();
		inOrder(root,list);
		System.out.println(list);
	}

	private void inOrder(BinarySearchTree<E>.Node node, List list) {
		// TODO Auto-generated method stub
		if(node==null) {
			return;
		}
		inOrder(node.left,list);
		list.add(node.e);
		inOrder(node.right,list);
	}
	public void levelOrder() {//广度优先遍历 也叫层序遍历
		ArrayList<E> list = new ArrayList<E>();
		// 用辅助队列实现层序遍历 
		Queue<Node> queue = new LinkedList<Node>();
		queue.add(root);
		while (!queue.isEmpty()) {
			Node cur = queue.poll();//出队
			list.add(cur.e);
			if (cur.left != null) {//出队的时候将当前结点的左右孩子结点添加进来
				queue.add(cur.left);
			}
			if (cur.right != null) {
				queue.add(cur.right);
			}
		}
		System.out.println(list);
	}
	//7获取最小值
	public E min() {
		if(size==0) {
			throw new IllegalArgumentException("空树");
		}
		return min(root).e;
	}

	private Node min(Node node) {
		// TODO Auto-generated method stub
		if(node.left==null) {
			return node;
		}
		return min(node.left);
	}
	//8.获取最大值
	public E max() {
		if(size==0) {
			throw new IllegalArgumentException("空树");
		}
		return max(root).e;
	}

	private Node max(Node node) {
		// TODO Auto-generated method stub
		if(node.right==null) {
			return node;
		}
		return max(node.right);
	}
	//9.删除最小值结点
	public E removemin() {
		E e=min();
		root=removemin(root);//删除后返回新的根结点
		return e;
	}

	private Node removemin(Node node) {
		// TODO Auto-generated method stub
		if(node.left==null) {
			Node rightnode=node.right;
			node.right=null;
			size--;
			return rightnode;
		}
		node.left=removemin(node.left);
		return node;
	}
	//10.删除最大值结点,并返回删除后的值。
	public E removemax() {
		E e=max();
		root=removemax(root);
		return e;
	}

	private Node removemax(Node node) {
		// TODO Auto-generated method stub
		if(node.right==null) {
			Node leftnode=node.left;
			node.left=null;
			size--;
			return leftnode;
		}
		node.right=removemax(node.right);
		return node;
	}
	//11.删除指定的元素
	//如果二叉树为空树或者找不到这个元素,就返回空
	public void remove(E e) {
		root=remove(root,e);
	}

	private Node remove(Node node, E e) {
		// TODO Auto-generated method stub
		if(node==null) {
			return null;
		}
		if(e.compareTo(node.e)>0) {//如果删除的值比当前结点的值大
			node.right=remove(node.right, e);
			return node;//这里的node一直返回给头
		}else if(e.compareTo(node.e)<0) {
			node.left=remove(node.left, e);
			return node;
		}else {//等于
			if(node.left==null) {
				Node rightnode=node.right;
				node.right=null;
				size--;
				return rightnode;//返会给删除的上一个结点
			}if(node.right==null) {
				Node leftnode=node.left;
				node.left=null;
				size--;
				return leftnode;
			}
			//如果这个结点的左右孩子结点都不为空
			Node temp=min(node.right);//找到当前结点右子树中最小的结点
			temp.right=removemin(node.right);//当前结点中的最小结点,如果不删,则会重复。
			temp.left=node.left;
			node.left=node.right=null;
			return temp;
		}
	}
	//12
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		StringBuilder sb=new StringBuilder();
		BSTlterator bs=new BSTlterator(root);
		while(bs.hasnext()) {
			sb.append(bs.next()+"\n");
		}
		//print(root,0,sb);
		return sb.toString();
	}

	private void print(Node node, int level, StringBuilder sb) {
		// TODO Auto-generated method stub
		/*
		 * 空子树用null代替
		 */
		if(node==null) {
			sb.append(printlevel(level)+"00\n");
		}else {
			//中序遍历打印  左中右
			
			print(node.left,level+1,sb);
			sb.append(printlevel(level)+node.e+"\n");
			print(node.right,level+1,sb);
		}
	}

	private String printlevel(int level) {
		// TODO Auto-generated method stub
		StringBuilder sb2=new StringBuilder();
		for(int i=0;i<level;i++) {
			sb2.append("  ");
		}
		return sb2.toString();
	}
	//13----------------------二叉搜索树迭代器-----------------
	//迭代器的实现其实和中序遍历一样,都是从小到大打印
	/*
	 * 只不过中序遍历是用递归是用递归实现,当数据量成千上万时,容易造成栈溢出。
	 */
	class BSTlterator{
		LinkedList<Node> stack=new LinkedList<>();
		public BSTlterator(Node root) {
			// TODO Auto-generated constructor stub
			Node cur=root;
			while(cur!=null) {
				stack.push(cur);
				cur=cur.left;
			}	
		}
		public E next() {
			Node n=stack.pop();
			Node cur=n.right;
			while(cur!=null) {
				stack.push(cur);
				cur=cur.left;
			}
			return n.e;
		}
		public boolean hasnext() {
			return !stack.isEmpty();
		}
	}
}

二分搜索树的时间复杂度为O(log(2,n))

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值