堆,最大堆,最小堆,最大左高树 源码

一些堆类结构的实现代码。。。

//Heap.h

#ifndef HEAP_H
#define HEAP_H

#include <iostream>
#include <iomanip>
using namespace std;

#include "Queue.h"
#include "Stack.h"
#include "HeapExceptions.h"

template <class T>
/*
   \brief: Heap built in an array,
   using array to simulate the heap.
   \mention: You can try another version
   (class BinaryHeap) of heap implemented 
   by a specialized binary tree.
*/
class Heap
{
   template <class T>
   friend ostream &operator<<(ostream &, const Heap<T> &);

public:
   Heap(T *, const int);
   Heap(const Heap &);
   ~Heap();

   int parent(int i) { return (i - 1) / 2; }
   int left(int i) { return 2 * i + 1; }
   int right(int i) { return (i + 1) * 2; }

   T *list;
   //length of array
   int length; 
   //size of heap
   int heapSize;
};


template <class T>
/*
   /brief: A max heap built in an array.
   from base class Heap. 
*/
class MaxHeap : public Heap<T>
{
   template <class T>
   friend void heap_sort(T *, const int);

public:
   MaxHeap(T *, const int);

   void maxHeapify(int = 0);
   void buildMaxHeap();

   void push(const T &);
   void pop();
};

/*
/brief: A min heap built in an array.
        from base class Heap.
*/
template <class T>
class MinHeap : public Heap<T>
{
   template <class T>
   friend void heap_sort(int, T *, const int);

public:
   MinHeap(T *, const int);

   void minHeapify(int = 0);
   void buildMinHeap();

   void push(const T &);
   void pop();
};

/*--------------Heap-----------------*/
template <class T>
Heap<T>::Heap(T *src, const int size) 
   : length(size), heapSize(size){
   list = new T[size];
   for (int i = 0; i < size; i++){
      list[i] = src[i];
   }
}

template <class T>
Heap<T>::Heap(const Heap<T> &src_heap){
   length = src_heap.length;
   heapSize = src_heap.heapSize;
   list = new T[heapSize];
   for (int i = 0; i < heapSize; i++){
      list[i] = src_heap.list[i];
   }
}

template <class T>
Heap<T>::~Heap(){
   if (!list){
      delete list;
   }
}

template <class T>
ostream &operator<<(ostream &out, const Heap<T> &heap){
   int i = 0;
   int j = 1;
   for (; i + j <= heap.heapSize; i += j, j *= 2){
      for (int k = i; k < i + j; k++){
         out << setw(4) << left << heap.list[k];
      }
      out << endl;
   }

   for (; i < heap.heapSize; i++){
      cout << setw(4) << left << heap.list[i];
   }
   out << endl;

   return out;
}

/*--------------MaxHeap-----------------*/
template <class T>
MaxHeap<T>::MaxHeap(T *src, const int size)
   : Heap<T>(src, size){
   buildMaxHeap();
}

template <class T>
void MaxHeap<T>::buildMaxHeap(){
   for (int i = heapSize / 2 - 1; i >= 0; i--){
      maxHeapify(i);
   }
}

template <class T>
void MaxHeap<T>::maxHeapify(int i){
   int largest = i;

   if (right(i) < heapSize && 
       list[largest] < list[right(i)]){
      largest = right(i);
   }

   if (left(i) < heapSize && 
       list[largest] < list[left(i)]){
      largest = left(i);
   }

   swap(list + i, list + largest);
   if (largest != i){
      maxHeapify(largest);
   }
}

template <class T>
void MaxHeap<T>::push(const T &k){
   //if full, double the storage space
   if (heapSize == length){
      T *buffer = new T[heapSize];
      for (int i = 0; i < heapSize; i++){
         buffer[i] = list[i];
      }
      list = new T[length *= 2];
      for (int i = 0; i < heapSize; i++){
         list[i] = buffer[i];
      }
   }

   //insert k
   list[heapSize++] = k;

   //maintain max heap property
   int j = heapSize - 1;
   while (j > 0 && list[parent(j)] < k){
      swap(list + j, list + parent(j));
      j = parent(j);
   }
}

template <class T>
void MaxHeap<T>::pop(){
   swap(list, list + heapSize - 1);
   heapSize--;
   maxHeapify(0);
}

template <class T>
void heap_sort(T *list, const int size){
   //coupling
   MaxHeap<T> heap(NULL, 0);
   heap.list = list;
   heap.length = heap.heapSize = size;
   heap.buildMaxHeap();

   for (int i = size - 1; i >= 1; i--){
      swap(list, list + i);
      heap.heapSize--;
      heap.maxHeapify(0);
   }

   //decoupling
   heap.list = NULL;
   heap.length = heap.heapSize = 0;
}

/*--------------MinHeap-----------------*/
template <class T>
MinHeap<T>::MinHeap(T *list, const int size)
: Heap<T>(list, size){
   buildMinHeap();
}

template <class T>
void MinHeap<T>::buildMinHeap(){
   for (int i = heapSize / 2 - 1; i >= 0; i--){
      minHeapify(i);
   }
}

template <class T>
void MinHeap<T>::minHeapify(int i){
   int least = i;
   if (left(i) < heapSize &&
       list[left(i)] < list[least]){
      least = left(i);
   }

   if (right(i) < heapSize &&
       list[right(i)] < list[least]){
      least = right(i);
   }

   swap(list + i, list + least);
   if (least != i){
      minHeapify(least);
   }
}

template <class T>
void MinHeap<T>::push(const T &k){
   //if full, double the storage space
   if (heapSize == length){
      T *buffer = new T[heapSize];
      for (int i = 0; i < heapSize; i++){
         buffer[i] = list[i];
      }
      list = new T[length *= 2];
      for (int i = 0; i < heapSize; i++){
         list[i] = buffer[i];
      }
   }

   //insert k
   list[heapSize++] = k;

   //maintain max heap property
   int j = heapSize - 1;
   while (j > 0 && list[parent(j)] > k){
      swap(list + j, list + parent(j));
      j = parent(j);
   }
}

template <class T>
void MinHeap<T>::pop(){
   swap(list, list + heapSize - 1);
   heapSize--;
   minHeapify(0);
}

template <class T>
void heap_sort(int m, T *list, const int size){
   //coupling
   MinHeap<T> heap(NULL, 0);
   heap.list = list;
   heap.length = heap.heapSize = size;
   heap.buildMinHeap();

   for (int i = size - 1; i >= 1; i--){
      heap.minHeapify(0);
      swap(heap.list, heap.list + i);
      heap.heapSize--;
   }

   //decoupling
   heap.length = heap.heapSize = 0;
   heap.list = NULL;
}

//utility function
template <class T>
void swap(T *p_1, T *p_2){
   T temp = *p_1;
   *p_1 = *p_2;
   *p_2 = temp;
}

template <class T>
/*
   \brief: Node for height-biased leftist tree,
   which has HBLT property: x.left.h >= x.right.h.
   \detail: data mem @h : length of the shortest
   simple path from this node to a leaf node.
*/
class HBLTNode
{
public:
   HBLTNode(HBLTNode<T> *p_1 = NULL, 
            HBLTNode<T> *p_2 = NULL,
            T k = T(), int s = 1)
            : left(p_1), right(p_2), key(k), h(s) { }

   HBLTNode<T> *left;
   HBLTNode<T> *right;
   T key;
   int h;
};

template <class T>
class HBLTMaxHeap
{
   template <class T>
   friend HBLTNode<T> *meld(HBLTNode<T> **, HBLTNode<T> **);
   template <class T>
   friend void meld(HBLTNode<T> **, HBLTNode<T> **, int);
   template <class T>
   friend void leftUp(HBLTNode<T> **, HBLTNode<T> **);
   template <class T>
   friend void rightUp(HBLTNode<T> **, HBLTNode<T> **);
   template <class T>
   friend void linkCpy(HBLTNode<T> **, HBLTNode<T> **);

public:
   HBLTMaxHeap(T *list, const int size);
   ~HBLTMaxHeap();

   bool isEmpty() { return NULL == root; }
   int size() { return length; }
   HBLTNode<T> *top() { return root; }
   void inorderTraverse();
   void pop();
   void push(const T &);
   void meldTree(HBLTMaxHeap<T> &);

private:
   void clearSubtree(HBLTNode<T> *);
   void output(HBLTNode<T> *);

   HBLTNode<T> *root;
   int length;
};

//#define USE_ITERATE 0

template <class T>
/*
   \mention:   
   1. There are two ways to initialize a 
      HBLTMaxHeap, use #define USE_ITERATE
      to choose the iterative onstructor,
      otherwise the class will choose the 
      default recursive constructor.

   2. Different constructors could build
      different heaps, even though they
      have the same parameters.                
*/
HBLTMaxHeap<T>::HBLTMaxHeap(T *list, const int size)
: length(size){
#ifndef USE_ITERATE //using recursive initialization
   HBLTNode<T> **nodes = new HBLTNode<T> *[size];
   for (int i = 0; i < size; i++){
      nodes[i] = new HBLTNode<T>;
      nodes[i]->key = list[i];
   }

   for (int k = 2; k < size; k *= 2){
      for (int i = 0; i < size - 1; i += k){
         nodes[i] = meld(&(nodes[i]), &(nodes[i + k / 2]));
      }
      if (size % k >= k / 2){
         int m = size - size % k;
         nodes[m - k] = meld(&(nodes[m - k]), &(nodes[m]));
      }
   }

   root = nodes[0];
#else //using iterative initialization
   ArrayQueue<HBLTNode<T> *> q(size);
   //initialize and load nodes  
   for (int i = 0; i < size; i++){
      HBLTNode<T> *node = new HBLTNode<T>(NULL, NULL, list[i]);
      HBLTNode<T> *&ptr = node;
      q.push(ptr);
   }

   for (int i = 0; i < size - 1; i++){
      HBLTNode<T> *r_1 = 
         (q.isEmpty()) ? NULL : q.front();
      q.pop();
      HBLTNode<T> *r_2 = 
         (q.isEmpty()) ? NULL : q.front();
      q.pop();

      HBLTNode<T> *node = meld<T>(0, &r_1, &r_2);
      HBLTNode<T> *&ptr = node;
      q.push(ptr);
   }

   root = q.front();
#endif
}

template <class T>
HBLTMaxHeap<T>::~HBLTMaxHeap(){
   clearSubtree(root);
}

template <class T>
void HBLTMaxHeap<T>::inorderTraverse(){
   output(root);
}

template <class T>
void HBLTMaxHeap<T>::output(HBLTNode<T> *cur){
   if (cur){
      output(cur->left);
      cout << setw(4) << cur->key;
      output(cur->right);
   }
}

template <class T>
void HBLTMaxHeap<T>::clearSubtree(HBLTNode<T> *cur){
   if (cur){
      clearSubtree(cur->left);
      clearSubtree(cur->right);
      delete cur;
   }
}

template <class T>
void HBLTMaxHeap<T>::pop(){
   try{
      if (isEmpty()){
         throw NullHeapException();
      }
   }
   catch (NullHeapException &exc){
      cout << exc.what();
   }

   HBLTNode<T> *del = root;
   root = meld<T>(&(root->left), &(root->right));
   delete del;
}

template <class T>
void HBLTMaxHeap<T>::push(const T &k){
   HBLTNode<T> *new_node = new HBLTNode<T>;
   new_node->key = k;

   root = meld<T>(&root, &new_node);
   length++;
}

template <class T>
void HBLTMaxHeap<T>::meldTree(HBLTMaxHeap<T> &heap){
   root = meld<T>(&root, &(heap.root));
   length += heap.length;
   heap.root = NULL;
   heap.length = 0;
}

template <class T>
/*
   \fn meld(HBLTNode<T> *r_1, HBLTNode<T> *r_2) 
   \return pointer to the root node of the
   new tree.

   \pre     r_1 and r_2 are roots of two distinct trees.
   \brief: merge two HBLT trees.
   \param r_1 A max heap and also a HBLT tree to be merged.
   \param r_2 The same as @param r_1.
   \post    two trees are merged together.
*/
HBLTNode<T> *meld(HBLTNode<T> **r_1, HBLTNode<T> **r_2){
   //if one of two (sub)trees is empty,
   //skip;
   if (*r_1 == NULL){
      *r_1 = *r_2;
      return *r_1;
   }
   if (*r_2 == NULL){
      return *r_1;
   }

   /*Maintain max heap property*/
   //make sure that r_1->key >= r_2->key
   if ((*r_1)->key < (*r_2)->key){
      swap<HBLTNode<T> *>(r_1, r_2);
   }

   //recursive
   (*r_1)->right = meld(&((*r_1)->right), r_2);

   /*maintain HBLT property*/
   if ((*r_1)->left != NULL){
      if ((*r_1)->left->h < (*r_1)->right->h){
         //fix HBLT property: left.h >= right.h
         swap<HBLTNode<T> *>(&((*r_1)->left), &((*r_1)->right));
      }
      //update r_1->h
      (*r_1)->h = (*r_1)->right->h + 1;
   }
   else{//left subtree of r_1 is empty
      (*r_1)->left = (*r_1)->right;
      (*r_1)->right = NULL;
      (*r_1)->h = 1;
   }

   return *r_1;
}

template <class T>
/*
   \fn      meld(HBLTNode<T> **r_1, HBLTNode<T> **r_2, int = 0)
   \return  pointer to root node of the merged tree.
   \pre     r_1 and r_2 are roots of two distinct trees.
   \brief   A iterative version of function 
            meld(HBLTNode<T> **r_1, HBLTNode<T> **r_2).
   \post    two trees are merged together.
   \mention When you want to use this iterative version, 
            remember to add a zero at the beginning of the 
            formal parameter list.
*/
HBLTNode<T> *meld(int m, HBLTNode<T> **r_1, HBLTNode<T> **r_2){
  //stack to store all the points that 've been changed.
   ArrayStack<HBLTNode<T> *> check_points;

   if ((*r_1)->h < (*r_2)->h){
      swap<HBLTNode<T> *>(r_1, r_2);
   }
   //temp: a parent node of two subtrees waiting to be merged.
   HBLTNode<T> **temp = new HBLTNode<T> *;
   *temp = new HBLTNode<T>((*r_1), (*r_2));
   //p: parent node of temp
   HBLTNode<T> **p = new HBLTNode<T> *;

   while (*r_1 != NULL && *r_2 != NULL){
      if ((*r_1)->h == (*r_2)->h &&
          (*r_1)->key > (*r_2)->key){
         (*temp)->left = *r_2;
         (*temp)->right = *r_1;
         swap<HBLTNode<T> *>(r_1, r_2);
      }

      if ((*r_1)->key <= (*r_2)->key){
         *p = *r_2;
         rightUp<T>(temp, p);
      }
      else{
         *p = *r_1;
         leftUp<T>(temp, p);
      }
      check_points.push(*p);

      (*r_1) = (*temp)->left;
      (*r_2) = (*temp)->right;
   }

   (*p)->right = ((*r_1) == NULL) ? (*r_2) : (*r_1);

   //recover
   HBLTNode<T> *res = NULL;
   while (!check_points.isEmpty()){
      res = check_points.top();
      check_points.pop();
      res->h = (res->right) ? res->right->h + 1 : 1;
   }

   delete (*temp);
   delete temp;
   delete p;

   return res;
}

template <class T>
/*
   \fn leftUp(HBLTNode<T> **down, HBLTNode<T> **up)
   \brief: Exchange the position of a parent node and
   a left child node.
   \param down A left (child) node.
   \param up   A parent node whose left child is @param down.
*/
void leftUp(HBLTNode<T> **down, HBLTNode<T> **up){
   HBLTNode<T> *r = (*down)->right;
   linkCpy(down, up);
   (*up)->left = *down;
   (*up)->right = r;
}

template <class T>
/*
   \fn rightUp(HBLTNode<T> **temp, HBLTNode<T> **p)
   \brief: Exchange the position of a parent node and
   a right child node.
   \param down A right (child) node.
   \param up   A parent node whose right child is @param down.
*/
void rightUp(HBLTNode<T> **down, HBLTNode<T> **up){
   HBLTNode<T> *r = (*down)->left;
   linkCpy(down, up);
   (*up)->left = r;
   (*up)->right = *down;
}

template <class T>
void linkCpy(HBLTNode<T> **dest, HBLTNode<T> **src){
   (*dest)->left = (*src)->left;
   (*dest)->right = (*src)->right;
}

#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值