| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 6968 人关注过本帖, 5 人收藏
标题:分享一份归并排序代码,欢迎测试改进
取消只看楼主 加入收藏
寒风中的细雨
Rank: 17Rank: 17Rank: 17Rank: 17Rank: 17
等 级:贵宾
威 望:66
帖 子:1710
专家分:8645
注 册:2009-9-15
结帖率:100%
收藏(5)
已结贴  问题点数:99 回复次数:8 
分享一份归并排序代码,欢迎测试改进
程序代码:
/**

 *\file merge_sort.h

 *\brief 归并排序

 *\date 2017/04/12

 */

#ifndef    __MERGE_SORT_H_2017_04_12__
#define    __MERGE_SORT_H_2017_04_12__

#ifdef     __cplusplus
extern "C"{
#endif


/**

 *\brief 归并排序中 设置merge_array的初始值

 *\param[in] len 待初始化的数据规模

 *\param[in] disoder_ary 等待排序的数据

 *\param[in] merge_ary 初始化的对象

 *\retval 1 初始化成功

 *\retval 0 初始化失败

 */
typedef int (*merge_set_fun)(unsigned int len, void *disoder_ary, void **merge_ary);

/**

 *\brief 归并排序中 两个元素对比函数

 *\param[in] cmp1 对比元素1

 *\param[in] cmp2 对比元素2

 *\retval 1 cmp1 > cmp2

 *\retval 0 cmp1 = cmp2

 *\retval -1 cmp1 < cmp2

 */
typedef int (*merge_cmp_fun)(void *cmp1, void *cmp2);

/**

 *\brief 归并排序中 赋值操作

 *\param[in] lopr 被赋值的 等号 左边的数

 *\param[in] ropr 赋值的 等号 右边的数

 *\retval 1 赋值成功

 *\retval 0 赋值失败 

 */
typedef int (*merge_agn_fun)(void **lopr, void *ropr);

/**

 *\brief 归并排序中 获取排序结果

 *\param[in] len 获取结果的数据规模

 *\param[in,out] res_ary 等待排序的数据

 *\param[in] merge_ary 归并排序后的结果

 *\retval 1 获取结果成功

 *\retval 0 获取结果失败

 */
typedef int (*merge_res_fun)(unsigned int len, void *res_ary, void **merge_ary);

/**

 *\brief 初始化归并排序环境

 *\param[in] len 待排序的规模

 *\param[in] disorder_array 待排序的数组

 *\param[in] f_set 设置merge_array初始值函数

 *\param[in] f_cmp 排序过程中需要的比较函数

 *\param[in] f_agn 赋值操作函数

 *\retval 1 初始化成功

 *\retval 0 初始化失败

 */
int merge_init(unsigned int len, void *disorder_array,
                merge_set_fun f_set, 
                merge_cmp_fun f_cmp, 
                merge_agn_fun f_agn);
                
/**

 *\brief 销毁

 */
void merge_destory(void);

/**

 *\brief 归并排序

 *\param[in] len 获取排序结果结果规模

 *\param[in,out] res_array 获取排序结果

 *\param[in] f_res 获取结果的回调

 */
void merge_sort(unsigned int len, void *res_array, merge_res_fun f_res);        

#ifdef    __cplusplus
}
#endif
#endif//__MERGE_SORT_H_2017_04_12__


程序代码:
/**

 *\file merge_sort.cc

 *\brief 归并排序

 *\date 2017/04/10

 */

#include "merge_sort.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>


static void **s_merge_array = (void**)0;    ///< 交换的变量
static void **s_merge_swap = (void**)0;    ///< 临时交换区
static unsigned int merge_len = 0;    ///< 待排序的规模
static merge_cmp_fun mcmp_fun = NULL;    ///< 对比函数
static merge_agn_fun magn_fun = NULL;    ///< 赋值函数
static merge_set_fun mset_fun = NULL;    ///< 设置merge_array的初始值

/**

 *\brief 初始化归并排序环境

 *\param[in] len 待排序的规模

 *\param[in] disorder_array 待排序的数组

 *\param[in] f_set 设置merge_array初始值函数

 *\param[in] f_cmp 排序过程中需要的比较函数

 *\param[in] f_agn 赋值操作函数

 *\retval 1 初始化成功

 *\retval 0 初始化失败

 */
int merge_init(unsigned int len, void *disorder_array,
                merge_set_fun f_set, 
                merge_cmp_fun f_cmp, 
                merge_agn_fun f_agn)
{
    assert(len > 1);
    assert((void**)0 != disorder_array);    
    assert(NULL != f_set);
    assert(NULL != f_set);
    assert(NULL != f_set);    
    
    s_merge_array = (void **) malloc (sizeof(void*) * len);
    s_merge_swap = (void **) malloc (sizeof(void*) * len);
    if ((void**)0 == s_merge_array || (void**)0 == s_merge_swap){
        
        printf("malloc failed errno(%d)!\n", errno);
        if (s_merge_array){
            
            free(s_merge_array);
            s_merge_array = (void**)0;
        }
        
        if (s_merge_swap){
            
            free(s_merge_swap);
            s_merge_swap = (void**)0;            
        }
        
        return 0;
    }
    merge_len = len;
    
    mset_fun = f_set;
    mcmp_fun = f_cmp;
    magn_fun = f_agn;
    
    return mset_fun(len, disorder_array, s_merge_array);
}

/**

 *\brief 执行 归并排序

 *\param[in] beg 起始位置下标

 *\param[in] end 结束位置下标

 */
static void __msort(unsigned int beg, unsigned int end)
{
    unsigned int mid = 0;
    unsigned int i = 0, j = 0, k = 0;
    int ret = 0;
    
    assert (end >= beg);
    
    if (end - beg >= 1){
        
        mid = (end - beg) / 2;
        __msort(beg, beg + mid);
        __msort(beg + mid + 1, end);
        
        // 归并 [beg, beg + mid]  和 [beg + mid + 1, end] 两个有序单元
        for (i = beg, j = beg + mid + 1, k = beg; i <= beg + mid && j <= end; ++k){
            
            ret = mcmp_fun(s_merge_array[i], s_merge_array[j]);
            if (-1 == ret){
                
                magn_fun(&s_merge_swap[k], s_merge_array[i]);
                ++i;
            }else{
                
                magn_fun(&s_merge_swap[k], s_merge_array[j]);
                ++j;
            }
        }
        
        while (i <= beg + mid){    // 将剩余的全部拷贝
            
            magn_fun(&s_merge_swap[k], s_merge_array[i]);
            ++k;
            ++i;
        }
        
        while(j <= end){    // 将剩余的全部拷贝
            
            magn_fun(&s_merge_swap[k], s_merge_array[j]);
            ++k;
            ++j;
        }
        memcpy(&s_merge_array[beg], &s_merge_swap[beg], (end - beg + 1) * sizeof(void*));
    }else{
        
        // end == beg 表示只有一个, 不处理
    }    
}

/**

 *\brief 归并排序

 *\param[in] len 获取排序结果结果规模

 *\param[in,out] res_array 获取排序结果

 *\param[in] f_res 获取结果的回调

 */
void merge_sort(unsigned int len, void *res_array, merge_res_fun f_res)
{
    __msort(0, merge_len - 1);
    
    if (len <= 0 || NULL == res_array || NULL == f_res){// 不期望返回结果
    
        return;
    }
    
    len = len > merge_len ? merge_len : len;    // 取小的
    f_res(len, res_array, s_merge_array);
}

/**

 *\brief 销毁

 */
void merge_destory(void)
{
    if (s_merge_array){
        
        free(s_merge_array);
        s_merge_array = (void**)0;
    }
    
    if (s_merge_swap){
        
        free(s_merge_swap);
        s_merge_swap = (void**)0;            
    }    
    
    merge_len = 0;
    
    mset_fun = NULL;
    mcmp_fun = NULL;
    magn_fun = NULL;
}


程序代码:
/**

 *\file main.cc

 *\brief 归并排序

 *\date 2017/04/10

 */
#include "merge_sort.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include <errno.h>

static int s_len = 0;        ///< 待排序的数列长度
static int s_ary[10000];    ///< 存放数列

/** 

 *\brief 根据输入 随机创建

 */
static void creat_ary(void)
{
    int i = 0;
    
    printf("输入随机生成数列的数量:");
    scanf("%d", &s_len);
    
    assert(s_len > 1 && s_len < 10000);
    
    srand(time(0));
    
    for (i = 0; i < s_len; ++i){
            
        s_ary[i] = rand()%10000;
    }
}

/**

 *\brief 输出随机产生的数列

 */
static void print_ary(void)
{
    int i = 0;
    
    for (i = 0; i < s_len; ++i){
        
        printf("%d ", s_ary[i]);
    }
    printf("\n");
}

/**

 *\brief 归并排序中 设置merge_array的初始值

 *\param[in] len 待初始化的数据规模

 *\param[in] disoder_ary 等待排序的数据

 *\param[in] merge_ary 初始化的对象

 *\retval 1 初始化成功

 *\retval 0 初始化失败

 */
int set_fun(unsigned int len, void *disoder_ary, void **merge_ary)
{
    unsigned int i = 0;
    int *ary1 = NULL, **ary2 = NULL;
    
    assert((void**)0 != disoder_ary);
    assert((void**)0 != merge_ary);
    
    ary1 = (int *)disoder_ary;
    ary2 = (int **)merge_ary;
    
    for (i = 0; i < len; ++i){
        
        ary2[i] = &ary1[i];
    }
    
    return 1;
}

/**

 *\brief 归并排序中 两个元素对比函数

 *\param[in] cmp1 对比元素1

 *\param[in] cmp2 对比元素2

 *\retval 1 cmp1 > cmp2

 *\retval 0 cmp1 = cmp2

 *\retval -1 cmp1 < cmp2

 */
int cmp_fun(void *cmp1, void *cmp2)
{
    int *int_cmp1 = NULL;
    int *int_cmp2 = NULL;

    assert(NULL != cmp1);
    assert(NULL != cmp2);
    
    int_cmp1 = (int*)cmp1;
    int_cmp2 = (int*)cmp2;
    if (*int_cmp1 > *int_cmp2){
        
        return 1;
    }else if (*int_cmp1 == *int_cmp2){
        
        return 0;
    }
    
    return -1;
}

/**

 *\brief 归并排序中 赋值操作

 *\param[in] lopr 被赋值的 等号 左边的数

 *\param[in] ropr 赋值的 等号 右边的数

 *\retval 1 赋值成功

 *\retval 0 赋值失败 

 */
int agn_fun(void **lopr, void *ropr)
{
    int **int_lopr = NULL;
    int *int_ropr = NULL;
    
    assert((void**)0 != lopr);
    assert(NULL != ropr);
    
    int_lopr = (int **)lopr;
    int_ropr = (int *)ropr;
    *int_lopr = int_ropr;
    
    return 1;
}

/**

 *\brief 归并排序中 获取排序结果

 *\param[in] len 获取结果的数据规模 

 *\param[in,out] res_ary 等待排序的数据

 *\param[in] merge_ary 归并排序后的结果

 *\retval 1 获取结果成功

 *\retval 0 获取结果失败

 */
int get_res_fun(unsigned int len, void *res_ary, void **merge_ary)
{
    int *buf = NULL, **ary = (int**)0, *res = NULL;
    unsigned int i = 0;
    
    assert(0 <= len);
    assert(NULL != res_ary);
    assert((void**)0 != merge_ary);
    
    buf = (int*) malloc (len * sizeof(int));
    if (NULL == buf){
        
        printf("malloc failed, errno(%d)\n", errno);
        return 0;
    }
    ary = (int **)merge_ary;
    res = (int *)res_ary;
    
    for (i = 0; i < len; ++i){
        
        buf[i] = *ary[i];    // 取指针指向的内容
    }
    
    memcpy(res, buf, len * sizeof(int));
    
    return 1;
}

int main(int argc, char **argv)
{
    creat_ary();
    
    print_ary();
    
    merge_init(s_len, (void *)s_ary, set_fun, cmp_fun, agn_fun);
    
    merge_sort(s_len, (void *)s_ary, get_res_fun);
    
    merge_destory();
    
    print_ary();
    
    return 0;
}


[此贴子已经被作者于2017-4-21 01:11编辑过]

搜索更多相关主题的帖子: file color 
2017-04-21 01:07
寒风中的细雨
Rank: 17Rank: 17Rank: 17Rank: 17Rank: 17
等 级:贵宾
威 望:66
帖 子:1710
专家分:8645
注 册:2009-9-15
收藏
得分:0 
程序代码:
object = main.o merge_sort.o
target = merge_sort

CFLAGS = -g
CPPFLAGS = -g
CC = g++

$(target) : $(object)
    $(CC) -o $(target) $(object)
    
.PHONY: clean
clean:
    -rm $(target) $(object)


2017-04-21 01:09
寒风中的细雨
Rank: 17Rank: 17Rank: 17Rank: 17Rank: 17
等 级:贵宾
威 望:66
帖 子:1710
专家分:8645
注 册:2009-9-15
收藏
得分:0 
程序代码:
测试数据
$ ./merge_sort 
输入随机生成数列的数量:10
9531 3434 5417 3335 5834 8781 5040 1465 9707 4451 
1465 3335 3434 4451 5040 5417 5834 8781 9531 9707 
2017-04-21 01:10
寒风中的细雨
Rank: 17Rank: 17Rank: 17Rank: 17Rank: 17
等 级:贵宾
威 望:66
帖 子:1710
专家分:8645
注 册:2009-9-15
收藏
得分:0 
回复 4楼 marlow
给出代码是递归实现的


实现看起来复杂  是为了让算法做到通用  做到不会因为排序的数据类型改变 而调整核心算法代码


2017-04-21 12:22
寒风中的细雨
Rank: 17Rank: 17Rank: 17Rank: 17Rank: 17
等 级:贵宾
威 望:66
帖 子:1710
专家分:8645
注 册:2009-9-15
收藏
得分:0 
回复 楼主 寒风中的细雨
int get_res_fun(unsigned int len, void *res_ary, void **merge_ary)


malloc 内存没有释放
2017-04-22 09:21
寒风中的细雨
Rank: 17Rank: 17Rank: 17Rank: 17Rank: 17
等 级:贵宾
威 望:66
帖 子:1710
专家分:8645
注 册:2009-9-15
收藏
得分:0 
回复 8楼 寒风中的细雨
基于上面二路归并的代码, 分享另个运用该归并模板的例子(找最邻近点对)
code.zip (7.29 KB)
2017-04-23 23:44
寒风中的细雨
Rank: 17Rank: 17Rank: 17Rank: 17Rank: 17
等 级:贵宾
威 望:66
帖 子:1710
专家分:8645
注 册:2009-9-15
收藏
得分:0 
方便浏览代码也贴一份
程序代码:
/******************************************************************************

 *\file closest_pair.h

 *\brief 二维平面上求给出的n个点中 找出邻近距离最小的点对

 *\date 2017/04/21

 *****************************************************************************/
#ifndef __CLOSEST_PAIR_H_2017_04_21__
#define    __CLOSEST_PAIR_H_2017_04_21__

#ifdef __cplusplus
extern "C"{
#endif


#define MAX_POINTS    (100)    ///< 最大支持的点的输入

/**

 *\brief 二维坐标点的结构

 */
typedef struct point_st{
    
    double    x;    ///< 坐标x
    double  y;    ///< 坐标y
}point_st;

/**

 *\brief 邻近点对结构

 */
typedef struct closest_pair_st{
    
    point_st p1;    ///< 第一个点
    point_st p2;    ///< 第二个点
    double      d;        ///< 两点间的距离
}closest_pair_st;

/**

 *\brief 点的表结构,按照x或y轴进行排序时使用

 */
typedef struct ptables_st{
    
    unsigned int    idx;    ///< 点在点的集合中位置
    double            xy;        ///< x轴 或 y轴的坐标
}ptables_st;

/**

 *\brief 获取最邻近的点对

 *\param[in] plist 待处理的点信息

 *\param[in] pnum 待处理的点数量

 *\param[out] pair 获取得到的结果

 *\retval 1 成功

 *\retval 0 失败

 */
int get_closest_pair(point_st *plist, unsigned int pnum, closest_pair_st *pair);

#ifdef __cplusplus
}
#endif

#endif//__CLOSEST_PAIR_H_2017_04_21__

程序代码:
/******************************************************************************

 *\file closest_pair.cc

 *\brief 二维平面上求给出的n个点中 找出邻近距离最小的点对

 *\date 2017/04/21

 *****************************************************************************/

#include "closest_pair.h"
#include "merge_sort.h"
#include <stdio.h>
#include <stdlib.h> 
#include <string.h>
#include <assert.h>
#include <math.h>
#include <errno.h>

static ptables_st x_ptables[MAX_POINTS];    // x轴排序列表
static ptables_st y_ptables[MAX_POINTS];    // y轴排序列表
static unsigned int s_spnum;
static ptables_st s_ptables[MAX_POINTS];    // 与垂直线相距特定距离点的列表

/**

 *\brief 归并排序中 设置merge_array的初始值

 *\param[in] len 待初始化的数据规模

 *\param[in] disoder_ary 等待排序的数据

 *\param[in] merge_ary 初始化的对象

 *\retval 1 初始化成功

 *\retval 0 初始化失败

 */
int set_fun(unsigned int len, void *disoder_ary, void **merge_ary)
{
    unsigned int i = 0;
    ptables_st *ary1 = NULL, **ary2 = NULL;
    
    assert((void**)0 != disoder_ary);
    assert((void**)0 != merge_ary);
    
    ary1 = (ptables_st *)disoder_ary;
    ary2 = (ptables_st **)merge_ary;
    
    for (i = 0; i < len; ++i){
        
        ary2[i] = &ary1[i];
    }
    
    return 1;
}

/**

 *\brief 归并排序中 两个元素对比函数

 *\param[in] cmp1 对比元素1

 *\param[in] cmp2 对比元素2

 *\retval 1 cmp1 > cmp2

 *\retval 0 cmp1 = cmp2

 *\retval -1 cmp1 < cmp2

 */
int cmp_fun(void *cmp1, void *cmp2)
{
    ptables_st *int_cmp1 = NULL;
    ptables_st *int_cmp2 = NULL;

    assert(NULL != cmp1);
    assert(NULL != cmp2);
    
    int_cmp1 = (ptables_st*)cmp1;
    int_cmp2 = (ptables_st*)cmp2;
    if (int_cmp1->xy > int_cmp2->xy){
        
        return 1;
    }else if (int_cmp1->xy == int_cmp2->xy){
        
        return 0;
    }
    
    return -1;
}

/**

 *\brief 归并排序中 赋值操作

 *\param[in] lopr 被赋值的 等号 左边的数

 *\param[in] ropr 赋值的 等号 右边的数

 *\retval 1 赋值成功

 *\retval 0 赋值失败 

 */
int agn_fun(void **lopr, void *ropr)
{
    ptables_st **int_lopr = NULL;
    ptables_st *int_ropr = NULL;
    
    assert((void**)0 != lopr);
    assert(NULL != ropr);
    
    int_lopr = (ptables_st **)lopr;
    int_ropr = (ptables_st *)ropr;
    *int_lopr = int_ropr;
    
    return 1;
}

/**

 *\brief 归并排序中 获取排序结果

 *\param[in] len 获取结果的数据规模 

 *\param[in,out] res_ary 等待排序的数据

 *\param[in] merge_ary 归并排序后的结果

 *\retval 1 获取结果成功

 *\retval 0 获取结果失败

 */
int get_res_fun(unsigned int len, void *res_ary, void **merge_ary)
{
    ptables_st *buf = NULL, **ary = (ptables_st**)0, *res = NULL;
    unsigned int i = 0;
    
    assert(0 <= len);
    assert(NULL != res_ary);
    assert((void**)0 != merge_ary);
    
    buf = (ptables_st*) malloc (len * sizeof(ptables_st)); // 这里需要开辟空间 merge_ary,指向的内存地址就是res_ary的元素地址
    if (NULL == buf){
        
        printf("malloc failed, errno(%d)\n", errno);
        return 0;
    }
    ary = (ptables_st **)merge_ary;
    res = (ptables_st *)res_ary;
    
    for (i = 0; i < len; ++i){
        
        memcpy(&buf[i], ary[i], sizeof(ptables_st));    // 取指针指向的内容
    }
    
    memcpy(res, buf, len * sizeof(ptables_st));
    
    free(buf);
    buf = NULL;

    return 1;
}
    
/**

 *\brief 获取两点间的距离

 *\brief[in] plist 点的列表

 *\param[in] i 第一个点在点的列表中下标值

 *\param[in] j 第二个点在点的列表中下标值

 *\retval 2点间的距离值

 */
static double __get_2points_dist(point_st *plist, unsigned int i, unsigned int j)
{
    double x, y;
    
    x = pow(plist[i].x - plist[j].x, 2.0);
    y = pow(plist[i].y - plist[j].y, 2.0);
    
    return sqrt(x + y);
}

/**

 *\brief 递归处理各个分支

 *\param[in] plist 存放所有点列表

 *\param[in] pnum plist列表中点的数量

 *\param[in] beg 待处理点的起始下标

 *\param[in] num 待处理点的数量 从beg下标开始算起

 *\param[out] pair 输出邻近的点对

 *\retval 1 成功

 *\retval 0 失败

 */
static int __do_closest_pair(point_st *plist, 
                             unsigned int pnum,
                             unsigned int beg, 
                             unsigned int num, 
                             closest_pair_st *pair)
{
    unsigned int i = 0, j = 0;
    closest_pair_st l_pair, r_pair, min_pair;
    
    if (num <= 3){
        
        pair->p1.x = plist[beg].x;
        pair->p1.y = plist[beg].y;
        pair->p2.x = plist[beg+1].x;
        pair->p2.y = plist[beg+1].y;
        pair->d = __get_2points_dist(plist, beg, beg + 1);
        
        // 直接计算两点间的距离
        for (i = 0; i < num; ++i){
            
            for (j = i + 1; j < num; ++j){
                
                if (pair->d > __get_2points_dist(plist, beg + i, beg + j)){
                    
                    pair->p1.x = plist[beg+i].x;
                    pair->p1.y = plist[beg+i].y;
                    pair->p2.x = plist[beg+j].x;
                    pair->p2.y = plist[beg+j].y;
                    pair->d = __get_2points_dist(plist, beg + i, beg + j);                    
                }
            }
        }
        
        return 1;
    }
    
    // 拆分成[1, num/2] 和 [num/2 + 1, num]
    __do_closest_pair(plist, pnum, beg, num/2, &l_pair);
    __do_closest_pair(plist, pnum, beg + num/2, num - num/2, &r_pair);
    if (l_pair.d < r_pair.d){
        
        memcpy(&min_pair, &l_pair, sizeof(closest_pair_st));
    }else{
        
        memcpy(&min_pair, &r_pair, sizeof(closest_pair_st));
    }
    
    // 计算两点一点落在左半边 一点落在右半边的情况, 统计所有与垂直直线 x = plist[beg + num/2].x 相距 min_pair.d 的距离的点
    for (i = 0, s_spnum = 0; i < pnum ; ++i){
        
        double dis = fabs(plist[beg + num/2].x - plist[y_ptables[i].idx].x);
        if (min_pair.d > dis){
            
            s_ptables[s_spnum].idx = y_ptables[i].idx;
            s_ptables[s_spnum].xy = y_ptables[i].xy;
            ++s_spnum;
        }
    }
    
    if (s_spnum < 2){
    
        memcpy(pair, &min_pair, sizeof(closest_pair_st));
        return 1;
    }
    
    pair->p1.x = plist[s_ptables[0].idx].x;
    pair->p1.y = plist[s_ptables[0].idx].y;
    pair->p2.x = plist[s_ptables[1].idx].x;
    pair->p2.y = plist[s_ptables[1].idx].y;
    pair->d = __get_2points_dist(plist, s_ptables[0].idx, s_ptables[1].idx);
    for (i = 0; i < s_spnum; ++i){
        
        for (j = i+1; j <= i + 8 && j < s_spnum; ++j){
            
            if (pair->d > __get_2points_dist(plist, s_ptables[i].idx, s_ptables[j].idx)){
                
                pair->p1.x = plist[s_ptables[i].idx].x;
                pair->p1.y = plist[s_ptables[i].idx].y;
                pair->p2.x = plist[s_ptables[j].idx].x;
                pair->p2.y = plist[s_ptables[j].idx].y;
                pair->d = __get_2points_dist(plist, s_ptables[i].idx, s_ptables[j].idx);                
            }        
        }
    }
    
    if (min_pair.d < pair->d){
        
        memcpy(pair, &min_pair, sizeof(closest_pair_st));
    }
    
    return 1;
}

/**

 *\brief 获取最邻近的点对

 *\param[in] plist 待处理的点信息

 *\param[in] pnum 待处理的点数量

 *\param[out] pair 获取得到的结果

 *\retval 1 成功

 *\retval 0 失败

 */
int get_closest_pair(point_st *plist, unsigned int pnum, closest_pair_st *pair)
{
    unsigned int i = 0;
    
    
    assert(NULL != plist);
    assert(NULL != pair);
    assert(MAX_POINTS >= pnum);
    
    // 1. 将plist的点 按照x轴 和 y轴排序(归并排序) 得到两张表
    for (i = 0; i < pnum; ++i){
        
        x_ptables[i].xy = plist[i].x;
        y_ptables[i].xy = plist[i].y;
        x_ptables[i].idx = i;
        y_ptables[i].idx = i;
    }
    // 调用归并排序
    merge_init(pnum, (void *)x_ptables, set_fun, cmp_fun, agn_fun);
    merge_sort(pnum, (void *)x_ptables, get_res_fun);
    merge_destory();
    merge_init(pnum, (void *)y_ptables, set_fun, cmp_fun, agn_fun);
    merge_sort(pnum, (void *)y_ptables, get_res_fun);
    merge_destory();    
        
    // 2.查找最小临近点对
    __do_closest_pair(plist, pnum, 0, pnum, pair);
    
    return 1;
}

程序代码:
/******************************************************************************

 *\file main.cc

 *\brief 二维平面上求给出的n个点中 找出邻近距离最小的点对

 *\date 2017/04/21

 *****************************************************************************/

#include "closest_pair.h"
#include <stdio.h>
#include <assert.h>


static unsigned int s_points_num;        ///< 点的数量
static point_st s_points[MAX_POINTS];    ///< 点的列表


/**

 *\brief 捕获终端输入信息

 *\retval 1 成功

 *\retval 0 失败

 */
static int get_input(void)
{
    unsigned int i = 0;
    
    printf("输入点的数量:");
    scanf("%u", &s_points_num);
    
    assert(MAX_POINTS >= s_points_num);
    
    printf("一行一个点 例如:4,5   其中4为x轴坐标 5为y轴坐标\n");
    for (i = 0; i < s_points_num; ++i){
        
        scanf("%lf,%lf", &s_points[i].x, &s_points[i].y);
    }
    
    return 0;
}

int main(void)
{
    closest_pair_st pair;
    
    get_input();
    
    if (get_closest_pair(s_points, s_points_num, &pair)){
    
        // 输出结果
        printf("(%lf, %lf)<->(%lf, %lf) dis[%lf]\n", pair.p1.x, pair.p1.y, pair.p2.x, pair.p2.y, pair.d);
    }
    
    return 0;
}

2017-04-23 23:47
寒风中的细雨
Rank: 17Rank: 17Rank: 17Rank: 17Rank: 17
等 级:贵宾
威 望:66
帖 子:1710
专家分:8645
注 册:2009-9-15
收藏
得分:0 
回复 10楼 寒风中的细雨
程序代码:
# ./closest_pair 
输入点的数量:4
一行一个点 例如:4,5   其中4为x轴坐标 5为y轴坐标
0.5,1
3,0.5
1,3
2.5,1.5
(3.000000, 0.500000)<->(2.500000, 1.500000) dis[1.118034]
-----------------
网上 找到的一个输入例子
# ./closest_pair 
输入点的数量:40
一行一个点 例如:4,5   其中4为x轴坐标 5为y轴坐标
24.11,33.1
11.33,15.66
24.18,5.42
33.95,43.44
98.19,4.31
17.06,96.67
91.65,43.67
23.62,11.38
51.54,4.45
82.93,55.06
28.46,48.33
93.33,17.01
3.84,47
93.94,21.12
20.07,92.17
7.92,33.13
53.34,18.44
3.92,4.22
14.99,50.57
1.58,31.62
4.13,60.96
55.23,33.77
6.44,5.84
81.8,22.3
80.61,9.14
22.43,94.26
99.5,67.04
46.68,84.16
92.07,54.53
86.19,48.15
53.22,73.18
26.2,41.52
1.4,15.14
20.51,97.44
40.44,84.3
53.73,21.76
71.55,3.4
14.62,50.11
16.45,60.28
16.92,24.16
(14.620000, 50.110000)<->(14.990000, 50.570000) dis[0.590339]
---------------------
2017-04-23 23:49
寒风中的细雨
Rank: 17Rank: 17Rank: 17Rank: 17Rank: 17
等 级:贵宾
威 望:66
帖 子:1710
专家分:8645
注 册:2009-9-15
收藏
得分:0 
回复 14楼 marlow
网上 搜索下 doxygen  

将代码注释 直接生成 API 文档
2017-04-25 00:03
快速回复:分享一份归并排序代码,欢迎测试改进
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.027373 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved