三分查找C语言实现
关键词: 变参函数
、函数指针
、三分查找
、C语言
昨天我动手实现了一下基于变参函数的一元N次函数的代码实现,以及三分查找的代码实现。这份代码中fact_func
函数是可变参函数;fact_func2
函数的参数是一个大小已知的数组(类似于Linux main函数中的argc, argv[]);thrid_search
函数是一个三分查找函数。 不过在调用函数指针的时候遇到了问题:
- 不清楚如何表示
变参函数指针
。 - 即使变参函数指针可以传递,变参函数的可变参数列表又该如何传递?(个人想到用C语言的变参宏,不过如果宏定义一个代码块,没有返回值,这个代码实现又有点鸡肋)
thrid_search
函数中使用了flag
参数,个人觉得具体代码实现有点low(重复代码段有点长,这里还可以优化)。- 这段代码有没有bug?边界条件可能处理不好。
/*************************************************************************
> File Name: 2.third_search.c
> Author: ChenXiansen
> Mail: 1494089474@qq.com
> Created Time: Sun 22 Nov 2020 02:30:21 PM CST
************************************************************************/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
typedef double T;
#define T_token "%lf"
#define epsl 1e-10
#define P(val) {\
printf("%s: "T_token"\n", #val, val);\
}
#define P_ans(ans, temp, x, n) {\
printf("ans += "T_token" + "T_token" * ("T_token" ^ %d)\n", ans, temp, x, n);\
}
#define P_func(n, argv) {\
__typeof(n) __temp = n;\
printf("Func(x) = ");\
while (--n > -1) {\
printf("[ "T_token" * (x ^ %d) ]", argv[n], n);\
n && printf(" + ");\
}\
printf("\n");\
n = __temp;\
}
T fact_func(T x, int n, ...) {
T ans = 0;
va_list arg;
va_start(arg, n);
while (n--) {
T temp = va_arg(arg, T);
P_ans(ans, temp, x, n);
ans += pow(x, n) * temp;
P(ans);
}
return ans;
}
T fact_func2(T x, int n, T* argv) {
T ans = 0;
while(--n > -1) {
T temp = argv[n];
ans += pow(x, n) * temp;
}
return ans;
}
T thrid_search(T head, T tail, int flag, T(*func)(T, int, T*), int n, T* argv) {
if (abs(tail - head) < epsl) return head;
T m1, m2, l = head, r = tail;
if (flag > 0) {
while (l + epsl < r) {
m1 = ((r - l) / 3) + l;
m2 = ((r - l) / 3 * 2) + l;
if (func(m1, n, argv) <= func(m2, n, argv)) {
r = m2;
} else {
l = m1;
}
}
return l;
} else {
while (l + epsl < r) {
m1 = ((r - l) / 3) + l;
m2 = ((r - l) / 3 * 2) + l;
if (func(m1, n, argv) <= func(m2, n, argv)) {
l = m1;
} else {
r = m2;
}
}
return l;
}
}
int main() {
int n, flag;
T left, right;
n = 3;
printf("请输入一元二次函数参数: ");
T* hz_argv = (T*)malloc(sizeof(T) * 3);
for (int i = n - 1; i >= 0; i--) {
scanf(T_token, &hz_argv[i]);
}
P_func(n, hz_argv);
printf("请输入待查询左右边界: ");
scanf(T_token, &left);
scanf(T_token, &right);
flag = (hz_argv[n - 1] > 0) ? 1 : -1;
printf("查找函数极值点:");
printf(T_token"\n", thrid_search(left, right, flag, fact_func2, n, hz_argv));
free(hz_argv);
return 0;
}