zoukankan      html  css  js  c++  java
  • Splay树

    class SplayNode {
    public:
        SplayNode *child[2];
        char value;
        int size;
        bool flip;
        SplayNode(char c) : value(c), size(1), flip(false) {
            child[0] = child[1] = NULL;
        }
        int getPosition()const {
            return child[0] ? child[0]->size + 1 : 1;
        }
        void maintain() {
            size = 1;
            if (child[0]) {
                size += child[0]->size;
            }
            if (child[1]) {
                size += child[1]->size;
            }
        }
        void pushDown() {
            if (flip) {
                swap(child[0], child[1]);
                for (int i = 0; i < 2; i++) {
                    if (child[i]) {
                        child[i]->flip ^= 1;
                    }
                }
                flip = false;
            }
        }
    };
    class SplayTree {
    public:
        SplayNode *root;
        SplayTree(char *a, int n);
        void build(SplayNode *&node, char *begin, char *end);
        void rotate(SplayNode *&node, int direction);
        void splay(SplayNode *&node, int position);
        void reverse(int begin, int end);
        void traverse(SplayNode *u);
        void traverse();
    };
    SplayTree::SplayTree(char *a, int n) {
        build(root, a, a + n - 1);
    }
    void SplayTree::build(SplayNode *&node, char *begin, char *end) {
        if (begin > end) {
            return;
        }
        char *middle = begin + (end - begin >> 1);
        node = new SplayNode(*middle);
        build(node->child[0], begin, middle - 1);
        build(node->child[1], middle + 1, end);
        node->maintain();
    }
    
    void SplayTree::rotate(SplayNode *&node, int direction) {
        SplayNode *child = node->child[direction ^ 1];
        node->child[direction ^ 1] = child->child[direction];
        child->child[direction] = node;
        node->maintain();
        child->maintain();
        node = child;
    }
    void SplayTree::splay(SplayNode *&node, int position) {
        node->pushDown();
        if (node->getPosition() != position) {
            int d = node->getPosition() < position;
            SplayNode *node2 = node->child[d];
            position -= d ? node->getPosition() : 0;
            node2->pushDown();
            if (node2->getPosition() != position) {
                int d2 = node2->getPosition() < position;
                position -= d2 ? node2->getPosition() : 0;
                splay(node2->child[d2], position);
                if (d == d2) {
                    rotate(node, d ^ 1);
                } else {
                    rotate(node->child[d], d);
                }
            }
            rotate(node, d ^ 1);
        }
    }
    void SplayTree::reverse(int begin, int end) {
        splay(root, begin);
        splay(root->child[1], end - begin + 2);
        root->child[1]->child[0]->flip ^= 1;
    }
    void SplayTree::traverse(SplayNode *u) {
        if (!u) {
            return;
        }
        u->pushDown();
        traverse(u->child[0]);
        if (u->value) {
            printf("%c", u->value);
        }
        traverse(u->child[1]);
    }
    void SplayTree::traverse() {
        traverse(root);
    }
    View Code

    Splay(root,p)表示 把以root为根的子树中前序遍历的第p个元素旋转到root子树的树根位置

    这个代码风格跟我不一样,晚上回去改一改。太菜了,改不了。

    Splay树的旋转过程按照二叉搜索树的性质操作,保证前序遍历是不变的。但是就节点值来说,未必满足二叉搜索树的性质(大概此时可以把节点值理解为<key,value>的键值对吧,只不过此时value值具体是多少根本没什么影响,就忽略掉了)......

    如何应用就有些困惑了,跟序列操作有关系的问题大概能往这个方面考虑一下,感觉就是以另一种思路实现了线段树的功能......但是能做一些线段树做不了的操作,比如区间反转,而且比线段树慢,别的一时就想不到了,还是刷题太少的缘故。

  • 相关阅读:
    高精度A+B
    基本定积分求面积
    二进制算子集和
    linux命令
    Dubbo
    java 集合区别
    Java中Comparable和Comparator区别
    synchronized实现原理
    ThreadLocal 原理
    java volatile关键字
  • 原文地址:https://www.cnblogs.com/dramstadt/p/8177173.html
Copyright © 2011-2022 走看看