zoukankan      html  css  js  c++  java
  • 左式堆的实现与详解

    定义:左式堆(Leftist Heaps)又称作最左堆、左倾堆,是计算机语言中较为常用的一个数据结构。左式堆作为堆的一种,保留了堆的一些属性。第1,左式堆仍然以二叉树的形式构建;第2,左式堆的任意结点的值比其子树任意结点值均小(最小堆的特性)。但和一般的二叉堆不同,左式堆不再是一棵完全二叉树(Complete tree),而且是一棵极不平衡的树。

    性质:

    零路径长:从X到一个不具有两个儿子的结点的最短路径的长。

    1. 任一结点的零路径长比他的诸儿子结点的零路径长的最小值多1

    2. 父节点属性值小于子节点属性值;

    3. 堆中的任何节点,其左儿子的零路径长>=右儿子的零路径长的二叉树。

    操作:

    左式堆的操作都是基于合并,而合并仅对右路做合并,而右路结点的数量为总数量的对数关系,所以左式堆的三个操作(合并,删除,插入)所花的时间为O(logN).

    左式堆的合并操作基于递归完成,算法如下:

    1.如果有一棵树是空树,则返回另一棵树;否则递归地合并根结点较小的堆的右子树根结点较大的堆

    2.使形成的新堆作为较小堆的右子树。

    3.如果违反了左式堆的特性,交换两个子树的位置。
    4.更新Npl。

     删除最小值/最大值:

    删除操作的做法相当的简单,删除左式堆的根节点,合并左右子树即可。

    插入:将需要插入的节点当做一棵左式堆树,进行合并即可。

    下面给出左式堆的c++类模板实现

      1 #include <iostream>
      2 using namespace std;
      3 
      4 template <typename Comparable>
      5 class LeftistHeap
      6 {
      7 public:
      8     LeftistHeap() :root(NULL){}
      9     LeftistHeap(const LeftistHeap &rhs)
     10     {
     11         *this = rhs;
     12     }
     13     ~LeftistHeap()
     14     { 
     15         MakeEmpty(); 
     16     }
     17 
     18     bool IsEmpty() const;
     19     const Comparable &FindMin() const;
     20 
     21     void Insert(const Comparable &x);
     22     void DeleteMin();
     23     void DeleteMin(Comparable &minItem);
     24     void MakeEmpty();
     25     void Merge(LeftistHeap &rhs);
     26 
     27     const LeftistHeap &operator=(const LeftistHeap &rhs);
     28 
     29 private:
     30     struct LeftistNode
     31     {
     32         Comparable element;
     33         LeftistNode *left;
     34         LeftistNode *right;
     35         int npl;
     36 
     37         LeftistNode(const Comparable &theElement, LeftistNode *lt = NULL, LeftistNode *rt = NULL, int np = 0) :
     38             element(theElement), left(lt), right(rt), npl(np){}
     39     };
     40     LeftistNode *root;
     41 
     42     LeftistNode *Merge(LeftistNode *h1, LeftistNode *h2);
     43     LeftistNode *Merge1(LeftistNode *h1, LeftistNode *h2);
     44 
     45     void SwapChildren(LeftistNode *t);
     46     void ReclaimMemory(LeftistNode *t);
     47     LeftistNode *Clone(LeftistNode *t) const
     48     {
     49         if (t == NULL)
     50             return NULL;
     51         else
     52             return new LeftistNode(t->element, clone(t->left), clone(t->right));
     53     }
     54 
     55 };
     56 
     57 
     58 
     59 template <typename Comparable>
     60 bool LeftistHeap<Comparable>::IsEmpty() const
     61 {
     62     return root == NULL;
     63 }
     64 
     65 template <typename Comparable>
     66 void LeftistHeap<Comparable>::Insert(const Comparable &x)
     67 {
     68     root = Merge(new LeftistNode(x), root);
     69 }
     70 
     71 template <typename Comparable>
     72 void LeftistHeap<Comparable>::Merge(LeftistHeap &rhs)
     73 {
     74     if (this == &rhs)//避免和自己合并
     75         return;
     76     root = Merge(root, rhs.root);
     77     rhs.root = NULL;
     78 }
     79 
     80 template <typename Comparable>
     81 void LeftistHeap<Comparable>::SwapChildren(LeftistNode *t)
     82 {
     83     LeftistNode *tmp = t->left;
     84     t->left = t->right;
     85     t->right = tmp;
     86 }
     87 
     88 template <typename Comparable>
     89 typename LeftistHeap<Comparable>::LeftistNode *LeftistHeap<Comparable>::Merge1(LeftistNode *h1, LeftistNode *h2)
     90 {
     91     if (h1->left == NULL)
     92         h1->left = h2;
     93     else
     94     {
     95         h1->right = Merge(h1->right, h2);
     96         if (h1->left->npl < h1->right->npl)
     97             SwapChildren(h1);
     98         h1->npl = h1->right->npl + 1;
     99     }
    100     return h1;
    101 }
    102 
    103 template <typename Comparable>
    104 typename LeftistHeap<Comparable>::LeftistNode *LeftistHeap<Comparable>::Merge(LeftistNode *h1, LeftistNode *h2)
    105 {
    106     if (h1 == NULL)
    107         return h2;
    108     if (h2 == NULL)
    109         return h1;
    110     if (h1->element < h2->element)
    111         return Merge1(h1, h2);
    112     else
    113         return Merge1(h2, h1);
    114 }
    115 
    116 
    117 
    118 
    119 
    120 template <typename Comparable>
    121 void LeftistHeap<Comparable>::DeleteMin()
    122 {
    123     if (IsEmpty())
    124         return;
    125     LeftistNode *oldRoot = root;
    126     root = Merge(root->left, root->right);
    127     delete oldRoot;
    128 }
    129 
    130 
    131 template <typename Comparable>
    132 void LeftistHeap<Comparable>::DeleteMin(Comparable &minItem)
    133 {
    134     minItem = FindMin();
    135     DeleteMin();
    136 }
    137 
    138 template <typename Comparable>
    139 const Comparable & LeftistHeap<Comparable>::FindMin() const
    140 {
    141     if (!IsEmpty())
    142         return root->element;
    143 }
    144 
    145 
    146 template <typename Comparable>
    147 void LeftistHeap<Comparable>::ReclaimMemory(LeftistNode *t)
    148 {
    149     if (t != NULL)
    150     {
    151         ReclaimMemory(t->left);
    152         ReclaimMemory(t->right);
    153         delete t;
    154     }
    155 }
    156 
    157 
    158 template <typename Comparable>
    159 void LeftistHeap<Comparable>::MakeEmpty()
    160 {
    161     ReclaimMemory(root);
    162     root = NULL;
    163 }
     1 #include "LeftistHeap.h"
     2 
     3 
     4 int main()
     5 {
     6     LeftistHeap<int> leftistHeap1, leftistHeap2;
     7     int m, n, num;
     8     cin >> m;
     9     for (int i = 0; i < m; ++i)
    10     {
    11         cin >> num;
    12         leftistHeap1.Insert(num);
    13     }
    14 
    15     cin >> n;
    16     for (int i = 0; i < n; ++i)
    17     {
    18         cin >> num;
    19         leftistHeap2.Insert(num);
    20     }
    21 
    22     leftistHeap1.Merge(leftistHeap2);
    23     cout << "min num is " << leftistHeap1.FindMin() << endl;
    24     if (leftistHeap1.IsEmpty())
    25     {
    26         cout << "leftistHeap1 is Empty!" << endl;
    27     }
    28     else
    29     {
    30         cout << "leftistHeap1 is not empty!" << endl;
    31     }
    32 
    33     int t;
    34     while (leftistHeap1.IsEmpty() == false)
    35     {
    36             leftistHeap1.DeleteMin(t);
    37             cout << t << " ";
    38     }
    39         cout << endl;
    40     if (leftistHeap1.IsEmpty())
    41     {
    42             cout << "leftistHeap1 is empty!" << endl;
    43     }
    44     else
    45     {
    46             cout << "leftistHeap1 is not empty!" << endl;
    47     }
    48 
    49 }

  • 相关阅读:
    一篇好文,以在迷茫时阅读
    [转]EeeBox 安裝 Debian 後驅動 Wireless 筆記
    SVN内外网版本库同步手册
    Android小试牛刀之1——对话框应用和SharedPeferences存储
    关于Lucene.net 2.9.2.2 中删除索引的若干问题
    提高SQL SERVER并发能力
    Entity Framework 4 Poco开发之旅 part 2
    在linux下安装dropbox
    Windows平台高性能站点手册
    利用java反射原理写了一个简单赋值和取值通用类【改】
  • 原文地址:https://www.cnblogs.com/zhangbaochong/p/5243463.html
Copyright © 2011-2022 走看看