📜  倾斜堆

📅  最后修改于: 2021-04-17 12:00:39             🧑  作者: Mango

偏斜堆(或自调整堆)是实现为二叉树的堆数据结构。倾斜堆是有利的,因为它们的合并能力比二进制堆更快。与二进制堆相比,没有结构约束,因此不能保证树的高度是对数的。仅需满足两个条件:

  1. 一般的堆顺序必须在那里(根是最小的,子树的递归也是如此),但是不需要平衡的属性(除了最后一个之外,所有级别都必须是完整的)。
  2. 歪斜堆的主要操作是合并。我们可以仅使用Merge来实现其他操作,例如insert,extractMin()等。

例子 :
1.考虑偏斜堆1为

2.要考虑的第二个堆

4.然后我们得到最终的合并树为

递归合并过程:
合并(h1,h2)

  1. 令h1和h2为要合并的两个最小歪斜堆。令h1的根小于h2的根(如果不小于,我们可以交换以获得相同的根)。
  2. 我们交换h1-> left和h1-> right。
  3. h1-> left = merge(h2,h1-> left)

例子 :

Let h1 be
        10
     /    \
   20      30
  /        /
40        50

Let h2 be
       15
     /    \
   25      35
  /  \
45    55

After swapping h1->left and h1->right, we get
        10
     /    \
   30      20
  /        /
50        40

Now we recursively Merge
   30
   /     AND   
  50

       15
     /    \
   25      35
  /  \
45    55
After recursive merge, we get (Please do it 
using pen and paper).
        15
     /     \
   30        25
  /  \     /    \
35    50  45    55

We make this merged tree as left of original
h1 and we get following result.
             10
         /         \
       15           20
    /      \       /   
   30       25    40   
 /   \    /    \
35   40  45    55

为了可视化:https://www.cs.usfca.edu/~galles/JavascriptVisual/LeftistHeap.html

CPP
// CPP program to implement Skew Heap
// operations.
#include 
using namespace std;
 
struct SkewHeap
{
    int key;
    SkewHeap* right;
    SkewHeap* left;
 
    // constructor to make a new
    // node of heap
    SkewHeap()
    {
        key = 0;
        right = NULL;
        left = NULL;
    }
 
    // the special merge function that's
    // used in most of the other operations
    // also
    SkewHeap* merge(SkewHeap* h1, SkewHeap* h2)
    {
        // If one of the heaps is empty
        if (h1 == NULL)
            return h2;
        if (h2 == NULL)
            return h1;
 
        // Make sure that h1 has smaller
        // key.
        if (h1->key > h2->key)
           swap(h1, h2);
 
        // Swap h1->left and h1->right
        swap(h1->left, h1->right);
 
        // Merge h2 and h1->left and make
        // merged tree as left of h1.
        h1->left = merge(h2, h1->left);
 
        return h1;
    }
 
    // function to construct heap using
    // values in the array
    SkewHeap* construct(SkewHeap* root,
                     int heap[], int n)
    {
        SkewHeap* temp;
        for (int i = 0; i < n; i++) {
            temp = new SkewHeap;
            temp->key = heap[i];
            root = merge(root, temp);
        }
        return root;
    }
 
    // function to print the Skew Heap,
    // as it is in form of a tree so we use
    // tree traversal algorithms
    void inorder(SkewHeap* root)
    {
        if (root == NULL)
            return;
        else {
            inorder(root->left);
            cout << root->key << "  ";
            inorder(root->right);
        }
        return;
    }
};
 
// Driver Code
int main()
{
    // Construct two heaps
    SkewHeap heap, *temp1 = NULL,
                   *temp2 = NULL;
    /*
            5
           / \
          /   \
         10   12    */
    int heap1[] = { 12, 5, 10 };
    /*
            3
           / \
          /   \
         7     8
        /
       /
      14    */
    int heap2[] = { 3, 7, 8, 14 };
    int n1 = sizeof(heap1) / sizeof(heap1[0]);
    int n2 = sizeof(heap2) / sizeof(heap2[0]);
    temp1 = heap.construct(temp1, heap1, n1);
    temp2 = heap.construct(temp2, heap2, n2);
 
    // Merge two heaps
    temp1 = heap.merge(temp1, temp2);
    /*
            3
           / \
          /   \
         5     7
        / \   /
       8  10 14
      /
     12    */
    cout << "Merged Heap is: " << endl;
    heap.inorder(temp1);
}


输出:
The heap obtained after merging is: 
12  8  5  10  3  14  7