单链表节点的添加和删除

  1. 单链表的节点定义
struct ListNode
{
  	int       m_nValue;
  	ListNode* m_pNext;
};
  1. 在单链表的末尾添加结点
void AddToTail(LIstNode** pHead,int value)
{
	ListNode* pNew = new ListNode();
	pNew->m_nValue = value;
	pNew->m_pNext = NULL;

	if(*pHead == NULL)
		*pHead = pNew;
	else
	{
		ListNode* pNode = *pHead;
		while(pNode->m_pNext != NULL)
		pNode=pNode->m_pNext;
		pNode->m_pNext = pNew;
	}
}
  1. 在单链表中找到第一个含有某个值的结点并删除
void RemoveNode(ListNode** pHead,int value)
{
	if(pHead == NULL || *pHead == NULL)
		return;
	//定义一个ListNode指针,用于释放要删除的结点
	ListNode* pToBeDeleted = NULL;
	if((*pHead)->m_nValue == value)
	{
		pToBeDeleted = *pHead;
		*pHead = *pHead->m_pNext;
	}
	else
	{
	// 定义一个临时的指针,用于遍历链表以找到要删除的结点(如果存在的话)的前一个结点
		ListNode* pNode = *pHead;
		while(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue != value)
			pNode = pNode->m_pNext;
		if(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue == value)
		{
			pToBeDeleted = pNode->m_pNext;
			pNode->m_pNext = pNode->m_pNext->m_pNext;
		}
		if(pToBeDeleted != NULL)
		{
			delete pToBeDeleted;
			pToBeDeleted = NULL;
		}
	}
}

重点问题:

  • 为什么在添加和删除函数参数中要用二级指针?

     首先要说的是,函数的参数在传递的过程中,传递的是实参的一个拷贝。在搜索别人的解释的过程中,也有人反复强调的另一点是:指针也是有地址的。ok,那么如果函数的参数是一级指针ListNode* pHead,那么函数中使用的pHead是什么?答案是,指向头结点的指针的副本,也就是另一个指向头结点的指针。

     

     好了,也就是说接下来在函数中所有的操作都是从这个临时的pHead开始的。从我们的函数名来看,AddToTail也就是从尾部插入,那这么看来,我只是从尾部插入新的结点,看起来并不影响头指针。

     那么问题来了,函数中的第七行的判断,如果头指针为空,也就是链表为空的时候,如果要新插入结点,那么从函数看来我们会改变头指针pHead另其指向新结点。但是! 前边我们说了,这个pHead只是函数中的一个 临时变量,这个指针本身的地址不同于函数外实参指针的地址,而它虽然指向了新结点,但函数外本身传入的头指针仍然为 NULL!

     同理,在删除结点的时候,如果要删除的结点即第一个结点,使用一级指针也会出错,此时会导致原头指针指向的链表为空。

时间: 2024-10-12 12:03:07

单链表节点的添加和删除的相关文章

链表的创建以及链表节点的添加和删除

单链表的创建过程有下面几步: 1 ) 定义链表的数据结构; 2 ) 创建一个空表; 3 ) 利用malloc ( )函数向系统申请分配一个节点; 4 ) 将新节点的指针成员赋值为空. 若是空表,将新节点连接到表头:若是非空表,将新节点接到表尾; 5 ) 推断一下是否有兴许节点要接入链表,若有转到3 ),否则结束; 单链表的输出过程有下面几步 1) 找到表头; 2) 若是非空表.输出节点的值成员,是空表则退出; 3 ) 跟踪链表的增长,即找到下一个节点的地址; 4) 转到2 ). 接下来来一步步实

C语言实现单链表节点的删除(带头结点)

我在之前一篇博客<C语言实现单链表节点的删除(不带头结点)>中具体实现了怎样在一个不带头结点的单链表的删除一个节点,在这一篇博客中我改成了带头结点的单链表.代码演示样例上传至 https://github.com/chenyufeng1991/DeleteLinkedList_HeadNode.删除类型有两种: (1)删除某个位置pos的节点: (2)推断x值是否在链表中,若存在则删除该节点: 核心代码例如以下: //删除某个位置pos的节点 Node *DeletePosNode(Node

父兄子节点的获取及子节点的添加、删除、克隆操作

第一.父兄子节点的获取 1.父节点的获取 某节点的parentNode属性值即为该节点的父节点.示例: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <body> <div id="father"> <div id="son1"></div> </

XML节点进行添加,删除,查找和删除操作

从网上整理所得 XMLDocument来操作XML比较简单,虽然有时效率不是很高.代码如下 已知有一个XML文件(bookstore.xml)如下: <?xml version="1.0" encoding="gb2312"?><bookstore> <book genre="fantasy" ISBN="2-3631-4"> <title>Oberon's Legacy<

链表节点的增加和删除

struct ListNode { int m_nValue; ListNode* m_pNext; }; //增加节点 /*第一个参数是一个指向指针的指针.当我们往一个空链表中插入一个节点时,新插入的节点 就是链表的头指针.由于此时会改动头指针,因此必须把pHead参数设为指向指针的指针*/ void addToTail(ListNode** pHead, int value) { ListNode* pNew = new ListNode(); pNew->m_pNext = NULL; p

删除单链表节点,时间复杂度为O(1)

一个编程练习,删除单链表一个节点,且时间复杂度控制在O(1)内. 1.核心操作代码如下: struct ListNode { int m_data; ListNode *m_pNext; }; void DeleteNode(ListNode **pListHead, ListNode *pToBeDeleted) { if(pListHead == NULL || pToBeDeleted == NULL) return; //=================================

单链表的逆向打印、删除无头的非尾节点、无头链表插入节点、约瑟环

//1.逆向打印链表(递归) void PrintTailToHead(ListNode *pHead) {                 ListNode *cur = pHead;                  if(cur != NULL)                 {                                 PrintTailToHead(cur->_next);                                 printf( "

数据结构-编程实现一个单链表节点的删除

1:代码如下: // ConsoleApplication15.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <malloc.h> #include <iostream> using namespace std; typedef struct node//定义链表结构体 { int data;//节点内容 node *next;//指向结构体的指针,下一个节点 }node; node *create()

13:在O(1)时间删除单链表节点

题目:给定单项链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点. 解析: 删除单向链表中的一个节点,常规做法是必须找到待删除节点的前一个节点才能实现,而这样做的时间复杂度是O(n),无法满足要求. 创新想法:当我们想删除一个节点时,并不一定要删除节点本身,可以用当前节点保存它下一节点的值,然后删除它的下一个节点. 情况案例: 1. 输入节点为NULL 2. 单链表只有一个节点,即删除头节点 3. 待删除节点是尾节点,即没有下一节点 4. 待删除不是尾节点 当待删除节点是尾节点时,