以种地和革命来讲解——红黑树

参考资料:【数据结构】红黑树_一个写湿的程序猿-CSDN博客_红黑树

规则:

1.所有节点不是种地的(黑色)就是搞革命的(红色)(把黑色节点理解为种黑底的,把红色节点理解为搞红色革命的)

2.根节点一定是种地的(黑色)(不然没有粮食基础啊)

3.叶子节点都是null并且是预备种地的(黑色)

4.搞革命的红色必定有两个种地的子节点。(不能两代人一起搞革命,不然没人种地没粮食)

5.任意节点到它的所有叶子节点上,种地的黑色节点数量是一致的。(保证每条线粮食相等,那么最长的节点的长度不大于最短节点的长度。)

查找:

因为红黑树是一个自平衡的二叉查找树,它满足黑高相等,因此最高的节点高度也不能大于最短节点高度的两倍。

近似于 2^高h = 总结点n

红黑树的左旋右旋操作:建议去看上文中作者讲的,真的非常清晰。

插入:

插入的节点默认为是红色的,这样就能一定满足规则1,2,3,5条,只需要解决可能出现的规则4问题(两代人一起搞红色革命)。

情形1:插入的节点就是根节点,染黑即可(得有人种地)。

情形2:插入的父节点是黑色的,直接插入(我搞革命有保障,满足5条规则)。

情形3:插入的父节点是红色的。两代人一起搞红色革命可不行。

那么出门在外有事就找爸爸的兄弟啊,也就是叔叔。

情形3.1:叔叔也是搞红色革命的。很好,这样爸爸和叔叔就有共同的认知了,到了我这一代我要搞革命,你们兄弟两就去种地吧(把爸爸节点和叔叔节点都染成黑色)。但是为了和其他线路上种地的数量保持一致,以前就爷爷一个人种地(已知爸爸和叔叔都为搞红色革命的,那么爷爷必定为种地的。)现在爸爸和叔叔都去种地了,那么只要让爷爷也去搞红色革命就行了,这样就和以前的种地人数一样多了。那么问题就来到了爷爷这里,爷爷变成了搞红色革命的,那么就有可能和爷爷的爸爸冲突,转换视角去看这个问题,把爷爷当作新加进来的节点,进行重新插入讨论……

情形3.2:叔叔是种地的。完咯,叔叔和爸爸不能齐心协力了,那么又只能分情形讨论。已知爸爸是搞红色革命的,那么爷爷一定是种黑地的(不能双红)。

情形3.2.1:我的父类是爷爷的左儿子,并且我是爸爸的左儿子。(LL)

那么为了顺利让我搞红色革命的,并且这条线上(爷爷,爸爸,我)只有一个种地的,那么就让爸爸去担负起爷爷的种地的责任,并且作为这条线上的顶梁柱,爷爷委屈顶到爸爸的名下做右儿子,并把原先爸爸的右儿子作为爷爷的左儿子。完成整个右旋操作。

情形3.2.2:我的父类是爷爷的右儿子,并且我是爸爸的右儿子。(RR)

基本操作同 【情形3.2.1】 ,只不过做的事左旋操作。

情形3.2.3:我的父类是爷爷的左儿子,并且我是爸爸的右儿子。(LR)

老爸不给力啊,数值还没我大,要是让老爸做顶梁柱,我就无处安放了,因此我决定,做自己的主人!先把老爸认作自己的左儿子,再认爷爷作为自己的老爸!于是乎情形来到了 【情形3.2.1】,接下来就按照 【情形3.2.1】处理,只不过主人公变成了原先的我的老爸!

情形3.2.3:我的父类是爷爷的右儿子,并且我是爸爸的左儿子。(RL)

老爸太给力了,但是我比爷爷的数值大啊,右旋操作后,老爸做顶梁柱,我就要和爷爷一起抢左节点的位置,那可不行,所以我决定做自己的主人!把老爸作为我的右儿子,把爷爷作为我的父节点,这样情形就来到了 【情形3.2.2】

删除:

删除的逻辑,让我们先来看看,如果我有两个子节点,我走了一定会让两个儿子争夺上位,为了避免这种情况,保持结构稳定,我决定选我左儿子中最大的节点,或者右儿子中最小的节点。这两个节点是离我最近的,他们坐上我的位置所有人都会信服(满足二叉树概念)。这样我的位置得到了解决,该干的事情接着干(颜色不变)。问题就来到了接替我的儿子的节点身上。只不过他们两一个没有右儿子节点,一个没有左儿子节点,问题就得到了简化!

简化后的情形:

情形a:我是搞红色革命的节点。太棒了,只要把我删除,让我儿子上位就好了,什么都不用修改,就满足了5条规则。

情形b:我是种黑地的节点。oh,no,我可是粮食的产出者,我走了就不能满足每条线上都是一样的种黑地的总值了。那么就分情况讨论吧:

情形b_a:我有一个搞红色革命的儿子(LL,LR),很好,就让他来继承我种黑地的事业(把儿子染成黑色),毕竟保证粮食非常的重要。

情形b_b:我没有搞红色的儿子。糟糕了,我没有儿子来继承我种黑地的事业!怎么办。问兄弟借侄子啊!已知我是种黑底的,那么我必定我是有兄弟的,因为从老爸那里看,他到所有叶子节点的路径上黑色的节点数是相等的。

如果兄弟是黑色的,那么有三种情况:

情形b_b_a:兄弟有左红色儿子。不错,让兄弟去顶替父亲的职责(黑红皆可),父亲委屈下来做兄弟的右儿子,接上我的子节点(右旋)。把原先兄弟的儿子和原先的父亲节点都染黑。这样就保证了黑高不变。

情形b_b_b:兄弟有右红色儿子。那可不能让兄弟去顶替父亲的职责,因为兄弟还得给父亲留右儿子的位置。因此可以先左旋,把兄弟作为兄弟儿子的左节点,兄弟儿子上位,交换颜色。于是情形又回到了 【情形b_b_a】。

情形b_b_c:兄弟有左右两个红色儿子。处理方式同 【情形b_b_a】。

但如果兄弟没有红色的儿子,那么就要去求父亲了。

情形b_b_d:父亲为红色。很好,让父亲接替我种黑地的职责,让兄弟节点去搞革命,这样一加一减又平衡了。

情形b_b_e:父亲为黑色。父亲无法为我分担责任,因为我两都是黑色的,那么就让父亲还是顶替我的位置,让问题变为如何删除父亲这个节点,重新开始删除判断。

如果兄弟是红色的,那么

情形b_b_f:交换父节点和兄弟节点的颜色,进行右旋,把问题转换回前面所说的,按照 【情形b_b_a】开始往下判断,完成整个删除过程。

在Unity中创建一个种田系统和天气系统涉及到游戏逻辑、场景设置以及可能的数据管理。这里我会给你提供一些基本的思路和代码片段,但请注意这只是一个基础框架,实际开发中你需要根据项目需求进行详细的定制。 **种田系统(Planting System)** 1. **创建资源**: - 设计种子对象(比如种子Prefab),包含生长速度、收获时间等属性。 - 创建田地(Farmland)或地块(GridCell)组件,用于存储种植状态和当前作物。 ```csharp public class Plant : MonoBehaviour { public int growthSpeed; public float harvestTime; // ... } ``` 2. **播种逻辑**: - 当玩家选择种植,检查田地是否有空位,然后放置种子并更新其生长状态。 ```csharp public void PlantSeed(PlantType type, Vector3 position) { if (Farmland.CanPlant(position)) { Farmland.Instance.PlacePlant(position, type); } } ``` 3. **收获逻辑**: - 定期检查作物是否成熟,成熟后移除植物并增加收益。 ```csharp void Update() { foreach (Plant plant in Farmland.Instance.GetPlants()) { if (plant.IsHarvestable()) { // 收获并更新田地 RemovePlantAt(plant.transform.position); } } } ``` **天气系统(Weather System)**: 1. **添加天气组件**: - 创建一个WeatherManager类负责控制天气变化。 ```csharp public class WeatherManager : MonoBehaviour { public List<Weather> weatherStates; private Weather currentWeather; // ... } ``` 2. **天气状态管理**: - 用枚举或字典定义不同的天气状态(晴天、雨天、风暴等),每个状态都有对应的效果和持续时间。 ```csharp public enum WeatherState { Sunny, Rainy, Stormy } private void ChangeWeather(WeatherState state) { currentWeather?.FadeOut(); currentWeather = weatherStates[state]; currentWeather.FadeIn(); } ``` 3. **随机或定时切换天气**: - 可以用`Random.Range`生成随机数决定天气变化,或者设定时间间隔轮换天气。 ```csharp void UpdateWeather() { // 随机选择新天气 RandomIndex = Random.Range(0, weatherStates.Count); // 检查是否到切换时间 if (currentWeather.ChangeTime <= Time.time) { ChangeWeather(weatherStates[RandomIndex]); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

椰子糖莫莫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值