//
// SplayTree.cpp
// playground
//
// Created by Adam Chang on 2015/4/11.
// Copyright (c) 2015年 Adam Chang. All rights reserved.
//
//C Implementation in reference of http://en.wikipedia.org/w/index.php?title=Splay_tree&oldid=533723000
//NON-Recursive Elementary
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <cmath>
#include <set>
#include <stack>
#include <cmath>
using namespace std;
struct node{
int data;
node *left;
node *right;
node *parent;
};
struct node *rotate_left(struct node *pivot,struct node *root){
struct node *x;
x = pivot->right;
//reassign x's left child to pivot's right child slot
pivot->right = x->left;
if (x->left != NULL) {
x->left->parent = pivot;
}
//reverse the parential relation between x and pivot
x->left = pivot;
if (pivot->parent != NULL) {
if (pivot == pivot->parent->left) {
pivot->parent->left = x;
}else{
pivot->parent->right = x;
}
}
x->parent = pivot->parent;
pivot->parent = x;
//return value for the splay func to change the tree root
if (pivot == root) {
//pivot is the original root,after rotate x become the new root
return x;
}else{
return root;
}
}
struct node *rotate_right(struct node *pivot,struct node *root){
//x is pivot's left child
struct node *x;
x = pivot->left;
//assign x's right child to pivot's left child slot
pivot->left = x -> right;
if (x->right != NULL) {
x->right->parent = pivot;
}
//reverse the parental relationship between x and pivot
x->right = pivot;
if (pivot->parent != NULL) {
if (pivot == pivot->parent->right) {
pivot->parent->right = x;
}else {
pivot->parent->left = x;
}
}
x->parent = pivot->parent;
pivot->parent = x;
//the return value is for the splay func to change the tree root
if (pivot == root) {
//pivot is the original root,after rotate x become the new root
return x;
}else{
return root;
}
}
void splay(struct node *x,struct node *root){
//x is root,no operation required
if (x == root) {
return;
}else if(x->parent == root){
//single rotation required
if (x == x->parent->left) {
//x on the root's left,let root be the pivot and throw the x onto the root pos
root = rotate_right(root, root);
}else{
//conversely
root = rotate_left(root, root);
}
}else {
//complex situation,multiple rotation required
node *p,*g;//p:parent node g:grandparent node
p = x->parent;
g = p->parent;
if (x == p->left && p == g->left) {
//double right rotation
root = rotate_right(g, root);
root = rotate_right(p, root);
}else if(x == p->right && p == g->right){
//double left rotation
root = rotate_left(g, root);
root = rotate_left(p, root);
}else if(x == p->left && p == g->right){
//perform right-left(zagzig) rotation
root = rotate_right(p, root);
root = rotate_left(g, root);
}else if(x == p->right && p == g->left){
//perform left-right(zigzag) rotation
root = rotate_left(p, root);
root = rotate_right(g, root);
}
//when in complex situation,the splay cannot terminate only after once,use recursion here.
splay(x, root);
}
}
struct node *insert(struct node *root,int value){
struct node *temp1,*temp2,*par;
if (root == NULL) {
//given subtree root doesn't exist,create one and return this new subroot for splay.
root = (struct node *)malloc(sizeof(struct node));
if (root != NULL) {
root->data = value;
root->parent = NULL;
root->left = NULL;
root->right = NULL;
}else{
//handle memory exception
printf("MEMORY ALLOCATION EXCEPTION\n");
exit(0);
}
}else{
temp2 = root;
while (temp2 != NULL) {
//iteriate until we find a good place to place the new node
temp1 = temp2;//save current node as the target node(or its place)'s parent
if (temp2->data > value) {
temp2 = temp2->left;
}else if(temp2->data < value){
temp2 = temp2->right;
}else{
//temp2->data==value no need to instert,just return this node
//(we don't accept nodes with same key),in this case insert becomes search
return temp2;
}
}
if (temp1->data > value) {
par = temp1;//par is now the target's parent
temp1->left = (struct node *)malloc(sizeof(struct node));
temp1 = temp1->left;//temp1 is now the target node
if (temp1 != NULL) {
temp1->data = value;
temp1->parent = par;
temp1->left = NULL;
temp1->right = NULL;
}else{
//handle memory exception
printf("MEMORY ALLOCATION EXCEPTION\n");
exit(0);
}
}else{
//only repeating itself(REFACTORIZATION REQUIRED)
par = temp1;//par is now the target's parent
temp1->right = (struct node *)malloc(sizeof(struct node));
temp1 = temp1->right;//temp1 is now the target node
if (temp1 != NULL) {
temp1->data = value;
temp1->parent = par;
temp1->left = NULL;
temp1->right = NULL;
}else{
//handle memory exception
printf("MEMORY ALLOCATION EXCEPTION\n");
exit(0);
}
}
}
splay(temp1, root);//splay the newly inserted node to root position
return temp1;//this func. returns the pointer of newly inserted node for futher ops.
}
struct node *lookup(struct node *root,int value){
struct node *temp1,*temp2;
if (root != NULL) {
temp1 = root;//temp2 is the target pos for return,temp1 is only for iteration
temp2 = temp1;
while (temp1 != NULL) {
temp2 = temp1;
if (temp1->data > value) {
temp1 = temp1->left;
}else if(temp1->data < value){
temp1 = temp1->right;
}else{
return temp1;//already found,just return it.
}
}
return temp2;//didn't find the node but we find it's parent(assuming the node exists),return the parent;
}else{
printf("ROOT NULL EXCEPTION\n");
exit(0);
}
}
struct node *successor(struct node *x){
//get the assuming node's right subtree's leftmost child
struct node *temp1,*temp2;
temp1 = temp2 = x->right;
while (temp1 != NULL) {
temp2 = temp1;
temp1 = temp1->left;
}
return temp2;
}
struct node *remove(struct node *root,int value){
struct node *x,*y,*s;//y is the new root after removal
x = lookup(root, value);
if (x->data == value) {
//we have located the node matched for remove
if (x->left == NULL && x->right == NULL) {
if (x == root) {
//special judge to avoid root fault
y = root = NULL;//if root is leaf,simply make NULL the new root
}else{
//if the node for remove is a leaf
y = x->parent;
if (x == (y->right)) {
y->right = NULL;
}else{
y->left = NULL;
}//unlink x from its parent
}
}else if(x->left != NULL && x->right == NULL){
if (x == root) {//root fault prevention
x->left->parent = NULL;//x's lch becomes the new root
y = x->left;
root = x->left;
}else{
//if the node for removal only have left child
y = x->parent;
if (x == y->left) {
x->left->parent = y;//relink the child
y->left = x->left;
}else{
x->left->parent = y;//relink
y->right = x->left;
}
}
}else if(x->left == NULL && x->right != NULL){
if(x == root) {
//avoid root fault
x->right->parent=NULL;//x's rch becomes the new root
y=x->right;
root=x->right;
}
else {
//if the node to remove only have right child
y = x->parent;
//we just repeat ourself as above...
if (x == y->left) {
x->right->parent = y;
y->left = x->right;
}else{
x->right->parent = y;
y->right = x->right;
}
}
}else{
//if the node for removal have both childs
if (x == root) {
s = successor(x);//find successor(rch's leftmost node)
if (s == x->right) {
//if successor is right at x's rch
y = s;
s->parent = NULL;//make s the new root,relink x's lch
x->left->parent = s;
s->left = x->left;
root = s;
}else{
y = s->parent;//s's parent should be the new root after splay
if (s->right != NULL) {
s->right->parent = y;//relink s's rch to s's parent(because s goes to root)
y->left = s->right;
}else{
y->left = NULL;//unlink s's parent's lch
}
s->parent = NULL;//s is now the new root
x->right->parent = s;//relink
x->left->parent = s;
s->right = x->right;
s->left = x->left;
root = s;
}
}else{
y = x->parent;
if (x == y->left) {
s = successor(x); //find x's right's leftmost to replace x
if (s != x->right) {
y = s->parent;
if (s->right != NULL) {
//if the successor have right child
s->right->parent = y;//relink its right child to x's parent(s goes to x's parent's left)
y->left = s->right;
}else{
y->left = NULL;
}
s->parent = s->parent;//the relink proccess can be better understood by illustration
x->right->parent = s;
x->left->parent = s;
s->right = x->right;
s->left = x->left;
x->parent->left = s;
}else{
y = s;
s->parent = x->parent;
x->left->parent = s;
s->left = x->left;
x->parent->left = s;
}
}else{
s = successor(x);//we are repeating
if (s != x->right) {
y = s->parent;
if (s->right != NULL) {
s->right->parent = y;
y->left = s->right;
}else{
y->left = NULL;
}
s->parent = x->parent;
s->right->parent = s;
x->left->parent = s;
s->right = x->right;
s->left = x->left;
x->parent->right = s;
}else{
y = s;
s->parent = x->parent;
s->left->parent = s;
s->left = x->left;
x->parent->right = s;
}
}
}
}
free(x);//destroy and free
splay(y, root);//splay y to the new root's position
return y;
}else{
splay(x, root);//found nothing to delete,but still we should splay
return x;
}
}
int main(){
return 0;
}