数据结构与算法(Java)之二叉排序树与AVL树
Posted 达少Rising
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法(Java)之二叉排序树与AVL树相关的知识,希望对你有一定的参考价值。
二叉排序数
package com.weeks.tree.binarysorttree;
/**
* @author 达少
* @version 1.0
* 二叉排序树:
* 每个结点的左子结点的值小于当前结点的值,右子结点的大于当前结点的值
* 如果有相同的值则放在左子结点或右子结点(下面的示例放在右子结点上)
*/
public class BinarySortTreeDemo {
public static void main(String[] args) {
int[] arr = {7, 3, 10, 12, 5, 1, 9, 2};
//构建二叉排序数
BinarySortTree binarySortTree = new BinarySortTree();
for (int i = 0; i < arr.length; i++){
binarySortTree.add(new Node(arr[i]));
}
System.out.println("中序遍历二叉排序树~~~");
binarySortTree.infixOrder(binarySortTree.getRoot());
//测试删除叶子结点
// binarySortTree.delNode(2);
// binarySortTree.delNode(5);
// binarySortTree.delNode(9);
// binarySortTree.delNode(12);
binarySortTree.delNode(10);
System.out.println("\\n中序遍历删除结点后的二叉排序树~~~");
binarySortTree.infixOrder(binarySortTree.getRoot());
}
}
//定义二叉排序树类
class BinarySortTree{
//根结点
private Node root;
public Node getRoot() {
return root;
}
public void setRoot(Node root) {
this.root = root;
}
//添加结点
public void add(Node node){
//如果根结点为空,直接将node赋值给根结点
if(root == null){
root = node;
}else{
root.add(node);
}
}
//中序遍历
public void infixOrder(Node root){
if(root == null){
System.out.println("空树不能遍历");
return;
}
root.infixOrder();
}
//查找指定值的结点
public Node search(int value){
if(root == null){//如果是空树直接返回
return null;
}
return root.search(value);
}
//查找指定值的父结点
public Node searchParent(int value){
if(root == null){
return null;
}
return root.searchParent(value);
}
//删除结点
public void delNode(int value){
//判断是否是空树
if(root == null){
System.out.println("空树,没有结点可删除!!!");
return;
}
//查找指定值的结点
Node targetNode = root.search(value);
//当发现没有查找到相应的结点时直接返回
if(targetNode == null){
return;
}
//当查找的二叉排序数只有一个结点,并且刚好是要查找的结点时
if(root.getLeft() == null && root.getRight() == null && root.getData() == value){
//直接将根结点置空
root = null;
return;
}
//查找指定值的父结点
Node parent = root.searchParent(value);
//第一种情况:删除的是叶子结点
if(targetNode.getLeft() == null && targetNode.getRight() == null){
//判断targetNode是parent的左子结点还是有右子结点
//如果parent的左子结点不为空,并且左子结点的值等于value
if(parent.getLeft() != null && parent.getLeft().getData() == value){
parent.setLeft(null);//将左子结点置空
}else if(parent.getRight() != null && parent.getRight().getData() == value){
//如果parent的右子结点不为空,并且右子结点的值等于value
parent.setRight(null);//将右子结点置空
}
}else if(targetNode.getLeft() != null && targetNode.getRight() != null){//第二种情况:删除的结点有左右子树
//有两种方式
//方式一:找到当前结点的右子树的最小值,替换当前当前的结点的值
// int min = searchRightMin(targetNode.getRight());
// targetNode.setData(min);
//方式二:找到当前结点的左子树的最大值,替换当前当前的结点的值
int max = searchLeftMax(targetNode.getLeft());
targetNode.setData(max);
}else{//第三种情况:删除的结点只有左子树或只有右子树
if(targetNode.getLeft() != null){//删除的结点只有左子树
//删除的结点为父节结点的左子树
if(parent.getLeft().getData() == value){
parent.setLeft(targetNode.getLeft());
}else{//删除的结点为父节结点的右子树
parent.setRight(targetNode.getLeft());
}
}else{//删除的结点只有右子树
//删除的结点为父节结点的左子树
if(parent.getLeft().getData() == value){
parent.setLeft(targetNode.getRight());
}else{//删除的结点为父节结点的右子树
parent.setRight(targetNode.getRight());
}
}
}
}
//查找以指定结点为父节的右子树的最小值
public int searchRightMin(Node node){
Node minTarget = node;
//循环查找
while(minTarget.getLeft() != null){
minTarget = minTarget.getLeft();
}
//删除最小值的结点
delNode(minTarget.getData());
return minTarget.getData();
}
//查找以指定结点为父节的右子树的最小值
public int searchLeftMax(Node node){
Node maxTarget = node;
//循环查找
while(maxTarget.getRight() != null){
maxTarget = maxTarget.getRight();
}
//删除最小值的结点
delNode(maxTarget.getData());
return maxTarget.getData();
}
}
//定义结点类
class Node{
private int data;
private Node left;
private Node right;
public Node(int data){
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
//添加结点
public void add(Node node){
if(node == null){//如果添加的结点为空
return;
}
//添加的结点值小于当前结点值
if(node.getData() < this.getData()){
//如果当前结点的左子结点为空
if(this.getLeft() == null){
//将添加的结点挂在当前结点的左子结点下
this.setLeft(node);
}else{//否则左递归
this.left.add(node);
}
}else{//添加的结点值大于或等于当前结点值
//如果当前结点的右子结点为空
if(this.getRight() == null){
//将添加的结点挂在当前结点的右子节点下
this.setRight(node);
}else{//否则右递归
this.right.add(node);
}
}
}
//中序遍历
public void infixOrder(){
//左递归
if(this.left != null){
this.left.infixOrder();
}
//输出当前值
System.out.print(this.data + " ");
//右递归
if(this.right != null){
this.right.infixOrder();
}
}
//根据指定的值查找结点
public Node search(int value){
//判断当前的结点的值是否等于要查找的值
if(this.data == value){
return this;
}
//判断当前的值与查找的值的大小
if(this.data > value){
//向左子结点递归查找
if(this.left == null){
return null;
}
return this.left.search(value);
}else {//向右子结点递归查找
if(this.right == null){
return null;
}
return this.right.search(value);
}
}
//查找指定结点的父节点
public Node searchParent(int value){
//如果要查找的结点是父结点,就返回父结点
if((this.left != null && this.left.data == value) ||
(this.right != null && this.right.data == value)){
return this;
}else{
//如果查找的值小于当前结点的值,并且当前结点的左子结点不为空
if(value < this.data && this.left != null){
return this.left.searchParent(value);
}else if(value >= this.data && this.right != null){
//如果查找的值大于或等于当前结点的值,并且当前结点的右子结点不为空
return this.right.searchParent(value);
}else{
return null;//没有找到父结点
}
}
}
}
AVL树
package com.weeks.tree.avltree;
/**
* @author 达少
* @version 1.0
*
* 平衡二叉树:是一棵二叉排序数,并且左右子树的高度差不大于1
*
* 平衡二叉树的提出是因为二叉排序数存在一定的劣势,向{1,2,3,4,5,6}构建成
* 二叉排序数时,就像单链表一样,两边的二叉树的高度差很大,造成无法体现二叉排
* 序树的快速查找优势,所以提出平衡二叉树
*
*/
public class AVLTreeDemo {
public static void main(String[] args) {
// int[] arr = {4, 3, 6, 5, 7, 8};
// int[] arr = {10, 12, 8, 9, 7, 6};
int[] arr = {10, 11, 7, 6, 8, 9};
//创建AVL树
AVLTree avlTree = new AVLTree();
for(int i : arr){
avlTree.add(new Node(i));
}
//中序遍历AVL树
avlTree.infixOrder(avlTree.getRoot());
//测试计算树的高度
System.out.println("\\navlTree的高度:" + avlTree.getRoot().height());
System.out.println("左子树的高度:" + avlTree.getRoot().leftHeight());
System.out.println("右子树的高度:" + avlTree.getRoot().rightHeight());
System.out.println("当前的根结点:" + avlTree.getRoot().getData());
}
}
//定义二叉排序树类
class AVLTree{
//根结点
private Node root;
public Node getRoot() {
return root;
}
public void setRoot(Node root) {
this.root = root;
}
//添加结点
public void add(Node node){
//如果根结点为空,直接将node赋值给根结点
if(root == null){
root = node;
}else{
root.add(node);
}
}
//中序遍历
public void infixOrder(Node root){
if(root == null){
System.out.println("空树不能遍历");
return;
}
root.infixOrder();
}
//查找指定值的结点
public Node search(int value){
if(root == null){//如果是空树直接返回
return null;
}
return root.search(value);
}
//查找指定值的父结点
public Node searchParent(int value){
if(root == null){
return null;
}
return root.searchParent(value);
}
//删除结点
public void delNode(int value){
//判断是否是空树
if(root == null){
System.out.println("空树,没有结点可删除!!!");
return;
}
//查找指定值的结点
Node targetNode = root.search(value);
//当发现没有查找到相应的结点时直接返回
if(targetNode == null){以上是关于数据结构与算法(Java)之二叉排序树与AVL树的主要内容,如果未能解决你的问题,请参考以下文章