伸展树的实现

#include <iostream>

template <typename T>
class Splay_Tree
{
public:
	Splay_Tree();
	bool find(const T& val);
	void insert(const T& val);
	void del(const T& val);
private:
	typedef struct tagNODE
	{
		T data;
		struct tagNODE *left, *right;
		tagNODE(const T& val, tagNODE* cl, tagNODE* cr)
		{
			data = val;
			left = cl;
			right = cr;
		}
	}NODE;
	NODE *tree_root;

	NODE* own_find(NODE* tree, const T& val);
	NODE* rolatewithleft(NODE* tree);
	NODE* rolatewithright(NODE* tree);
};
template <typename T> Splay_Tree<T>::Splay_Tree()
{
	tree_root = NULL;
}
template <typename T> typename Splay_Tree<T>::NODE* Splay_Tree<T>::rolatewithleft(NODE* tree)
{
	NODE *p = tree->left;
	tree->left = p->right;
	p->right = tree;
	return p;
}
template <typename T> typename Splay_Tree<T>::NODE* Splay_Tree<T>::rolatewithright(NODE* tree)
{
	NODE *p = tree->right;
	tree->right = p->left;
	p->left = tree;
	return p;
}
template <typename T> typename Splay_Tree<T>::NODE* Splay_Tree<T>::own_find(NODE* tree, const T& val)
{
	if (NULL == tree)
		return tree;
	else if  (tree->data > val)
	{
		tree->left = own_find(tree->left, val);
		if (tree->left && tree->left->data == val)
			tree = rolatewithleft(tree);
	}
	else if (tree->data < val)
	{
		tree->right = own_find(tree->right, val);
		if (tree->right && tree->right->data == val)
			tree = rolatewithright(tree);
	}
	return tree;
}

template <typename T> bool Splay_Tree<T>::find(const T& val)
{
	NODE *p = own_find(tree_root, val);
	if (NULL != p)
		tree_root = p;
	return p != NULL;
}
template <typename T> void Splay_Tree<T>::insert(const T& val)
{
	NODE *p = tree_root, *pr = NULL;
	NODE *pn = new NODE(val, NULL, NULL);
	while (p && p->data != val)
	{
		pr = p;
		if (val > p->data)
			p = p->right;
		else if (val < p->data)
			p = p->left;
	}
	if (NULL == tree_root)
		tree_root = pn;
	else if (NULL == p)
	{
		if (pr->data > val)
			pr->left = pn;
		else
			pr->right = pn;
	}
}
template <typename T> void Splay_Tree<T>::del(const T& val)
{
	if (NULL != own_find(tree_root, val))
	{
		NODE *pl = tree_root->left;
		NODE *pr = tree_root->right;
		delete tree_root;
		if (NULL != pl && NULL != pr)
		{
			pl->right = pr->left;
			pr->left = pl;
			tree_root = pr;
		}
		else if (NULL == pl || NULL == pr)
			tree_root = (NULL == pl) ? pr : pl;
		else
			tree_root = NULL;
	}
}

时间: 2024-11-05 21:24:53

伸展树的实现的相关文章

poj_3468 伸展树

题目大意 一个数列,每次操作可以是将某区间数字都加上一个相同的整数,也可以是询问一个区间中所有数字的和.(这里区间指的是数列中连续的若干个数)对每次询问给出结果. 思路 1. 伸展树的一般规律 对于区间的查找更新操作,可以考虑使用伸展树.线段树等数据结构.这里使用伸展树来解决.     伸展树对数组进行维护的核心思想是,将需要维护的一组数单独提取出来,形成一棵子树(一般为整棵树的根节点的右子节点的左孩子节点 为根),然后再这个子树上进行操作.此时进行某些操作(如 ADD, SUM 等),只需要在

HYSBZ 1503 郁闷的出纳员 伸展树

题目链接: https://vjudge.net/problem/26193/origin 题目描述: 中文题面....... 解题思路: 伸展树, 需要伸展树的模板, 突然发现自己昨天看到的模板不是太好, 现在又新找了一个,  很简练, 自己将模板的实现从头到尾看了一遍, 觉得数组实现的实在是非常的巧妙, 然后自己照着敲了一遍, 边敲边看, 崩掉了.....肯定是哪里手残了, 没有必要浪费时间去改了, 有那时间不如看点别的 代码: #include <iostream> #include &

伸展树整理

伸展树 1.在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置.因此,在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方.伸展树应运而生.伸展树是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去. 2.操作 (1)伸展操作 伸展操作Splay(x,S)是在保持伸展树有序性的前提下,通过一系列旋转将伸展树S中的元素x调整至树的

Splay伸展树

伸展树,感觉对我这种菜鸟还是有些吃力,主要也是旋转的时候吧,把要查询的节点旋转到根节点,看网上是有两种方法,一是从上到下,一是从下到上.从上到下,是把树拆分成中树,左树和右树,始终保证目标节点在中树,不断向下把中树的节点添到右树或者左树,直到目标节点为中树的根,再将三树合并起来.另外一种从下到上,旋转操作类似AVL树中的旋转,但是判断好像不是很好写,我写的是从上到下的,另外删除也很巧妙,先把目标节点旋转到根,若此时左子树为空直接删除,否则找到左子树最右的节点当头,利用伸展树的特殊旋转就可以一步删

HNOI2002(伸展树)

营业额统计 Time Limit:5000MS     Memory Limit:165888KB     64bit IO Format:%lld & %llu Submit Status Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动

伸展树

伸展树(Splay Tree)树平衡二叉查找树的一种,具有二叉查找树的所有性质.在性能上又比普通的二叉查找树有所改进:普通的二叉查找树在最坏情况下的查找操作的时间复杂度为O(n)(当二叉树退化成一条链的时候),而伸展树在任何情况下的平摊时间复杂度均为 O(log2n). 特性 和普通的二叉查找树相比,具有任何情况下.任何操作的平摊O(log2n)的复杂度,时间性能上更好 和一般的平衡二叉树比如 红黑树.AVL树相比,维护更少的节点额外信息,空间性能更优,同时编程复杂度更低 在很多情况下,对于查找

[转载]伸展树(一)之 图文解析 和 C语言的实现

概要 本章介绍伸展树.它和"二叉查找树"和"AVL树"一样,都是特殊的二叉树.在了解了"二叉查找树"和"AVL树"之后,学习伸展树是一件相当容易的事情.和以往一样,本文会先对伸展树的理论知识进行简单介绍,然后给出C语言的实现.后序再分别给出C++和Java版本的实现:这3种实现方式的原理都一样,选择其中之一进行了解即可.若文章有错误或不足的地方,希望您能不吝指出! 目录 1. 伸展树的介绍 2. 伸展树的C实现 3. 伸展树的

uva 11922 - Permutation Transformer(伸展树)

题目链接:uva 11922 - Permutation Transformer 题目大意:给定一个序列,每次操作取出区间a~b,翻转后放到末尾,随后输出序列. 解题思路:就是伸展树,对于每个节点设一个flip,表示是否为翻转转态.每次将a旋转到根,然后分裂,再将b翻转到根,分裂,然后将mid翻转放到最后. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; str

区间查询/二分/树状数组/伸展树

一.手写二分 #include <bits/stdc++.h> int a[5] = {5, 3, 3, 2, 1}; template <class T> inline T bfind(T r, T key) { T l = 1, m, k, flag = 0; while(l != r) { m = (r + l) / 2; if(a[m] > key) l = m + 1; if(a[m] < key) r = m - 1; if(a[m] == key) { r

数据结构-伸展树

声明:本文是对某高中生的竞赛论文学习的文章 介绍: 二叉查找树能够支持多种动态集合操作.对于一个含有n个结点的完全二叉树,这些操作的最还情况运行时间是O(lgn),但如果树是含有n个结点的线性链,则这些操作的最坏情况运行时间为O(n).而像红黑树.AVL树这种二叉查找树的变形在最坏情况下,仍能保持较好性能. 本文将要介绍的伸展树也是二叉查找树的变形,它对空间要求及编程难度的要求相对不高. 伸展树: 伸展树与二叉查找树一样,具有有序性.即伸展树的每一个结点x满足:该结点的左子树中的每个元素都小于x