链表中用标兵结点简化代码

标兵结点(头结点)是在链表中的第一个结点,不存放数据,仅仅是个标记

利用标兵结点可以简化代码。下面实现双向链表中的按值删除元素的函数,分别实现

带标兵结点和不带标兵结点两版本,对比可见标兵结点的好处。

结点声明如下:

struct Node
{
	int value;
	Node *prev;
	Node *next;
}
int del_doublelist(Node*&h,int v)//不带标兵结点
{
	Node*p=h;
	while(p!=NULL&&p->value!=v)
	{
		p=p->next;
	}
	if(p==NULL)return 0;//空链表
	if(p->value==v)
	{
		if(p->next==NULL&&p->prev==NULL)//只有一个结点
		{
			h=NULL;
			free(p);
		}
		else if(p->next==NULL)//尾结点
		{
			p->prev->next=NULL;
			free(p);
		}
		else if(p->prev==NULL)//头结点
		{
			h=p->next;
			h->prev=NULL;
			free(p);
		}
		else//中间结点
		{
			p->prev->next=p->next;
			p->next->prev=p->prev;
			free(p);
		}
		return 1;
	}
}
int del_doublelist(Node*&h,int v)//带标兵结点
{
	Node*p=h->next;
	while(p!=NULL&&p->value!=v)
	{
		p=p->next;
	}
	if(p==NULL)return 0;
	if(p->value==v)
	{
		if(p->next==NULL)//尾结点
		{
			p->next->prev=p->prev;
			free(p);
		}
		else//中间结点
		{
			p->next->prev=p->prev;
			p->prev->next=p->next;
			free(p);
		}
		return 1;
	}
}
				
时间: 2024-10-12 16:41:20

链表中用标兵结点简化代码的相关文章

关于链表中哨兵结点问题的深入剖析

最近正在学习UC Berkeley的CS61B这门课,主要是采用Java语言去实现一些数据结构以及运用数据结构去做一些project.这门课不仅告诉你这个东西怎么做,而且一步一步探寻为什么要这样做以及为什么会有这些功能.我们有时在接触某段代码或功能的实现时,可能直接就看到了它最终的面貌,而不知道如何一步步演化而来,其实每一个功能的添加或优化都是对应一个问题的解决.下面就这门课中关于链表中哨兵结点的相关问题进行总结. 什么是哨兵结点 哨兵顾名思义有巡逻.检查的功能,在我们程序中通过增加哨兵结点往往

设计鲁棒性的方法:输入一个链表的头结点,逆序遍历打印该链表出来

之前有过整理链表等的概念和基本算法.比较重要的是插入,删除,遍历,建表(尾插法,头插法) 回忆链表尾部插入结点:  1 #include <iostream> 2 using namespace std; 3  4 typedef struct Node{ 5     int data;//数据域 6     Node *next;//指针域 7 } Node, *List; 8  9 //在单链表的末位添加一个结点10 void addNode(List *head, int value)1

在O(1)的时间内删除链表的指定结点

题目:给定单项链表的头指针和一个结点指针,定义一个函数在o(1)的时间删除该结点,链表的定义如下: struct ListNode{ int value; ListNode* next; }; 函数定义:void DeleteNode(ListNode** PListHead,ListNode* pToBedelete); 如上图所示,想要删除一个单链表的中的某个结点有两种方式: 1.如上图中的( b)所示:要删除i结点,必须从头扫描,扫到h(i的前一个结点),然后让其next值指向j(i的下一

链表《4》删除链表中的结点

下图是一个创建好的链表 下面我们需要删除一个结点,例如删除第3个结点 首先定义一个指针p,并且将p指向第二个结点 然后定义一个指针q,将q指向需要删除的结点 将p指向的结点和q指向的结点相连 p->pNext = q->pNext 清空q指向的结点 free(q); q = NULL; 删除后的链表 程序代码: #include <stdio.h> #include <stdlib.h> typedef struct Node//结点结构 { int data;//数据

给定一个链表,删除链表的倒数第 n 个节点(已知该结点存在),并且返回链表的头结点。

思路: 找到倒数第n个结点的前一个结点,让该结点的后继为倒数第n个结点的后继 子问题:找到倒数第n个结点的前驱 1.有两个引用,第一个引用指向首节点,然后走n步 2.第二个结点指向首节点,此时两结点之间隔了n-1个结点,保持这样的距离,共同向后移动 3.当第一个引用到达尾节点时,第二个引用离尾节点有n-1个结点, 4.此时第二个结点为倒数第n+1个结点,即倒数第n个结点的前驱 特殊情况: 1.链表只有一个结点或者为空链表,直接返回空即可: 2.链表的长度刚好等于n,即删除首节点,第一个引用从头结

用block做事件回调来简化代码,提高开发效率

我们在自定义view的时候,通常要考虑view的封装复用,所以如何把view的事件回调给Controller就是个需要好好考虑的问题, 一般来说,可选的方式主要有target-action和delegate,以及这次要强烈推荐的block. target-action和delegate方式有个很不方便的地方,就是配置代码和action代码不在同一个地方,你肯定要多写一个selector方法或者delegate方法,这就带来一个问题,一旦代码比较长或者selector方法比较多,找起来就很不方便.

题目:输入一个链表的头结点,反转该链表,并返回反转后链表的头结点。

题目:输入一个链表的头结点,反转该链表,并返回反转后链表的头结点.链表结点定义如下: struct ListNode { int       m_nKey; ListNode* m_pNext; }; c语言实现 /* File : rlink.c Author : Date : 2015/4/4 platform : windows7 x86_64 version : 1.0 Function : 反转一个链表 */ #include <stdio.h> #include <stdli

Scala学习笔记——简化代码和柯里化

1.简化代码 package com.scala.first import java.io.File import javax.management.Query /** * Created by common on 17-4-5. */ object FileMatcher { def main(args: Array[String]) { for (file <- filesHere) println(file) println() for (file <- filesMatching(&q

单链表 使用哑结点避免特殊情况 利大于弊?

哑结点,就是链表的根节点.   一般的, 单链表的插入要考虑空链表的处理, 但如果有哑结点, 就无需这样考虑. 那这样好吗? 如果这样,你需要保证进入插入函数前, 单链表有哑结点,  所以你需要创建,  而且每次操作单链表需要跳过哑结点.   也就是说,  增加哑结点并没有减少特殊情况的处理,  相反, 这些处理分散到其他函数里.     我认为, 为了提高模块的独立性,   应该把空链表处理补上.