我想了解算法的知识,我一直在使用以下书籍:Algorithms in a nutshell
在第65页,他们打印了一个插入排序算法。该算法非常简单易懂。我的问题来自他们实施它的方式。我主要使用托管语言(C#/ Java),所以我的指针功夫有点生锈。以下是他们提供的代码示例:
void sortPointers(void **ar, int n, int(*cmp)(const void *, const void *)) {
int j;
for(j = 1; j < n; j++) {
int i = j - 1;
void* value = ar[j];
while(i >= 0 && cmp(ar[i], value) > 0) {
ar[i+1] = ar[i];
i--;
}
ar[i+1] = value;
}
}
以下是我添加的工作示例:
int cmp(const void* t1, const void* t2) {
if(t1 > t2) {
return 1;
}
else if(t2 > t1) {
return -1;
}
else {
return 0;
}
}
void main() {
int values[] = { 51, 3, 5, 60, 9, 2, 7};
sortPointers((void**)values, 7, cmp);
for(int i = 0; i < 7; i++) {
cout << values[i] << " ";
}
}
虽然这有效但我不完全理解为什么以及如何?另外,为什么main函数中的(void **)转换工作,为什么它们使用双指针间接等?
回到学校,我们使用多个间接的唯一地方是动态分配多维数组。我所知道的唯一其他用途是,当您需要能够修改地址时,您传递给方法的指针成立。
此外,我继续修改代码看起来像这样,它的工作正常:
void sortPointers2(int* arr, int n, int (*cmp)(int, int)) {
int j;
for(j = 1; j < n; j++) {
int i = j - 1;
int value = arr[j];
while(i >= 0 && cmp(arr[i], value) > 0) {
arr[i+1] = arr[i];
i--;
}
arr[i+1] = value;
}
}
int cmp2(int t1, int t2) {
if(t1 > t2) {
return 1;
}
else if(t2 > t1) {
return -1;
}
else {
return 0;
}
}
void main() {
int values[] = { 51, 3, 5, 60, 9, 2, 7};
sortPointers2(values, 7, cmp2);
for(int i = 0; i < 7; i++) {
cout << values[i] << " ";
}
}
我很确定我错过了一些基本而明显的东西。感谢任何阅读此内容的人,并提出一两个想法。如果您需要任何其他详细信息或我搞砸了术语,请告诉我。
编辑:修复了第一个cmp函数中的拼写错误
答案 0 :(得分:2)
如果我正确地关注了示例,他们会使用void **
,因为它实际上是(void *)[]
;一系列无类型内存。比较函数有两个指向无类型内存(void *
)的指针,并被要求比较数据。
您不理解的是,在第一个示例中,您的数组应该是指针的数组,而不是值的数组。您的数组应如下所示:
int *val0 = malloc(sizeof(int)); *val0 = 51;
int *val1 = malloc(sizeof(int)); *val1 = 3;
// ... for all values
int *values[] = { val0, val1, val2, ... };
然后比较函数cmp
需要返回基于值的比较值,而不是它给出的指针。代码:
int cmp(const void* t1, const void* t2) {
if((const int)(*t1) > (const int)(*t2)) {
return 1;
}
else if((const int)(*t2) > (const int)(*t1)) {
return -1;
}
else {
return 0;
}
}
这样,给定无类型内存的指针,比较函数会在那些指针处找到两个整数,并比较这些值。
你的cmp
函数处理本书代码的唯一原因是因为你告诉排序函数你的数组充满了指向无类型内存的指针,而它实际上只是一个整数数组。然后,您的比较函数将被赋予指向内存的指针,这些指针实际上只是整数,然后比较指针,就像它们是值一样。在这种情况下,他们是。
本书的算法使用void **
的原因是因为它是泛型。 sort
函数可以取一个包含任何数据的数组,并将通用数据提供给compare函数,该函数可以取消引用指针并解释它们希望的那些地址的数据。