`
sudongfeng
  • 浏览: 8190 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

平衡二叉树的java实现

阅读更多

平衡二叉树求解步骤:


(1)插入节点
(2)找出不平衡因子,在插入过程中找到不平衡因子
(3)旋转,根据不平衡因子判断旋转方式
(4)生成新的平衡二叉树


在求解过程中,最重要步骤详解:


找出不平衡因子(也就是左右子树的高度差值为2或-2的情况)


方法1步骤:
a.节点中添加两个属性,左子树高度、右子树高度。
b.插入节点
c.返回的过程中动态的计算插入节点过程中经过的节点的左子树或右子树的高度。并计算各个节点的因子.
d.当节点因子为0时,返回过程中停止计算树的高度。当节点因子为2或-2时,即为不平衡因子,进行旋转
e.所有的旋转分为四种类型:LL顺时针旋转, RR逆时针旋转, LR先逆时针、然后顺时针,RL先顺时针在逆时针,旋转过程中调整各个节点的左右子树高度
f.旋转完成周调整,父节点的对应的左子树或者右子树的高度


这个方法通过给节点添加左右子树高度属性的方法,优点:节点的左右子树,只需要管理自己的高度,分而自治减少复杂性。代码中实现的是这个方法

 

 

package ProductCosume;

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

public class BinaryTreeTest {

	enum BalanceFactory {
		LeftFactory(1), RightFactory(-1), EqualFacotry(0), LeftLossBalanceFactory(
				2), RightLossBalanceFactory(-2), InvalideFactory(-3);
		int value = 0;

		private BalanceFactory(int value) {
			this.value = value;
		}
	}

	// 节点
	static class Node {

		public Node(int value) {
			key = value;
		}

		int key;
		private BalanceFactory af = BalanceFactory.EqualFacotry;

		Node leftNode = null;
		Node rightNode = null;
		Node parentNode = null;

		int leftNodeHeight = 0;
		int rightNodeHeight = 0;

		public int getNodeHeight() {
			return leftNodeHeight > rightNodeHeight ? leftNodeHeight
					: rightNodeHeight;
		}

		// 获取平衡因子
		public BalanceFactory getAf() {
			int factor = leftNodeHeight - rightNodeHeight;
			BalanceFactory resultBalanceFactory = null;
			switch (factor) {
			case 0:
				resultBalanceFactory = BalanceFactory.EqualFacotry;
				break;
			case 1:
				resultBalanceFactory = BalanceFactory.LeftFactory;
				break;
			case -1:
				resultBalanceFactory = BalanceFactory.RightFactory;
				break;
			case 2:
				resultBalanceFactory = BalanceFactory.LeftLossBalanceFactory;
				break;
			case -2:
				resultBalanceFactory = BalanceFactory.RightLossBalanceFactory;
				break;
			default:
				resultBalanceFactory = BalanceFactory.InvalideFactory;
				break;
			}
			af = resultBalanceFactory;
			return af;
		}
	}

	boolean isTaller = false;

	// 插入新的节点
	public Node inserNode(Node tree, Node node) {

		if (tree == null) {
			tree = node;
			return tree;
		}

		if (tree.key == node.key)
			return tree;

		Node parentNode = tree.parentNode;

		if (tree.key > node.key) {
			// 左路插入
			if (tree.leftNode == null) {
				tree.leftNode = node;
				node.parentNode = tree;
				tree.leftNodeHeight = tree.leftNodeHeight + 1;
				tree.getAf();
				isTaller = true;
				System.out.println("root:" + tree.key + " left insert "
						+ "  node:" + node.key);
				if (tree.getAf() == BalanceFactory.EqualFacotry)
					isTaller=false;
				return tree;
			} else {
				inserNode(tree.leftNode, node);
				if(isTaller){
					tree.leftNodeHeight = tree.leftNode.getNodeHeight() + 1;
					if (tree.getAf() == BalanceFactory.EqualFacotry)
						isTaller = false;
				}
			}
		} else {
			// 右路插入
			if (tree.rightNode == null) {
				tree.rightNode = node;
				node.parentNode = tree;
				tree.rightNodeHeight += 1;
				isTaller = true;
				System.out.println("root:" + tree.key + " right insert "
						+ "  node:" + node.key);
				if (tree.getAf() == BalanceFactory.EqualFacotry)
					isTaller=false;
				return tree;
			} else {
				inserNode(tree.rightNode, node);
				if(isTaller){
					tree.rightNodeHeight = tree.rightNode.getNodeHeight() + 1;
					if (tree.getAf() == BalanceFactory.EqualFacotry)
						isTaller = false;
				}
			}
		}

		if (isTaller) {
			boolean isRightNode = false;
			
			//非常重要:通过父亲类来判断插入到那一边
			if(parentNode!=null){
				if(parentNode.leftNode!=null&&parentNode.leftNode.key==tree.key)
					isRightNode = false;
				else
					isRightNode= true;
			}
			if (BalanceFactory.LeftLossBalanceFactory == tree.getAf()
					|| BalanceFactory.RightLossBalanceFactory == tree.getAf()) {
				
				tree = rotateTree(tree);
				if (parentNode != null){
					if(isRightNode)
						parentNode.rightNode = tree;
					else
						parentNode.leftNode = tree;
				}
			}
		}

		return tree;
	}

	// 破坏平衡旋转平衡二叉树
	public Node rotateTree(Node tree) {
		Node rootNode = tree;
		if (rootNode == null)
			return tree;
		System.out.println("旋转前------------------------------");
		widthSearch(rootNode);
		Node secondNode = null;

		if (rootNode.getAf() == BalanceFactory.RightLossBalanceFactory) {

			// 右边失去平衡
			secondNode = rootNode.rightNode;
			if (secondNode.af == BalanceFactory.RightFactory) {
				// RR类型
				System.out.println("RR类型旋转-------------");
				antiClockWiseRoate(tree);
			}

			if (secondNode.af == BalanceFactory.LeftFactory) {
				// RL类型的
				System.out.println("RL类型旋转-------------");
				clockwiseRotate(secondNode);
				secondNode = secondNode.parentNode;//注意,第二个点变化了
				widthSearch(secondNode);
				rootNode.rightNode = secondNode;
				antiClockWiseRoate(rootNode);
			}

		} else {
			// 左边失去平衡
			secondNode = rootNode.leftNode;
			if (secondNode.af == BalanceFactory.LeftFactory) {
				// LL类型
				System.out.println("LL类型旋转-------------");
				clockwiseRotate(tree);
			}

			if (secondNode.af == BalanceFactory.RightFactory) {
				// LR类型的
				System.out.println("LR类型旋转-------------");
				antiClockWiseRoate(secondNode);
				secondNode = secondNode.parentNode;//注意,第二个点变化了
				rootNode.leftNode = secondNode;
				widthSearch(secondNode);
				clockwiseRotate(tree);
			}
		}

		System.out.println("旋转后------------------------------");
		widthSearch(secondNode);

		System.out.println("旋转结束------------------------------");
		return secondNode;
	}

	// LL树 顺时针旋转
	public void clockwiseRotate(Node tree) {
		if (tree == null || tree.leftNode == null)
			return;

		Node secondNode = tree.leftNode;
		secondNode.parentNode = tree.parentNode;
		tree.parentNode = secondNode;
		tree.leftNode = secondNode.rightNode;
		secondNode.rightNode = tree;

		tree.leftNodeHeight = secondNode.rightNodeHeight;
		secondNode.rightNodeHeight = tree.getNodeHeight() + 1;
	}

	// RR树 逆时针旋转
	public void antiClockWiseRoate(Node tree) {
		if (tree == null || tree.rightNode == null)
			return;

		Node secondNode = tree.rightNode;
		secondNode.parentNode = tree.parentNode;
		tree.parentNode = secondNode;
		tree.rightNode = secondNode.leftNode;
		secondNode.leftNode = tree;

		tree.rightNodeHeight = secondNode.leftNodeHeight;
		secondNode.leftNodeHeight = tree.getNodeHeight() + 1;

	}

	public static void main(String[] args) {
		BinaryTreeTest binaryTreeTest = new BinaryTreeTest();
		Node node = new Node(8);
		binaryTreeTest.inserNode(null, node);

		Node node2 = new Node(10);
		Node node3 = new Node(16);
		Node node4 = new Node(6);
		Node node5 = new Node(3);
		Node node6 = new Node(78);
		Node node7 = new Node(9);
		Node node8 = new Node(24);
		Node node9 = new Node(15);
		Node node10 = new Node(19);
		Node node11 = new Node(2);
		Node node12 = new Node(45);
		Node node13 = new Node(65);
		Node node14 = new Node(78);
		Node node15 = new Node(102);
		Node node16 = new Node(1);
		Node node17 = new Node(32);
		Node node18 = new Node(33);

		Node root = binaryTreeTest.inserNode(node, node2);
		root = binaryTreeTest.inserNode(root, node3);
		root = binaryTreeTest.inserNode(root, node4);
		root = binaryTreeTest.inserNode(root, node5);
		root = binaryTreeTest.inserNode(root, node6);
		root = binaryTreeTest.inserNode(root, node7);
		root = binaryTreeTest.inserNode(root, node8);
		root = binaryTreeTest.inserNode(root, node9);
		root = binaryTreeTest.inserNode(root, node10);
		root = binaryTreeTest.inserNode(root, node11);
		root = binaryTreeTest.inserNode(root, node12);

		System.out.println("------------------------------");
		binaryTreeTest.widthSearch(root);

		root = binaryTreeTest.inserNode(root, node13);
		root = binaryTreeTest.inserNode(root, node14);
		root = binaryTreeTest.inserNode(root, node15);
		root = binaryTreeTest.inserNode(root, node16);
		root = binaryTreeTest.inserNode(root, node17);
		root = binaryTreeTest.inserNode(root, node18);
		binaryTreeTest.widthSearch(root);
	}

	public void widthSearch(Node node) {
		if (node != null) {
			System.out.println("node:" + node.key);
			widthSearch(node.leftNode);
			widthSearch(node.rightNode);
		}
	}

}



 

 

方法2:不需要左右子树的高度属性,每次计算各自的平衡因子

 

 

 

 

分享到:
评论

相关推荐

    平衡二叉树

    平衡二叉树Java实现,平衡二叉树Java实现,平衡二叉树Java实现,平衡二叉树Java实现,

    java 实现平衡二叉树

    文档中是我自己实现的用java语言实现(1)判断给定的二叉树是否平衡;(2)二叉树插入新数据后,如果失衡自我旋转调整的方法。

    java平衡二叉树

    在Java中实现平衡二叉树,通常需要以下步骤: 1. **定义节点类**:首先,我们需要定义一个表示树节点的类,包含键值(key)、左子节点(left)、右子节点(right)以及可能的平衡因子(balance factor),用于判断...

    java-平衡二叉树AVL的实现

    在Java编程领域,平衡二叉树(特别是AVL树)是一种高效的数据结构,它通过保持树的高度平衡来确保查找、插入和删除操作的最优化。AVL树是最早被提出的自平衡二叉搜索树,由G. M. Adelson-Velsky和E. M. Landis于1962...

    java 二叉排序树与平衡二叉树的实现

    10. **algorithm**:可能是一个包含各种算法实现的文件夹,如二叉排序树和平衡二叉树的插入、查找和删除算法。 通过这个课程设计,学生将深入理解二叉排序树和平衡二叉树的概念,以及它们在实际问题中的应用,同时...

    JAVA实现读取TXT文件并建立平衡二叉树及查找功能

    在本文中,我们将深入探讨如何使用Java编程语言从TXT文件中读取数据,构建一个平衡二叉树(例如AVL树或红黑树),并实现查找功能以及打印节点的访问路径。首先,让我们理解每个部分的基本概念。 1. **TXT文件读取**...

    java下非递归实现平衡二叉树

    平衡二叉树的一个常见类型是AVL树,本文将深入探讨如何在Java下非递归地实现AVL树,并介绍其增删查改的基本操作。 **AVL树的特性:** 1. 左右子树高度差不超过1。 2. 对于任意节点,其左子树和右子树的高度最大差别...

    平衡二叉树 java源码.zip

    在Java中实现平衡二叉树,通常会用到AVL树或红黑树等算法。 AVL树是最早被提出的一种自平衡二叉搜索树,由G. M. Adelson-Velsky和E. M. Landis于1962年提出,因此得名AVL树。AVL树的关键特性是保持平衡因子为-1、0...

    数据结构-二叉树 JAVA语言实现

    总结来说,理解和掌握二叉树以及如何用JAVA实现它们是成为优秀程序员的关键一步。通过实践,你可以更深入地了解数据结构的精髓,提升算法设计能力,并为解决复杂问题打下坚实基础。对于初学者,可以从简单的二叉树...

    中南民族大学平衡二叉树

    在中南民族大学的数据结构课程设计中,学生可能会被要求实现这两种平衡二叉树的数据结构,包括基本操作(如插入、删除和查找)以及平衡调整算法。此外,可能还会涉及到对这两种树的性能分析,比较它们在不同场景下的...

    数据结构 二叉树 java图形界面实现

    二叉树的主要类型包括满二叉树、完全二叉树和平衡二叉树(如AVL树和红黑树)。 二叉树的基本操作主要包括: 1. 插入节点:在二叉树中插入一个新节点,需要找到合适的位置,通常根据二叉树的性质(如二叉搜索树)...

    平衡二叉树数据结构课程设计

    在课程设计中,我们将学习如何实现这两种平衡二叉树的数据结构,包括初始化、插入、删除和查找等基本操作。此外,我们还将讨论平衡条件的检测以及何时需要进行旋转操作。对于AVL树,这将涉及单旋和双旋的实现;对于...

    广工数据结构课程设计大作业-平衡二叉树-Java实现(数据结构期末)

    在Java实现过程中,首先需要定义一个表示树节点的类,包含节点值、左右子节点引用以及额外的平衡因子(用于判断是否需要旋转)。然后,创建一个树的类,提供上述操作的接口和实现。插入和删除操作通常会涉及递归,而...

    基于java实现的平衡二叉树源码.zip

    在给定的压缩包"基于java实现的平衡二叉树源码.zip"中,可能包含了AVL树或红黑树的Java实现。`README.md`文件通常会提供项目的简介、如何构建和运行代码的指导,以及任何依赖项的说明。`pom.xml`文件是Maven项目对象...

    基于JAVA开发的二叉树课程设计与实现

    - 二叉树类型:满二叉树、完全二叉树、平衡二叉树(如AVL树、红黑树)等。 - 特殊操作:插入、删除、查找等操作在二叉树中的实现。 2. **Java编程**: - 类与对象:二叉树的实现通常通过创建一个表示节点的类,...

    java前序中序构造二叉树

    4. **Java实现**: 在Java中,可以定义一个二叉树节点类(`TreeNode`),包含一个值字段和左右子节点的引用。然后通过递归方法,根据给定的前序和中序遍历数组,创建对应的二叉树结构。 5. **后序遍历**: 在构造...

    java编写的二叉树的各种操作(包括二叉排序树和平衡二叉树)

    本压缩包文件“DataStructTest”包含了对二叉排序树和平衡二叉树的实现,旨在帮助学习者深入理解这些概念。 首先,让我们了解一下二叉树的基本概念。二叉树是由节点构成的树形结构,每个节点最多有两个子节点,分别...

    java实现二叉树最佳方法

    此外,二叉树的应用还包括在构建二叉搜索树、平衡二叉树、堆等特殊二叉树结构时使用,这些结构在数据库索引、优先级队列等场景中有广泛的应用。 总之,Java实现二叉树的最佳方法依赖于对二叉树性质的深入理解以及对...

    数据结构二叉树专题java代码实现

    以上仅是二叉树操作的一部分,实际的`BinaryTree.java`文件可能包含更多功能,如层序遍历、最小(最大)元素查找、平衡二叉树操作等。二叉树的性质和操作是数据结构和算法课程的重点,熟练掌握这些概念和实现对于...

Global site tag (gtag.js) - Google Analytics