0
点赞
收藏
分享

微信扫一扫

CS107编程范式-学习笔记-5


第五讲

看下面这个swap函数:

void *lsearch3(void *key, void *base, int n, int elemSize, int (*cmpfn)(void *, void *)) {
for (int i = 0; i < n; i++ ) {
void *elemAddr = (char*)base + i * elemSize;
if (cmpfn(key, elemAddr) == 0) {
cout << i << endl;
return elemAddr;
}
}
return NULL;
}

这里出现了函数指针,cmpfn是一个指向函数的指针。

对于int类型的查找,我们编写intCmp函数如下:

int intCmp(void *elem1, void *elem2) {
int *ip1 = (int*)elem1;
int *ip2 = (int*)elem2;
return *ip1 - *ip2;
}

运行以下代码: 

int array[] = {4, 2, 3, 7, 11, 6};
int size = 6;
int number = 7;
int *found = (int*)lsearch3(&number, array, size, sizeof(int), intCmp);
if (found == NULL) {
cout << ":(" << endl;
}
else {
cout << ":)" << endl;
}

运行结果如下: 

CS107编程范式-学习笔记-5_泛型

也就是在array[3]时找到了number。

老师源码中的部分如下:

int *ip1 = elem1;
int *ip2 = elem2;

int *found = lsearch3(&number, array, size, sizeof(int), intCmp);

编译器中有如下报错,应该是void*泛型转换不允许了。 

CS107编程范式-学习笔记-5_字符串_02

CS107编程范式-学习笔记-5_字符串_03

再看char*类型的查找:

int strCmp(void *vp1, void *vp2) {
char *s1 = *(char**)vp1;
char *s2 = *(char**)vp2;
return strcmp(s1, s2);
}

char *notes[] = {"Ab", "F#", "B", "Gb", "D"};
char *favorateNode = "Eb";
char **found = (char**)lsearch3(&favorateNode, notes, 5, sizeof(char*), strCmp);
if (found == NULL) {
cout << ":(" << endl;
}
else {
cout << ":)" << endl;
}

 内存如下:

CS107编程范式-学习笔记-5_字符串_04

运行结果:

CS107编程范式-学习笔记-5_二分搜索_05

这段代码中,strCmp的:

char *s1 = *(char**)vp1;
char *s1 = (char*)vp1;

有什么区别?

这里实际在内存中执行向前两跳的操作,即指向vp1所对应的字符串首地址,然后解引用。

如果直接char *s1 = (char*)vp1,那么s1就是vp1所在的内存地址所对应“字符串”了。

CS107编程范式-学习笔记-5_字符串_06

如果要实现,该怎么做呢?

那么我们对内存执行一跳就好了:

注意哪些地方有改动

int strCmp(void *vp1, void *vp2) {
char *s1 = (char*)vp1;
char *s2 = (char*)vp2;
return strcmp(s1, s2);
}

char *notes[] = {"Ab", "F#", "B", "Gb", "D"};
char *favorateNode = "Eb";
char **found = (char**)lsearch3(favorateNode, notes, 5, sizeof(char), strCmp);
if (found == NULL) {
cout << ":(" << endl;
}
else {
cout << ":)" << endl;
}

 运行结果:

CS107编程范式-学习笔记-5_字符串_07

二分搜索

上面说的都是线性搜索,编写一个二分搜索的泛型函数:

我自己实现了一下,老师只给了模板:

void *bsearch(void *key, void *base, int b, int n, int elemSize, int (*cmp)(void *, void *)) {
int low = b, high = n, middle;
middle = (low + high) / 2;
void *elemAddr = (char*)base + middle * elemSize;
if (cmp(key, elemAddr) == 0) {
cout << middle << endl;
return elemAddr;
}
else if (low < high) {
if (cmp(key, elemAddr) > 0) {
return bsearch(key, base, middle, n, elemSize, cmp);
}
else if (cmp(key, elemAddr) < 0) {
return bsearch(key, base, b, middle, elemSize, cmp);
}
}
return NULL;
}

int array2[] = {2, 3, 4, 6, 7, 11};
int size = 6;
int number = 7;
int *found2 = (int*)bsearch(&number, array2, 0, size, sizeof(int), intCmp);
if (found2 == NULL) {
cout << ":(" << endl;
}
else {
cout << ":)" << endl;
}

运行结果:

CS107编程范式-学习笔记-5_字符串_08

来使用内存操作的思想,编写一个栈。

我们写一个stack.h的头文件如下,定义一下栈的结构和常用操作:

typedef struct {
int *elems;
int logicalLength;
int allocLength;
}stack;
void StackNew(stack *s);
void StackDispose(stack *s);
void StackPush(stack *s, int value);
void StackPop(stack *s);

函数实现如下: 

void StackNew(stack *s) {
s->logicalLength = 0;
s->logicalLength = 4;
s->elems = (int*)malloc(4 * sizeof(int));
assert(s->elems != NULL);
}

 

举报

相关推荐

0 条评论