首页 > 编程语言 >数据结构和算法系列课程(01)--- 排序二叉树和红黑树

数据结构和算法系列课程(01)--- 排序二叉树和红黑树

时间:2023-06-20 13:02:26浏览次数:50  
标签:黑树 01 TreeNode public right 二叉树 return 节点 left


把排序二叉树放在这个系列课程的第一个部分似乎有些唐突,但是考虑到它在面试中出现的可能性,把它放在这样的一个位置也就不足为奇了。


关于树和二叉树的基础知识,可以到下面的链接中下载我的课件进行了解。


下面给出一个排序二叉树的Java实现:

packag com.loonstudio;

/**
 * 排序二叉树
 * @author 骆昊
 *
 * @param <T> 泛型参数 树节点存储的元素的类型
 */
public class BST<T extends Comparable<T>> {
	private TreeNode root;	// 排序二叉树的根节点
	
	/**
	 * 描述树节点结构的内部类
	 * @author 骆昊
	 *
	 */
	private class TreeNode {
		private T value;			// 树节点存储的元素
		private TreeNode left, right;	// 指向左右孩子节点的引用
		
		public TreeNode(T value) {
			this.value = value;
		}
	}
	
	/**
	 * 返回树的节点个数
	 * @return
	 */
	public int size() {
		return size(root);
	}
	
	private int size(TreeNode x) {
		if(x == null) {
			return 0;
		}
		return size(x.left) + size(x.right) + 1;
	}
	
	/**
	 * 添加树节点
	 * @param t 待添加的元素
	 */
	public void add(T t) {
		root = add(root, t);
	}
	
	private TreeNode add(TreeNode x, T t) {
		if(x == null) {
			return new TreeNode(t);	// 如果当前根节点为空 则创建新节点作为根节点
		}
		int cmp = t.compareTo(x.value);
		if(cmp < 0) {
			x.left = add(x.left, t);	// 小于根节点在左子树上添加
		}
		else if(cmp > 0) {
			x.right = add(x.right, t);	// 大于根节点在右子树上添加
		}
		return x;
	}
	
	/**
	 * 删除树节点
	 * @param t 待删除的元素
	 */
	public void delete(T t) {
		root = delete(root, t);
	}
	
	private TreeNode delete(TreeNode x, T t) {
		if(x == null) {
			return null;
		}
		int cmp = t.compareTo(x.value);
		if(cmp < 0) {
			x.left = delete(x.left, t);
		}
		else if(cmp > 0) {
			x.right = delete(x.right, t);
		}
		else {
			if(x.right == null) {
				return x.left;	// 被删除的节点没有右子树则返回左子树替代被删除节点
			}
			if(x.left == null) {
				return x.right;	// 被删除的节点没有左子树则返回右子树替代被删除节点
			}
			TreeNode temp = x;	
			x = min(x.right);	// 找到被删除节点右子树上最小节点(没有左子树)替代被删除节点
			x.right = deleteMin(temp.right);	// 将被删除节点原来的右子树去掉最小节点后作为替代节点的右子树
			x.left = temp.left;		// 将被删除节点原来的左子树作为替代节点的左子树
		}
		return x;
	}
	
	private TreeNode deleteMin(TreeNode x) {
		if(x.left == null) {
			return x.right;
		}
		x.left = deleteMin(x.left);
		return x;
	}
	
	private TreeNode min(TreeNode x) {
		if(x.left == null) {
			return x;
		}
		return min(x.left);
	}
	
	/**
	 * 中序遍历(左-根-右): 排序二叉树的中序遍历可以得到一个有序序列
	 * @param v 元素访问器接口(实现元素访问操作的解耦合)
	 */
	public void inOrder(Visitor<T> v) {
		inOrder(root, v);
	}
	
	private void inOrder(TreeNode x, Visitor<T> v) {
		if(x != null) {
			inOrder(x.left, v);
			v.visit(x.value);
			inOrder(x.right, v);
		}
	}

	/**
	 * 先序遍历(根-左-右)
	 * @param v 树元素访问器接口
	 */
	public void preOrder(Visitor<T> v) {
		preOrder(root, v);
	}
	
	private void preOrder(TreeNode x, Visitor<T> v) {
		if(x != null) {
			v.visit(x.value);
			preOrder(x.left, v);
			preOrder(x.right, v);
		}
	}
}



元素访问器接口:

public interface Visitor<T> {

	public void visit(T t);
}




下面是一段简单的测试代码:

package com.loonstudio.test;

import com.accp.util.BST;
import com.accp.util.Visitor;

public class Test01 {

	private static void printTree(BST<Integer> tree) {
		System.out.println("先序: ");
		tree.preOrder(new Visitor<Integer>() {
			
			@Override
			public void visit(Integer t) {
				System.out.print(t + "\t");
			}
		});
		System.out.println();
		System.out.println("中序: ");
		tree.inOrder(new Visitor<Integer>() {
			
			@Override
			public void visit(Integer t) {
				System.out.print(t + "\t");
			}
		});
		System.out.println();
	}
	
	public static void main(String[] args) {
		Integer[] a = {54, 38, 76, 62, 38, 26, 40, 83, 50, 98, 80};
		
		BST<Integer> tree = new BST<Integer>();
		for(int i = 0; i < a.length; i++) {
			tree.add(a[i]);
		}
		
		printTree(tree);
		
		tree.delete(54);
		
		printTree(tree);
		
		tree.delete(38);
		
		printTree(tree);
		
		
		
	}
}





标签:黑树,01,TreeNode,public,right,二叉树,return,节点,left
From: https://blog.51cto.com/u_16166070/6521814

相关文章

  • 欧姆龙CP1H与三菱变频器通讯 CIF01(232串口方式)可直接拿来实用了,欧姆龙CP1H 与变频器
    欧姆龙CP1H与三菱变频器通讯CIF01(232串口方式)可直接拿来实用了,欧姆龙CP1H与变频器modbus通讯案例采用的器件:欧姆龙CP1HPLC,2个CP1WCIF01(232串口单元),RS232转RS485转换器,三菱FR-E740变频器进行modbusRTU模式通讯。接线方式:PLC的两个串口单元CIF01,一个接MCGS触摸屏,一个接RS23......
  • PTA_乙级_1015 德才论(C++_模拟_快排)
    宋代史学家司马光在《资治通鉴》中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人。凡取人之术,苟不得圣人,君子而与之,与其得小人,不若得愚人。”现给出一批考生的德才分数,请根据司马光的理论给出录取排名。输入格式:输入第一行给出3个......
  • 【问题解决】 网关代理Nginx 301暴露自身端口号
    一般项目上常用Nginx做负载均衡和静态资源服务器,本案例中项目上使用Nginx作为静态资源服务器出现了很奇怪的现象,我们一起来看看。“诡异”的现象部署架构如下图,Nginx作为静态资源服务器监听8080端口,客户浏览器通过API网关的443端口(就是https)获取Nginx静态资源。现象是用户浏览......
  • Windows Server 2016 OVF, updated Jun 2023 (sysin) - VMware 虚拟机模板
    WindowsServer2016OVF,updatedJun2023(sysin)-VMware虚拟机模板2023年6月版本更新,现在自动运行sysprep,支持ESXiHostClient部署请访问原文链接:https://sysin.org/blog/windows-server-2016-ovf/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org现在......
  • 华大电子MCU CIU32M010、CIU32M030嵌入式闪存及中断和事件
    1.嵌入式闪存1.1模块介绍CIU32M010、CIU32M030集成了嵌入式FLASH控制模块,该模块控制FLASH的擦除、编程以及读取数据。上电时会从FLASH中读取相关数据进行校验以及初始化配置,保证芯片程序在正确且安全的情况下运行。1.2功能特点•支持高达64K主闪存空间的FLASH•......
  • 从零开始学Python第01课:初识Python
    Python简介Python(英式发音:/ˈpaɪθən/;美式发音:/ˈpaɪθɑːn/)是由荷兰人吉多·范罗苏姆(GuidovonRossum)发明的一种编程语言,是目前世界上最受欢迎和拥有最多用户群体的编程语言。Python强调代码的可读性和语法的简洁性,相较于C或Java,Python让使用者能够用更少的代码表达自己......
  • CCF_201912-1 报数(C++_模拟)
    思路代码可能写的有点啰嗦冗余,写的时候有点急写完一节就直接复制粘贴了蛤蛤蛤,所以导致中间有些代码比较重复。Code#include<bits/stdc++.h>//模拟usingnamespacestd;intn,sum=0,a,b,c,d;booljudge(ints){ inttemp=s; if(temp%7==0) return0; while......
  • CCF_201912-2 回收站选址(C++_暴力_枚举)
    思路本来想用dfs来着,有垃圾的地方就标一后来看到数的大小为,数量却只有就果断暴力了…Code#include<bits/stdc++.h>//暴力枚举usingnamespacestd;typedeflonglongll;llx[1010],y[1010],num[1010],score[1010],ans[10];intmain(){ intn; cin>>n; for(inti=......
  • CCF_201612-4 压缩编码(C++_区间DP)
    问题描述       给定一段文字,已知单词a1,a2,…,an出现的频率分别t1,t2,…,tn。可以用01串给这些单词编码,即将每个单词与一个01串对应,使得任何一个单词的编码(对应的01串)不是另一个单词编码的前缀,这种编码称为前缀码。使用前缀码编码一段文字是指将这段文字中的每......
  • PTA_乙级_1001 害死人不偿命的(3n+1)猜想 (C++_数论)
    卡拉兹(Callatz)猜想:对任何一个正整数n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把(3n+1)砍掉一半。这样一直反复砍下去,最后一定在某一步得到n=1。卡拉兹在1950年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很傻很天真的命题,结果闹......