首页 > 技术文章 > 删除链表之two star programming

rain-lei 2014-03-09 20:34 原文

最近偶尔看到一篇关于Linus Torvalds的访问,大神说大部分人都不理解指针。假设被要求写一段链表删除节点的程序,大多数的做法都是跟踪两个指针,当前指针cur和其父节点pre,这种实现很容易理解,但是并没有用到指针的精髓。

Linus是怎么写的呢,且看源代码

//链表之two star programming
#include <stdio.h>

typedef struct node
{
	int value;
	struct node *next;
}listNode;

listNode *insert(listNode *head, int value)
{
	listNode *newNode = new listNode;
	newNode->value = value;
	newNode->next = head;
	return newNode;
}

void erase(listNode **head_in, int value)
{
	listNode **cur = head_in;
	while (*cur)
	{
		listNode *p = *cur;
		if (p->value == value)
		{
			*cur = p->next;
			delete p;
		}
		else
		{
			cur = &(p->next);
		}
	}
	//return head;
}

void printList(listNode *head)
{
	listNode *p = head;
	while(p)
	{
		printf("%d ", p->value);
		p = p->next;
	}
	printf("\n");
}

int main()
{
	listNode *head = NULL;
	int select, a;
	do 
	{
		printf("请输入选择 1--插入, 2--删除, 3--输出,其他跳出\n");
		scanf("%d", &select);
		if(select == 1)
		{
			printf("输入将要插入的值, -1表示结束\n");
			while(scanf("%d", &a), a != -1)
			{
				head = insert(head, a);
			}
		}
		else if(select == 2)
		{
			printf("输入将要删除的值, -1表示结束\n");
			while(scanf("%d", &a), a != -1)
			{
				erase(&head, a);
			}
		}
		else if(select == 3)
		{
			printList(head);
		}
		else break;
	
	} while (1);

	getchar();
	return 0;
}

运行结果

在链表的删除节点函数earse()中,并不是把头结点指针head作为参数传入,而是传入指针head的引用,小雨来分析一下运行过程,直接上图说明

    

  

可以看出cur的移动比较有意思,它是沿着节点之间的指针移动的,在这里,我们也可以把指针当成一种特殊的节点。

当然现在并不提倡这种编程风格,虽然看起来很简洁,但是太晦涩,不能让人一眼看懂,Linus说一般操作系统核心部分用这种方式。

 

推荐阅读