Java学习笔记——二叉树结构实现

二叉树实现基本原理:取第一个数据为保存的根节点,小于等于根节点的数据要放在节点的左子树,大于节点的数据要放在节点的右子树。
在这里插入图片描述
如果要进数据检索,就需要进行节点的判断,时间复杂度是O(logn)。
数据查询三种形式:前序遍历(根-左-右)、中序遍历(左-根-右)、后续遍历(左-右-根)。以中序遍历为例,遍历顺序:10、20、25、30、38、50、80、100.

二叉树的基础实现

实现二叉树的处理之中最为关键性的问题在于数据的保存,而且数据由于牵扯到对象比较的问题,那么一定要有比较器的支持,而比较器首选的一定就是Comparable。

	private String name;
	private int age;

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	@Override
	public int compareTo(Person o) {
		// TODO Auto-generated method stub
		return this.age - o.age;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}

随后如果要想进行数据的保存,首先一定需要有一个节点类。节点类里面由于牵扯到数据的保存问题,所以使用到Comparable(可以区分大小)


package demo;

import java.util.Arrays;
import java.util.Comparator;

public class JavaDemoComparable {
	public static void main(String[] args) {
		BinaryTree<Person> tree = new BinaryTree<Person>();
		tree.add(new Person("Cherry-17", 17));
		tree.add(new Person("Cherry-10", 10));
		tree.add(new Person("Cherry-27", 27));
		tree.add(new Person("Cherry-87", 87));
		tree.add(new Person("Cherry-57", 57));
		tree.add(new Person("Cherry-37", 37));
		System.out.println(Arrays.toString(tree.toArray()));
	}
}

class PersonCompatator implements Comparator<Person> {
	@Override
	public int compare(Person o1, Person o2) {
		// TODO Auto-generated method stub
		return o1.getAge() - o2.getAge();
	}
}

/**
 * 实现二叉树操作
 * 
 * @author
 *
 * @param <T> 要进行二叉树的实现
 */
class BinaryTree<T extends Comparable<T>> {
	private class Node {
		private Comparable<T> data;// 存放Comparable,可以比较大小
		private Node parent;// 保存父节点
		private Node left;// 保存左子树
		private Node right;// 保存右子树

		public Node(Comparable<T> data) {// 构造方法直接进行数据的存储
			this.data = data;
		}

		/**
		 * 实现节点数据的实当位置的存储
		 * 
		 * @param newNode 创建新的节点
		 */
		public void addNode(Node newNode) {
			if (newNode.data.compareTo((T) this.data) <= 0) {// 比当前节点数据小
				if (this.left == null) {// 没有左子树
					this.left = newNode;// 保存左子树
					newNode.parent = this;// 保存父节点
				} else {
					this.left.addNode(newNode);// 继续向下判断
				}
			} else {// 比根节点的数据大
				if (this.right == null) {
					this.right = newNode;
					newNode.parent = this;
				} else {
					this.right.addNode(newNode);
				}
			}
		}
		/**
		 * 实现所有数据的获取处理,按照中序遍历的形式来完成
		 */
		public void toArrayNode(){
			if(this.left != null) {
				this.left.toArrayNode();
			}
			BinaryTree.this.returnData[BinaryTree.this.foot++] = this.data ;
			if (this.right != null) {
				this.right.toArrayNode();
			}
		}
	}

	// ---------一下为二叉树的功能实现----------
	private Node root;// 保存根节点
	private int count;// 保存数据个数
	private Object [] returnData; //返回数据
	private int foot = 0;//脚标控制
	/**
	 * 进行数据的保存
	 * 
	 * @param data 要保存的数据内容
	 * @exception NullPointerException 保存数据为空时抛出异常
	 */
	public void add(Comparable<T> data) {
		if (data == null) {
			throw new NullPointerException("保存的数据不允许为空	");
		}
		// 所有的数据本身不具备有节点关系的匹配,那么一定要将其包装在Node类之中
		Node newNode = new Node(data);
		if (this.root == null) {// 现在没有根节点
			this.root = newNode;
		} else {// 需要为其保存到一个合适的节点
			this.root.addNode(newNode);// 交由Node类负责处理
		}
		this.count++;
	}
	/**
	 * 以对象数组的形式返回全部数据,如果没有数据返回null
	 * @return 返回全部数据
	 */
	public Object[] toArray() {
		if(this.count == 0) {
			return null;
		}
		this.returnData = new Object[this.count];//保存长度为数组长度
		this.foot = 0;//脚标清零
		this.root.toArrayNode();//直接通过Node类负责
		return this.returnData ;
	}

}

class Person implements Comparable<Person> {
	private String name;
	private int age;

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	@Override
	public int compareTo(Person o) {
		// TODO Auto-generated method stub
		return this.age - o.age;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]\n";
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}
#[Person [name=Cherry-10, age=10]
, Person [name=Cherry-17, age=17]
, Person [name=Cherry-27, age=27]
, Person [name=Cherry-37, age=37]
, Person [name=Cherry-57, age=57]
, Person [name=Cherry-87, age=87]
]

载进行数据添加的时候只是实现了节点关系的保存,而这种关系保存后的结果就是所有的数据都是有序排列。

数据删除

二叉树之中的数据删除操作是非常复杂的,因为在进行数据删除的时候需要考虑的情况较多:
1:如果待删除节点没有子节点,那么直接删掉即可;
在这里插入图片描述

2:如果待删除结点只有一个子节点,那么直接删掉,并用其子节点取顶替它;
此时考虑两种情况:

  • 只有一个左子树。
    在这里插入图片描述

  • 只有一个右子树。
    在这里插入图片描述

3:如果待删除节点有两个子节点,这种情况比较复杂:首选找出它的后继节点,然后处理"后继节点"和"被删除节点的父节点"之间的关系,最后处理“后继节点的子节点”和“被删除节点的子节点”之间的关系。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值