⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myquicksort.c

📁 提供了rbtree ttree avltree list hashtable等常用容器的算法,代码经过uclinux + arm44b0平台验证
💻 C
字号:
/**
 *
 * @file MyQuickSort.c 快速排序
 *
 * @author lin shao chuan (email:lsccsl@tom.com, msn:lsccsl@163.net)
 *
 */
#include "MyAlgorithm.h"
#include <assert.h>
#include "mymempool.h"
#include "myutility.h"
#include "__def_fun_def.h"


#define THRESHOLD 16


typedef struct __quick_sort_cal_session_
{
	/*
	* 记录处理区间
	*/
	size_t start;
	size_t end;

	/*
	* 记录当前剩余的递归次数
	*/
	size_t depth_limit;
}quick_sort_cal_session;

typedef struct __quick_sort_stack_t_
{
	/*
	* 栈的起始地址与大小
	*/
	quick_sort_cal_session * s;
	size_t s_size;

	/*
	* 栈顶指针
	*/
	size_t top;
}quick_sort_stack_t;


/**
 * @brief 创建栈
 */
static __INLINE__ quick_sort_stack_t * quick_sort_stack_create(size_t dep_limit)
{
	quick_sort_stack_t * s = (quick_sort_stack_t *)MyMemPoolMalloc(NULL, sizeof(*s));

	s->s_size = (dep_limit + 1) * 2;
	s->s = (quick_sort_cal_session *)MyMemPoolMalloc(NULL, s->s_size * sizeof(quick_sort_cal_session));
	s->top = 0;

	return s;
}

/**
 * @brief 销毁栈
 */
static __INLINE__ void quick_sort_stack_destroy(quick_sort_stack_t * s)
{
	assert(s);

	MyMemPoolFree(NULL, s->s);

	MyMemPoolFree(NULL, s);
}

/**
 * @brief 入栈
 */
static __INLINE__ void quick_sort_stack_push(quick_sort_stack_t * s, quick_sort_cal_session * cs)
{
	assert(s && cs && s->top < s->s_size);

	s->s[s->top] = *cs;
	s->top ++;
}

/**
 * @brief 出栈
 */
static __INLINE__ void quick_sort_stack_pop(quick_sort_stack_t * s, quick_sort_cal_session * cs)
{
	assert(s && cs);

	*cs = s->s[s->top - 1];

	s->top --;
}

/**
 * @brief 判断栈是否为空
 */
static __INLINE__ int quick_sort_stack_empty(quick_sort_stack_t * s)
{
	assert(s);

	return (s->top == 0);
}


/**
 * @brief 计算2的对数 用于计算快速排序时的最大递归次数,防止出现恶化的现象
 */
static __INLINE__ size_t __lg__(size_t v)
{
	size_t ret = 0;
	for(; v > 1; v >>= 1)
		ret ++;

	return ret;
}

/**
 * @brief 三点中值
 */
static __INLINE__ void * __median__(void * a, void * b, void * c,
									ALG_COMPARE compare, const void * context)
{
	assert(a && b && c && compare);

	if(compare(a ,b, context) > 0)
	{
		if(compare(a, c, context) > 0)
			return a;
		else
			return c;
	}
	else
	{
		if(compare(b, c, context) > 0)
			return b;
		else
			return c;
	}
}

/**
 * @brief 根据value_patition的值的出分割点
 */
static __INLINE__ size_t _partition_(void * buf, size_t start, size_t end, size_t step_size,
								   ALG_COMPARE compare, ALG_SWAP swaper,
								   const void * value_partition,
								   const void * context)
{
	assert(buf && (start < end) && compare && swaper && value_partition);

	while(1)
	{
		while(compare(value_partition, GET_INDEX_PTR(buf, start, step_size), context) > 0)
			start ++;

		while(compare(GET_INDEX_PTR(buf, end, step_size), value_partition, context) > 0)
			end --;

		if(start >= end)
			return start;

		swaper(GET_INDEX_PTR(buf, start, step_size), GET_INDEX_PTR(buf, end, step_size), step_size, context);

		start ++;
	}
}

/**
 * @brief 根据len大小计算递归次数,防止出现分区恶化的情况递归调用快速排序
 *
 * @todo 如果len小于一个临界值(假设为16)采用插入式排序
 */
static __INLINE__ int quick_sort(void * buf, size_t len, size_t step_size,
					  ALG_COMPARE compare, ALG_SWAP swaper, ALG_MOVE move, ALG_COPY copier,
					  const void * context, void * swap_buf, size_t swap_buf_size)
{
	quick_sort_cal_session cs = {0};
	quick_sort_stack_t * _stack = NULL;
	size_t start = 0;
	size_t end = len - 1;

	/*
	* 计算递归次数
	*/
	size_t dep_limit = __lg__(len);

	assert(buf && compare && swap_buf && swap_buf_size >= step_size);
	assert(swaper && move && copier);

	/*
	* 创建栈
	*/
	_stack = quick_sort_stack_create(dep_limit);

	/*
	* 初始信息入栈
	*/
	cs.depth_limit = dep_limit;
	cs.start = 0;
	cs.end = len - 1;
	quick_sort_stack_push(_stack, &cs);

	while(!quick_sort_stack_empty(_stack))
	{
		void * middle = NULL;
		size_t cut = 0;
		size_t start = 0;
		size_t end = 0;

		/*出栈*/
		quick_sort_stack_pop(_stack, &cs);

		start = cs.start;
		end = cs.end;
		assert(start < len && end < len && end >= start);

		/**
		 * 如果当前区间的大小小于一个值(如16) 直接用插入式排序完成这一子区间的排序
		 */
		if(end - start <= THRESHOLD)
		{
			MyAlgInsertSort(GET_INDEX_PTR(buf, start, step_size), end - start + 1, step_size,
				compare, swaper, move, copier, 
				context, swap_buf, swap_buf_size);
			continue;
		}

		/*
		* 如果递归次数为零,对此区间进行堆排序,防止出现分区恶化
		*/
		if(0 == cs.depth_limit)
		{
			MyAlgHeapMakeAndSort(GET_INDEX_PTR(buf, start, step_size), end - start + 1, step_size,
				compare, copier, context,
				swap_buf, swap_buf_size);
			continue;
		}

		/*
		* 找出中值
		*/
		middle = __median__(GET_INDEX_PTR(buf, start, step_size),
							GET_INDEX_PTR(buf, end, step_size),
							GET_INDEX_PTR(buf, (start + end + 1) / 2, step_size), compare, context);
		copier(swap_buf, middle, step_size, context);

		cut = _partition_(buf, start, end, step_size, compare, swaper, swap_buf, context);

		cs.depth_limit --;
		cs.end = cut - 1;
		if(cs.end > cs.start)
			quick_sort_stack_push(_stack, &cs);

		cs.start = cut;
		cs.end = end;
		if(cs.end > cs.start)
			quick_sort_stack_push(_stack, &cs);
	}
	
	quick_sort_stack_destroy(_stack);

	return 0;
}


/**
 *
 * @brief 快速排序
 *
 * @param buf:要排序的数据缓冲区起始地址
 * @param buf_size:缓冲区的大小
 * @param step_size:指针下走的跨度(1表示一字节)
 * @param context:用户自定义的上下文数据
 *
 */
int MyAlgQuickSort(void * buf, size_t buf_size, size_t step_size,
				   ALG_COMPARE compare, ALG_SWAP swaper, ALG_MOVE move, ALG_COPY copier,
				   const void * context, void * swap_buf, size_t swap_buf_size)
{
	if(NULL == buf || NULL == compare)
		return -1;

	if(NULL == move)
		move = __def_alg_move_;

	if(NULL == swaper)
		swaper = __def_alg_swap_;

	if(NULL == copier)
		copier = __def_alg_copy_;

	if(swap_buf && swap_buf_size >= step_size)
	{
		quick_sort(buf, buf_size, step_size, compare, swaper, move, copier, context, swap_buf, swap_buf_size);
		return 0;
	}

	swap_buf = MyMemPoolMalloc(NULL, step_size);
	swap_buf_size = step_size;

	quick_sort(buf, buf_size, step_size, compare, swaper, move, copier, context, swap_buf, swap_buf_size);
	
	MyMemPoolFree(NULL, swap_buf);

	return 0;
}

















⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -