二次ポインタは一方向チェーンを削除します。
2724 ワード
今夜ここで文章を見ました。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
");
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
", 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("
");
}
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 。