アルゴリズム導論コード第6章スタックソート
10050 ワード
第6章スタックの順序付け
6.4スタック並べ替えアルゴリズム
6.5優先キュー
6.5.1優先キュー
6.5.2インデックス・スタック・ベースの優先キュー
6.4スタック並べ替えアルゴリズム
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
int parent(int i)
{
return (i - 1) / 2;
}
int left_child(int i)
{
return i * 2 + 1;
}
int right_child(int i)
{
return i * 2 + 2;
}
void swap(void *a, void *b, size_t elem_size)
{
if(a==NULL||b==NULL||a==b)
return;
char temp[elem_size]; /* */
memcpy(temp, a, elem_size);
memcpy(a, b, elem_size);
memcpy(b, temp, elem_size);
}
void max_heapify(void *base, size_t elem_size, int i, int heap_size,
int (*comp) (const void *, const void *))
{
char *cbase = base;
int left = left_child(i);
int right = right_child(i);
int largest = i;
if (left < heap_size
&& comp(&cbase[largest * elem_size],
&cbase[left * elem_size]) < 0) {
largest = left;
}
if (right < heap_size
&& comp(&cbase[largest * elem_size],
&cbase[right * elem_size]) < 0) {
largest = right;
}
if (largest != i) {
swap(&cbase[i * elem_size], &cbase[largest * elem_size],
elem_size);
max_heapify(base, elem_size, largest, heap_size, comp);
}
}
void build_max_heap(void *base, size_t elem_size, int length,
int (*comp) (const void *, const void *))
{
int heap_size = length;
for (int i = parent(length - 1); i >= 0; i--) {
max_heapify(base, elem_size, i, heap_size, comp);
}
}
void heap_sort(void *base, size_t elem_size, int length,
int (*comp) (const void *, const void *))
{
char *cbase = base;
build_max_heap(base, elem_size, length, comp);
int heap_size = length;
for (int i = length - 1; i > 0; i--) {
swap(&cbase[i * elem_size], &cbase[0 * elem_size], elem_size);
--heap_size;
max_heapify(base, elem_size, 0, heap_size, comp);
}
}
void randomized_in_place(void *array, size_t elem_size, int length)
{
char *carray = array;
for (int i = 0; i < length; i++) {
int n_rand_index = rand() % (length - i) + i;
swap(&carray[i * elem_size], &carray[n_rand_index * elem_size],
elem_size);
}
}
void print_array(int a[], int length)
{
for (int i = 0; i < length; i++) {
printf("%d ", a[i]);
}
printf("
");
}
int cmp_int(const void *p1, const void *p2)
{
const int *pa = p1;
const int *pb = p2;
if (*pa < *pb)
return -1;
if (*pa == *pb)
return 0;
return 1;
}
int main(void)
{
srand((unsigned)time(NULL));
int a[10];
for (int i = 0; i < 10; i++) {
a[i] = i;
}
randomized_in_place(a, sizeof(int), 10);
printf(" :
");
print_array(a, 10);
heap_sort(a, sizeof(int), 10, cmp_int);
printf(" :
");
print_array(a, 10);
return 0;
}
6.5優先キュー
6.5.1優先キュー
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
typedef struct priority_queue_type *priority_queue;
struct priority_queue_type {
int heap_size;
void **array;
int (*comp) (const void *, const void *);
};
int parent(int i)
{
return (i - 1) / 2;
}
int left_child(int i)
{
return i * 2 + 1;
}
int right_child(int i)
{
return i * 2 + 2;
}
void swap(void *a, void *b, size_t elem_size)
{
if(a==NULL||b==NULL||a==b)
return;
char temp[elem_size]; /* */
memcpy(temp, a, elem_size);
memcpy(a, b, elem_size);
memcpy(b, temp, elem_size);
}
void heapify(priority_queue pq, int i)
{
int left = left_child(i);
int right = right_child(i);
int largest = i;
if (left < pq->heap_size
&& pq->comp(pq->array[largest], pq->array[left]) < 0) {
largest = left;
}
if (right < pq->heap_size
&& pq->comp(pq->array[largest], pq->array[right]) < 0) {
largest = right;
}
if (largest != i) {
swap(&pq->array[i], &pq->array[largest], sizeof(void *));
heapify(pq, largest);
}
}
void fix_up(priority_queue pq, int i)
{
while (i > 0 && pq->comp(pq->array[parent(i)], pq->array[i]) < 0) {
swap(&pq->array[parent(i)], &pq->array[i], sizeof(void *));
i = parent(i);
}
}
priority_queue priority_queue_create(int n_length,
int (*comp) (const void *, const void *))
{
priority_queue pq = malloc(sizeof(struct priority_queue_type));
pq->array = malloc(sizeof(void *) * n_length);
pq->heap_size = 0;
pq->comp = comp;
return pq;
}
void *priority_queue_top(priority_queue pq)
{
return pq->array[0];
}
/* */
void *priority_queue_extract_top(priority_queue pq)
{
swap(&pq->array[0], &pq->array[pq->heap_size - 1], sizeof(void *));
--pq->heap_size;
heapify(pq, 0);
return pq->array[pq->heap_size];
}
/* key */
void priority_queue_insert(priority_queue pq, void *key)
{
++pq->heap_size;
int i = pq->heap_size - 1;
memcpy(&pq->array[i], &key, sizeof(void *));
fix_up(pq, i);
}
bool priority_queue_is_empty(priority_queue pq)
{
return pq->heap_size == 0;
}
void priority_queue_destroy(priority_queue pq, void (*free_key) (void *))
{
while (!priority_queue_is_empty(pq)) {
void *p = priority_queue_extract_top(pq);
free_key(p);
}
free(pq->array);
free(pq);
}
int cmp_int(const void *p1, const void *p2)
{
const int *pa = p1;
const int *pb = p2;
if (*pa < *pb)
return -1;
if (*pa == *pb)
return 0;
return 1;
}
int main()
{
priority_queue pq = priority_queue_create(10, cmp_int);
for (int i = 0; i < 10; i++) {
int *p = malloc(sizeof(int));
*p = i;
priority_queue_insert(pq, p);
}
printf(" :
");
while (!priority_queue_is_empty(pq)) {
int *p = priority_queue_extract_top(pq);
printf("%d ", *p);
free(p);
}
printf("
");
priority_queue_destroy(pq, free);
return 0;
}
6.5.2インデックス・スタック・ベースの優先キュー
#include <stdio.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
/* */
typedef struct priority_queue_index_type *priority_queue;
struct priority_queue_index_type {
int heap_size;
int *index_array;
int *index_pos_array; /* */
void *data_array;
size_t elem_size;
int (*comp) (const void *, const void *);
};
static int parent(int i)
{
return (i - 1) / 2;
}
static int left_child(int i)
{
return i * 2 + 1;
}
static int right_child(int i)
{
return i * 2 + 2;
}
void swap(void *a, void *b, size_t elem_size)
{
if(a==NULL||b==NULL||a==b)
return;
char temp[elem_size]; /* */
memcpy(temp, a, elem_size);
memcpy(a, b, elem_size);
memcpy(b, temp, elem_size);
}
static void swap_index(priority_queue pq, int i, int j)
{
swap(&pq->index_pos_array[i], &pq->index_pos_array[j], sizeof(int));
pq->index_array[pq->index_pos_array[i]] = i;
pq->index_array[pq->index_pos_array[j]] = j;
}
/* */
static bool compare(priority_queue pq, int left, int right)
{
if (pq->data_array == NULL)
return false;
char *pc_array = pq->data_array;
return pq->comp(&pc_array[left * pq->elem_size],
&pc_array[right * pq->elem_size]) > 0;
}
static void heapify(priority_queue pq, int i)
{
int left = left_child(i);
int right = right_child(i);
int largest = i;
if (left < pq->heap_size
&& compare(pq, pq->index_array[largest], pq->index_array[left])) {
largest = left;
}
if (right < pq->heap_size
&& compare(pq, pq->index_array[largest], pq->index_array[right])) {
largest = right;
}
if (largest != i) {
swap_index(pq, pq->index_array[i], pq->index_array[largest]);
heapify(pq, largest);
}
}
static void fix_up(priority_queue pq, int i)
{
while (i > 0
&& compare(pq, pq->index_array[parent(i)], pq->index_array[i])) {
swap_index(pq, pq->index_array[parent(i)], pq->index_array[i]);
i = parent(i);
}
}
priority_queue priority_queue_create(void *p_data_array, size_t elem_size,
int length, int (*comp) (const void *,
const void *))
{
priority_queue pq = malloc(sizeof(struct priority_queue_index_type));
pq->index_array = malloc(sizeof(int) * length);
pq->index_pos_array = malloc(sizeof(int) * length);
pq->data_array = p_data_array;
pq->elem_size = elem_size;
pq->heap_size = 0;
pq->comp = comp;
return pq;
}
void priority_queue_destroy(priority_queue pq)
{
free(pq->index_array);
free(pq->index_pos_array);
free(pq);
}
int priority_queue_top(priority_queue pq)
{
return pq->index_array[0];
}
/* */
int priority_queue_extract_top(priority_queue pq)
{
swap_index(pq, pq->index_array[0], pq->index_array[pq->heap_size - 1]);
--pq->heap_size;
heapify(pq, 0);
return pq->index_array[pq->heap_size];
}
/* */
void priority_queue_insert(priority_queue pq, int index)
{
++pq->heap_size;
int i = pq->heap_size - 1;
pq->index_array[i] = index;
pq->index_pos_array[index] = i;
fix_up(pq, i);
}
bool priority_queue_is_empty(priority_queue pq)
{
return pq->heap_size == 0;
}
/* index , */
void priority_queue_change_index(priority_queue pq, int index)
{
fix_up(pq, pq->index_pos_array[index]);
heapify(pq, pq->index_pos_array[index]);
}
int cmp_int(const void *p1, const void *p2)
{
const int *pa = p1;
const int *pb = p2;
if (*pa < *pb)
return -1;
if (*pa == *pb)
return 0;
return 1;
}
int g_array[10];
int main()
{
priority_queue pq =
priority_queue_create(g_array, sizeof(int), 10, cmp_int);
for (int i = 0; i < 10; i++) {
g_array[i] = 100+i;
/* i pq */
priority_queue_insert(pq, i);
}
/* chang_index , , */
int change_index = 5;
g_array[change_index] = INT_MAX;
priority_queue_change_index(pq, change_index);
printf(" :
");
while (!priority_queue_is_empty(pq)) {
printf("%d ", g_array[priority_queue_extract_top(pq)]);
}
printf("
");
priority_queue_destroy(pq);
return 0;
}