ヒープソートの実装

はじめに

C++ を勉強したり、久々にコードを書いたりしている経緯で、
練習用に、[Cormen+Leiserson+Rivest+Stein 01] Introduction to Algorithms 2nd edition の Chap. 6 から、
ヒープソートを実装したので貼り付けました。



サブルーチンの切り分けは、
pp127〜142 に記載の擬似コードにできるだけ忠実にしました。
エレガントで新しいデバッグ技法をほとんど存じ上げない為、
「cout」がデバッグ用に頻出しております。



main 関数内に「/* */」のコメントが膨大にありますが、
これは関数それぞれのテスト用です。
こちらも、エレガントで新しいテスト技法をほとんど存じ上げない為、
こういうテストをしております。



課題

  • エレガントで新しいデバッグ技法とテスト技法を習得する。
  • しっかりしたコーディングスタイルを身に着ける。

ソースコード

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <math.h>

using namespace std;

#define INFTY 99999

/* prototype declarations */
int parent(int);
int left(int);
int right(int);

void hsort(int []);
void max_heapify(int [], int);
void build_max_heap(int []);
void swap(int [], int, int);

int heap_maximum(int []);
int heap_extract_max(int []);

void heap_increase_key(int [], int, int);
void max_heap_insert(int[], int);

void build_max_heap_p(int []);

int heap_size = 4;

/* a main function */
main()
{
  int v[5] = {2, 3, 5, 1, 4};
  int i;

  /* heap sort
  hsort(v);
  for (i = 0; i <= 4; i++)
  cout << v[i] << " ";

  cout << "\n";
  */

  /* build max heap and heap extract max
  build_max_heap(v);
  for (i = 0; i <= heap_size; i++)
  cout << v[i] << " ";

  cout << "\n";
  
  cout << "heap_extract_max = " << heap_extract_max(v) << "\n\n";
  for (i = 0; i <= heap_size ; i++)
  cout << v[i] << " ";

  cout << "\n";
  */

  /* build max heap and increase key and insert key
  build_max_heap(v);
  for (i = 0; i <= heap_size; i++)
  cout << v[i] << " ";

  cout << "\n";
  
  heap_increase_key(v, 4, 8); 
  cout << "heap_increase_key 3 to 8 \n\n";
  for (i = 0; i <= heap_size ; i++)
  cout << v[i] << " ";

  cout << "\n";

  max_heap_insert(v, 3);
  cout << "insert 3 \n\n";
  for (i = 0; i <= heap_size ; i++)
  cout << v[i] << " ";

  cout << "\n";
  */

  /* build max heap' */

  cout << "input \n";

  for (i = 0; i <= heap_size; i++)
  cout << v[i] << " ";

  cout << "\n";

  cout << "build_max_heap' \n";
  build_max_heap_p(v);
  for (i = 0; i <= heap_size; i++)
  cout << v[i] << " ";

  cout << "\n";

  return 0;
}

void hsort(int v[])
{
  int length_v = 4;
  int i, j;
  
  build_max_heap(v);
  cout << "build max heap has done.\n\n";

    for (i = 0; i <=4; i++)
    cout << v[i] << " ";

  cout << "\n";
  cout << "heap_maximum = " << heap_maximum(v) << "\n";

  cout << "a main routine of a heap sort starts.\n\n";
  
  for (i = length_v; i >= 2; i--) {
    cout << "length_v are down to 2. Now i = " << i << "\n";
    swap(v, 0, i);
    cout << "swap(v, 0, i): i = " << i << "\n";
 
    for (j = 0; j <= heap_size; j++){
    cout << v[j] << " ";
    }
    cout << "\n";

    heap_size--;
    max_heapify(v, 0);
  }
}

void max_heapify(int v[], int i)
{
  int l = left(i);
  int r = right(i);
  int largest;

  if ((l <= heap_size) && (v[l] > i)){
    largest = l;
    cout << "a largest is left:" << l << "\n";  
  }
  else {
    largest = i;
    cout << "a largest is i:" << i << "\n";  
  }
  if ((r <= heap_size) && (v[r] > v[largest])){
    largest = r;
    cout << "a largest is right:" << r << "\n";  
  }
  if (largest != i){
    cout << "Since a largest is not i, swap and max_heapify:" << i <<"\n";  
    swap(v, i, largest);

    for (i = 0; i <=4; i++)
    cout << v[i] << " ";

  cout << "\n";

  cout << "Now, max_heapify recursively calls max heapify.\n";

    max_heapify(v, largest);
  }
}

void build_max_heap(int v[])
{
  int length_v = 4;
  int i;

  for (i = int(floor(length_v / 2) - 1); i >= 0; i--){
    cout << "build max heap: i = " << i << " max heapify starts.\n";
    max_heapify(v, i);
    cout << "\n\n";
  }
}

void swap(int v[], int i, int j)
{
  int temp; 

  temp = v[i];
  v[i] = v[j];
  v[j] = temp;
  cout << i << " and " << j << " are swapped. \n";
}

int parent(int i)
{
  cout << "a parent is " << int(floor((i - 1) / 2)) << "\n"; 
  return int(floor((i - 1) / 2));
}

int left(int i)
{
  cout << "a left is " << 2 * i + 1 << "\n"; 
  return 2 * i + 1;
}

int right(int i)
{
  cout << "a right is " << 2 * i + 2 << "\n"; 
  return 2 * i + 2;
}

int heap_maximum(int v[])
{
  return v[0];
}

int heap_extract_max(int v[])
{
  int max;

  if (heap_size < 0) {
    cout << "heap underflow \n";
  }

  max = v[0];
  v[0] = v[heap_size];
  heap_size--;
  max_heapify(v, 0);
  return max;
}

void heap_increase_key(int v[], int i, int key)
{
  if (key < v[i]) {
    cout << "new key is smaller than current key\n";
  }
  v[i] = key;
  while ((i > 0) && v[parent(i)] < v[i]) {
    swap(v, i, parent(i));
    i = parent(i);
  }
}

void max_heap_insert(int v[], int key)
{
  heap_size++;
  v[heap_size] = -INFTY;
  heap_increase_key(v, heap_size, key);
}

void build_max_heap_p(int v[])
{
  int i;

  heap_size = 0;
  for (i = 1; i <= 4; i++){
    max_heap_insert(v, v[i]);
  }
}