手写一个节点大小平衡树(SBT)模板,留着用
看了一下午,感觉有了些了解。应该没有错,有错希望斧正,感谢
#include<stdio.h>
#include<string.h>
struct s
{
int key,left,right,size;
}tree[10010];
int top;
void left_rot(int &x)// 左旋
{
int y=tree[x].right;
tree[x].right=tree[y].left;
tree[y].left=x;
tree[y].size=tree[x].size;
tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
x=y;
}
void right_rot(int &x)//右旋
{
int y=tree[x].left;
tree[x].left=tree[y].right;
tree[y].right=x;
tree[y].size=tree[x].size;
tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1;
x=y;
}
void maintain(int &x,bool flag)//维护SBT状态
{
if(flag==false)//左边
{
if(tree[tree[tree[x].left].left].size>tree[tree[x].right].size)//左孩子的左孩子大于右孩子
right_rot(x);
else
if(tree[tree[tree[x].left].right].size>tree[tree[x].right].size)//左孩子的右孩子大于右孩子
{
left_rot(tree[x].left);
right_rot(x);
}
else
return;
}
else//右边
{
if(tree[tree[tree[x].right].right].size>tree[tree[x].left].size)//右孩子的右孩子大于左孩子
left_rot(x);
else
if(tree[tree[tree[x].right].left].size>tree[tree[x].left].size)//右孩子的左孩子大于左孩子
{
right_rot(tree[x].right);
left_rot(x);
}
else
return;
}
maintain(tree[x].left,false);
maintain(tree[x].right,true);
maintain(x,true);
maintain(x,false);
}
void insert(int &x,int key)//插入
{
if(x==0)
{
x=++top;
tree[x].left=0;
tree[x].right=0;
tree[x].size=1;
tree[x].key=key;
}
else
{
tree[x].size++;
if(key<tree[x].key)
insert(tree[x].left,key);
else
insert(tree[x].right,key);//同样元素可插右子树
maintain(x,key>=tree[x].key);
}
}
int remove(int &x,int key)//利用后继删除
{
tree[x].size--;
if(key>tree[x].key)
remove(tree[x].right,key);
else
if(key<tree[x].key)
remove(tree[x].left,key);
else
if(tree[x].left!=0&&tree[x].right==0)//有左子树,无右子树
{
int temp=x;
x=tree[x].left;
return temp;
}
else
if(!tree[x].left&&tree[x].right!=0)//有右子树,无左子树
{
int temp=x;
x=tree[x].right;
return temp;
}
else
if(!tree[x].left&&!tree[x].right)//无左右子树
{
int temp=x;
x=0;
return temp;
}
else//左右子树都有
{
int temp=tree[x].right;
while(tree[temp].left)
temp=tree[temp].left;
tree[x].key=tree[temp].key;
remove(tree[x].right,tree[temp].key);
}
}
int getmin(int x)//求最小值
{
while(tree[x].left)
x=tree[x].left;
return tree[x].key;
}
int getmax(int x)//求最大值
{
while(tree[x].right)
x=tree[x].right;
return tree[x].key;
}
int pred(int &x,int y,int key)//前驱,y初始前驱,从0開始, 终于要的是返回值的key值
{
if(x==0)
return y;
if(key>tree[x].key)
return pred(tree[x].right,x,key);
else
return pred(tree[x].left,y,key);
}
int succ(int &x,int y,int key)//后继。同上
{
if(x==0)
return y;
if(key<tree[x].key)
return succ(tree[x].left,x,key);
else
return succ(tree[x].right,y,key);
}
int select(int &x,int k)//选第k小的数
{
int r=tree[tree[x].left].size+1;
if(r==k)
return tree[x].key;
else
if(r<k)
return select(tree[x].right,k-r);
else
return select(tree[x].left,k);
}
int rank(int &x,int key)//key排第几
{
if(key<tree[x].key)
{
return rank(tree[x].left,key);
}
else
if(key>tree[x].key)
return rank(tree[x].right,key)+tree[tree[x].left].size+1;
else
return tree[tree[x].left].size+1;
}
void order(int &x)
{
if(x==0)
return;
order(tree[x].left);
printf("%d\n",tree[x].key);
order(tree[x].right);
}
int main()
{
top=0;
}
手写一个节点大小平衡树(SBT)模板,留着用的更多相关文章
- 剖析手写Vue,你也可以手写一个MVVM框架
剖析手写Vue,你也可以手写一个MVVM框架# 邮箱:563995050@qq.com github: https://github.com/xiaoqiuxiong 作者:肖秋雄(eddy) 温馨提 ...
- 手写一个LRU工具类
LRU概述 LRU算法,即最近最少使用算法.其使用场景非常广泛,像我们日常用的手机的后台应用展示,软件的复制粘贴板等. 本文将基于算法思想手写一个具有LRU算法功能的Java工具类. 结构设计 在插入 ...
- 【redis前传】自己手写一个LRU策略 | redis淘汰策略
title: 自己手写一个LRU策略 date: 2021-06-18 12:00:30 tags: - [redis] - [lru] categories: - [redis] permalink ...
- 『练手』手写一个独立Json算法 JsonHelper
背景: > 一直使用 Newtonsoft.Json.dll 也算挺稳定的. > 但这个框架也挺闹心的: > 1.影响编译失败:https://www.cnblogs.com/zih ...
- 教你如何使用Java手写一个基于链表的队列
在上一篇博客[教你如何使用Java手写一个基于数组的队列]中已经介绍了队列,以及Java语言中对队列的实现,对队列不是很了解的可以我上一篇文章.那么,现在就直接进入主题吧. 这篇博客主要讲解的是如何使 ...
- 【spring】-- 手写一个最简单的IOC框架
1.什么是springIOC IOC就是把每一个bean(实体类)与bean(实体了)之间的关系交给第三方容器进行管理. 如果我们手写一个最最简单的IOC,最终效果是怎样呢? xml配置: <b ...
- 放弃antd table,基于React手写一个虚拟滚动的表格
缘起 标题有点夸张,并不是完全放弃antd-table,毕竟在react的生态圈里,对国人来说,比较好用的PC端组件库,也就antd了.即便经历了2018年圣诞彩蛋事件,antd的使用者也不仅不减,反 ...
- 搞定redis面试--Redis的过期策略?手写一个LRU?
1 面试题 Redis的过期策略都有哪些?内存淘汰机制都有哪些?手写一下LRU代码实现? 2 考点分析 1)我往redis里写的数据怎么没了? 我们生产环境的redis怎么经常会丢掉一些数据?写进去了 ...
- 手写一个简单的ElasticSearch SQL转换器(一)
一.前言 之前有个需求,是使ElasticSearch支持使用SQL进行简单查询,较新版本的ES已经支持该特性(不过貌似还是实验性质的?) ,而且git上也有elasticsearch-sql 插件, ...
随机推荐
- bash脚本编程知识储备
bash脚本编程: 脚本程序:解释器解释执行: 首先得理清一些琐碎的知识点,我尽量把我所学的帮朋友一起梳理一下 编程环境:(我会在接下来的篇章,图文例子三结合的方式带大家一起学习) ...
- jQuery插件 -- Cookie插件
Cookie是站点设计者放置在client的小文本文件.Cookie能为用户提供非常多的使得,比如购物站点存储用户以前浏览过的产品列表.或者门户站点记住用户喜欢选择浏览哪类新闻. 在用户同意的情况下. ...
- 2015.03.16,外语,读书笔记-《Word Power Made Easy》 00 “如何最大限度的利用本书”学习笔记
备注:蓝色表明是自己学习或笔记的部分,红色表明特别的地方,例如自己不理解或需要重点关注的地方.加粗单词表明是要加入生词库学习的词语.单词后面括号中的蓝色部分,是单词的解释和音标. 1.this is ...
- 使用dbms_metadata.get_ddl遇到ORA-31603
建了一个外部表,想看看这个表的信息,一查就报错了: SQL> select dbms_metadata.get_ddl('TABLE','ext_case1') from dual; ERROR ...
- python爬虫:爬取读者某一期内容
学会了怎么使用os模块 #!/usr/bin/python# -*- encoding:utf-8 -*- import requestsimport osfrom bs4 import Beauti ...
- C#数组大小分析(附测试过程中想起的debug和release区别)
C#数组的理论最大长度到底是多少呢?曾经一度问过度娘,谷歌,貌似都没有得出一个比较准确的答案,无外乎是什么Int32的最大值啊什么的,今天终于决定写个软件来自己测试一下,在几台不同的电脑里面实际测试看 ...
- APUE学习笔记7——进程间通信
1 管道 管道一般是一种半双工的进程间通信方式,只能够在具有公共祖先的进程之间使用,比如一个管道由一个进程创建,然后该进程调用fork,之后父.子进程就可以使用该管道. 管道是调用pipe函数创建的. ...
- 0-NULL-nullptr
NULL In C A null-pointer constant is an integral constant expression that evaluates to zero (like 0 ...
- css3背景渐变以及图片混合渲染模式(一)
一.CSS3 渐变(Gradients):CSS3 渐变(gradients)可以让你在两个或多个指定的颜色之间显示平稳的过渡. 以前,你必须使用图像来实现这些效果.但是,通过使用 CSS3 渐变(g ...
- 移动端和pc端,响应式设计布局
1.什么是响应式 Web 设计? 响应式 Web 设计让你的网页能在所有设备上有好显示. 响应式 Web 设计只使用 HTML 和 CSS. 响应式 Web 设计不是一个程序或Javascript脚本 ...