头部哑节点使用方法

转自:https://blog.csdn.net/muclenerd/article/details/42008855
在删除节点,或者进行有序插入时,带有头部哑节点的链表可以简化代码的逻辑。
这种简化体现在我们循环链表时,我们的代码可以不用考虑第一个节点的特殊情况。
我们分别实现两种情况的删除和有序插入接口,就能看出有无头部哑节点对我们代码逻辑的影响。

1.插入

1.1头部有哑节点情况
//按从小到大插入到链表中
void link_insert(link_t *l, link_node_t *node)
{
	if( l == NULL )
	{
		return NULL;
	}
 
	link_node_t *p = NULL;
 
	for( p = l; p->next != NULL; p=p->next)
	{
		if( node->id < p->next->id )
		{
			node->next = p->next;
			p->next = node;
			return;
		}
	}
 
	if( p->next == NULL )
	{
		p->next = node;
		node->next = NULL;
	}
}

1.2头部没有哑节点情况

//按从小到大插入到链表中
link_t *link_insert(link_t *l, link_node_t *node)
{
	if( l == NULL )
	{
		return NULL;
	}
	
	if( node->id < l->id )
	{
		node->next = l;
		return node;
	}
	
	//now make sure that the first element is smaller than node
	link_t *p = l->next;
	
	for( ; p->next != NULL; p=p->next)
	{
		if( node->id < p->next->id )
		{
			node->next = p->next;
			p->next = node;
			return l;
		}		
	}
 
	if( p->next == NULL )
	{
		p->next = node;
		node->next = NULL;
	}
	
	return l;	
}

2.删除

2.1头部有哑节点情况
enum {true, false};
 
int link_delete(link_t *l, int key)
{
	link_t *p = l;
	
	for(; p->next != NULL; p = p->next )
	{
		if(p->next->id == key)
		{
			link_t *t = p->next;
			p->next = t->next;
			t->next = NULL;
			free(t);
			return true;
		}
	}
 
	return false;
}

2.2头部没有哑节点情况
int link_delete(link_t **l, int key)
{
	if( (*l) == NULL )
	{
		return NULL;
	}
	
	if( (*l)->id == key )
	{
		*l = (*l)->next;
		(*l)->next = NULL;
		free(*l);
		return;
	}
 
	link_t *p = (*l);
	
	for(; p->next != NULL; p = p->next )
	{
		if(p->next->id == key)
		{
			link_t *t = p->next;
			p->next = t->next;
			t->next = NULL;
			free(t);
			return true;
		}
	}
 
	return false;
}

可以看到,没有头部哑节点,导致每次我们必须每次在插入或者删除时,必须要对特殊情况,即头节点进行处理。
有了头部的哑节点,我们的处理逻辑就简化了很多。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值