数据结构—树
树的定义
树:n(n>=0)个节点构成的有限集合。当n=0时称为空树。
对于任一个非空树(n>0),它具备以下性质。
(1)有且仅有一个特定的称为根(root)的结点;
(2)其余结点可分为m(m>0)个互不相交的有限集T1,T2,...,Tm,其中每一个集合本身又是一棵树,并称为根的子树(SubTree)
(a)树T
(b)子树T1
(c)子树T2
(d)子树T3
(e)子树T4
树的一些基本术语
01 节点的度:节点的子树个数
例如 树T 的根节点(即A节点)的度为4;
B节点的度为2;
C节点的度为1;
D节点的度为3;
E节点的度为0;
02树的度:树的节点中最大的度数
树T的度为4;
03叶节点:度为0的节点
比如树T 的F,L,H,M,J,K,E都是页节点。
04父节点:有子树的节点是其子树的根节点的父节点
比如A节点是子树T1 的根节点B的父节点。
05子节点:若A节点是B节点的父节点,则称B节点是A节点的子节点,子节点也称为孩子节点
比如B节点是A节点的子节点
06兄弟节点:具有同一父节点的各节点彼此是兄弟节点
比如B,C,D,E彼此是兄弟节点
07路径和路径长度:从节点N1到Nk的路径为一个节点序列N1,N2,...,NK,Ni是Ni+1的父节点。路径所包含的个数为路径的长度。
比如从A节点到L节点的路径的长度为4
08祖先节点:沿树根到某一节点路径上的所有节点都是这个节点的祖先节点
比如A节点到L节点的路径上A,B,G都是L节点的祖先节点
09子孙节点:某一节点的子树中的所有节点是这个节点的子孙
比如A节点的子树T1的所有节点B,F,G,L都是A节点的子孙
10节点的层次:规定根节点在第一层,其他任一节点的层数是其父节点的层数加1
比如B节点的层次是2,F节点的层次是3,L节点的层次是4
11树的深度:树中所有节点中的最大层次是这个树的深度
树T的深度为4
二叉树
二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。
由二叉树定义以及图示分析得出二叉树有以下特点
01.每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点
02.如果有两个子结点,则其中一个子结点的值必须小于父结点,另一个子结点的值必须大于父结点
03.在二叉树的第i层上最多有2i-1 个节点 。(i>=1)
04.二叉树中如果深度为k,那么最多有2k-1个节点。
下面是使用java语言实现二叉查找树
/**
* @author wwd
* @title: BinaryTree
* @description: 二叉树
* @date 2022/3/299:04
*/
public class BinaryTree<Key extends Comparable<Key>,Value> {
/**
* 根节点
**/
private Node root;
/**
* 节点数量
**/
private int n;
private class Node{
/**
* 节点键
**/
public Key key;
/**
* 节点值
**/
private Value value;
/**
* 左子节点
**/
public Node left;
/**
* 右子节点
**/
public Node right;
/**
* 父节点
**/
public Node parent;
public Node(Key key, Value value,
Node left, Node right,Node parent) {
this.key = key;
this.value = value;
this.left = left;
this.right = right;
this.parent = parent;
}
}
public int size(){
return n;
}
public void put(Key key,Value value){
root=put(root,key,value,root);
}
private Node put(Node x,Key key,Value value,Node parent){
if (x == null){
//空树
Node node = new Node(key,value,null,null,parent);
n++;
return node;
}
int compare = key.compareTo(x.key);
if (compare>0){
x.right = put(x.right, key, value,x);
}else if (compare<0){
x.left = put(x.left, key, value,x);
}
return x;
}
public Value get(Key key){
return get(root,key);
}
private Value get(Node node,Key key){
if (node == null){
return null;
}
int compare = key.compareTo(node.key);
if (compare>0){
return get(node.right,key);
}else if (compare<0){
return get(node.left,key);
}
return node.value;
}
public void delete(Key key){
delete(root,key);
}
private void delete(Node node,Key key){
if (null == node){
//如果父节点为空直接返回
return;
}
//查找到需要删除的节点
int compare = key.compareTo(node.key);
if (compare>0){
//如果要删除的节点大于当前节点
// 就去当前节点的右子节点递归查找
delete(node.right,key);
}else if (compare<0){
//如果要删除的节点小于当前节点
// 就去当前节点的左子节点递归查找
delete(node.left,key);
}else{
//找到需要删除的节点
n--;
Node p = node.parent;
//情况1:没有子节点
if (node.left==null && node.right == null){
//没有子节点
if (root == node){
//如果删除的节点是根节点
root = null;
}else {
//删除的不是根节点
if (p.left==node){
//删除的是父节点的左节点
p.left = null;
}else{
p.right = null;
}
}
}else if (node.right == null){
//情况2:删除的节点只有左节点
Node ln = node.left;
//删除的节点为根节点,将删除节点的左节点设置成根节点
if (p==null){
ln.parent = null;
root = ln;
}else{
//非根节点
if (node == p.left){
p.left = ln;
}else{
p.right = ln;
}
}
}else if (node.left == null){
//情况2:删除的节点只有右节点
Node lr = node.right;
if (p==null){
lr.parent = null;
root = lr;
}else{
if (node== p.left){
p.left = lr;
}else{
p.right = lr;
}
}
}else {
//有两个节点,找到后继节点,将值赋给删除节点,然后将后继节点删除掉即可
//寻找
Node successor = successor(node);//获取到后继节点
node.value = successor.value;
//后继节点为右子节点
if (node.right == successor){
//右子节点有右子节点
if (successor.right != null) {
node.right = successor.right;
successor.right.parent = node;
}else {//右子节点没有子节点
node.right = null;
}
}else {//后继节点必定是左节点
successor.parent.left = null;
}
}
}
}
/**
* 查找后继节点
* @param node 删除节点
* @return 后继节点
*/
private Node successor(Node node) {
Node r = node.right;//r节点必定不为空
while (r.left != null){
r = r.left;
}
return r;
}
/**
* 前序遍历
* @param e 开始遍历元素
*/
public void prevIterator(Node e){
if (e != null) {
System.out.print(e.key + " ");
prevIterator(e.left);
prevIterator(e.right);
}
}
/**
* 中序遍历
* @param e
*/
public void midIterator(Node e){
if (e != null){
midIterator(e.left);
System.out.print(e.key + " ");
midIterator(e.right);
}
}
/**
* 后续遍历
* @param e 开始遍历元素
*/
public void subIterator(Node e){
if (e != null) {
subIterator(e.left);
subIterator(e.right);
System.out.print(e.key + " ");
}
}
public static void main(String[] args) {
BinaryTree<String,String> binaryTree = new BinaryTree<>();
binaryTree.put("18","哈哈18");
binaryTree.put("16","哈哈16");
binaryTree.put("17","哈哈15");
binaryTree.put("30","哈哈30");
binaryTree.put("32","哈哈32");
binaryTree.put("10","哈哈10");
binaryTree.put("25","哈哈25");
binaryTree.midIterator(binaryTree.root);
System.out.println();
String o = binaryTree.get("30");
System.out.println(o);
binaryTree.delete("17");
binaryTree.midIterator(binaryTree.root);
System.out.println();
}
}
下图是运行结果
如果对代码有疑问请留言交流哦
END
微信搜索 ”Java软件编程技术“ 关注我们获取更多软件开发技术
查看更多精彩内容