二级指针删除单向链表

今晚在这里看到一篇文章,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 就是一个指针了。


你可能感兴趣的:(二级指针删除单向链表)