二叉树
主要包括根节点,左孩子和右孩子
二叉排序的基本原理:
把第一个元素作为根节点,之后的元素如果比第一个元素大,放到右面,否则放到左面
算法步骤
先声明一个节点类Node,里面有根节点,左孩子和右孩子
然后创建一个构造函数里面放的是根节点
然后写一个添加节点的方法,我们给他起名为add方法
先把创建树的代码写一下
class Node,声明一个节点类Node
里面有根节点,左右孩子,然后创建一个根节点的构造方法,方便后面使用。
class newTree{
class Node{
int data;//根节点
Node left;//左孩子
Node right;//右孩子
public Node(int data) {//构造方法
this.data = data;
}
}
}
举个例子
这个是一个数组,首先我们把第一个元素拿出来作为二叉树的根节点,然后看第二个元素5,大于根节点,放在根节点的右面。
然后在看下一个元素2,小于根节点放在根节点的左面。
在看下一个元素8,比根节点大,放在右面,然后在和右面的元素5比较,比5大放在5这个节点的右边。
在看下一个元素4,比根节点大,放在右面,比右面二个节点5小,所以放在5的左面。
下一个元素6,大于根节点,并且大于右面第二个节点5,但是小于5右面的节点8,所以这个元素放在5元素的左节点4的右边。
以此类推,最后就是这个样子
接下来我们要做的事情就是想我们刚才举的例子一样把数组中的元素创建成一个二叉树。
首先放第一个元素的时候要创建根节点,如果不是第一次放入,我们需要两个指针,p和parent,初始化都指向根节点。
那么这两个的指针分别是什么作用,p指针可以理解成是探底的,找到该放元素的位置结束循环,Parent指针永远指向p指针的上一个元素,p.next就是元素要放的位置。
比如现在有一个新的节点1 ,把他放入到二叉树中,我们可以看到1比根节点小,那么他应该放到3的左面,首先移动p指针,他去比较,找到1因该放到的位置。
现在p指向这个位置,然后2节点比1大,然后移动p指针,这次parent指针要移动了,现在是这个样子
p指针找到要放的位置,然后结束循环,然后parent指针的下一个元素就是1要放的位置,我们现在找到元素要放的位置,那么要如何放进去,这个时候我们要进行判断,看数据要放在这个节点的左面还是右面,那么就要进行比较。
private Node root;//根节点
public void add(int data) {
Node newNode = new Node(data);//新的根节点
//第一次放入-->要创建根节点
if(root == null) {
root = newNode;
return ;
}
//不是第一次放入 -->双指针
Node p = root;//探底,结束循环
Node partent = root;//作用指向p的上一级
//作用找到元素的位置
while(p != null) {
partent = p;
if(data > p.data) {//大于在右边
p = p.right;
}else {
p = p.left;//否则在左边
}
}
//将元素放进去
if(data > partent.data) {
partent.right = newNode;
}else {
partent.left = newNode;
}
}
二叉树有三种遍历方式,前序,中序和后序
前序遍历:根左右
中序遍历:左根右
后序遍历:左右根
可以发现起名前,中,后,这个命名方式和根在位置一样,看对角线,方便 记忆一些
然后我们就分别写,前,中,后序遍历的方法
//前序遍历
private void preOrder(Node node) {
if(node != null) {
System.out.print(node.data + " ");
preOrder(node.left);
preOrder(node.right);
}
}
//中序
private void midOrder(Node node) {
if(node != null) {
midOrder(node.left);
System.out.print(node.data + " ");
midOrder(node.right);
}
}
//后序
private void afterOrder(Node node) {
if(node != null) {
preOrder(node.left);
preOrder(node.right);
System.out.print(node.data + " ");
}
}
因为我方法定义的是私有的所以需要给外界提供一个公共的方法调用
//前序
public void preOrder() {//给外界提供一个公共方法调用
preOrder(root);
}
//中序
public void midOrder() {
midOrder(root);
}
//后序
public void afterOrder() {
afterOrder(root);
}
这样就写好了,完整代码如下
public class BinarySortTree {
public static void main(String[] args) {
int [] arr = {3,5,2,8,4,6,7,9,4};
SortTree tree = new SortTree();
for(int i : arr) {
tree.add(i);
}
System.out.println("前序遍历:");
tree.preOrder();
System.out.println(" ");
System.out.println("中序遍历:");
tree.midOrder();
System.out.println(" ");
System.out.println("后序遍历:");
tree.afterOrder();
System.out.println(" ");
}
}
class SortTree{
class Node{
int data;//根节点
Node left;//左孩子
Node right;//右孩子
public Node(int data) {//构造方法
this.data = data;
this.left = null;
this.right = null;
}
}
private Node root;//根节点
public void add(int data) {
Node newNode = new Node(data);//新的根节点
//第一次放入要创建根节点
if(root == null) {
root = newNode;
return ;
}
//如果不是第一次放入,双指针
Node p = root;
Node parent = root;//parent 的作用是一直指向p的上一级
while(p != null) {
parent = p;
if(data > p.data) {
p = p.right;
}else {
p = p.left;
}
}
if(data > parent.data) {
parent.right = newNode;
}else {
parent.left = newNode;
}
}
//前序遍历
private void preOrder(Node node) {
if(node != null) {
System.out.print(node.data + " ");
preOrder(node.left);
preOrder(node.right);
}
}
//中序
private void midOrder(Node node) {
if(node != null) {
midOrder(node.left);
System.out.print(node.data + " ");
midOrder(node.right);
}
}
//后序
private void afterOrder(Node node) {
if(node != null) {
preOrder(node.left);
preOrder(node.right);
System.out.print(node.data + " ");
}
}
//前序
public void preOrder() {//给外界提供一个公共方法调用
preOrder(root);
}
//中序
public void midOrder() {
midOrder(root);
}
//后序
public void afterOrder() {
afterOrder(root);
}
}
输出
前序遍历:
3 2 5 4 4 8 6 7 9
中序遍历:
2 3 4 4 5 6 7 8 9
后序遍历:
2 5 4 4 8 6 7 9 3
可以看出中序遍历就是数组从小到大排序。
如果有哪里理解的不对,欢迎指正,谢谢~