今晚在这里看到一篇文章,http://coolshell.cn/articles/8990.html,原文给的是代码片段,本着动手实践的原则,另外顺便复习一下链表,写了下代码
#include <stdio.h>
#include <stdlib.h>
typedef struct _node {
int n;
struct _node *next;
} node;
typedef int (* remove_fn)(node const *n);
node *create_link();
void destory_link(node *head);
void print_link(node *head);
int should_remove(node const *n);
node *remove_if(node *head, remove_fn should_remove);
void remove_if2(node **head, remove_fn should_remove);
int main() {
node *head = create_link();
print_link(head);
//head = remove_if(head, should_remove);
remove_if2(&head, should_remove);
print_link(head);
destory_link(head);
return 0;
}
node *create_link() {
node *head = malloc(sizeof(node));
if (head == NULL) {
printf("malloc head failed\n");
return NULL;
}
head->n = 0;
head->next = NULL;
node *pre = head;
for (int i=1; i<10; i++) {
node *cur = malloc(sizeof(node));
if (cur == NULL) {
printf("malloc node %d failed\n", i);
return NULL;
}
pre->next = cur;
cur->n = i;
cur->next = NULL;
pre = cur;
}
return head;
}
void destory_link(node *head) {
node *cur = head;
while (cur) {
node *next = cur->next;
free(cur);
cur = next;
}
}
void print_link(node *head) {
node *cur = head;
while (cur) {
printf("%d\t", cur->n);
cur = cur->next;
}
printf("\n");
}
int should_remove(node const *n) {
if (n == NULL) {
return 0;
}
return (n->n)%2 == 0;
}
node *remove_if(node *head, remove_fn should_remove) {
for (node *pre = NULL, *cur = head; cur;) {
node * const next = cur->next;
if (should_remove(cur)) {
if (pre) {
pre->next= next;
} else {
head = next;
}
free(cur);
} else {
pre = cur;
}
cur = next;
}
return head;
}
void remove_if2(node **head, remove_fn should_remove) {
for (node **cur = head; *cur;) {
node *entry = *cur;
if (should_remove(entry)) {
*cur = entry->next;
free(entry);
} else {
cur = &(entry->next);
}
}
}
编译运行一下
1 | zrj@zrj-desktop:~/c$ gcc -g -std=gnu99 link.c && ./a.out |
2 | 0 1 2 3 4 5 6 7 8 9 |
3 | 1 3 5 7 9 |
其实道理不复杂,自己多读两遍代码就懂了,不得不承认这种写法确实很巧妙,而且就可读性来说,其实也没有下降多少
总结:
这里熟悉一下:指向函数的指针的用法。
typedef
int
(* remove_fn)(node
const
*n); 之后,remove_fn声明的类型 就是指向 这样函数的指针。
调用int
should_remove(node
const
*n);的名字 should_remove 就是一个指针了。