【问题标题】:How would I edit this code to make it possible for a min heap?我将如何编辑此代码以使最小堆成为可能?
【发布时间】:2023-03-23 22:44:01
【问题描述】:

我有一个最大堆,但我想编辑代码以使创建最小堆成为可能。需要明确的是,我想让从 Max 堆到 Min 堆的切换变得容易,因为我会将它用于两个单独的优先级队列,一个基于 Min,另一个基于 Max。

这是我的 Heap.cpp

// *********************************************************
// Implementation file Heap.cpp for the ADT heap.
// *********************************************************
#include "Heap.h"  // header file for heap

heapClass::heapClass() : Size(0)
{
}  // end default constructor

bool heapClass::HeapIsEmpty() const
{
return bool(Size == 0);
}  // end HeapIsEmpty

void heapClass::HeapInsert(const heapItemType& NewItem,
                       bool& Success)
// Method: Inserts the new item after the last item in the
// heap and trickles it up to its proper position. The
// heap is full when it contains MAX_HEAP items.
{
Success = bool(Size < MAX_HEAP);

if (Success)
{  // place the new item at the end of the heap
    Items[Size] = NewItem;

    // trickle new item up to its proper position
    int Place = Size;
    int Parent = (Place - 1)/2;
    while ( (Parent >= 0) &&
           (Items[Place].Key() > Items[Parent].Key()) )
    {  // swap Items[Place] and Items[Parent]
        heapItemType Temp = Items[Parent];
        Items[Parent] = Items[Place];
        Items[Place] = Temp;

        Place = Parent;
        Parent = (Place -1 )/2;
    }  // end while

    ++Size;
}  // end if
}  // end HeapInsert

void heapClass::HeapDelete(heapItemType& RootItem,
                       bool& Success)
// Method: Swaps the last item in the heap with the root
// and trickles it down to its proper position.
{
Success = bool(!HeapIsEmpty());

if (Success)
{  RootItem = Items[0];
    Items[0] = Items[--Size];
    RebuildHeap(0);
}  // end if
}  // end HeapDelete

void heapClass::RebuildHeap(int Root)
{
// if the root is not a leaf and the root's search key
// is less than the larger of the search keys in the
// root's children
int Child = 2 * Root + 1;  // index of root's left
// child, if any
if ( Child < Size )
{  // root is not a leaf, so it has a left child at Child
    int RightChild = Child + 1;  // index of right child,
    // if any

    // if root has a right child, find larger child
    if ( (RightChild < Size) &&
        (Items[RightChild].Key() > Items[Child].Key()) )
        Child = RightChild;  // index of larger child

    // if the root's value is smaller than the
    // value in the larger child, swap values
    if ( Items[Root].Key() < Items[Child].Key() )
    {  heapItemType Temp = Items[Root];
        Items[Root] = Items[Child];
        Items[Child] = Temp;

        // transform the new subtree into a heap
        RebuildHeap(Child);
    }  // end if
   }  // end if

// if root is a leaf, do nothing
}  // end RebuildHeap

堆.h

 // *********************************************************
 // Header file Heap.h for the ADT heap.
// *********************************************************

#include "Data.h"  // definition of itemClass
#include "PrecondViolatedExcep.h"

#pragma once

const int MAX_HEAP = 20;
typedef itemClass keyType;

typedef itemClass heapItemType;

class heapClass
{
public:
heapClass();  // default constructor
// copy constructor and destructor are
// supplied by the compiler

// heap operations:
virtual bool HeapIsEmpty() const;
// Determines whether a heap is empty.
// Precondition: None.
// Postcondition: Returns true if the heap is empty;
// otherwise returns false.

virtual void HeapInsert(const heapItemType& NewItem,
                        bool& Success);
// Inserts an item into a heap.
// Precondition: NewItem is the item to be inserted.
// Postcondition: If the heap was not full, NewItem is
// in its proper position and Success is true;
// otherwise Success is false.

virtual void HeapDelete(heapItemType& RootItem,
                        bool& Success);
// Retrieves and deletes the item in the root of a heap.
// This item has the largest search key in the heap.
// Precondition: None.
// Postcondition: If the heap was not empty, RootItem
// is the retrieved item, the item is deleted from the
// heap, and Success is true. However, if the heap was
// empty, removal is impossible and Success is false.

protected:
void RebuildHeap(int Root);
// Converts the semiheap rooted at index Root
// into a heap.

private:
heapItemType Items[MAX_HEAP];  // array of heap items
int          Size;             // number of heap items
};  // end class
// End of header file.

包含 itemClass 的片段

#include <stdio.h>

#include "Data.h"

/* Put in definitions of methods declared in Data.h
 - modify as you wish. */

/*  ==================================================
 Default constructor
 ================================================== */
itemClass::itemClass() : trackRequest(-100),
serialNum(-1)
{
}

/*  ==================================================
 Constructor
 ================================================== */
itemClass::itemClass(int trkR, int srlNum, bool dir)
: trackRequest(trkR),
 serialNum (srlNum),direction(dir)
{
}

   /*  ==================================================
  Key
  ================================================== */
/* This method returns the search key.
 Here we assume the key is the item itself. */

itemClass itemClass::Key() const
{
return *this ;
}

/*  ==================================================
 Equality Test
 ================================================== */
bool itemClass::operator== (const itemClass& Rhs) const
{
return (trackRequest == Rhs.trackRequest)
&& (serialNum == Rhs.serialNum) && (direction== Rhs.direction);
}

/*  ==================================================
 non-Equality Test
 ================================================== */
bool itemClass::operator!= (const itemClass& Rhs) const
{
return !(*this==Rhs) ;
}

 /*  ==================================================
 Less-Than Test
 ================================================== */
bool itemClass::operator< (const itemClass& Rhs) const
{

   return(trackRequest < Rhs.trackRequest) && (direction      <=Rhs.direction);
//return true;
 }

/*  ==================================================
 Less-Than-Or-Equal Test
 ================================================== */
bool itemClass::operator<= (const itemClass& Rhs) const
{
return (*this<Rhs) || (*this==Rhs) ;
}

 /*  ==================================================
 Greater-Than Test
 ================================================== */
bool itemClass::operator> (const itemClass& Rhs) const
{
return (!(*this<Rhs) && !(*this==Rhs)) ;
/* OR return (Rhs<*this); */
}

/*  ==================================================
 Greater-Than-Or-Equal Test
 ================================================== */
bool itemClass::operator>= (const itemClass& Rhs) const
{
return ( !(*this<Rhs) ) ;
}

【问题讨论】:

  • "Min heap" 究竟能做什么?
  • @Kenney 它会在顶部有最小的元素。
  • @Kenney 插入 heapItemTypes,最小值位于堆的根部。

标签: c++ c++11 data-structures heap priority-queue


【解决方案1】:

您想要做的是让您的heapClass 构造函数采用一个比较函子,您可以将其保存在您的班级内部。然后让您的 heapClass 函数使用仿函数进行比较。您可以默认它,以便它占用您的itemClass 中的operator&lt;。但是你也可以传入operator&gt;来切换排序。

例如,看一下 Compare functor 如何传递给 std::set 以定义它的排序 http://en.cppreference.com/w/cpp/container/set

【讨论】:

    【解决方案2】:

    有一些简单的方法。一种方法是将仿函数参数添加到heapClass 以进行比较。

    template <typename Compare = std::greater<itemClass>>
    class heapClass {
    
      private:
    
        Compare cmp;
    
      public:
    
        heapClass(Compare cmp = Compare()) : cmp(cmp);
    
        void HeapInsert(const heapItemType& NewItem,
                             bool& Success)
          // Method: Inserts the new item after the last item in the
          // heap and trickles it up to its proper position. The
          // heap is full when it contains MAX_HEAP items.
          {
          Success = bool(Size < MAX_HEAP);
    
          if (Success)
          {  // place the new item at the end of the heap
              Items[Size] = NewItem;
    
              // trickle new item up to its proper position
              int Place = Size;
              int Parent = (Place - 1)/2;
              while ( (Parent >= 0) &&
                     (cmp(Items[Place].Key(), Items[Parent].Key())) )
              {  // swap Items[Place] and Items[Parent]
                  heapItemType Temp = Items[Parent];
                  Items[Parent] = Items[Place];
                  Items[Place] = Temp;
    
                  Place = Parent;
                  Parent = (Place -1 )/2;
              }  // end while
    
              ++Size;
          }        // end if
        }  // end HeapInsert
    };
    

    另外两种方法是使用std::priority_queue 或std::make_heap、std::heap_pop、std::heap_push 等...两者都可以提供最小堆和最大堆语义。

    【讨论】:

      【解决方案3】:

      现在您的 HeapInsert 函数可以:

      while ( (Parent >= 0) &&
             (Items[Place].Key() > Items[Parent].Key()) )
      

      只需将&gt; 替换为&lt;。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-20
        • 1970-01-01
        • 2016-09-30
        • 1970-01-01
        • 2012-09-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多