Splay伸展树

Doubi Gao3 posted @ 2014年9月06日 21:34 in DataStructure with tags Splay , 1966 阅读

                         Splay伸展树

Splay是二叉查找树,不是一颗平衡树,但可以通过自调整达到一种近似平衡的情况。Splay在连续M次操作中均摊时间复杂度是M*logn,其中n为节点的个数,M为操作的次数。Splay的操作与特点将在以下介绍。

  • 当访问一个节点时,立即把当前访问的节点旋转到根节点,让访问(插入)的节点立马成为新的根节点。
  • 旋转操作与AVL很像,有两种旋转,左旋、右旋。
  • Splay操作有两种不同的实现方式。一种是自底向上的旋转,需要记录当前节点的父亲节点。另外一种是自顶向上的实现方式,不需要记录父亲节点。
  • 由于Splay把当前访问的节点放在根节点,很容易求出当前节点的前驱与后继。
  • Splay支持merge、split、findMin、findMax、predecessor、successor、insert、remove等操作。
  • 在信息学竞赛中,Splay可以实现能实现线段树的所有的功能,即pushup、pushdown维护区间信息在Splay中用的很活,但Splay又支持快速的序列分离和合并,这是线段树做不到的。
  • 验证自己手写的数据结构是否正确可以去OJ写一写用到该数据结构的题。

今天按照数据结构那本书上的代码实现了Splay,并过了【HNOI2002】营业额统计,代码比较冗长,很多地方可以简化。

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cstring>
using namespace std;

typedef int Comparable;

struct Node
{
	Node *left, *right;
	int element;
	Node(int v=0, Node *lt=0, Node *rt=0):element(v),left(lt),right(rt) {}
};

Node *null = new Node();

void rotateWithLeftChild(Node *&t)
{
	Node *k = t->left;
	t->left = k->right;
	k->right = t;
	t = k;
}

void rotateWithRightChild(Node *&t)
{
	Node *k = t->right;
	t->right = k->left;
	k->left = t;
	t = k;
}

void splay(Node *&t, const Comparable &x)
{
	Node *leftTreeMax, *rightTreeMin;
	
	static Node head;
	
	head.left = head.right = null;
	
	leftTreeMax = rightTreeMin = &head;
	null->element = x;
	
	for(;;)
	{
		if(x < t->element)
		{
			if(x < t->left->element)
				rotateWithLeftChild(t);
			if(t->left == null) break;
			
			//Link Right
			rightTreeMin->left = t;
			rightTreeMin = t;
			t = t->left;
		}
		else if(x > t->element)
		{
			if(x > t->right->element)
				rotateWithRightChild(t);
			if(t->right == null) break;
			
			//Link left
			leftTreeMax->right = t;
			leftTreeMax = t;
			t = t->right;
		}
		else break;
	}
	
	leftTreeMax->right = t->left;
	rightTreeMin->left = t->right;
	
	t->left = head.right;
	t->right = head.left;
}

int insert(Node *&root, const Comparable &x)
{
	Node* newNode = new Node(x);
	
	if(root == null)
	{
		newNode->left = newNode->right = null;
		root = newNode;
		return 0;
	}
	
	splay(root, x);
	if(x < root->element)
	{
		newNode->left = root->left;
		newNode->right = root;
		root->left = null;
		root = newNode;
	}
	else if(x > root->element)
	{
		newNode->right = root->right;
		newNode->left = root;
		root->right = null;
		root = newNode;
	}
	else return -1;
	
	newNode = NULL;
	
	return 1;
}

Node *findMin(Node *o)
{
	if(o == null) return null;
	while(o->left != null)
		o = o->left;
	return o;
}

Node *findMax(Node *o)
{
	if(o == null) return null;
	while(o->right != null)
		o = o->right;
	return o;
}

Node *predecessor(Node *o, int x)
{
	splay(o, x);
	return findMax(o->left);
}

Node *successor(Node *o, int x)
{
	splay(o, x);
	
	return findMin(o->right);
}

void printTree(Node *o)
{
	if(o != null)
	{	
		printf("%d ", o->element);
		printTree(o->left);
		printTree(o->right);
	}
}

///////////////////////
int n;

int abs2(int x) { return x >= 0? x : -x; }

int main()
{
	while(~scanf("%d", &n))
	{
		int x; 
		Node* root = null; root->left = null; root->right = null;
		
		int ans = 0;
		for(int i = 1; i <= n; i++)
		{
			if(scanf("%d", &x) == EOF) x = 0;
			
			if(i == 1)
			{
				ans = x; insert(root, x);
				continue ;
			}
			int p = insert(root, x);
			if(p == -1) continue ;
			
			Node *pre = predecessor(root, x);
			Node *next = successor(root, x);
			int t = 1000000000;
			if(pre != null) t = min(t, abs2(x-pre->element));
			if(next != null) t = min(t, abs2(x-next->element));
			//printTree(root), puts("");
			ans += t;
		}
		printf("%d\n", ans);
	}
	return 0;
}
Liwovosa 说:
2021年4月29日 14:55

Excellent website! I adore how it is easy on my eyes it is. I am questioning how I might be notified whenever a new post has been made. Looking for more new updates. Have a great day! 123 movies

jackjohnny 说:
2021年7月12日 18:43

I haven’t any word to appreciate this post.....Really i am impressed from this post....the person who create this post it was a great human..thanks for shared this with us. 먹튀검증

AP 10th Social Quest 说:
2022年9月10日 19:31 Social Study is most important students to all students of AP 10th Class, here we have provided the study material with solved question bank for all government and private school TM, EM, UM and HM students in chapter wise from past years old exams and we have provided the AP 10th Social Model Paper 2023 Pdf suggested by subject experts. AP 10th Social Question Paper All BSEAP 10th class regular and private course students can follow the list of chapters under SSC Social Study to practice study material with previous question bank to get a better score in summative assessment (SA) and formative assessment (FA) SA-1, SA-2, FA-1, FA-2, FA-3, FA-4 along with Assignments exams previously called Unit Test-1, Unit Test-2, Unit Test-3, Unit Test-4 and Three Months.

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter