只得说说完结地点. 例如上边,  理论到实施 中间有举不胜举进度. 算法方面本身啥也不懂

引言 – 从实践狗讲起

引言 – 从推行狗讲起

  理论到实施(有了算法到贯彻) 中间有无数进度. 算法方面自个儿啥也不懂,
只好说说实现地点. 例如上面

  理论到执行 中间有诸多进度. 算法方面自己啥也不懂, 只好说说实现地方.
例如下边

一个家常的插入排序.

3个常备的插入排序.

//
// 插入排序默认从大到小
//
extern void sort_insert_int(int a[], int len) {
    int i, j;
    for (i = 1; i < len; ++i) {
        int key = a[j = i];
        // 从小到大
        while (j > 0 && a[j - 1] < key) {
            a[j] = a[j - 1];
            --j;
        }
        a[j] = key;
    }
}
//// 插入排序默认从大到小//extern void sort_insert_int(int a[], int len) {    int i, j;    for (i = 1; i < len; ++i) {        int key = a[j = i];        // 从小到大        while (j > 0 && a[j - 1] < key) {            a[j] = a[j - 1];            --j;        }        a[j] = key;    }}

 

那时有人就想了, 那数组是 double 的, 那怎么弄了. 也有一种缓解方案

这儿有人就想了, 那数组是 double 的, 那怎么弄了. 也有一种缓解方案

#define sort_insert \    _Generic(a            , int *     : sort_insert_int            , double *  : sort_insert_double            , default   : sort_insert_default) 
#define sort_insert(a, len) \
    _Generic(a
            , int *     : sort_insert_int
            , double *  : sort_insert_double
            , default   : sort_insert_default) (a, len)

是否有所启发. 当然了. 对于地点是选用从大到小封装.
那假使须求从小到大呢. 能够如此做

 

static inline int _compare_2(const int left, const int key) {    return left - key;} extern void sort_insert_2(int a[], int len,    int compare(const int left, const int key)) {    int i, j;    for (i = 1; i < len; ++i) {        int key = a[j = i];        while (j > 0 && compare(a[j - 1], key) < 0) {            a[j] = a[j - 1];            --j;        }        a[j] = key;    }}

是或不是拥有启发. 当然了. 对于地方是行使从大到小封装.
那假若急需从小到大呢. 能够这么做

独自把比较的作为抽象出来, 注册进去. 是否很笑容可掬.

static inline int _compare_2(const int left, const int key) {
    return left - key;
} 

extern void sort_insert_2(int a[], int len,
    int compare(const int left, const int key)) {
    int i, j;
    for (i = 1; i < len; ++i) {
        int key = a[j = i];
        while (j > 0 && compare(a[j - 1], key) < 0) {
            a[j] = a[j - 1];
            --j;
        }
        a[j] = key;
    }
}

前言 – 细致一点卷入

独立把比较的行为抽象出来, 注册进去. 是或不是很满面红光.

  或然到此地会更和颜悦色. 既然能透过高科学技术泛型模拟出来.
那我们不也足以选用旧科技(science and technology)弄弄.

 

typedef int (* compare_f)(const void * left, const void * key);static inline int _compare_3(const void * left, const void * key) {    return *(int *)left - *(int *)key;}extern void sort_insert_3_(void * data, size_t ez, int len, compare_f compare) {    char * a = data;    void * key;    int i, j;    if ((key = malloc == NULL)        return;    for (i = 1; i < len; ++i) {        memcpy(key, &a[i * ez], ez);        for (j = i; j > 0 && compare(&a[(j - 1) * ez], key) < 0; --j)            memcpy(&a[j * ez], &a[(j - 1) * ez], ez);        if (j != i)            memcpy(&a[j * ez], key, ez);    }    free;}#define sort_insert_3(a, len, compare) \    sort_insert_3_(a, sizeof, len, (compare_f)compare)

前言 – 细致一点封装

是还是不是很巧妙, 一切都编制程序 void * 了. 当然了一旦应用 C99 版本以上,
只怕说用高版本的 GCC.

  大概到此处会更安心乐意. 既然能通过高科学和技术泛型模拟出来.
那大家不也得以行使旧科学和技术弄弄.

能够写的更好.

typedef int (* compare_f)(const void * left, const void * key);

static inline int _compare_3(const void * left, const void * key) {
    return *(int *)left - *(int *)key;
}

extern void sort_insert_3_(void * data, size_t ez, int len, compare_f compare) {
    char * a = data;
    void * key;
    int i, j;

    if ((key = malloc(ez)) == NULL)
        return;

    for (i = 1; i < len; ++i) {
        memcpy(key, &a[i * ez], ez);
        for (j = i; j > 0 && compare(&a[(j - 1) * ez], key) < 0; --j)
            memcpy(&a[j * ez], &a[(j - 1) * ez], ez);
        if (j != i)
            memcpy(&a[j * ez], key, ez);
    }

    free(key);
}

#define sort_insert_3(a, len, compare) \
    sort_insert_3_(a, sizeof(*(a)), len, (compare_f)compare)
extern void sort_insert_4_(void * data, size_t ez, int len, compare_f compare) {    char * a = data;    char key[ez];    int i, j;    for (i = 1; i < len; ++i) {        memcpy(key, &a[i * ez], ez);        for (j = i; j > 0 && compare(&a[(j - 1) * ez], key) < 0; --j)            memcpy(&a[j * ez], &a[(j - 1) * ez], ez);        if (j != i)            memcpy(&a[j * ez], key, ez);    }}

是否很抢眼, 一切都编程 void * 了.  当然了倘若利用 C99 版本以上,
也许说用高版本的 GCC.

此处用了 C99 的 VLA 性格. 不理解细心的校友是不是和思考. GCC 是怎么落到实处 VLA
可变长数组呢.

能够写的更好.

拨动云雾见青天, 我们不妨来个实验求证一哈. 看上边测试代码

extern void sort_insert_4_(void * data, size_t ez, int len, compare_f compare) {
    char * a = data;
    char key[ez];
    int i, j;

    for (i = 1; i < len; ++i) {
        memcpy(key, &a[i * ez], ez);
        for (j = i; j > 0 && compare(&a[(j - 1) * ez], key) < 0; --j)
            memcpy(&a[j * ez], &a[(j - 1) * ez], ez);
        if (j != i)
            memcpy(&a[j * ez], key, ez);
    }
}
#include <stdio.h>#include <stdlib.h>/* * file : vla.c * make : gcc -g -Wall -O2 -o vla.exe vla.c *  */int main(int argc, char * argv[]) {    char a[10];    int b = 7;    char c[b];    int * d = malloc(sizeof(int));    if (d == NULL)        exit(EXIT_FAILURE);    *d = 1000;    char e[*d];    printf("%p : char a[10]\n", a);    printf("%p : int b\n", &b);    printf("%p : char c[b]\n", c);    printf("%p : int * d\n", d);    printf("%p : char e[*d]\n", e);    free;    return EXIT_SUCCESS;}

 

说到底输出结果是

那边用了 C99 的 VLA 天性. 不驾驭细心的同窗是还是不是和思考. GCC 是怎么落到实处 VLA
可变长数组呢.

图片 1

拨动云雾见青天, 我们无妨来个试验验证一哈. 看上面测试代码

经过地点匹配对于 vla 可变数组, GCC是坐落栈上的. 全体能够推断,
当可变数组大小太大. 函数栈会直接崩溃.

#include <stdio.h>
#include <stdlib.h>

/*
 * file : vla.c
 * make : gcc -g -Wall -O2 -o vla.exe vla.c
 * 
 */
int main(int argc, char * argv[]) {
    char a[10];
    int b = 7;
    char c[b];
    int * d = malloc(sizeof(int));
    if (d == NULL)
        exit(EXIT_FAILURE);
    *d = 1000;
    char e[*d];

    printf("%p : char a[10]\n", a);
    printf("%p : int b\n", &b);
    printf("%p : char c[b]\n", c);
    printf("%p : int * d\n", d);
    printf("%p : char e[*d]\n", e);

    free(d);
    return EXIT_SUCCESS;
}

假定您有想法, 那么就去贯彻它, 多数简短大家还能够独立捉出来滴~~

终极输出结果是

正文 – 通用套路

图片 2

  还有一种套路, 选取宏模板去落到实处, 简单提一下这几个思路. 看上边代码

由此地点匹配对于 vla 可变数组, GCC是身处栈上的. 全体可以估算,
当可变数组大小太大. 函数栈会直接崩溃.

#if defined#define __f sort_insert_##type#define __F __fstatic void __F (__T a[], int len, int compare(const __T left, const __T key)) {    int i, j;    for (i = 1; i < (int)len; ++i) {        __T key = a[j = i];        while (j > 0 && compare(a[j - 1], key) < 0) {            a[j] = a[j - 1];            --j;        }        a[j] = key;    }}#endif

假定你有想法, 那么就去落成它, 多数简单易行大家仍是可以够独立捉出来滴~~

貌似而言上边模板函数都会封装在叁个片段文件中利用的时候也很便利,
例如上面这样

 

// 定义部分, 声明和定义分离可以自己搞#undef  __T#define __T int#include "sort_insert.c"// 使用部分和普通函数无异sort_insert_int, _compare_2);

正文 – 通用套路

理所当然除了上面一种基于文件的函数模板. 还用一种纯基于函数宏的函数模板达成.

  还有一种套路, 选用宏模板去达成, 不难提一下以此思路. 看上面代码

#define sort_insert_definition \    static void sort_insert_##T (T a[], int len, int compare(const T left, const T key)) { \        int i, j; \        for (i = 1; i < len; ++i) { \            T key = a[j = i]; \            while (j > 0 && compare(a[j - 1], key) < 0) { \                a[j] = a[j - 1]; \                --j; \            } \            a[j] = key; \        } \    }sort_insert_definition(int)
#if defined(__T)

#define __f(type) sort_insert_##type
#define __F(type) __f(type)

static void __F(__T) (__T a[], int len, int compare(const __T left, const __T key)) {
    int i, j;
    for (i = 1; i < (int)len; ++i) {
        __T key = a[j = i];
        while (j > 0 && compare(a[j - 1], key) < 0) {
            a[j] = a[j - 1];
            --j;
        }
        a[j] = key;
    }
}

#endif

采用依然一如既往 sort_insert_int, _compare_2); 跑起来. 第3种函数模板,
在嵌入式用的多.

相似而言上边模板函数都会封装在多少个片段文件中动用的时候也很便宜,
例如上面那样

其次种在实战中用的多, 对于拍卖各种算法相关的代码很普遍.
到此处应该能够精通地点那多少个

// 定义部分, 声明和定义分离可以自己搞
#undef  __T
#define __T int
#include "sort_insert.c"

// 使用部分和普通函数无异
sort_insert_int(a, LEN(a), _compare_2);

C 封装中八个小函数存在的套路.

 

后记 – 路越来越窄, 越来越明晰

理所当然除了上边一种基于文件的函数模板. 还用一种纯基于函数宏的函数模板完毕.

谬误是足以改良的, 欢迎指正 ~ 表示多谢哈哈

#define sort_insert_definition(T) \
    static void sort_insert_##T (T a[], int len, int compare(const T left, const T key)) { \
        int i, j; \
        for (i = 1; i < len; ++i) { \
            T key = a[j = i]; \
            while (j > 0 && compare(a[j - 1], key) < 0) { \
                a[j] = a[j - 1]; \
                --j; \
            } \
            a[j] = key; \
        } \
    }

sort_insert_definition(int)

<<曾几何时成为津门先是哟>>
:http://music.163.com/\#/mv?id=197148

行使还是一如既往  sort_insert_int(a, LEN(a), _compare_2); 跑起来.
第三种函数模板, 在嵌入式用的多.

图片 3

其次种在实战中用的多, 对于拍卖各类算法相关的代码很普遍.
到这边应该能够理解地点这些

对不起 ~ 什么都了然的好晚 ~

C 封装中贰个小函数存在的套路.

 

后记 – 路越来越窄, 越来越清晰

      错误是能够校正的, 欢迎指正 ~ 表示感激哈哈

     
<<什么时候成为津门第壹哟>>
http://music.163.com/\#/mv?id=197148

      图片 4

      对不起 ~ 什么都精通的好晚 ~

相关文章