排序二叉树及其Java实现

定义

排序二叉树的定义也是递归定义的,需要满足:

(1)若它的左子树不为空,则左子树上所有节点的值要均小于根节点的值;

(2)若它的右子树不为空,则右子树上所有节点的值要均大于根节点的值;

(3)左、右子树也分别是排序二叉树

如下图,对于排序二叉树,若按中序遍历就可以得到由小到大的有序序列。

创建

创建排序二叉树的步骤就是不断像排序二叉树中添加新节点(p)的过程:

(1)以根节点(root)为当前节点(current)开始搜索;

(2)用新节点p的值和current的值进行比较;

(3)如果p.data>current.data,则current=current.right;若p.data<current.data,则current=current.left;

(4)重复(2)(3),直到找到合适的叶子节点位置;

(5)将p添加到上面找到的合适位置,若新节点更大,则添加为右子节点;否则,加为左子节点

删除节点

当从排序二叉树中删除节点后,要保持它依然是二叉树,必须对它进行维护:

待删除节点p,p的父节点q,p的左子树pL,p的右子树pR

(1·)p是叶子节点,直接将它从其父节点中删除;

(2)p只有左(右)子树,将pL(pR)添加成p的父节点q的左(右)子树即可;

(3)p左右子树均非空,有两种处理方法:

  • 将pL设为q的左或右子节点(取决于p是其父节点q的左、右子节点),将pR设为p的中序前驱结点s的右子节点(s是pL最右下的节点,也就是pL中最大的节点)
  • 以p的中序前驱或后继替代p所指节点,然后再从原排序二叉树中删去中序前驱或后继节点(也就是用大于p的最小节点或小于p的最大节点代替p节点)

Java实现代码:

package com.liuhao.DataStructures;

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

public class SortedBinTree <T extends Comparable>{

	static class Node{
		Object data;
		Node parent;
		Node left;
		Node right;

		public Node(Object data, Node parent, Node left, Node right) {
			this.data = data;
			this.parent = parent;
			this.left = left;
			this.right = right;
		}

		public String toString(){
			return "[data=" + data + "]";
		}

		public boolean equals(Object obj){
			if(this == obj){
				return true;
			}

			if(obj.getClass() == Node.class){
				Node target = (Node) obj;
				return data.equals(target.data) && left == target.left
						&& right == target.right && parent == target.parent;
			}

			return false;
		}

	}

	private Node root;

	public SortedBinTree(){
		root = null;
	}	

	public SortedBinTree(T o){
		root = new Node(o, null, null, null);
	}

	/**
	 * 添加节点
	 * @param ele 新节点的元素
	 */
	public void add(T ele){
		if(root == null){
			root = new Node(ele, null, null, null);
		}
		else{
			Node current = root;
			Node parent = null;
			int cmp;

			//搜索合适的叶子节点,以该叶子节点为父节点添加新节点
			do{
				parent = current;
				cmp = ele.compareTo(current.data);

				//如果新节点的值大于当前节点的值
				if(cmp > 0){
					//以当前节点的右子节点作为当前节点
					current = current.right;
				}else{
					current = current.left;
				}
			}while(current != null);

			//创建新节点
			Node newNode = new Node(ele, parent, null, null);

			//如果新节点的值大于父节点的值
			if(cmp > 0){
				parent.right = newNode;
			}else{
				parent.left = newNode;
			}
		}
	}

	/**
	 * 删除节点
	 * @param ele
	 */
	public void remove(T ele){
		Node target = getNode(ele);

		if(target == null){
			return;
		}

		//左右子树都为空
		if(target.left == null && target.right == null){
			if(target == root){
				root = null;
			}
			else{
				//被删除节点是父节点的左子节点
				if(target == target.parent.left){
					//将target的父节点的left设为null
					target.parent.left = null;
				}else{
					target.parent.right = null;
				}

				target.parent = null;
			}
		}

		//左空右不空
		else if(target.left == null && target.right != null){
			if(target == root){
				root = target.right;
			}
			else{
				//被删除节点是父节点的左子节点
				if(target == target.parent.left){
					target.parent.left = target.right;
				}
				else{
					target.parent.right = target.right;
				}

				//让target的右子树的parent指向target的parent
				target.right.parent = target.parent;
			}
		}

		else if(target.left != null && target.right == null){
			if(target == root){
				root = target.left;
			}
			else{
				//被删除节点是父节点的左子节点
				if(target == target.parent.left){
					target.parent.left = target.left;
				}
				else{
					target.parent.right = target.left;
				}

				//让target的右子树的parent指向target的parent
				target.left.parent = target.parent;
			}
		}

		//左右都不为空
		else{
			//leftMaxNode:target的左子树中值最大的节点
			Node leftMaxNode = target.left;

			//搜索target的左子树中值最大的节点
			while(leftMaxNode.right != null){
				leftMaxNode = leftMaxNode.right;
			}

			//从原来的子树中删除leftMaxNode节点
			leftMaxNode.parent.right = null;

			leftMaxNode.parent = target.parent;

			if(target == target.parent.left){
				target.parent.left = leftMaxNode;
			}
			else{
				target.parent.right = leftMaxNode;
			}

			leftMaxNode.left = target.left;
			leftMaxNode.right = target.right;
			target.parent = target.left = target.right = null;
		}
	}

	/**
	 * 根据指定值搜索节点
	 * @param ele 指定值
	 * @return 节点
	 */
	public Node getNode(T ele){
		//从根节点开始搜索
		Node p = root;
		while(p != null){
			int cmp = ele.compareTo(p.data);

			if(cmp < 0){
				p = p.left;
			}
			else if(cmp > 0){
				p = p.right;
			}
			else{
				return p;
			}
		}

		return null;
	}

	/**
	 * 广度优先遍历
	 * @return
	 */
	public List<Node> breadthFirst(){
		Queue<Node> queue = new ArrayDeque<Node>();
		List<Node> list = new ArrayList<Node>();

		if(root != null){
			queue.offer(root);
		}

		while(!queue.isEmpty()){
			//将该队列的“队尾”元素添加到List中
			list.add(queue.peek());
			//弹出队尾节点
			Node p = queue.poll();

			//如果左子节点不为null,将它加入“队列”
			if(p.left != null){
				queue.offer(p.left);
			}

			if(p.right != null){
				queue.offer(p.right);
			}
		}

		return list;
	}

	/**
	 * 中序遍历
	 * @return
	 */
	public List<Node> inIterator(){
		return inIterator(root);
	}

	private List<Node> inIterator(Node node){
		List<Node> list = new ArrayList<Node>();

		//递归处理左子树
		if(node.left != null){
			list.addAll(inIterator(node.left));
		}

		//处理根节点
		list.add(node);

		//递归处理右子树
		if(node.right != null){
			list.addAll(inIterator(node.right));
		}

		return list;
	}
}

排序二叉树及其Java实现

时间: 2024-11-05 18:53:11

排序二叉树及其Java实现的相关文章

java学习-排序二叉树

(排序)二叉树的创建及中序遍历 写起来比C复杂一点,思路大同小异~ 1 package Collection; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 /* 6 * (排序)二叉树的创建及中序遍历 7 */ 8 public class Node { 9 public Node LNode; 10 public Node RNode; 11 public Object value; // 结点的值 12 13 publ

Java学习-排序二叉树性能简单测试

1.创建4万个随机数,然后用分别用冒泡法,选择法,二叉树法3种排序算法进行排序,比较哪种更快 1 package Collection; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class sortSpeedTest { 7 8 public static void main(String[] args) { 9 int num = 40000; // 元素个数 10 int rnd1[] = new

排序二叉树的基本操作

描述 二叉树的构建.插入新的结点.树的先中后序以及层序四种遍历 代码 import java.util.LinkedList; import java.util.Queue; class Node{ public int data; public Node left; public Node right; public Node(int data){ this.data=data; this.left=null; this.right=null; } } public class BinaryT

一步一图一代码:排序二叉树

作者:禅楼望月(http://www.cnblogs.com/yaoyinglong/) 属性: ①若它的左子树不为空,则左子树上所有节点的值均小于它的根节点的值. ②若它的右子树不为空,则右子树上所有节点的值均大于它的根节点的值. ③它的左.右子树也都是排序二叉树. 添加操作: 当根节点为空时,添加进的节点作为根节点.然后每次添加节点时,都从根节点过滤,以根节点作为当前节点,如果新节点大于当前节点,则走当前节点的右子节点分支,如果新节点小于当前节点,则走当前节点的左子节点分支.然后再用右子节点

[转]各种排序算法及其java程序实现

原文:http://blog.csdn.net/t12x3456/article/details/7430700 各种排序算法:冒择路(入)兮(稀)快归堆,桶式排序,基数排序 冒泡排序,选择排序,插入排序,稀尔排序,快速排序,归并排序,堆排序,桶式排序,基数排序 一.冒泡排序(BubbleSort)1. 基本思想: 两两比较待排序数据元素的大小,发现两个数据元素的次序相反时即进行交换,直到没有反序的数据元素为止.2. 排序过程: 设想被排序的数组R[1..N]垂直竖立,将每个数据元素看作有重量的

【数据结构与算法】二叉树的Java实现及特点总结

转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 二叉树是一种非常重要的数据结构,它同时具有数组和链表各自的特点:它可以像数组一样快速查找,也可以像链表一样快速添加.但是他也有自己的缺点:删除操作复杂. 我们先介绍一些关于二叉树的概念名词. 二叉树:是每个结点最多有两个子树的有序树,在使用二叉树的时候,数据并不是随便插入到节点中的,一个节点的左子节点的关键值必须小于此节点,右子节点的关键值必须大于或者是等于此节点,所以又称二叉查找树.二叉排序树.二叉搜索

计算机程序的思维逻辑 (42) - 排序二叉树

40节介绍了HashMap,41节介绍了HashSet,它们的共同实现机制是哈希表,一个共同的限制是没有顺序,我们提到,它们都有一个能保持顺序的对应类TreeMap和TreeSet,这两个类的共同实现基础是排序二叉树,为了更好的理解TreeMap/TreeSet,本节我们先来介绍排序二叉树的一些基本概念和算法. 基本概念 先来说树的概念,现实中,树是从下往上长的,树会分叉,在计算机程序中,一般而言,与现实相反,树是从上往下长的,也会分叉,有个根节点,每个节点可以有一个或多个孩子节点,没有孩子节点

二叉树的Java实现及特点总结

二叉树是一种非常重要的数据结构,它同时具有数组和链表各自的特点:它可以像数组一样快速查找,也可以像链表一样快速添加.但是他也有自己的缺点:删除操作复杂. 我们先介绍一些关于二叉树的概念名词. 二叉树:是每个结点最多有两个子树的有序树,在使用二叉树的时候,数据并不是随便插入到节点中的,一个节点的左子节点的关键值必须小于此节点,右子节点的关键值必须大于或者是等于此节点,所以又称二叉查找树.二叉排序树.二叉搜索树. 完全二叉树:若设二叉树的高度为h,除第 h 层外,其它各层 (1-h-1) 的结点数都

排序二叉树,平衡二叉树和红黑树的概念以及相关的操作讲解

1. 排序二叉树     排序二叉树是一种特殊结构的二叉树,可以非常方便地对树中所有节点进行排序和检索. 排序二叉树要么是一棵空二叉树,要么是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值: 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值: 它的左.右子树也分别为排序二叉树. 图 1 显示了一棵排序二叉树: 图 1. 排序二叉树 对排序二叉树,若按中序遍历就可以得到由小到大的有序序列.如图 1 所示二叉树,中序遍历得: {2,3,4,8,9,9