📜  左派树左派堆(1)

📅  最后修改于: 2023-12-03 15:39:22.785000             🧑  作者: Mango

左派树与左派堆

什么是左派树与左派堆

左派树与左派堆都是一种基于二叉树的数据结构,它们在某些场景下能够提供比传统数据结构更加优秀的性能。

左式堆

左式堆是一种二叉树,它具有以下性质:

  1. 当前节点的值小于等于其左子节点的值,大于等于其右子节点的值。
  2. 每个节点都具有一个rank值,即节点到最近叶子节点的距离(叶子节点的rank值为0)。
  3. 每个节点的左子树rank值大于等于右子树rank值。

这样的数据结构相比传统的二叉堆多了一个rank值的属性,左子树rank值大于等于右子树rank值的属性使得左式堆具有一定的左偏性质。由于左偏性质,左式堆能够在合并两棵堆的函数中进行优化,使得合并两棵堆的时间复杂度能够达到O(logN)。

左式堆的主要操作包括建堆、插入节点、删除堆顶节点、合并两个堆。

以下是一个简单的左式堆的C++实现(仅包含合并操作):

template<typename T>
struct Node {
    T value;
    Node* left;
    Node* right;
    int rank;

    Node() : value(0), left(nullptr), right(nullptr), rank(1) {}
    Node(T v) : value(v), left(nullptr), right(nullptr), rank(1) {}
};

template<typename T>
class LeftistHeap {
public:
    LeftistHeap() : root(nullptr) {}

    void merge(Node<T>* left, Node<T>* right) {
        if (left == nullptr) {
            root = right;
            return;
        }
        if (right == nullptr) {
            root = left;
            return;
        }
        if (left->value > right->value) swap(left, right);
        left->right = merge(left->right, right);
        if (left->left == nullptr || left->left->rank < left->right->rank) swap(left->left, left->right);
        left->rank = (left->right == nullptr) ? 0 : left->right->rank + 1;
        root = left;
    }

private:
    Node<T>* root;
};
左偏树

左偏树是一种基于左式堆的数据结构,它主要通过path compression来优化合并和删除操作。

和左式堆不同的是,左偏树中的节点不再需要保证左子树rank值不小于右子树rank值。因为它同时具有左式堆和右式堆的性质,所以被称作左偏堆。

左偏树中的主要操作包括建树、插入节点、删除堆顶节点、合并两个堆。

以下是一个简单的左偏树的C++实现(仅包含合并操作):

template<typename T>
struct Node {
    T value;
    Node* left;
    Node* right;
    int rank;

    Node() : value(0), left(nullptr), right(nullptr), rank(0) {}
    Node(T v) : value(v), left(nullptr), right(nullptr), rank(0) {}
};

template<typename T>
class LeftistTree {
public:
    LeftistTree() : root(nullptr) {}

    void merge(Node<T>* left, Node<T>* right) {
        if (left == nullptr) {
            root = right;
            return;
        }
        if (right == nullptr) {
            root = left;
            return;
        }
        if (left->value > right->value) swap(left, right);
        left->right = merge(left->right, right);
        if (left->left == nullptr || left->left->rank < left->right->rank) swap(left->left, left->right);
        left->rank = (left->right == nullptr) ? 0 : left->right->rank + 1;

        // path compression
        if (root != left && left->left == nullptr && left->rank > 1 && left->rank > left->right->rank + 1) {
            swap(left->left, left->right);
            left->rank = left->right->rank + 1;
        }

        root = left;
    }

private:
    Node<T>* root;
};
总结

左派树与左派堆是一种基于二叉树的数据结构,它们的合并操作能够达到O(logN)的时间复杂度。左派树在左式堆的基础上进行了优化,加入了path compression的策略,性能比左式堆更加优秀。左派树在实际应用中能够解决一些复杂度较高的场景,比如任务调度、最大割问题等。