手写一个节点大小平衡树(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;
	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;
	}
	maintian(tree[x].left,false);
	maintian(tree[x].right,true);
	maintian(x,true);
	maintian(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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 15:07:35

手写一个节点大小平衡树(SBT)模板,留着用的相关文章

放弃antd table,基于React手写一个虚拟滚动的表格

缘起 标题有点夸张,并不是完全放弃antd-table,毕竟在react的生态圈里,对国人来说,比较好用的PC端组件库,也就antd了.即便经历了2018年圣诞彩蛋事件,antd的使用者也不仅不减,反而有所上升. 客观地说,antd是开源的,UI设计得比较美观(甩出其他组件库一条街),而且是蚂蚁金服的体验技术部(一堆p7,p8,p9,基本都是大牛级的)在持续地开发维护,质量可以信任. 不过,antd虽好,但一些组件在某一些场景下,是很不适用的.例如,以表格形式无限滚动地展示大量数据(1w+)时,

利用SpringBoot+Logback手写一个简单的链路追踪

目录 一.实现原理 二.代码实战 三.测试 最近线上排查问题时候,发现请求太多导致日志错综复杂,没办法把用户在一次或多次请求的日志关联在一起,所以就利用SpringBoot+Logback手写了一个简单的链路追踪,下面详细介绍下. 一.实现原理 Spring Boot默认使用LogBack日志系统,并且已经引入了相关的jar包,所以我们无需任何配置便可以使用LogBack打印日志. MDC(Mapped Diagnostic Context,映射调试上下文)是log4j和logback提供的一种

手写一个模块化的 TCP 服务端客户端

前面的博客 基于 socket 手写一个 TCP 服务端及客户端 写过一个简单的 TCP 服务端客户端,没有对代码结构进行任何设计,仅仅是实现了相关功能,用于加深对 socket 编程的认识. 这次我们对整个代码结构进行一下优化,使其模块化,易扩展,成为一个简单意义上的“框架”. 对于 Socket 编程这类所需知识偏底层的情况(OS 协议栈的运作机制,TCP 协议的理解,多线程的理解,BIO/NIO 的理解,阻塞函数的运作原理甚至是更底层处理器的中断.网卡等外设与内核的交互.核心态与内核态的切

手写一个词法分析器

前言 最近大部分时间都在撸 Python,其中也会涉及到将数据库表转换为 Python 中 ORM 框架的 Model,但我们并没有找到一个合适的工具来做这个意义不大的"体力活",所以每次新建表后大家都是根据自己的表结构手写一遍 Model. 一两张表还好,一旦 10 几张表都要写一遍时那痛苦只有自己知道:这时程序员的 slogan 再次印证:一切毫无意义的体力劳动终将被计算机取代. intellij plugin 既然没有现成的工具那就自己写一个吧,演示效果如下: 考虑到我们主要是用

Spring系列之手写一个SpringMVC

目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 Spring系列之AOP的原理及手动实现 Spring系列之手写注解与配置文件的解析 引言 在前面的几个章节中我们已经简单的完成了一个简易版的spring,已经包括容器,依赖注入,AOP和配置文件解析等功能.这一节我们来实现一个自己的springMvc. 关于MVC/SpringMVC springMvc是一个基于mvc模式的web框架,SpringMVC框架是一种提供了MVC(模型 - 视图 - 控制器)架

css手写一个表头固定

Bootstrap,layui等前端框架里面都对表头固定,表格滚动有实现,偏偏刚入职的公司选择了手动渲染表格,后期又觉得表格数据拉太长想要做表头固定.为了避免对代码改动太大,所以决定手写表头固定 主要遇到的个问题就是固定以后数据表格与表头的对齐问题,也看了很多我文章试下来都不怎么成功,只好自己一点点试 表头固定的一般思路是布两个table,一个放表头,一个放表格体,然后将表格体加上高度height以及overflow-y <div class="content"> <

手写一个IOC容器

链接:https://pan.baidu.com/s/1MhKJYamBY1ejjjhz3BKoWQ 提取码:e8on 明白什么是IOC容器: IOC(Inversion of Control,控制反转).这是spring的核心,贯穿始终.所谓IOC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系. 传统的java代码中,我们需要使用哪个对象,就new一个对象,很正常对吧? 然而,这时出现了一个新思想:IOC(控制反转) 由它创建和管理所有的对象,我们需要的时

使用LruCache和DiskLruCache手写一个ImageLoader

一.概述 在分析OkHttp3的缓存机制之前先手写一个实现了三级缓存的ImageLoader来整体感受一下LruCache和DiskLruCache的用法.本例实现了三级缓存,利用LruCache实现内存缓存,利用DiskLruCache实现磁盘缓存.整体的流程是:当用户请求一张图时,首先检查内存中是否有缓存图片,如果有就直接返回,如果没有就检查磁盘中是否有,有就返回,没有就启用网络下载图片,然后把图片缓存在磁盘缓存和内存缓存中.下面看看具体的实现步骤. 二.源程序介绍 1.ImageLoade

爬虫入门 手写一个Java爬虫

本文内容 涞源于  罗刚 老师的 书籍 << 自己动手写网络爬虫一书 >> ; 本文将介绍 1: 网络爬虫的是做什么的?  2: 手动写一个简单的网络爬虫; 1: 网络爬虫是做什么的?  他的主要工作就是 跟据指定的url地址 去发送请求,获得响应, 然后解析响应 , 一方面从响应中查找出想要查找的数据,另一方面从响应中解析出新的URL路径, 然后继续访问,继续解析;继续查找需要的数据和继续解析出新的URL路径  . 这就是网络爬虫主要干的工作.  下面是流程图: 通过上面的流程图