二叉树:
在java的api当中,有一些数据结构已经封装好了,比如链表linkedlist,栈stack,队列queue和优先队列PriorityQueue等等。
但是二叉树(BinaryTree)在api中没有显式的定义,需要我们自己定义那我们来看一下二叉树的定义和基本操作。
节点类:
public class Node {
//long数据项
public long data;
//String数据项
public String sData;
//左孩子节点
public Node leftChild;
//右子节点
public Node rightChild;
//是否被访问
public boolean wasVisited;
//构造方法
public Node(long data, String sData) {
this.data = data;
this.sData = sData;
}
}二叉树类:需要一个根节点
//二叉树
public class BinaryTree {
//根节点
public Node root;
//……这里还有很多操作,在下面
}下面介绍一点基本的建立操作:
1、增加数据:根据任何左孩子都要比跟节点小,右孩子比跟大的特点,我们写出如下代码:
//插入一个节点
public void insert(long data , String sData) {
//封装节点
Node newNode = new Node(data , sData);
//两个引用
//当前节点
Node current = root;
//父节点
Node parent;
//第一次插入直接赋值
if(current == null) {
root = newNode;
return;
}
//循环左走右走
while (true) {
//父节点指向当前节点
parent = current;
//比较大小左右走
if (current.data > data) {
current = current.leftChild;
if(current == null) {
parent.leftChild = newNode;
return;
}
}
else {
current = current.rightChild;
if(current == null) {
parent.rightChild = newNode;
return;
}
}
}
}2、查找节点:
//查找节点
public Node find(long data) {
//引用当前节点
Node current = root;
while(current.data != data) {
//进行比较和当前节点大小
if (current.data > data) {
current = current.leftChild;
} else {
current = current.rightChild;
}
//查不到
if(current == null) {
return null;
}
}
return current;
}3、遍历:4种
(1)前序遍历:先访问跟节点,再访问根节点的左子树(左子树也同样前序遍历,先左子树的跟,再左子树的左子树,以此类推),最后访问右子树(同理)。
/*前序遍历
* 1.访问根节点
* 2.递归前序遍历左子树
* 3.递归前序遍历右子树
*/
public void frontOrder(Node localNode) {
if(localNode != null) {
System.out.print(localNode.data + "," + localNode.sData + " ; ");
frontOrder(localNode.leftChild);
frontOrder(localNode.rightChild);
}
}(2)中序遍历(可按升序输出):
/*
* 中序遍历
* 1.递归中序遍历左子树
* 2.访问根节点
* 3.递归中序遍历右子树
*/
public void inOrder(Node localNode) {
if (localNode != null) {
inOrder(localNode.leftChild);
System.out.print(localNode.data + "," + localNode.sData + " ; ");
inOrder(localNode.rightChild);
}
}(3)后序遍历:
/*
* 后序遍历
* 1.递归后序遍历左子树
* 2.递归后序遍历右子树
* 3.访问根节点
*/
public void afterOrder(Node localNode) {
if (localNode != null) {
afterOrder(localNode.leftChild);
afterOrder(localNode.rightChild);
System.out.print(localNode.data + "," + localNode.sData + " ; ");
}
}(4)层序遍历:利用到了队列的特点
//层序遍历
public void LevelOrder(Node root) {
Queue<Node> queue = new LinkedList<Node>();
Node now = root;
queue.add(root);
while (!queue.isEmpty()) {
now = queue.poll();
if (now != null) {
System.out.print(now.data + "," + now.sData + " ; ");
}
if (now.leftChild != null) {
queue.add(now.leftChild);
}
if (now.rightChild != null) {
queue.add(now.rightChild);
}
}
}前三种遍历方式我们用到了递归的思想,这样容易理解,代码也简单。如果不用递归也可以实现,具体参照https://blog.csdn.net/likunkun__/article/details/80183599
4、删除节点(原理另开一章讲,这里先贴代码):
//先寻找中序后继节点,再进行删除
//寻找中序后继节点
public Node getHouJiNode(Node delNode) {
//定义中序后继节点
Node houji = delNode;
//定义中序后继的父节点
Node houjiparent = delNode;
//当前节点
Node current = delNode.rightChild;
while(current != null) {
houjiparent = houji;
houji = current;
current = current.leftChild;//往左边找
}
//把删除节点替换成终须后继节点
//1.如果删除节点的右节点不是后继节点(正常右左左……找到的)
if(houji != delNode.rightChild) {
//中序后继的父节点的左子节点指向中序后继节点的右子节点(中序后继节点没有左子节点)
houjiparent.leftChild = houji.rightChild;
//后继的右边接上删除的右边,左边接上删除的左边
houji.rightChild = delNode.rightChild;
houji.leftChild = delNode.leftChild;
}
//2.删除节点的右节点就是中序后继节点,右边不用动,吧左边接上就可以
else {
houji.leftChild = delNode.leftChild;
}
return houji;
}
//删除节点delete
public boolean delete(long data) {
//引用当前节点
Node current = root;
//引用当前节点的父节点
Node parent = root;
//是左子节点还是右节点
boolean isLeftChild = true;
//循环找到要删的节点
while (current.data != data) {
parent = current;
if (current.data > data) {
current = current.leftChild;
isLeftChild = true;
} else {
current = current.rightChild;
isLeftChild = false;
}
//没有
if(current == null) {
return false;
}
}
//循环结束,current指向要删除节点,parent指向父节点
//进行删除current节点
//1.如果是叶子节点(没有子节点)
if (current.leftChild == null &¤t.rightChild ==null) {
if (current == root) {
root = null;
}
//如果是左边的节点
else if (isLeftChild) {
parent.leftChild = null;
}
//如果是右边的节点
else {
parent.rightChild = null;
}
}
//2.删除带有一个子节点的节点
else if (current.rightChild == null) {
//子节点是左子节点
if (current == root) {
root = current.leftChild;
}
else if (isLeftChild) {//删除的节点是左节点
//把父节点的左子节点指向删除节点的左子节点(接上去)
parent.leftChild = current.leftChild;
}
else {//删除的节点是右节点
parent.rightChild = current.leftChild;
}
}
else if (current.leftChild == null) {
//子节点是右子节点
if (current == root) {
root = current.rightChild;
}
else if (isLeftChild) {//删除的节点是左节点
parent.leftChild = current.rightChild;
}
else {//删除的节点是右节点
parent.rightChild = current.rightChild;
}
}
//3.删除有2个子节点的节点,需要寻找中续后继节点来替换删除节点
else {
Node houji = getHouJiNode(current);
if (current == root) {
root = houji;
}
else if (isLeftChild) {
parent.leftChild = houji;
}
else {
parent.rightChild = houji;
}
}
return true;
}
本文介绍了如何在Java中自定义二叉树的数据结构,包括节点类的定义,二叉树类的创建,以及增、删、查、遍历等基本操作。文章详细讲解了前序、中序、后序和层序四种遍历方法,并提到了删除节点的实现,虽然删除原理未展开,但提供了相关代码参考链接。
——二叉树的构造(增删查遍历)&spm=1001.2101.3001.5002&articleId=80242751&d=1&t=3&u=62db7e7e6b2042cf89bfd37eb5636777)
1万+

被折叠的 条评论
为什么被折叠?



