算法导论代码 第6章 堆排序

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("\n");
}

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("排序前:\n");
	print_array(a, 10);
	heap_sort(a, sizeof(int), 10, cmp_int);
	printf("排序后:\n");
	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("最大堆结果:\n");
	while (!priority_queue_is_empty(pq)) {
		int *p = priority_queue_extract_top(pq);
		printf("%d ", *p);
		free(p);
	}
	printf("\n");
	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("最小堆结果:\n");
	while (!priority_queue_is_empty(pq)) {
		printf("%d ", g_array[priority_queue_extract_top(pq)]);
	}
	printf("\n");
	priority_queue_destroy(pq);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值