zoukankan      html  css  js  c++  java
  • Java数据结构之树和二叉树(2)

    从这里始将要继续进行Java数据结构的相关讲解,Are you ready?Let's go~~

    Java中的数据结构模型可以分为一下几部分:

    1.线性结构

    2.树形结构

    3.图形或者网状结构

    接下来的几章,我们将会分别讲解这几种数据结构,主要也是通过Java代码的方式来讲解相应的数据结构。

    今天要讲解的是:Java线性结构

    对于之前普通树和二叉树的讲解请参考地址:

    今天我们将要进行的是Java树中的哈夫曼树(HaffmanTree),哈夫曼编码(HaffmanTreeCode),排序二叉树

    和红黑树进行相应的讲解,由于内容比较多,请耐心学习,同时有不足的地方也欢迎批评指正。谢谢~~~

    1.哈夫曼树的讲解

      哈夫曼树又称为最优二叉树,是一种带权路径最短的二叉树。哈夫曼树是二叉树的又一种应用,在信息检索中经常会使用到的。

      下面还是简单的介绍一下哈夫曼树的基本特性,至于更详细的信息请自己百度哦。

       节点之间的路径的长度:

       从一个节点到另外一个节点的分支的数量,我们称之为两个节点之间的路径的长度。

       树的路径长度:

       从根节点到树中每个节点的路径的长度之和,我们称之树的路径的长度。

       节点的带权路径的长度:

       从该节点到根节点之间路径的长度与节点权值的乘积

       树的带权路径的长度:

       树中所有的节点的带权路径之和

       带权路径最小的二叉树,我们称之为哈夫曼树或者为最优二叉树

       对于具有n个叶子节点的二叉树,一共需要2*n-1个节点。

       下面给出具体的代码来实现创建哈夫曼树的过程:

       废话也不多说,如果感兴趣的话请仔细查看下面的代码哦。

      

    package com.yonyou.test;
    
    import java.util.ArrayDeque;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Queue;
    
    
    
    
    
    
    
    
    /**
     * 测试类
     * @author 小浩
     * @创建日期 2015-3-20
     */
    public class Test
     { 
    	public static void main(String[] args)
    	{
    		List<HuffmanTree.Node<String>> nodes = new ArrayList<HuffmanTree.Node<String>>();
    		nodes.add(new HuffmanTree.Node<String>("A" , 40.0));
    		nodes.add(new HuffmanTree.Node<String>("B" , 7.0));
    		nodes.add(new HuffmanTree.Node<String>("C" , 10.0));
    		nodes.add(new HuffmanTree.Node<String>("D" , 30.0));
    		nodes.add(new HuffmanTree.Node<String>("E" , 12.0));
    		nodes.add(new HuffmanTree.Node<String>("F" , 2.0));
    		HuffmanTree.Node<String> root = HuffmanTree.createTree(nodes);
    		System.out.println(HuffmanTree.breadthFirst(root));
    	}
     }
    
    
    
    /**
     * 创建哈夫曼树的过程
     * @author 小浩
     * @创建日期 2015-3-23
     * @param <E>
     */
    class HuffmanTree
    {
    	public static class Node<E>
    	{
    		//节点中存储的数据
    		E data;
    		//当前节点所对应的权值
    		double weight;
    		//当前节点的左节点
    		Node<E> leftChild;
    		//当前节点的右节点
    		Node<E> rightChild;
    		public Node(E data , double weight)
    		{
    			this.data = data;
    			this.weight = weight;
    		}
    		public String toString()
    		{
    			return "Node[data=" + data
    				+ ", weight=" + weight + "]";
    		}
    	}
    	
    	/**
    	 * 构造哈夫曼树
    	 * @param nodes 节点集合
    	 * @return 构造出来的哈夫曼树的根节点
    	 */
    	public static <E> Node<E> createTree(List<Node<E>> nodes)
    	{
    		// 只要nodes数组中还有2个以上的节点
    		while (nodes.size() > 1)
    		{
    			//快速排序,对当前节点进行快排操作...
    			quickSort(nodes);
    			// 获取权值最小的两个节点
    			Node<E> left = nodes.get(nodes.size() - 1);
    			Node<E> right = nodes.get(nodes.size() - 2);
    			// 生成新节点,新节点的权值为两个子节点的权值之和
    			Node<E> parent = new Node<E>(null , left.weight + right.weight);
    			// 让新节点作为权值最小的两个节点的父节点
    			parent.leftChild = left;
    			parent.rightChild = right;
    			// 删除权值最小的两个节点
    			nodes.remove(nodes.size() - 1);
    			nodes.remove(nodes.size() - 1);
    			// 将新生成的父节点添加到集合中
    			nodes.add(parent);
    		}
    		// 返回nodes集合中唯一的节点,也就是根节点
    		return nodes.get(0);
    	}
    	
    	/**
    	 *  将指定数组的i和j索引处的元素交换
    	 * @param nodes
    	 * @param i
    	 * @param j
    	 */
    	private static <E> void swap(List<Node<E>> nodes, int i, int j)
    	{
    		Node<E> tmp;
    		tmp = nodes.get(i);
    		nodes.set(i , nodes.get(j));
    		nodes.set(j , tmp);
    	}
    	
    	/**
    	 * 实现快速排序算法,用于对节点进行排序
    	 * @param nodes
    	 * @param start
    	 * @param end
    	 */
    	private static <E> void subSort(List<Node<E>> nodes
    		, int start , int end)
    	{
    		// 需要排序
    		if (start < end)
    		{
    			// 以第一个元素作为分界值
    			Node base = nodes.get(start);
    			// i从左边搜索,搜索大于分界值的元素的索引
    			int i = start;
    			// j从右边开始搜索,搜索小于分界值的元素的索引
    			int j = end + 1;
    			while(true)
    			{
    				// 找到大于分界值的元素的索引,或i已经到了end处
    				while(i < end && nodes.get(++i).weight >= base.weight);
    				// 找到小于分界值的元素的索引,或j已经到了start处
    				while(j > start && nodes.get(--j).weight <= base.weight);
    				if (i < j)
    				{
    					swap(nodes , i , j);
    				}
    				else
    				{
    					break;
    				}
    			}
    			swap(nodes , start , j);
    			// 递归左子序列
    			subSort(nodes , start , j - 1);
    			// 递归右边子序列
    			subSort(nodes , j + 1, end);
    		}
    	}
    	
    	/**
    	 * 快速排序
    	 * @param nodes
    	 */
    	public static <E> void quickSort(List<Node<E>> nodes)
    	{
    		subSort(nodes , 0 , nodes.size() - 1);
    	}
    	
    	/**
    	 * 广度优先遍历
    	 * @param root
    	 * @return
    	 */
    	public static List<Node> breadthFirst(Node root)
    	{
    		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.leftChild != null)
    			{
    				queue.offer(p.leftChild);
    			}
    			// 如果右子节点不为null,将它加入“队列”
    			if(p.rightChild != null)
    			{
    				queue.offer(p.rightChild);
    			}
    		}
    		return list;
    	}
    }
    

    2.排序二叉树的讲解

      所谓排序二叉树:指的是给定一棵树,要么这棵树是一棵空树,要么这棵树具有以下特点:

         1)、如果它的左子树不空,那么它的左子树上面的所有节点都小于根节点

         2)、如果它的右子树不空,那么它的右子树上面的所有节点都大于根节点

         3)、它的左、右子树也分别是一棵排序二叉树

     

      具体的请看代码:

     

    package com.yonyou.test;
    
    import java.util.ArrayDeque;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Queue;
    
    
    
    
    
    
    
    
    /**
     * 测试类
     * @author 小浩
     * @创建日期 2015-3-20
     */
    public class Test
     { 
    	public static void main(String[] args)
    	{
    	}
     }
    
    
    
    /**
     * 创建排序二叉树的过程
     * @author 小浩
     * @创建日期 2015-3-23
     * @param <E>
     */
    class SortedBinTree<T extends Comparable>
    {
    	/**
    	 * 用于存储的节点的相关信息
    	 * @author 小浩
    	 * @创建日期 2015-3-23
    	 */
    	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
    	 */
    	@SuppressWarnings("unchecked")
    	public void add(T ele)
    	{
    		// 如果根节点为null
    		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;
    			}
    		}
    	}
    	
    	/**
    	 * 删除节点
    	 * @param ele
    	 */
    	public void remove(T ele)
    	{
    		// 获取要删除的节点
    		Node target = getNode(ele);
    		// 如果要删除的节点为null,直接返回
    		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的父节点的right设为null
    					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的父节点的left指向target的右子树
    					target.parent.left = target.right;
    				}
    				// 如果要删除节点是父节点的右子节点
    				else
    				{
    					// 让target的父节点的right指向target的右子树
    					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的父节点的left指向target的左子树
    					target.parent.left = target.left;
    				}
    				else
    				{
    					// 让target的父节点的right指向target的左子树
    					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
    			leftMaxNode.parent = target.parent;
    			// 要删除节点是父节点的左子节点
    			if (target == target.parent.left)
    			{
    				// 让target的父节点的left指向leftMaxNode
    				target.parent.left = leftMaxNode;
    			}
    			// 要删除节点是父节点的右子节点
    			else
    			{
    				// 让target的父节点的right指向leftMaxNode
    				target.parent.right = leftMaxNode;
    			}
    			leftMaxNode.left = target.left;
    			leftMaxNode.right = target.right;
    			target.parent = target.left = target.right = null;
    		}
    	}
    	// 根据给定的值搜索节点
    	@SuppressWarnings("unchecked")
    	public Node getNode(T ele)
    	{
    		//从根节点开始搜索
    		Node p = root;
    		while (p != null)
    		{
    			int cmp = ele.compareTo(p.data);
    			// 如果搜索的值小于当前p节点的值
    			if (cmp < 0)
    			{
    				// 向左子树搜索
    				p = p.left;
    			}
    			// 如果搜索的值大于当前p节点的值
    			else if (cmp > 0)
    			{
    				// 向右子树搜索
    				p = p.right;
    			}
    			else
    			{
    				return p;
    			}
    		}
    		return null;
    	}
    	// 广度优先遍历
    	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);
    			}
    			// 如果右子节点不为null,将它加入“队列”
    			if(p.right != null)
    			{
    				queue.offer(p.right);
    			}
    		}
    		return list;
    	}
    }
    

    3、红黑树的讲解

     

    public class RedBlackTree<T extends Comparable>
    {
    	// 定义红黑树的颜色
    	private static final boolean RED   = false;
    	private static final boolean BLACK = true;
    	static class Node
    	{
    		Object data;
    		Node parent;
    		Node left;
    		Node right;
    		// 节点的默认颜色是黑色
    		boolean color = BLACK;
    		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
    				+ ", color=" + color + "]";
    		}
    		public boolean equals(Object obj)
    		{
    			if (this == obj)
    			{
    				return true;
    			}
    			if (obj.getClass() == Node.class)
    			{
    				Node target = (Node)obj;
    				return data.equals(target.data)
    					&& color == target.color
    					&& left == target.left
    					&& right == target.right
    					&& parent == target.parent;
    			}
    			return false;
    		}
    	}
    	private Node root;
    	// 两个构造器用于创建排序二叉树
    	public RedBlackTree()
    	{
    		root = null;
    	}
    	public RedBlackTree(T o)
    	{
    		root = new Node(o , null , null , null);
    	}
    	// 添加节点
    	public void add(T ele)
    	{
    		// 如果根节点为null
    		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;
    			}
    			// 维护红黑树
    			fixAfterInsertion(newNode);
    		}
    	}
    	// 删除节点
    	public void remove(T ele)
    	{
    		// 获取要删除的节点
    		Node target = getNode(ele);
    		// 如果要删除节点的左子树、右子树都不为空
    		if (target.left != null && target.right != null)
    		{
    			// 找到target节点中序遍历的前一个节点
    			// s用于保存target节点的左子树中值最大的节点
    			Node s = target.left;
    			// 搜索target节点的左子树中值最大的节点
    			while (s.right != null)
    			{
    				s = s.right;
    			}
    			// 用s节点来代替p节点
    			target.data = s.data;
    			target = s;
    		}
    		// 开始修复它的替换节点,如果该替换节点不为null
    		Node replacement = (target.left != null ?
    			target.left : target.right);
    		if (replacement != null)
    		{
    			// 让replacement的parent指向target的parent
    			replacement.parent = target.parent;
    			// 如果target的parent为null,表明target本身是根节点
    			if (target.parent == null)
    			{
    				root = replacement;
    			}
    			// 如果target是其父节点的左子节点
    			else if (target == target.parent.left)
    			{
    				// 让target的父节点left指向replacement
    				target.parent.left  = replacement;
    			}
    			// 如果target是其父节点的右子节点
    			else
    			{
    				// 让target的父节点right指向replacement
    				target.parent.right = replacement;
    			}
    			// 彻底删除target节点
    			target.left = target.right = target.parent = null;
    
    			// 修复红黑树
    			if (target.color == BLACK)
    			{
    				fixAfterDeletion(replacement);
    			}
    		}
    		// target本身是根节点
    		else if (target.parent == null)
    		{
    			root = null;
    		}
    		else
    		{
    			// target没有子节点,把它当成虚的替换节点。
    			// 修复红黑树
    			if (target.color == BLACK)
    			{
    				fixAfterDeletion(target);
    			}
    			if (target.parent != null)
    			{
    				// 如果target是其父节点的左子节点
    				if (target == target.parent.left)
    				{
    					// 将target的父节点left设为null
    					target.parent.left = null;
    				}
    				// 如果target是其父节点的右子节点
    				else if (target == target.parent.right)
    				{
    					// 将target的父节点right设为null
    					target.parent.right = null;
    				}
    				// 将target的parent设置null
    				target.parent = null;
    			}
    		}
    	}
    	// 根据给定的值搜索节点
    	public Node getNode(T ele)
    	{
    		// 从根节点开始搜索
    		Node p = root;
    		while (p != null)
    		{
    			int cmp = ele.compareTo(p.data);
    			// 如果搜索的值小于当前p节点的值
    			if (cmp < 0)
    			{
    				// 向左子树搜索
    				p = p.left;
    			}
    			// 如果搜索的值大于当前p节点的值
    			else if (cmp > 0)
    			{
    				// 向右子树搜索
    				p = p.right;
    			}
    			else
    			{
    				return p;
    			}
    		}
    		return null;
    	}
    	// 广度优先遍历
    	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);
    			}
    			// 如果右子节点不为null,将它入“队列”
    			if(p.right != null)
    			{
    				queue.offer(p.right);
    			}
    		}
    		return list;
    	}
    	// 插入节点后修复红黑树
    	private void fixAfterInsertion(Node x)
    	{
    		x.color = RED;
    		// 直到x节点的父节点不是根,且x的父节点不是红色
    		while (x != null && x != root
    			&& x.parent.color == RED)
    		{
    			// 如果x的父节点是其父节点的左子节点
    			if (parentOf(x) == leftOf(parentOf(parentOf(x))))
    			{
    				// 获取x的父节点的兄弟节点
    				Node y = rightOf(parentOf(parentOf(x)));
    				// 如果x的父节点的兄弟节点是红色
    				if (colorOf(y) == RED)
    				{
    					// 将x的父节点设为黑色
    					setColor(parentOf(x), BLACK);
    					// 将x的父节点的兄弟节点设为黑色
    					setColor(y, BLACK);
    					// 将x的父节点的父节点设为红色
    					setColor(parentOf(parentOf(x)), RED);
    					x = parentOf(parentOf(x));
    				}
    				// 如果x的父节点的兄弟节点是黑色
    				else
    				{
    					// 如果x是其父节点的右子节点
    					if (x == rightOf(parentOf(x)))
    					{
    						// 将x的父节点设为x
    						x = parentOf(x);
    						rotateLeft(x);
    					}
    					// 把x的父节点设为黑色
    					setColor(parentOf(x), BLACK);
    					// 把x的父节点的父节点设为红色
    					setColor(parentOf(parentOf(x)), RED);
    					rotateRight(parentOf(parentOf(x)));
    				}
    			}
    			// 如果x的父节点是其父节点的右子节点
    			else
    			{
    				// 获取x的父节点的兄弟节点
    				Node y = leftOf(parentOf(parentOf(x)));
    				// 如果x的父节点的兄弟节点是红色
    				if (colorOf(y) == RED)
    				{
    					// 将x的父节点设为黑色。
    					setColor(parentOf(x), BLACK);
    					// 将x的父节点的兄弟节点设为黑色
    					setColor(y, BLACK);
    					// 将x的父节点的父节点设为红色
    					setColor(parentOf(parentOf(x)), RED);
    					// 将x设为x的父节点的节点
    					x = parentOf(parentOf(x));
    				}
    				// 如果x的父节点的兄弟节点是黑色
    				else
    				{
    					// 如果x是其父节点的左子节点
    					if (x == leftOf(parentOf(x)))
    					{
    						//将x的父节点设为x
    						x = parentOf(x);
    						rotateRight(x);
    					}
    					// 把x的父节点设为黑色
    					setColor(parentOf(x), BLACK);
    					// 把x的父节点的父节点设为红色
    					setColor(parentOf(parentOf(x)), RED);
    					rotateLeft(parentOf(parentOf(x)));
    				}
    			}
    		}
    		// 将根节点设为黑色
    		root.color = BLACK;
    	}
    	// 删除节点后修复红黑树
    	private void fixAfterDeletion(Node x)
    	{
    		// 直到x不是根节点,且x的颜色是黑色
    		while (x != root && colorOf(x) == BLACK)
    		{
    			// 如果x是其父节点的左子节点
    			if (x == leftOf(parentOf(x)))
    			{
    				// 获取x节点的兄弟节点
    				Node sib = rightOf(parentOf(x));
    				// 如果sib节点是红色
    				if (colorOf(sib) == RED)
    				{
    					// 将sib节点设为黑色
    					setColor(sib, BLACK);
    					// 将x的父节点设为红色
    					setColor(parentOf(x), RED);
    					rotateLeft(parentOf(x));
    					// 再次将sib设为x的父节点的右子节点
    					sib = rightOf(parentOf(x));
    				}
    				// 如果sib的两个子节点都是黑色
    				if (colorOf(leftOf(sib)) == BLACK
    					&& colorOf(rightOf(sib)) == BLACK)
    				{
    					// 将sib设为红色
    					setColor(sib, RED);
    					// 让x等于x的父节点
    					x = parentOf(x);
    				}
    				else
    				{
    					// 如果sib的只有右子节点是黑色
    					if (colorOf(rightOf(sib)) == BLACK)
    					{
    						// 将sib的左子节点也设为黑色
    						setColor(leftOf(sib), BLACK);
    						// 将sib设为红色
    						setColor(sib, RED);
    						rotateRight(sib);
    						sib = rightOf(parentOf(x));
    					}
    					// 设置sib的颜色与x的父节点的颜色相同
    					setColor(sib, colorOf(parentOf(x)));
    					// 将x的父节点设为黑色
    					setColor(parentOf(x), BLACK);
    					// 将sib的右子节点设为黑色
    					setColor(rightOf(sib), BLACK);
    					rotateLeft(parentOf(x));
    					x = root;
    				}
    			}
    			// 如果x是其父节点的右子节点
    			else
    			{
    				// 获取x节点的兄弟节点
    				Node sib = leftOf(parentOf(x));
    				// 如果sib的颜色是红色
    				if (colorOf(sib) == RED)
    				{
    					// 将sib的颜色设为黑色
    					setColor(sib, BLACK);
    					// 将sib的父节点设为红色
    					setColor(parentOf(x), RED);
    					rotateRight(parentOf(x));
    					sib = leftOf(parentOf(x));
    				}
    				// 如果sib的两个子节点都是黑色
    				if (colorOf(rightOf(sib)) == BLACK
    					&& colorOf(leftOf(sib)) == BLACK)
    				{
    					// 将sib设为红色
    					setColor(sib, RED);
    					//让x等于x的父节点
    					x = parentOf(x);
    				}
    				else
    				{
    					// 如果sib只有左子节点是黑色
    					if (colorOf(leftOf(sib)) == BLACK)
    					{
    						// 将sib的右子节点也设为黑色
    						setColor(rightOf(sib), BLACK);
    						// 将sib设为红色
    						setColor(sib, RED);
    						rotateLeft(sib);
    						sib = leftOf(parentOf(x));
    					}
    					// 将sib的颜色设为与x的父节点颜色相同
    					setColor(sib, colorOf(parentOf(x)));
    					// 将x的父节点设为黑色
    					setColor(parentOf(x), BLACK);
    					// 将sib的左子节点设为黑色
    					setColor(leftOf(sib), BLACK);
    					rotateRight(parentOf(x));
    					x = root;
    				}
    			}
    		}
    		setColor(x, BLACK);
    	}
    	// 获取指定节点的颜色
    	private boolean colorOf(Node p)
    	{
    		return (p == null ? BLACK : p.color);
    	}
    	// 获取指定节点的父节点
    	private Node parentOf(Node p)
    	{
    		return (p == null ? null: p.parent);
    	}
    	// 为指定节点设置颜色
    	private void setColor(Node p, boolean c)
    	{
    		if (p != null)
    		{
    			p.color = c;
    		}
    	}
    	// 获取指定节点的左子节点
    	private Node leftOf(Node p)
    	{
    		return (p == null) ? null: p.left;
    	}
    	// 获取指定节点的右子节点
    	private Node rightOf(Node p)
    	{
    		return (p == null) ? null: p.right;
    	}
    	/**
    	 * 执行如下转换
    	 *  p        r
    	 *     r   p
    	 *  q        q
    	 */
    	private void rotateLeft(Node p)
    	{
    		if (p != null)
    		{
    			// 取得p的右子节点
    			Node r = p.right;
    			Node q = r.left;
    			// 将r的左子节点链到p的右节点链上
    			p.right = q;
    			// 让r的左子节点的parent指向p节点
    			if (q != null)
    			{
    				q.parent = p;
    			}
    			r.parent = p.parent;
    			// 如果p已经是根节点
    			if (p.parent == null)
    			{
    				root = r;
    			}
    			// 如果p是其父节点的左子节点
    			else if (p.parent.left == p)
    			{
    				// 将r设为p的父节点的左子节点
    				p.parent.left = r;
    			}
    			else
    			{
    				// 将r设为p的父节点的右子节点
    				p.parent.right = r;
    			}
    			r.left = p;
    			p.parent = r;
    		}
    	}
    	/**
    	 * 执行如下转换
    	 *     p       l
    	 *  l              p
    	 *     q       q
    	 */
    	private void rotateRight(Node p)
    	{
    		if (p != null)
    		{
    			// 取得p的左子节点
    			Node l = p.left;
    			Node q = l.right;
    			// 将l的右子节点链到p的左节点链上
    			p.left = q;
    			// 让l的右子节点的parent指向p节点
    			if (q != null)
    			{
    				q.parent = p;
    			}
    			l.parent = p.parent;
    			// 如果p已经是根节点
    			if (p.parent == null)
    			{
    				root = l;
    			}
    			// 如果p是其父节点的右子节点
    			else if (p.parent.right == p)
    			{
    				// 将l设为p的父节点的右子节点
    				p.parent.right = l;
    			}
    			else
    			{
    				// 将l设为p的父节点的左子节点
    				p.parent.left = l;
    			}
    			l.right = p;
    			p.parent = l;
    		}
    	}
    	// 实现中序遍历
    	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;
    	}
    }
    

      

     

      

          

  • 相关阅读:
    Scala学习(八)---Scala继承
    Scala学习(九)---文件和正则表达式
    Scala学习(六)---Scala对象
    jemter----命令行模式(cmd)导出测试报告
    js数据类型
    定期任务,如每月清理(SpringBoot Mybatis-Plus)
    定时执行任务(SpringBoot Mybatis-Plus)
    图片服务映射(SpringBoot mybatis-plus)
    图片压缩上传(Springboot mybatis-plus)
    java生成pdf
  • 原文地址:https://www.cnblogs.com/xiohao/p/4360581.html
Copyright © 2011-2022 走看看