二叉树、二叉搜索树、AVL树的java实现

数据结构一直都是断断续续的看,总是觉得理解的不够深入,特别是对树的理解,一直都很浅显,今儿又看了一遍,来做个总结吧。

首先,树中的一些概念:

1、树的节点包含一个数据元素,以及若干指向其子树的分支。节点拥有的子树的数量称为节点的度。节点的最大层次称为树的深度或高度

2、二叉树是一种树形结构,其特点是每个节点至多有两棵子树,且子树有左右之分,次序不能随意颠倒。

3、满二叉树:一棵深度为k且有2^k – 1个节点的二叉树,称之为满二叉树。

4、完全二叉树:对一个深度为k,节点个数为n的二叉树,当且仅当每个节点都与深度为k的满二叉树中编号从1至n的节点一一对应时,称之为完全二叉树。

5、哈夫曼树:又称最优树,是一类带权路径长度最短的树。

6、二叉查找树(Binary Search Tree):对任一个节点,左子树的所有值都小于它,右子树的所有值都大于它。

7、AVL树:带有平衡条件的二叉查找树。

8、伸展树:任一个节点被访问后,它就要经过一系列的AVL树的旋转,将该节点放到根上。

9、B-树:另外一种常用的查找树。有几个特点,对于M阶的B树,首先,根节点如果不是叶子,则其子节点的数量在2-M之间。其次,除根之外,所有的非叶子节点的子节点数在M/2 - M之间。最后,所有的叶子节点有相同的深度。

概念讲到这儿,下面来实战几种树。这里主要讲三种,分别是:

1、普通二叉树

2、二叉搜索树

3、AVL树

详细的代码下载地址:https://github.com/BLYang7/DataStructure/tree/master/BinNode

普通二叉树:讲一些树结构的定义,普通生成、前序中序后序遍历的实现(递归实现和用栈来实现)、层次遍历、获取二叉树的深度、判断是否平衡、寻找两个节点最近的共同父节点。  

package com.BinNode;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 * 树结构
 */
public class TreeNode {

	/**
	 * 定义一棵二叉树
	 */
	private static class BinNode{
		public int Element;
		public BinNode Left;
		public BinNode Right;
		public BinNode(int element){
			this.Element = element;
		}
		public BinNode(int element, BinNode left, BinNode right){
			this.Element = element;
			this.Left = left;
			this.Right = right;
		}
		public boolean isLeaf(){
			return this.Left == null && this.Right == null;
		}
	}

	/**
	 * 测试数据的构建
	 */
	public static BinNode root = new BinNode(0);
	public static BinNode left = new BinNode(1);
	public static BinNode right = new BinNode(2);
	public static BinNode leftLeft = new BinNode(3);
	public static BinNode leftRight = new BinNode(4);
	public static BinNode rightLeft = new BinNode(5);
	public static BinNode rightRight = new BinNode(6);
	static{
		root.Left = left;
		root.Right = right;
		left.Left = leftLeft;
		left.Right = leftRight;
		right.Left = rightLeft;
		right.Right = rightRight;
	}
	

	/**
	 * 前序遍历,先遍历跟节点,再遍历左子树,后遍历右子树
	 * @param root 待遍历的根节点
	 */
	private static void preOrder(BinNode root){
		if( root == null ){
			return;
		}
		System.out.print(root.Element + "  "); //遍历打印输出
		preOrder(root.Left);
		preOrder(root.Right);
	}
	
	/**
	 * 中序遍历,先遍历左节点,再遍历跟节点,后遍历右子树
	 * @param root 待遍历的根节点
	 */
	private static void middleOrder(BinNode root){
		if( root == null ){
			return;
		}
		middleOrder(root.Left);
		System.out.print( root.Element + "  " );
		middleOrder(root.Right);
	}
	
	/**
	 * 后序遍历, 先遍历左节点,再遍历右节点,最后遍历根节点
	 * @param root 待遍历的根节点
	 */
	private static void postOrder(BinNode root){
		if( root == null ){
			return;
		}
		postOrder(root.Left);
		postOrder(root.Right);
		System.out.print( root.Element + "  " );
	}
	
	/**
	 * 前序遍历,不用递归实现,使用栈来实现
	 */
	private static void preOrder1(BinNode root){
		Stack stack = new Stack();
		BinNode temp = root;
		
		//入栈
		while( temp != null ){
			System.out.print( temp.Element + "  " );
			if( temp.Right != null ){
				stack.push(temp.Right);
			}
			temp = temp.Left;
		}
		
		//出栈
		while( stack.size() > 0 ){
			temp = (BinNode) stack.pop();
			while( temp != null ){
				System.out.print(temp.Element + "  " );
				if( temp.Right != null ){
					stack.push(temp.Right);
				}
				temp = temp.Left;
			}
		}
	}
	
	
	/**
	 * 中序遍历,不用递归实现,使用栈区来实现
	 * @param root
	 */
	private static void middleOrder1( BinNode root ){
		Stack stack = new Stack();
		BinNode temp = root;
		
		//入栈
		while( temp != null ){
			if( temp != null ){
				stack.push(temp);
			}
			temp = temp.Left;
		}
		
		//出栈
		while( stack.size() > 0 ){
			temp = (BinNode) stack.pop();
			System.out.print( temp.Element + "  ");
			if( temp.Right != null ){
				temp = temp.Right;
				stack.push(temp);
				while( temp != null ){
					if( temp.Left != null){
						stack.push(temp.Left);
					}
					temp = temp.Left;
				}
			}
		}
	}
	
	
	/**
	 * 后序遍历,不用递归实现,使用栈来记录。这里有点繁,根节点还是要重新装载进栈
	 * @param root
	 */
	private static void postOrder1( BinNode root ){
		Stack stack = new Stack();
		BinNode temp = root;
		
		//入栈
		while(temp != null){
			if(temp != null){
				stack.push(temp);
			}
			temp = temp.Left;
		}
		
		//出栈
		while( stack.size() > 0 ){
			BinNode lastVisit = temp;
			temp = (BinNode) stack.pop();
			if(temp.Right == null || temp.Right == lastVisit){
				System.out.print( temp.Element + "  " );
			} else if ( temp.Left == lastVisit ){
				stack.push(temp);  //再装载进去
				temp = temp.Right;
				stack.push(temp);
				while( temp != null ){
					if( temp.Left != null ){
						stack.push(temp.Left);
					}
					temp = temp.Left;
				}
			}
		}
	}
	
	
	/**
	 * 逐层打印二叉树的每一层 层次遍历
	 * 采用广度搜索优先的遍历方法,利用队列的方式实现
	 */
	private static void printTree( BinNode root ){
		if( root == null ){
			return;
		}
		BinNode tmp = null;
		Queue<BinNode> queue = new LinkedList<BinNode>();
		//队列中把根节点加进去
		queue.add(root);
		//遍历整棵二叉树
		while( !queue.isEmpty() ){
			tmp = (BinNode) queue.poll();
			System.out.print( tmp.Element + "  ");
			
			//将左节点加入到队列中
			if( tmp.Left != null ){
				queue.add(tmp.Left);
			}
			
			//将右节点加入到队列中
			if( tmp.Right != null ){
				queue.add(tmp.Right);
			}
		}
	}
	
	

	/**
	 * 获取二叉树的深度
	 */
	private static int getDepth(BinNode root){
		if( root == null ){
			return 0;
		}
		int leftLength = getDepth(root.Left);
		int rightLength = getDepth(root.Right);
		
		return (leftLength > rightLength ? leftLength : rightLength) + 1;
	}
	
	
	/**
	 * 判断是否为平衡二叉树
	 * 平衡的条件是:左右子树的深度相差不超过1
	 */
	private static boolean isBalanceTree(BinNode root){
		if( root == null ){
			return true;
		}
		
		int leftLength = getDepth(root.Left);
		int rightLength = getDepth(root.Right);
		
		int distance = (leftLength > rightLength) ? (leftLength - rightLength) : (rightLength - leftLength);
		
		if( distance > 1 ){
			return false;
		} else {
			return isBalanceTree(root.Left) && isBalanceTree(root.Right);
		}
	}
	

	
	/**
	 * 寻找两个节点最近的共同父节点
	 * 将两个节点的父节点栈进行对比,一次弹出相同的节点,最后一次弹出的相同节点即为最近的公共父节点
	 */
	private static BinNode findParentNode(BinNode root, BinNode node1, BinNode node2){
		
		java.util.Stack stack1 = new java.util.Stack();
		getPositionByNode(root, node1, stack1);
		
		java.util.Stack stack2 = new java.util.Stack();
		getPositionByNode(root, node2, stack2);
		
		BinNode tempNode = null;
		while( stack1.peek() == stack2.peek() ){
			tempNode = (BinNode) stack1.pop();
			stack2.pop();
		}
		return tempNode;
	}
	//把某个节点的所有父节点依次添加到栈中
	private static boolean getPositionByNode(BinNode root, BinNode node, java.util.Stack stack){
		
		if( root == null ){
			return false;
		}
		else if( root == node ){
			stack.push(root);
			return true;
		}
		else if( getPositionByNode(root.Left, node, stack) || getPositionByNode(root.Right, node, stack) ){
			stack.push(root);
			return true;
		}
		return false;
	}
	
	
	
	//测试
	public static void main(String[] args) {
		//前序遍历,递归调用
		preOrder(root);
		System.out.println();
		
		//中序遍历,递归调用
		middleOrder(root);
		System.out.println();
		
		//后序遍历,递归调用
		postOrder(root);
		System.out.println();
		
		//前序遍历,栈来实现
		preOrder1(root);
		System.out.println();
		
		//中序遍历,栈来实现
		middleOrder1(root);
		System.out.println();
		
		//后序遍历,栈来实现
		postOrder1(root);
		System.out.println();
		
		//层次遍历
		printTree(root);
		System.out.println();
		
		//获取二叉树的深度
		System.out.println(getDepth(root));
		
		//判断是否为平衡二叉树
		System.out.println(isBalanceTree(root));
		
		//寻找两个节点最近的共同父节点
		System.out.println(findParentNode(root, leftLeft, leftRight).Element);	
	}
}

二叉搜索树:这里重点是节点的插入和节点的删除,请看代码:

package com.BinNode;
/** 
 * 二叉搜索树 Binary Search Tree
 * 
 * 此程序实现一个二叉查找树的功能,可以进行动态插入、删除关键字; 
 * 查询给定关键字、最小关键字、最大关键字;转换为有序列表(用于排序) 
 */
import java.util.ArrayList;
import java.util.List;

public class BinarySearchTree {

	// 树的根结点
	private TreeNode root = null;

	// 遍历结点列表
	private List<TreeNode> nodelist = new ArrayList<TreeNode>();

	// 树的节点类
	private class TreeNode {

		private int key;
		private TreeNode leftChild;
		private TreeNode rightChild;
		private TreeNode parent;

		public TreeNode(int key, TreeNode leftChild, TreeNode rightChild,
				TreeNode parent) {
			this.key = key;
			this.leftChild = leftChild;
			this.rightChild = rightChild;
			this.parent = parent;
		}

		public int getKey() {
			return key;
		}

		public String toString() {
			String leftkey = (leftChild == null ? "" : String
					.valueOf(leftChild.key));
			String rightkey = (rightChild == null ? "" : String
					.valueOf(rightChild.key));
			return "(" + leftkey + " , " + key + " , " + rightkey + ")";
		}
	}

	/**
	 * isEmpty: 判断二叉查找树是否为空;若为空,返回 true ,否则返回 false .
	 * 
	 */
	public boolean isEmpty() {
		if (root == null) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * TreeEmpty: 对于某些二叉查找树操作(比如删除关键字)来说,若树为空,则抛出异常。
	 */
	public void TreeEmpty() throws Exception {
		if (isEmpty()) {
			throw new Exception("树为空!");
		}
	}

	/**
	 * search: 在二叉查找树中查询给定关键字
	 * 
	 * @param key 给定关键字
	 * @return 匹配给定关键字的树结点
	 */
	public TreeNode search(int key) {
		TreeNode pNode = root;
		while (pNode != null && pNode.key != key) {
			if (key < pNode.key) {
				pNode = pNode.leftChild;
			} else {
				pNode = pNode.rightChild;
			}
		}
		return pNode;
	}

	/**
	 * minElemNode: 获取二叉查找树中的最小关键字结点
	 * 
	 * @return 二叉查找树的最小关键字结点
	 * @throws Exception 若树为空,则抛出异常
	 */
	public TreeNode minElemNode(TreeNode node) throws Exception {
		if (node == null) {
			throw new Exception("树为空!");
		}
		TreeNode pNode = node;
		while (pNode.leftChild != null) {
			pNode = pNode.leftChild;
		}
		return pNode;
	}

	/**
	 * maxElemNode: 获取二叉查找树中的最大关键字结点
	 * 
	 * @return 二叉查找树的最大关键字结点
	 * @throws Exception 若树为空,则抛出异常
	 */
	public TreeNode maxElemNode(TreeNode node) throws Exception {
		if (node == null) {
			throw new Exception("树为空!");
		}
		TreeNode pNode = node;
		while (pNode.rightChild != null) {
			pNode = pNode.rightChild;
		}
		return pNode;
	}

	/**
	 * successor: 获取给定结点在中序遍历顺序下的后继结点
	 * 
	 * @param node 给定树中的结点
	 * @return 若该结点存在中序遍历顺序下的后继结点,则返回其后继结点;否则返回 null
	 * @throws Exception
	 */
	public TreeNode successor(TreeNode node) throws Exception {
		if (node == null) {
			return null;
		}

		// 若该结点的右子树不为空,则其后继结点就是右子树中的最小关键字结点
		if (node.rightChild != null) {
			return minElemNode(node.rightChild);
		}
		// 若该结点右子树为空
		TreeNode parentNode = node.parent;
		while (parentNode != null && node == parentNode.rightChild) {
			node = parentNode;
			parentNode = parentNode.parent;
		}
		return parentNode;
	}

	/**
	 * precessor: 获取给定结点在中序遍历顺序下的前趋结点
	 * 
	 * @param node  给定树中的结点
	 * @return 若该结点存在中序遍历顺序下的前趋结点,则返回其前趋结点;否则返回 null
	 * @throws Exception
	 */
	public TreeNode precessor(TreeNode node) throws Exception {
		if (node == null) {
			return null;
		}

		// 若该结点的左子树不为空,则其前趋结点就是左子树中的最大关键字结点
		if (node.leftChild != null) {
			return maxElemNode(node.leftChild);
		}
		// 若该结点左子树为空
		TreeNode parentNode = node.parent;
		while (parentNode != null && node == parentNode.leftChild) {
			node = parentNode;
			parentNode = parentNode.parent;
		}
		
		return parentNode;
	}

	/**
	 * insert: 将给定关键字插入到二叉查找树中
	 * 
	 * @param key 给定关键字
	 */
	public void insert(int key) {
		TreeNode parentNode = null;
		TreeNode newNode = new TreeNode(key, null, null, null);
		TreeNode pNode = root;
		if (root == null) {
			root = newNode;
			return;
		}
		
		while (pNode != null) {
			parentNode = pNode;
			if (key < pNode.key) {
				pNode = pNode.leftChild;
			} else if (key > pNode.key) {
				pNode = pNode.rightChild;
			} else {
				// 树中已存在匹配给定关键字的结点,则什么都不做直接返回
				return;
			}
		}
		
		if (key < parentNode.key) {
			parentNode.leftChild = newNode;
			newNode.parent = parentNode;
		} else {
			parentNode.rightChild = newNode;
			newNode.parent = parentNode;
		}

	}

	/**
	 * insert: 从二叉查找树中删除匹配给定关键字相应的树结点
	 * 
	 * @param key 给定关键字
	 */
	public void delete(int key) throws Exception {
		TreeNode pNode = search(key);
		if (pNode == null) {
			throw new Exception("树中不存在要删除的关键字!");
		}
		delete(pNode);
	}

	/**
	 * delete: 从二叉查找树中删除给定的结点.
	 * 
	 * @param pNode 要删除的结点。前置条件是给定结点在二叉查找树中已经存在
	 * @throws Exception
	 */
	private void delete(TreeNode pNode) throws Exception {
		if (pNode == null) {
			return;
		}
		if (pNode.leftChild == null && pNode.rightChild == null) { // 该结点既无左孩子结点,也无右孩子结点
			TreeNode parentNode = pNode.parent;
			if (pNode == parentNode.leftChild) {
				parentNode.leftChild = null;
			} else {
				parentNode.rightChild = null;
			}
			return;
		}
		if (pNode.leftChild == null && pNode.rightChild != null) { // 该结点左孩子结点为空,右孩子结点非空
			TreeNode parentNode = pNode.parent;
			if (pNode == parentNode.leftChild) {
				parentNode.leftChild = pNode.rightChild;
				pNode.rightChild.parent = parentNode;
			} else {
				parentNode.rightChild = pNode.rightChild;
				pNode.rightChild.parent = parentNode;
			}
			return;
		}
		if (pNode.leftChild != null && pNode.rightChild == null) { // 该结点左孩子结点非空,右孩子结点为空
			TreeNode parentNode = pNode.parent;
			if (pNode == parentNode.leftChild) {
				parentNode.leftChild = pNode.leftChild;
				pNode.rightChild.parent = parentNode;
			} else {
				parentNode.rightChild = pNode.leftChild;
				pNode.rightChild.parent = parentNode;
			}
			return;
		}
		
		// 该结点左右孩子结点均非空,则删除该结点的后继结点,并用该后继结点取代该结点
		TreeNode successorNode = successor(pNode);
		delete(successorNode);
		pNode.key = successorNode.key;
	}

	/**
	 * inOrderTraverseList: 获得二叉查找树的中序遍历结点列表
	 * 
	 * @return 二叉查找树的中序遍历结点列表
	 */
	public List<TreeNode> inOrderTraverseList() {
		if (nodelist != null) {
			nodelist.clear();
		}
		inOrderTraverse(root);
		return nodelist;
	}

	/**
	 * inOrderTraverse: 对给定二叉查找树进行中序遍历
	 * 
	 * @param root 给定二叉查找树的根结点
	 */
	private void inOrderTraverse(TreeNode root) {
		if (root != null) {
			inOrderTraverse(root.leftChild);
			nodelist.add(root);
			inOrderTraverse(root.rightChild);
		}
	}

	/**
	 * toStringOfOrderList: 获取二叉查找树中关键字的有序列表
	 * 
	 * @return 二叉查找树中关键字的有序列表
	 */
	public String toStringOfOrderList() {
		StringBuilder sbBuilder = new StringBuilder(" [ ");
		for (TreeNode p : inOrderTraverseList()) {
			sbBuilder.append(p.key);
			sbBuilder.append(" ");
		}
		sbBuilder.append("]");
		return sbBuilder.toString();
	}

	/**
	 * 获取该二叉查找树的字符串表示
	 */
	public String toString() {
		StringBuilder sbBuilder = new StringBuilder(" [ ");
		for (TreeNode p : inOrderTraverseList()) {
			sbBuilder.append(p);
			sbBuilder.append(" ");
		}
		sbBuilder.append("]");
		return sbBuilder.toString();
	}

	public TreeNode getRoot() {
		return root;
	}

	public static void testNode(BinarySearchTree bst, TreeNode pNode)
			throws Exception {
		System.out.println("本结点: " + pNode);
		System.out.println("前趋结点: " + bst.precessor(pNode));
		System.out.println("后继结点: " + bst.successor(pNode));
	}

	public static void testTraverse(BinarySearchTree bst) {
		System.out.println("二叉树遍历:" + bst);
		System.out.println("二叉查找树转换为有序列表: " + bst.toStringOfOrderList());
	}

	// 测试
	public static void main(String[] args) {
		try {
			BinarySearchTree bst = new BinarySearchTree();
			System.out.println("查找树是否为空? " + (bst.isEmpty() ? "是" : "否"));
			int[] keys = new int[] { 15, 6, 18, 3, 7, 13, 20, 2, 9, 4 };
			for (int key : keys) {
				bst.insert(key);
			}
			System.out.println("查找树是否为空? " + (bst.isEmpty() ? "是" : "否"));
			TreeNode minkeyNode = bst.minElemNode(bst.getRoot());
			System.out.println("最小关键字: " + minkeyNode.getKey());
			testNode(bst, minkeyNode);
			TreeNode maxKeyNode = bst.maxElemNode(bst.getRoot());
			System.out.println("最大关键字: " + maxKeyNode.getKey());
			testNode(bst, maxKeyNode);
			System.out.println("根结点关键字: " + bst.getRoot().getKey());
			testNode(bst, bst.getRoot());
			testTraverse(bst);
			System.out.println("****************************** ");
			testTraverse(bst);
		} catch (Exception e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
	}

}

AVL树:平衡二叉树,对于这种树,涉及到旋转。当新插入一个节点时,要判断节点插入之后当前树是否平衡,如果不平衡,肯定是当前插入的节点破坏了原来节点的平衡关系。需要讲三层的子树旋转成两层。具体的几种旋转如图示:

《二叉树、二叉搜索树、AVL树的java实现》

上代码:

package com.BinNode;
/**
 * AVL树
 *
 */
public class AVLTree<T extends Comparable<? super T>> {

	/**
	 * AVL树节点的定义
	 */
	private static class AvlNode<T> {
		AvlNode(T theElement) {
			this(theElement, null, null);
		}
		AvlNode(T theElement, AvlNode<T> lt, AvlNode<T> rt) {
			element = theElement;
			left = lt;
			right = rt;
			height = 0;
		}
		T element; // 节点中的数据
		AvlNode<T> left; // 左儿子
		AvlNode<T> right; // 右儿子
		int height; // 节点的高度
	}

	// avl树根
	private AvlNode<T> root;

	public AVLTree() {
		root = null;
	}

	// 在avl树中插入数据,重复数据复略
	public void insert(T x) {
		root = insert(x, root);
	}

	// 在avl中删除数据,没有实现
	public void remove(T x) {
		System.out.println("Sorry, remove unimplemented");
	}

	// 在avl树中找最小的数据
	public T findMin() throws Exception {
		if (isEmpty())
			throw new Exception("空");
		return findMin(root).element;
	}

	// 在avl树中找最大的数据
	public T findMax() throws Exception {
		if (isEmpty())
			throw new Exception("空");
		return findMax(root).element;
	}

	// 搜索
	public boolean contains(T x) {
		return contains(x, root);
	}

	public void makeEmpty() {
		root = null;
	}

	public boolean isEmpty() {
		return root == null;
	}

	// 排序输出avl树
	public void printTree() {
		if (isEmpty())
			System.out.println("Empty tree");
		else
			printTree(root);
	}
	
	/**
	 * AVL树的插入,重点就是这儿了
	 * @param x 要插入的元素
	 * @param t 树的根节点
	 * @return
	 */
	private AvlNode<T> insert(T x, AvlNode<T> t) {
		if (t == null){
			return new AvlNode<T>(x, null, null);
		}

		int compareResult = x.compareTo(t.element);

		if (compareResult < 0) {
			t.left = insert(x, t.left);// 将x插入左子树中
			
			// 打破平衡
			if (height(t.left) - height(t.right) == 2){
				// LL型(左左型)
				if (x.compareTo(t.left.element) < 0){
					t = rotateWithLeftChild(t);
				}
				// LR型(左右型)
				else{
					t = doubleWithLeftChild(t);
				}
			}
				
		} else if (compareResult > 0) {
			// 将x插入右子树中
			t.right = insert(x, t.right);
			
			// 打破平衡
			if (height(t.right) - height(t.left) == 2){
				// RR型(右右型)
				if (x.compareTo(t.right.element) > 0){
					t = rotateWithRightChild(t);
				}
				else{
					// RL型
					t = doubleWithRightChild(t);
				}
			}
		} else{
			; // 重复数据,什么也不做
		}
			
		t.height = Math.max(height(t.left), height(t.right)) + 1;// 更新高度
		return t;
	}
	

	// 带左子树旋转,适用于LL型
	private AvlNode<T> rotateWithLeftChild(AvlNode<T> k2) {
		AvlNode<T> k1 = k2.left;
		k2.left = k1.right;
		k1.right = k2;
		k2.height = Math.max(height(k2.left), height(k2.right)) + 1;
		k1.height = Math.max(height(k1.left), k2.height) + 1;
		return k1;
	}

	// 带右子树旋转,适用于RR型
	private AvlNode<T> rotateWithRightChild(AvlNode<T> k1) {
		AvlNode<T> k2 = k1.right;
		k1.right = k2.left;
		k2.left = k1;
		k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
		k2.height = Math.max(height(k2.right), k1.height) + 1;
		return k2;
	}

	// 双旋转,适用于LR型
	private AvlNode<T> doubleWithLeftChild(AvlNode<T> k3) {
		k3.left = rotateWithRightChild(k3.left);
		return rotateWithLeftChild(k3);
	}

	// 双旋转,适用于RL型
	private AvlNode<T> doubleWithRightChild(AvlNode<T> k1) {
		k1.right = rotateWithLeftChild(k1.right);
		return rotateWithRightChild(k1);
	}
	
	

	// 找最小
	private AvlNode<T> findMin(AvlNode<T> t) {
		if (t == null)
			return t;

		while (t.left != null)
			t = t.left;
		return t;
	}

	// 找最大
	private AvlNode<T> findMax(AvlNode<T> t) {
		if (t == null)
			return t;

		while (t.right != null)
			t = t.right;
		return t;
	}

	// 搜索(查找)
	private boolean contains(T x, AvlNode<T> t) {
		while (t != null) {
			int compareResult = x.compareTo(t.element);

			if (compareResult < 0)
				t = t.left;
			else if (compareResult > 0)
				t = t.right;
			else
				return true; // Match
		}

		return false; // No match
	}

	// 前序遍历avl树
	private void printTree(AvlNode<T> t) {
		if (t != null) {
			System.out.println(t.element);
			printTree(t.left);
			printTree(t.right);
		}
	}

	// 求高度
	private int height(AvlNode<T> t) {
		return t == null ? -1 : t.height;
	}


	// Test program
	public static void main(String[] args) {
		AVLTree<Integer> t = new AVLTree<Integer>();
		final int NUMS = 100;
		final int GAP = 37;

		for (int i = GAP; i != 0; i = (i + GAP) % NUMS){
			t.insert(i);
		}
			
		t.printTree();
	}
}

至此,三种常见的树就完成了

    原文作者:AVL树
    原文地址: https://blog.csdn.net/sinat_22013331/article/details/51235151
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞