平衡二叉树 记录

这篇博客详细介绍了如何使用JAVA编程实现平衡二叉树,并通过JFrame进行结果展示。
摘要由CSDN通过智能技术生成

JAVA实现,以及JFrame 结果展示

package com.example.fndemo.tree;

import java.util.Stack;


/**
 * 平衡二叉树,旋转
 * @author zq
 * @date 2020-09-08  18:20
 */
public class AVLTree {
	Node<Integer> rootNode;
	public static void main(String[] args) {
		Integer[] datas = {2, 1, 0, 3, 4, 5, 6, 9, 8, 7};
		AVLTree avlTree = new AVLTree();
		for (Integer data : datas) {
			avlTree.insert(data);
		}
		avlTree.midTraversing();
		System.out.println();
		// 窗口展示
		DrawTree drawTree = new DrawTree(avlTree.rootNode);
	}
	public void insert(Integer data) {
		if (null == rootNode) {
			rootNode = new Node<Integer>(data);
			return;
		}
		Node insert = new Node<Integer>(data).insert(rootNode);
		this.adjust(insert);
		
		System.out.println("是否插入成功:" + (null != insert.getParent()) + " 当前key:" + insert.getKey() + " 父亲key:" + (null == insert.getParent() ? null : insert.getParent().getKey()));
	}
	
	public Node<Integer> getRootNode() {
		return rootNode;
	}
	
	//平衡检查以及调整
	public  void adjust(Node leafNode){
		//回溯四层,判断是否发生失衡
		Node current = leafNode;
		int index=1;
		while (current!=null&&index<5){
			if (current.getBalance() > 1) {
				if (current.getLeftChild().getBalance() < 0) {
					rotateLeft(current.getLeftChild());
				}
				rotateRight(current);
				return;
			}
			if (current.getBalance() < -1) {
				if (current.getRightChild().getBalance() > 0) {
					rotateRight(current.getRightChild());
				}
				rotateLeft(current);
				return;
			}
			current=current.getParent();
			index++;
		}
		
	}
	
	//当前节点左旋
	public void rotateLeft(Node  currentNode){
		Node parent = currentNode.getParent();
		Node rightChild = currentNode.getRightChild();
		Node rightChildLeftChild = rightChild.getLeftChild();
		
		currentNode.setParent(rightChild);
		currentNode.setRightChild(rightChildLeftChild);
		
		rightChild.setParent(parent);
		rightChild.setLeftChild(currentNode);
		
		if (parent != null) {
			if (parent.getRightChild().equals(currentNode)) {
				parent.setRightChild(rightChild);
			}
			if (parent.getLeftChild().equals(currentNode)) {
				parent.setRightChild(rightChild);
			}
		}else{
			rootNode=rightChild;
		}
		if (null != rightChildLeftChild) {
			rightChildLeftChild.setParent(currentNode);
		}
		
		
	}
	
	//当前节点右旋
	public void rotateRight(Node  currentNode){
		Node parent = currentNode.getParent();
		Node leftChild = currentNode.getLeftChild();
		Node leftChildRightChild = leftChild.getRightChild();
		leftChild.setRightChild(currentNode);
		leftChild.setParent(parent);
		currentNode.setParent(leftChild);
		currentNode.setLeftChild(leftChildRightChild);
		if (parent != null) {
			if (parent.getRightChild()!=null&&parent.getRightChild().equals(currentNode)) {
				parent.setRightChild(leftChild);
			}
			if (parent.getLeftChild()!=null&&parent.getLeftChild().equals(currentNode)) {
				parent.setRightChild(leftChild);
			}
		}else {
			rootNode=leftChild;
		}
		if (null != leftChildRightChild) {
			leftChildRightChild.setParent(currentNode);
		}
		
	}
	
	//非递归前序序遍历
	public void preTraversing() {
		Node currentNode = rootNode;
		Node preNode = currentNode;
		Stack<Node> nodeStack = new Stack<>();
		nodeStack.push(rootNode);
		//方法二
		while (!nodeStack.isEmpty()) {
			currentNode = nodeStack.peek();
			//什么时候访问并退栈
			if (currentNode != null) {
				System.out.print(currentNode.getData() + "  ");
				nodeStack.pop();
			}
			//什么入栈
			if (currentNode != null && currentNode.getRightChild() != null) {
				nodeStack.push(currentNode.getRightChild());
			}
			if (currentNode != null && currentNode.getLeftChild() != null) {
				nodeStack.push(currentNode.getLeftChild());
			}
			
		}
		//方法一
		//		while (!nodeStack.isEmpty()) {
		//			currentNode = nodeStack.pop();
		//			if (currentNode == null) {
		//				continue;
		//			}
		//			System.out.print(currentNode.getData() + "  ");
		//			if (currentNode.getRightChild() != null) {
		//				nodeStack.push(currentNode.getRightChild());
		//			}
		//			if (currentNode.getLeftChild() != null) {
		//				nodeStack.push(currentNode.getLeftChild());
		//			}
		//		}
	}
	
	//非递归中序遍历
	public void midTraversing() {
		Node currentNode = rootNode;
		Node preNode = rootNode;
		Stack<Node> nodeStack = new Stack<>();
		nodeStack.push(rootNode);

		//		方法二
		while (!nodeStack.isEmpty()) {
			while (currentNode != null && currentNode.getLeftChild() != null) {
				currentNode = currentNode.getLeftChild();
				nodeStack.push(currentNode);
			}
			
			currentNode = nodeStack.pop();
			System.out.print(currentNode.getData() + "  ");
			currentNode = currentNode.getRightChild();
			if (currentNode != null) {
				nodeStack.push(currentNode);
			}
		}

	}
	
	//非递归后序序遍历,如果当前节点的左右节点都被访问则访问本节点
	public void postTraversing() {
		Node currentNode = rootNode;
		Node preNode = rootNode;
		Stack<Node> nodeStack = new Stack<>();
		nodeStack.push(rootNode);
		
		while (!nodeStack.isEmpty()) {
			currentNode = nodeStack.peek();
			//什么时候访问并退栈
			if ((currentNode.getLeftChild() == null && currentNode.getRightChild() == null) || currentNode.getRightChild() == preNode || currentNode.getLeftChild() == preNode) {
				System.out.print(currentNode.getData() + "  ");
				preNode = currentNode;
				nodeStack.pop();
				continue;
			}
			//什么时候入栈
			if (currentNode.getRightChild() != null) {
				nodeStack.push(currentNode.getRightChild());
			}
			if (currentNode.getLeftChild() != null) {
				nodeStack.push(currentNode.getLeftChild());
			}
			
		}
	}
}


package com.example.fndemo.tree;

import javax.swing.*;
import java.awt.*;
import java.util.HashMap;
import java.util.Stack;


/**
 * 二叉树 绘图
 * @author zq
 * @date 2020-09-08  18:23
 */

public class DrawTree extends JFrame {
	PositionMap positionMap;
	
	public DrawTree(Node root) throws HeadlessException {
		this.setSize(800, 600);
		this.setTitle("窗口测试");
		this.setVisible(true);
		this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		this.setLocationRelativeTo(null);
		this.setContentPane(new EVLDrawPanel(root));
		double rate = Math.tan(Math.toRadians(35));
		//地图参数
		this.positionMap = new PositionMap(root,100,500,30,rate);
	}
	
	public  class Point {
		public int x;
		public int y;
		
		public Point(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}
	
	class EVLDrawPanel extends JPanel {
		Node root;
		
		public EVLDrawPanel(Node root) {
			this.root = root;
		}
		
		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			drawTree(g);
		}
		
		public void drawTree(Graphics g) {
			Node currentNode = root;
			Stack<Node> nodeStack = new Stack<>();
			nodeStack.push(root);
			//方法二
			while (!nodeStack.isEmpty()) {
				currentNode = nodeStack.peek();
				//什么时候访问并退栈
				if (currentNode != null) {
					drawCycle(currentNode, g);//绘图
					nodeStack.pop();
				}
				//什么入栈
				if (currentNode != null && currentNode.getRightChild() != null) {
					nodeStack.push(currentNode.getRightChild());
				}
				if (currentNode != null && currentNode.getLeftChild() != null) {
					nodeStack.push(currentNode.getLeftChild());
				}
				
			}
		}
		
		public void drawCycle(int x, int y, int radius, Graphics g) {
			g.drawOval(x - radius, y - radius, radius * 2, radius * 2);
		}
		
		public void drawCycle(Node node, Graphics g) {
			int radius = 5;//默认半径
			Point point = positionMap.get(node, root);
			drawCycle(point.x, point.y, radius, g);
			g.drawString(String.valueOf(node.getData()), point.x + radius + 3, point.y + radius / 2);
			if (node.getParent() != null) {
				Point father = positionMap.get(node.getParent(), root);
				g.drawLine(point.x, point.y, father.x, father.y);
			}
		}
		
	}
	
	
	/**
	 * 二叉树 节点坐标地图
	 */
	class PositionMap {
		HashMap<Integer, HashMap<Integer, Point>> map = new HashMap<>();
		public int maxLevel = 0;
		
		PositionMap(Node rootNode,int startX, int startY, int radiusMargin,double rate) { //生成节点地图
			this.maxLevel = rootNode.getHeight();
			generator(startX, startY, radiusMargin,rate);
		}
		
		/**
		 *
		 * @param startX 最左下角节点坐标x
		 * @param startY 最左下角节点坐标y
		 * @param radiusMargin 兄弟节点圆心距离
		 * @param rate 叶子节点开始高度增长比率 double rate = Math.tan(Math.toRadians(35));
		 */
		void generator(int startX, int startY, int radiusMargin,double rate) {
			
			for (int level = this.maxLevel; level > 0; level--) {
				HashMap<Integer, Point> item = new HashMap<>();
				map.put(level, item);
				int nodeNumber = (int) Math.pow(2, level - 1);
				for (int i = 0; i < nodeNumber; i++) {
					item.put(i, new Point(startX + radiusMargin * i, startY));
				}
				startX = startX + radiusMargin / 2;
				radiusMargin = radiusMargin * 2;
				int h = (int) Math.round(rate * radiusMargin / 2);
				startY = startY - h;
			}
			
		}
		
		public Point get(Integer level, Integer index) {
			assert level > -1 && level <= maxLevel;
			return map.get(level).get(index);
		}
		
		public Point get(Node node, Node rootNode) {
			assert null != node;
			return pointCalc(node, rootNode);
		}
		
		//坐标计算,二分查找定位
		public Point pointCalc(Node node, Node rootNode) {
			//中轴
			int index = 0;
			int level = 1;
			Node currentNode = rootNode;
			while (currentNode != null) {
				if (currentNode.equals(node)) {
					break;
				}
				if (currentNode.getKey().intValue() > node.getKey().intValue()) {
					currentNode = currentNode.getLeftChild();
					index = (index + 1) * 2 - 2;
					level++;
				}
				if (currentNode.getKey().intValue() < node.getKey().intValue()) {
					currentNode = currentNode.getRightChild();
					index = (index + 1) * 2 - 1;
					level++;
				}
			}
			if (currentNode == null) {
				System.out.println("节点未找到");
				return null;
			}
			return get(level, index);
		}
	}
	
}


package com.example.fndemo.tree;

import java.util.Objects;


/**
 * @author zq
 * @date 2020-09-08  18:20
 */
class Node<T> {
	private T data;
	private Number key;
	private Node parent;
	private Node leftChild;
	private Node rightChild;
	
	public Node(T data) {
		assert null != data : "节点数据Null";
		this.data = data;
		this.key = data instanceof Number ? (Number) data : data.hashCode();
	}
	
	
	public Node insert(Node rootNode) {
		if (null == rootNode) {
			return this;
		}
		if (this.key.intValue() == rootNode.getKey().intValue()) {
			throw new RuntimeException("排序树中不允许key值相等的存在");
		}
		if (this.key.intValue() < rootNode.getKey().intValue()) {
			if (rootNode.getLeftChild() == null) {
				rootNode.setLeftChild(this);
				this.setParent(rootNode);
				
				return this;
			}
			this.insert(rootNode.getLeftChild());
		}
		
		if (this.key.intValue() > rootNode.getKey().intValue()) {
			if (rootNode.getRightChild() == null) {
				rootNode.setRightChild(this);
				this.setParent(rootNode);
				return this;
			}
			this.insert(rootNode.getRightChild());
		}
		return this;
	}

	
	public T getData() {
		return data;
	}
	
	public Node setData(T data) {
		this.data = data;
		return this;
	}
	
	public Number getKey() {
		return key;
	}
	
	public Node setKey(Number key) {
		this.key = key;
		return this;
	}
	
	public int getHeight() {
		return Math.max(null == leftChild ? 0 : leftChild.getHeight(), null == rightChild ? 0 : rightChild.getHeight()) + 1;
	}
	public int getBalance() {
		return (null == leftChild ? 0 : leftChild.getHeight())-(null == rightChild ? 0 : rightChild.getHeight());
	}
	
	public Node getParent() {
		return parent;
	}
	
	public Node setParent(Node parent) {
		this.parent = parent;
		return this;
	}
	
	public Node getLeftChild() {
		return leftChild;
	}
	
	public Node setLeftChild(Node leftChild) {
		this.leftChild = leftChild;
		return this;
	}
	
	public Node getRightChild() {
		return rightChild;
	}
	
	public Node setRightChild(Node rightChild) {
		this.rightChild = rightChild;
		return this;
	}
	
	@Override
	public boolean equals(Object o) {
		if (this == o)
			return true;
		if (o == null || getClass() != o.getClass())
			return false;
		Node<?> node = (Node<?>) o;
		return data.equals(node.data);
	}
	
	@Override
	public int hashCode() {
		return Objects.hash(data, key, parent, leftChild, rightChild);
	}
	
	public void preTraversing() {
		System.out.print(this.data);
		System.out.print("  ");
		if (this.getLeftChild() != null) {
			this.getLeftChild().preTraversing();
		}
		if (this.getRightChild() != null) {
			this.getRightChild().preTraversing();
		}
	}
	
	public void midTraversing() {
		
		if (this.getLeftChild() != null) {
			this.getLeftChild().midTraversing();
		}
		System.out.print(this.data);
		System.out.print("  ");
		if (this.getRightChild() != null) {
			this.getRightChild().midTraversing();
		}
	}
	
	public void postTraversing() {
		
		if (this.getLeftChild() != null) {
			this.getLeftChild().postTraversing();
		}
		if (this.getRightChild() != null) {
			this.getRightChild().postTraversing();
		}
		System.out.print(this.data);
		System.out.print("  ");
	}
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值