C ++
 Computer >> コンピューター >  >> プログラミング >> C ++

C ++の整数ストリーム(整数の実行)の中央値


問題の説明

整数がデータストリームから読み取られると仮定します。効率的な方法でそのように読み取られた要素の中央値を見つけます

ストリームの最初の要素を読み取った後-10->中央値-10

ストリームの2番目の要素を読み取った後-10、20->中央値-15

ストリームの3番目の要素を読み取った後-10、20、30->中央値-20など...

アルゴリズム

1. Use a max heap on left side to represent elements that are less than effective median,
   and a min heap on right side to represent elements that are greater than effective median
2. After processing an incoming element, the number of elements in heaps differ utmost by 1 element
3. When both heaps contain same number of elements, we pick average of heaps root data as effective median
4. When the heaps are not balanced, we select effective median from the root of heap containing more elements

#include <iostream>
using namespace std;
#define MAX_HEAP_SIZE (128)
#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])
inline void Exch(int &a, int &b){
   int aux = a;
   a = b;
   b = aux;
}
bool Greater(int a, int b){
   return a > b;
}
bool Smaller(int a, int b){
   return a < b;
}
int Average(int a, int b){
   return (a + b) / 2;
}
int Signum(int a, int b){
   if( a == b ) {
      return 0;
   }
   return a < b ? -1 : 1;
}
class Heap{
   public:
      Heap(int *b, bool (*c)(int, int)) : A(b), comp(c){
         heapSize = -1;
      }
      virtual ~Heap(){
         if( A ) {
            delete[] A;
         }
      }
      virtual bool Insert(int e) = 0;
      virtual int GetTop() = 0;
      virtual int ExtractTop() = 0;
      virtual int GetCount() = 0;
      protected:
      int left(int i){
         return 2 * i + 1;
      }
      int right(int i){
         return 2 * (i + 1);
      }
      int parent(int i){
         if( i <= 0 ) {
            return -1;
         }
         return (i - 1)/2;
      }
      int *A;
      bool (*comp)(int, int);
      int heapSize;
      int top(void){
         int max = -1;
         if( heapSize >= 0 ) {
            max = A[0];
         }
         return max;
      }
      int count(){
         return heapSize + 1;
      }
      void heapify(int i){
         int p = parent(i);
         if( p >= 0 && comp(A[i], A[p]) ) {
            Exch(A[i], A[p]);
            heapify(p);
         }
      }
      int deleteTop(){
         int del = -1;
         if( heapSize > -1) {
            del = A[0];
            Exch(A[0], A[heapSize]);
            heapSize--;
            heapify(parent(heapSize+1));
         }
         return del;
      }
      bool insertHelper(int key){
         bool ret = false;
         if( heapSize < MAX_HEAP_SIZE ) {
            ret = true;
            heapSize++;
            A[heapSize] = key;
            heapify(heapSize);
         }
         return ret;
      }
};
class MaxHeap : public Heap{
private:
public:
   MaxHeap() : Heap(new int[MAX_HEAP_SIZE], &Greater) { }
   ~MaxHeap() { }
   int GetTop(){
      return top();
   }
   int ExtractTop(){
      return deleteTop();
   }
   int GetCount(){
      return count();
   }
   bool Insert(int key){
      return insertHelper(key);
   }
};
class MinHeap : public Heap{
private:
public:
   MinHeap() : Heap(new int[MAX_HEAP_SIZE], &Smaller) { }
   ~MinHeap() { }
   int GetTop(){
      return top();
   }
   int ExtractTop(){
      return deleteTop();
   }
   int GetCount(){
      return count();
   }
   bool Insert(int key){
      return insertHelper(key);
   }
};
int getMedian(int e, int &m, Heap &l, Heap &r){
   int sig = Signum(l.GetCount(), r.GetCount());
   switch(sig){
      case 1:
         if( e < m ) {
            r.Insert(l.ExtractTop());
            l.Insert(e);
         } else {
            r.Insert(e);
         }
         m = Average(l.GetTop(), r.GetTop());
         break;
         case 0:
         if( e < m ) {
            l.Insert(e);
            m = l.GetTop();
         } else {
            r.Insert(e);
            m = r.GetTop();
         }
         break;
         case -1:
         if( e < m ) {
            l.Insert(e);
         } else { 
            l.Insert(r.ExtractTop());
            r.Insert(e);
         }
         m = Average(l.GetTop(), r.GetTop());
         break;
      }
   return m;
}
void printMedian(int A[], int size){
   int m = 0;
   Heap *left = new MaxHeap();
   Heap *right = new MinHeap();
   for(int i = 0; i < size; ++i) {
      m = getMedian(A[i], m, *left, *right);
      cout << m << endl;
   }
   delete left;
   delete right;
}
// Driver code
int main(){
   int A[] = {10, 20, 30};
   int size = ARRAY_SIZE(A);
   cout "Result:\n";
   printMedian(A, size);
   return 0;
}
出力 上記のプログラムをコンパイルして実行する場合。次の出力を生成します-

Result:
10
15
20

  1. C++でカウントソートを使用した中央値と最頻値

    サイズnの配列があるとすると、カウントソート手法を使用して中央値と最頻値を見つける必要があります。この手法は、配列要素が限られた範囲にある場合に役立ちます。要素が{1、1、1、2、7、1}であり、最頻値が1、中央値が1.5であるとします。中央値とは何か、最頻値とは何かを見てみましょう- 中央値は、並べ替えられた数値リストの中央値です モードは、リスト内で出現回数が最大の要素です 中央値と最頻値を取得するには、次の手順に従う必要があります- 入力配列のサイズがnであると想定します 前のカウントを次のインデックスに合計する前に、カウント配列を取得します 格納されている最大値のインデックスは

  2. C++でのstatic_cast

    static_castは、通常/通常の型変換に使用されます。これは、暗黙的な型強制の原因となるキャストでもあり、明示的に呼び出すこともできます。 floatをintに、charをintに変換する場合などに使用する必要があります。これにより、関連する型クラスをキャストできます。 例 #include <iostream> using namespace std; int main() {    float x = 4.26;    int y = x; // C like cast    int z = static_cas