排序二叉树: 排序二叉树是一种特殊结构的二叉树,通过它可以非常方便的对树中所有节点进行排序和检索。 排序二叉树要么是一棵空二叉树,要么是具有以下性质的二叉树: 若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值 它的左、右子树也分别为排序二叉树 对于排序二叉树,用中序遍历就可以得到由小到大的有序序列。 创建排序二叉树的步骤,就是不断地向排序二叉树添加节点的过程,具体如下:
![](https://images2015.cnblogs.com/blog/842253/201703/842253-20170313170311401-1519770327.png)
![](https://images2015.cnblogs.com/blog/842253/201703/842253-20170313170342104-1171090539.png)
![](https://images2015.cnblogs.com/blog/842253/201703/842253-20170313170356901-1339031428.png)
1、拿根节点为当前节点开始搜索 2、拿新节点的值和当前节点的值比较 3、如果新节点的值更大,则以当前节点的右子节点作为新的当前节点;如果新节点的值更小,则以当前节点的左子节点作为新的当前节点 4、重复2、3步骤,知道搜索到合适的叶子节点 5、将新节点添加为第4步找到的叶子节点的子节点,如果新节点值更大,则添加为右子节点,否则,加为左子节点 当程序从排序二叉树中删除一个节点之后,为了让它依然保持为排序二叉树,就必须对该排序二叉树进行维护,维护可分为如下几种情况: 1、被删除的节点时叶子节点,只需将它从其父节点中删除 2、被删除节点p只有左子树,将p的左子树pL添加成p的父节点的左子树即可,被删除节点p只有右子树,将p的右子树pR添加成p的父节点的右子树即可 3、若被删除节点p的左、右子树均为空,有一下两种做法: 看图描述,用文字真绕。敲代码不打注释敲得眼花。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.test_one;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
/**
* Created by Administrator on 2017/3/13.
*/
public class SortedBinTree {
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);
}
public void add(T ele){
if(root == null){
root = new Node(ele , null , null , null);
}else{
Node current = root;
Node parent = null;
int cmp = 0;
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;
}
}
}
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.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.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.left.parent = target.parent;
}
}else{
Node leftMaxNode = target.left;
while(leftMaxNode.right != null){
leftMaxNode = leftMaxNode.right;
}
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;
}
}
public Node getNode(T ele){
Node p = root;
while(p != null){
Object obj = new Object();
int cmp = ele.compareTo(p.data);
if(cmp < 0){
p = p.left;
}else if(cmp > 0){
p = p.right;
}else{
return p;
}
}
return null;
}
public List breadthFirst(){
Queue queue = new ArrayDeque();
List list = new ArrayList();
if(root != null){
queue.offer(root);
}
while(!queue.isEmpty()){
list.add(queue.peek());
Node p = queue.poll();
if(p.left != null){
queue.offer(p.left);
}
if(p.right != null){
queue.offer(p.right);
}
}
return list;
}
}
package com.test_one;
/**
* Created by Administrator on 2017/3/13.
*/
public class SortedBinTreeTest {
public static void main(String[] args){
SortedBinTree tree = new SortedBinTree();
tree.add(50);
tree.add(20);
tree.add(10);
tree.add(3);
tree.add(8);
tree.add(15);
tree.add(30);
System.out.println(tree.breadthFirst());
tree.remove(20);
System.out.println(tree.breadthFirst());
}
}
View Code
红黑树
![](https://images2015.cnblogs.com/blog/842253/201703/842253-20170313170427041-1579117934.png)
排序二叉树虽然可以快速检索,但是在最坏的情况下,如果插入的节点本身就是有序的,最后得到的排序二叉树将变成链表,其检索效率就会很差。 为了改变排序二叉树的存在的不足,出现了红黑树。 红黑树在原有的排序二叉树上增加了如下几个要求: 1、每个节点要么是红色,要么是黑色 2、根节点永远是黑色 3、所有的叶子节点都是空节点(null),而且是黑色的 4、每个红色节点的两个子节点都是黑色 5、从任一节点到其子树中每个叶子节点的路径都包含相同数量的黑色节点 根据性质5,红黑树从根节点到每个也叶子节点的路径都包含相同数量的黑色节点,因此从根节点到叶子节点的路径中包含的黑色节点数被称为树的黑色高度 性质4保证了从根节点到叶子节点的最长路径的长度不会超过其他路径的2倍。 红黑树通过上面的这种限制来保证它大致是平衡的——因为红黑树的高度不会无限增高,这样能保证红黑树在最坏情况下都是高效的,不会出现普通排序二叉树的情况。 红黑树的插入和删除操作都需要进行一定的维护,以保证插入节点、删除节点之后的树依旧是红黑树。 插入操作的步骤: 1、以排序二叉树的方法插入新节点,并将它设为空色 2、进行颜色调换和树旋转 看不下去了,有点难
|