Foundation: Comparison Counting Sort

#include "distribution_counting.h"

/* [Distribution Counting Sort] 
 * First used with radix sorting by H.Seward, 1954.
 * Then published with "Mathsort" by W.Feurzeig, CACM 3 (1960), 601
 */


static int *counting_table = NULL;
static int cur_table_len = 0;

static int
create_counting_table(int cnt)
{
	F_S();

	counting_table = (int*)malloc(sizeof(int) * cnt);
	if(counting_table == NULL) {
		debug("malloc failed. [%s] \r\n", __FUNCTION__);
		return 0;
	}

	cur_table_len = cnt;

	F_E();

	return 1;
}

void
free_counting_table(void)
{
	F_S();

	if (counting_table == NULL) return;
	free(counting_table);
	counting_table = NULL;
	cur_table_len = 0;

	F_E();
}


/* we guess all the items located in [@min, @max],
 * and do the counting for sorting.
 */
int* 
do_distribution_counting_sort(void* src, int src_sz, int item_cnt, int min, int max, void *out, 
							  GET_ITEM_FUNC get_item, SET_ITEM_FUNC set_item)
{
	int rt;
	int i,j;
	char *li,*ri;
	long ki;
	
	F_S();

	if (src == NULL || src_sz <= 0 || item_cnt <= 0) return NULL;
	if (min < 0 || max <= 0 || min > max) return NULL;


	/* try create auxiliary table for counting
	 */
	if (counting_table == NULL) {
        rt = create_counting_table(max+1);
		if (!rt) return NULL;
	}
	else {
		if (max > cur_table_len) {
			free_counting_table();
			rt = create_counting_table(max+1);
			if (!rt) return NULL;
		}
	}


	/* clear auxiliary table as boundary
	 */
	for (i = min; i <= max; ++i) counting_table[i] = 0;


	/* loop and increase
	 */
	for (i = 0, li = (char*)src; i < item_cnt; ++i, li += src_sz) {

		ki = get_item(li);
		if (ki < 0) {
			debug("Tip: do not support nagative number.\r\n");
			return NULL;
		}

		if (ki < min) {
			debug("Tip: the minimal counting boundary is too big.\r\n");
			return NULL;
		}

		if (ki >= max) {
			debug("Tip: not malloced enough aux table. \r\n");
			return NULL;
		}

		counting_table[ki]++;
	}


	/* accumulate
	 */
	for (j = min+1; j <= max; ++j) counting_table[j] += counting_table[j-1];


	/* loop and output
	 */
	for (i = 0, li = (char*)src; i < item_cnt; ++i, li += src_sz) {

		ki = get_item(li);
		j = --counting_table[ki];
		ri = (char*)out + j * src_sz;
		set_item(ri,ki);
	}


	F_E();

	return counting_table;
}

#ifdef DISTRIBUTION_COUNTING_SORT_DEBUG

long
get_int_item(void *src)
{
	return (long)*(int*)src;
}

void
set_int_item(void *src, long val)
{
	*(int*)src = (int)val;
}

long
get_char_item(void *src)
{
	return (long)*(char*)src;
}

void
set_char_item(void *src, long val)
{
	*(char*)src = (char)val;
}

int
main(int argc, char* argv[])
{
	int i,j,k;
	int cnt;
	int* counting_table;
	int min,max;
	const int int_items[16] = { 503, 87, 512, 61, 908, 170, 897, 275, 
		                        653, 426, 154, 509, 612, 677, 765, 703
	                          };
	char *char_items = "hello world";

	int out[16];
	char char_out[16];

	min = 80;
	max = 512;

	debug("[Testing distribution counting sort].. \r\n");

	cnt = sizeof(int_items)/sizeof(int_items[0]);

	debug("src database:\r\n----\r\n");
	for (i = 0; i < cnt; ++i) {
		debug("%d ", int_items[i]);
	}
	debug("\r\n----\r\n");


	counting_table = do_distribution_counting_sort((void*)int_items, sizeof(int), cnt, 
													min, max, out,
													get_int_item, set_int_item);
	if (counting_table == NULL) {
		min = 0;
		max = 1024;
		counting_table = do_distribution_counting_sort((void*)int_items, sizeof(int), cnt, 
														min, max, out,
														get_int_item, set_int_item);
		if (counting_table == NULL) {
			debug("do comparison counting sor failed. \r\n");
			goto END;
		}
	}

	debug("dst database:\r\n----\r\n");
	for (i = 0; i < cnt; ++i) {
		debug("%d ", out[i]);
	}
	debug("\r\n----\r\n");

	debug("\r\n");


	min = 0;
	max = 256;

	debug("[Testing distribution counting sort].. \r\n");

	cnt = strlen(char_items);

	debug("src database:\r\n----\r\n");
	for (i = 0; i < cnt; ++i) {
		debug("%c ", char_items[i]);
	}
	debug("\r\n----\r\n");


	counting_table = do_distribution_counting_sort((void*)char_items, sizeof(char), cnt, 
													min, max, char_out,
													get_char_item, set_char_item);
	if (counting_table == NULL) {
		debug("do comparison counting sor failed. \r\n");
		goto END;
	}

	debug("dst database:\r\n----\r\n");
	for (i = 0; i < cnt; ++i) {
		debug("%c ", char_out[i]);
	}
	debug("\r\n----\r\n");

	debug("\r\n");
	free_counting_table();

	debug("[Testing distribution counting sort]..done. \r\n");

END:
	while(1);
	return 0;
}

#endif /* COMPARISON_COUNTING_SORT_DEBUG */
#ifndef __COMPARISON_COUNTING_SORT_H__
#define __COMPARISON_COUNTING_SORT_H__

#define COMPARISON_COUNTING_SORT_DEBUG

#define MAX_TABLE_LEN 1024

typedef int(*cmp_func)(void*,void*);

int* do_cmp_counting_sort(void* src, int src_sz, int n, cmp_func cmp);

#endif /* __COMPARISON_COUNTING_SORT_H__ */
#include 
#include 
#include 
#include 
#include 
#include 

#define MY_DEBUG
#ifdef MY_DEBUG
#define debug printf
#else
#define debug(x,argc, __VA_ARGS__)	;
#endif /* MY_DEBUG */

#define F_S() debug("[%s]..\r\n", __FUNCTION__)
#define F_E() debug("[%s]..done. \r\n", __FUNCTION__)

 

Foundation: Comparison Counting Sort_第1张图片

Mars

Sep 8th, 2013
Any to share, e-me: [email protected]

你可能感兴趣的:(algorithm,codes)