splay树

这篇具有很好参考价值的文章主要介绍了splay树。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

洛谷 P3369文章来源地址https://www.toymoban.com/news/detail-534519.html

#include <iostream>
#include <istream>
#include <sstream>
#include <vector>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <numeric>
#include <chrono>
#include <ctime>
#include <cmath>
#include <cctype>
#include <string>
#include <cstdio>
#include <iomanip>


#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <iterator>
using namespace std;

template <typename _Type>
class Splay {
private:
	template <typename _T>
	struct SplayNode {
		SplayNode() :data(), l(nullptr), r(nullptr),fa(nullptr), c(1), sub(1) {}
		_T data;
		SplayNode* l, * r,*fa;
		int c, sub;//副本个数 子树节点个数
	};
public:
	typedef SplayNode<_Type>  value_Type;
	typedef SplayNode<_Type>* point;
public:
	Splay() :m_root(nullptr), m_tot(0) {}
	~Splay() { clear(m_root); }
	void clear(typename Splay<_Type>::point& input);
public:
	int  GetSubCnt(typename Splay<_Type>::point node) {
		if (node == nullptr) return 0;
		return node->sub;
	}
	void flush(typename Splay<_Type>::point node) {
		if (node == nullptr) return;
		node->sub = GetSubCnt(node->l) + GetSubCnt(node->r) + node->c;
	}
	typename Splay<_Type>::point GetNode(_Type&& input);
public:
	typename Splay<_Type>::point insert(_Type input);//插入
	void remove(_Type input);//删除
	typename Splay<_Type>::point find(_Type x);//查找x
	typename Splay<_Type>::point splay(typename  Splay<_Type>::point& input);//
	typename Splay<_Type>::point findKth(int k);	//查找第k大
	int findRank(_Type x);
	typename Splay<_Type>::point findPre(_Type x);	//查找x前驱
	typename Splay<_Type>::point findNext(_Type x);//查找x后继
public:
	void  rotate_left(typename  Splay<_Type>::point& input);	//左旋转
	void  rotate_right(typename Splay<_Type>::point& input);	//右旋转
private:
	typename Splay<_Type>::point   m_root;
	int m_tot;
};

//
template <class _Type>
typename Splay<_Type>::point Splay<_Type>::GetNode(_Type&& input) {
	Splay<_Type>::point ret = new Splay<_Type>::value_Type();
	if (ret)ret->data = input, m_tot++;
	return ret;
}
template <class _Type>
void Splay<_Type>::clear(typename Splay<_Type>::point& input) {
	if (input == nullptr) return;
	clear(input->l);
	clear(input->r);
	input->l = nullptr;
	input->r = nullptr;
	delete(input);
	input = nullptr;
}

template <class _Type>
typename Splay<_Type>::point Splay<_Type>::findKth(int k)	//查找第k大
{
	if (m_root == nullptr || k > m_tot) return nullptr;
	Splay<_Type>::point cur = m_root;
	while (cur) {
		int l = GetSubCnt(cur->l);
		int r = GetSubCnt(cur->r);
		int m = cur->c;
		if (k <= l) {
			cur = cur->l;
		}
		else if (k <= l + m) {
			return splay(cur);
		}
		else {
			k -= l + m;
			cur = cur->r;
		}
	}
	return nullptr;
}

template <class _Type>
int Splay<_Type>::findRank(_Type x) {
	Splay<_Type>::point cur = m_root;

	int ans = 0;
	while (cur) {
		if (cur->data > x) {
			cur = cur->l;
		}
		else if (cur->data < x) {
			ans += GetSubCnt(cur->l) + cur->c;
			cur = cur->r;
		}
		else break;
	}
	if (cur == nullptr) return ans + 1;

	ans += GetSubCnt(cur->l) + 1;
	splay(cur);
	return ans;
}

template <class _Type>
typename Splay<_Type>::point Splay<_Type>::findPre(_Type x)	//查找x前驱
{
	Splay<_Type>::point cur = m_root, ret = nullptr;
	while (cur) {
		if (cur->data < x)ret = cur, cur = cur->r;
		else cur = cur->l;
	}
	return splay(ret);
}

template <class _Type>
typename Splay<_Type>::point Splay<_Type>::findNext(_Type x)//查找x后继
{
	Splay<_Type>::point cur = m_root, ret = nullptr;
	while (cur) {
		if (cur->data > x)ret = cur, cur = cur->l;
		else cur = cur->r;
	}
	return splay(ret);
}

template <class _Type>
typename Splay<_Type>::point Splay<_Type>::find(_Type x)//查找x
{
	Splay<_Type>::point cur = m_root;
	while (cur) {
		if (cur->data == x) {
			break;
		}
		else if (cur->data > x) {
			cur = cur->l;
		}
		else {
			cur = cur->r;
		}
	}
	return splay(cur);
}

template <class _Type>
typename Splay<_Type>::point Splay<_Type>::insert(_Type input)//插入
{
	if (m_root == nullptr) return m_root = GetNode(std::forward<_Type>(input));
	else {
		Splay<_Type>::point cur = m_root;
		while (cur) {
			if (cur->data == input) {
				cur->c++;
				m_tot++;
				break;
			}
			else if (cur->data > input) {
				if (cur->l)cur = cur->l;
				else {
					cur->l = GetNode(std::forward<_Type>(input));
					cur->l->fa = cur;
					cur = cur->l;
					break;
				}
			}
			else {
				if (cur->r)cur = cur->r;
				else {
					cur->r = GetNode(std::forward<_Type>(input));
					cur->r->fa = cur;
					cur = cur->r;
					break;
				}
			}
		}
		return splay(cur);
	}
}

template <class _Type>
void Splay<_Type>::remove(_Type input)//删除
{
	Splay<_Type>::point p = find(input), l,r;
	if (p == nullptr) return;
	p = splay(p);
	if (--p->c > 0)return;

	if (p->l == nullptr) {
		m_root = p->r;
		if(p->r)p->r->fa = nullptr;
	}
	else if (p->r == nullptr) {
		m_root = p->l;
		if (p->l)p->l->fa = nullptr;
	}
	else {
		//分裂成2棵子树
		l = p->l;
		r = p->r;
		l->fa = r->fa = nullptr;

		m_root = l;
		l = findPre(p->data); //查找左子树的前驱 相当于左子树的最大值 没有右子树
		//合并2棵子树
		l->r = r;
		r->fa = l;
	}
	delete p;
	m_tot--;
	flush(m_root);
}

template <class _Type>
typename Splay<_Type>::point Splay<_Type>::splay(typename  Splay<_Type>::point& input)
{
	if (input == nullptr) return nullptr;

	while (input->fa) {
		Splay<_Type>::point fa = input->fa, ffa = fa->fa;
		bool bol = fa->l == input;
		//父节点是根节点
		if (!ffa) {
			//左子树
			if (bol) rotate_right(fa);
			else rotate_left(fa);
		}
		else {
			bool bofl = ffa->l == fa;
			//LL
			if (bofl && bol) {
				rotate_right(ffa);
				rotate_right(fa);
			}
			else if (!bofl && !bol) {
				//RR
				rotate_left(ffa);
				rotate_left(fa);
			}
			else if (bofl && !bol) {
				//LR
				rotate_left(fa);
				rotate_right(ffa);
			}
			else {
				//RL
				rotate_right(fa);
				rotate_left(ffa);
			}
		}
	}
	return m_root = input;
}

template <class _Type>
void  Splay<_Type>::rotate_left(typename Splay<_Type>::point& node)//左旋转
{
	if (node == nullptr || node->r == nullptr) return;
	Splay::point r = node->r;
	Splay::point rl = r->l;

	if (node->fa) {
		if (node->fa->l == node) node->fa->l = r;
		else node->fa->r = r;
	}
	r->fa = node->fa;
	node->fa = r;

	r->l = node;
	node->r = rl;
	if(rl)rl->fa = node;

	node = r;

	flush(node->l);
	flush(node);
}

template <class _Type>
void  Splay<_Type>::rotate_right(typename Splay<_Type>::point& node)//右旋转
{
	if (node == nullptr || node->l == nullptr) return;
	Splay::point l = node->l;
	Splay::point lr = l->r;

	if (node->fa) {
		if (node->fa->l == node) node->fa->l = l;
		else node->fa->r = l;
	}
	l->fa = node->fa;
	node->fa = l;

	l->r = node;
	node->l = lr;
	if(lr)lr->fa = node;

	node = l;
	flush(node->r);
	flush(node);
}
//void rfIO()
//{
//	FILE *stream1;
//	freopen_s(&stream1,"in.txt", "r", stdin);
//	freopen_s(&stream1,"out.txt", "w", stdout);
//}

inline int read(int& x) {
	char ch = getchar();
	int f = 1; x = 0;
	while (ch > '9' || ch < '0') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + ch - '0'; ch = getchar(); }
	return x * f;
}
//void ReadFile() {
//	FILE* stream1;
//	freopen_s(&stream1,"in.txt", "r", stdin);
//	freopen_s(&stream1,"out.txt", "w", stdout);
//}

static auto speedup = []() {ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); return nullptr; }();


int n;
int main()
{
	Splay<int> tree;
	cin >> n;

	int a, b;
	for (int i = 1; i <= n; i++) {
		cin >> a >> b;
		switch (a)
		{
		case 1:tree.insert(b); break;
		case 2:tree.remove(b); break;
		case 3:cout << tree.findRank(b) << endl;  break;
		case 4:
		{
			Splay<int>::point ret = tree.findKth(b);
			if (ret == nullptr) cout << -1 << endl;
			else cout << ret->data << endl;
			break;
		}
		case 5:
		{
			Splay<int>::point ret = tree.findPre(b);
			if (ret == nullptr) cout << -1 << endl;
			else cout << ret->data << endl;
			break;
		}
		case 6:
		{
			Splay<int>::point ret = tree.findNext(b);
			if (ret == nullptr) cout << -1 << endl;
			else cout << ret->data << endl;
			break;
		}
		default:
			break;
		}
	}
	return 0;
}

到了这里,关于splay树的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构与算法——数据结构有哪些,常用数据结构详解

    数据结构是学习数据存储方式的一门学科,那么,数据存储方式有哪几种呢?下面将对数据结构的学习内容做一个简要的总结。 数据结构大致包含以下几种存储结构: 线性表,还可细分为顺序表、链表、栈和队列; 树结构,包括普通树,二叉树,线索二叉树等; 图存储结构

    2024年02月15日
    浏览(63)
  • 【数据结构与算法】不就是数据结构

      嗨喽小伙伴们你们好呀,好久不见了,我已经好久没更新博文了!之前因为实习没有时间去写博文,现在已经回归校园了。我看了本学期的课程中有数据结构这门课程(这么课程特别重要),因为之前学过一点,所以就想着深入学习一下子。毕竟这门课程对于 考研 和 就业

    2024年02月07日
    浏览(49)
  • 【数据结构与算法】1.数据结构绪论

    📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 🙏小杨水平有限,欢迎各位大佬指点,相互学习进步! 数据结构是计算机中存储、组织数据的方式。 数据结构是一种具有一定逻辑关系,

    2024年01月23日
    浏览(54)
  • 数据结构与算法——什么是数据结构

    当你决定看这篇文章,就意味着系统学习数据结构的开始。下面我们先来讲什么是数据结构。 数据结构,直白地理解,就是研究数据的存储方式。 我们知道,数据存储只有一个目的,即为了方便后期对数据的再利用,就如同我们使用数组存储  {1,2,3,4,5}  是为了后期取得它们

    2024年02月15日
    浏览(55)
  • 数据结构--》掌握数据结构中的排序算法

            当我们面对海量数据时,如何高效地将其排序是数据结构领域中一个重要的问题。排序算法作为其中的关键部分,扮演着至关重要的角色。         无论你是初学者还是进阶者,本文将为你提供简单易懂、实用可行的知识点,帮助你更好地掌握排序算法在数据

    2024年02月08日
    浏览(43)
  • 【数据结构与算法】一、数据结构的基本概念

    抽象数据类型(ADT)定义举例:Circle的定义 如何处理杂乱无章且多样化的数据: 数据元素 :数据中的个体被称为数据元素。 数据对象 :性质相同的数据元素组成的集合。 数据结构 :数据元素加上数据元素之间的关系,就形成了数据结构。 逻辑结构 :数据结构的逻辑模型。

    2023年04月17日
    浏览(99)
  • 数据结构--》掌握数据结构中的查找算法

            当你需要从大量数据中查找某个元素时,查找算法就变得非常重要。         无论你是初学者还是进阶者,本文将为你提供简单易懂、实用可行的知识点,帮助你更好地掌握查找在数据结构和算法中的重要性,进而提升算法解题的能力。接下来让我们开启数据

    2024年02月08日
    浏览(57)
  • 数据结构--》从数据结构开始,打好算法基础

    目录 数据结构的基本概念 数据结构的三要素 算法的基本概念 数据结构的基本概念         在学习某个知识之前,我们是否都有问过自己我们到底在学习的目的是什么?学习数据结构也一样,我们学习数据结构 主要是为了 用程序把现实世界的问题信息化;用计算机高效

    2024年02月09日
    浏览(53)
  • 《数据结构与算法》之栈结构

    在计算机发明之初是为了计算,所以叫计算机,对我们给定的一个算式,然后给定的一套规则 加,减,乘,除,等,它就可以自己进行计算了,然后返回一个结果给我们 对于一般的算式 : 2+3+4 很显然,从左往右依次扫描,依次相加很简单的计算出来,因为它们是同级运算,

    2024年02月06日
    浏览(48)
  • 有哪些数据结构与算法是程序员必须要掌握的?——“数据结构与算法”

    作为IT程序员,学习算法的原因主要有以下几点: 提升问题解决能力:算法可以帮助程序员分析、优化和解决复杂问题。了解算法原理和实现方式将有助于程序员更快地找到合适的解决方案。这对于解决实际工作中的问题是非常有帮助的。 提高代码效率:通过学习不同的算法

    2024年02月13日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包