アルゴリズム導論コード第6章スタックソート

10050 ワード

第6章スタックの順序付け
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; }