【数据结构基础_有[*pHead]和[*pEnd]的单向链表_(C语言实现)】
单向链表(含头尾指针)
本文主要是针对(含头尾指针)单向链表进行增、删、改、查操作
创建一个结构体当做节点
struct Node
{int iData;struct Node* pNext;
};
定义头尾指针
struct Node* pHead = NULL;
struct Node* pEnd = NULL;
pEnd指针是为了增加尾添加的效率,否则就要循环找尾
增加:1.尾添加
无(*pEnd)指针的尾添加
void AddToEndNopEnd(struct Node** pHead, struct Node** pEnd, int iData)
{//创建节点struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));if (NULL != pTemp){//节点成员赋值pTemp->iData = iData;pTemp->pNext = NULL;//链接if (NULL == *pHead){*pHead = pTemp;}else{struct Node* pt = *pHead;while (pt->pNext != NULL) //找尾巴{pt = pt->pNext;}pt->pNext = pTemp;}}
}
有(*pEnd)指针的尾添加
void AddToEnd(struct Node** pHead, struct Node** pEnd, int iData)
{//创建节点struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));if (NULL != pTemp){//节点成员赋值pTemp->iData = iData;pTemp->pNext = NULL;//连接链表if (NULL == *pHead)//空链表{*pHead = pTemp;//*pEnd = pTemp;}else{(*pEnd)->pNext = pTemp;//*pEnd = pTemp;}*pEnd = pTemp;}
}
增加:2.头添加
void AddToHead(struct Node** pHead, struct Node** pEnd, int iData)
{//创建节点struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));if (NULL != pTemp){//节点成员赋值pTemp->iData = iData;pTemp->pNext = NULL;//连接链表if (NULL == *pHead)//空链表{//*pHead = pTemp;*pEnd = pTemp;}else{pTemp->pNext = *pHead;//*pHead = pTemp;}*pHead = pTemp;}
}
此时咱们链表的最简单的两个添加,已经完成,我们可以遍历链表来查看,并且释放链表
遍历链表
void Look(struct Node* pHead)
{while (pHead != NULL){printf("%d ", pHead->iData);pHead = pHead->pNext;}putchar('\n');
}
释放链表
void FreeList(struct Node** pHead, struct Node** pEnd)
{struct Node* pTemp = *pHead;while (pTemp != NULL){struct Node* pt = pTemp;pTemp = pTemp->pNext;free(pt);}*pHead = NULL;*pEnd = NULL;
}
释放链表记得指针要置空哈
查找:1.根据下标查询
struct Node* FindNodeByIndex(struct Node* pHead, int iIndex)
{//参数合法性检测if (NULL == pHead || iIndex < 0){printf("链表为空/位置输入有误,无法查节点\n");return NULL;}//循环链表int i = 0;while (pHead != NULL){if (i == iIndex)return pHead;i++;pHead = pHead->pNext;}printf("位置输入过大,无法查节点\n");return NULL;
}
查找:2.根据数值查询
struct Node* FindNodeByData(struct Node* pHead, int iData)
{//参数合法性检测if (NULL == pHead || iData < 0){printf("链表为空/位置输入有误,无法查节点\n");return NULL;}//循环链表while (pHead != NULL){if (pHead->iData == iData)return pHead;pHead = pHead->pNext;}return NULL;
}
升级版添加:1.在指定下标节点处添加节点
void InsertNodeByIndex(struct Node** pHead, struct Node** pEnd, int iIndex, int iData)
{//参数合法性检测if (iIndex < 0){printf("下标输入有误,请重新输入\n");return;}//下标为0,直接头添加if (0 == iIndex){AddToHead(pHead, pEnd, iData);}else{//找位置struct Node* pTemp = FindNodeByIndex(*pHead, iIndex - 1);if (pTemp != NULL){//申请节点空间struct Node* pT = (struct Node*)malloc(sizeof(struct Node));if (pT != NULL){//节点成员赋值pT->iData = iData;pT->pNext = NULL;//链接 先连后断pT->pNext = pTemp->pNext;pTemp->pNext = pT;}}else{printf("查无此节点");}}
}
升级版添加:2.在指定数值添加多个节点
看着很高大上,其实你只需要调用头添加即可,此时的头非彼头;
void AddSomeNode(struct Node** pHead, struct Node** pEnd, unsigned int iCount, unsigned int iData)
{for (unsigned int i = 0; i < iCount; i++){AddToEnd(pHead, pEnd, iData);}
}
修改:1.根据数值改变此节点数据
void ChengeData(struct Node* pHead, int iResData, int iDecData)
{struct Node* pRec = FindNodeByData(pHead, iResData);if (NULL == pRec){printf("查无此节点\n");}else{pRec->iData = iDecData;}
}
修改:2.根据数值改变此节点所有相同数据(一)
void ChengeSomeData(struct Node* pHead, int iResData, int iDecData)
{//参数合法性检测if (NULL == pHead){printf("查无此节点\n");return;}while (pHead != NULL){if (pHead->iData == iResData)pHead->iData = iDecData;pHead = pHead->pNext;}
}
修改:2.根据数值改变此节点所有相同数据(一)
void ChengeSomeDataText(struct Node* pHead, int iResData, int iDecData)
{//参数合法性检测if (NULL == pHead){printf("查无此节点\n");return;}while (FindNodeByData(pHead, iResData) != NULL){ChengeData(pHead, iResData, iDecData);}
}
删除:1.删除头结点
void DeleteHead(struct Node** pHead, struct Node** pEnd)
{//参数合法性检测if (NULL == pHead)return;if (*pHead == *pEnd || (*pHead)->pNext == NULL)//只有一个节点{free(*pHead);*pHead = NULL;*pEnd = NULL;}else{struct Node* pT = *pHead;(*pHead) = (*pHead)->pNext;free(pT);}
}
删除:2.删除尾结点
void DeleteEnd(struct Node** pHead, struct Node** pEnd)
{//参数合法性检测if (NULL == pHead)return;if (*pHead == *pEnd || (*pHead)->pNext == NULL)//只有一个节点{free(*pHead);*pHead = NULL;*pEnd = NULL;}else{//找到结尾的前一个struct Node* pT = *pHead;while (pT->pNext != *pEnd){pT = pT->pNext;}free(*pEnd);*pEnd = pT;(*pEnd)->pNext = NULL;}
}
删除:3.根据数值删除此节点(只删除一个哟)
struct Node* DeleteOneDataByData(struct Node** pHead, struct Node** pEnd, int iData)
{if (NULL == *pHead)return NULL;if ((*pHead)->iData == iData){DeleteHead(pHead, pEnd);return *pHead;}else if ((*pEnd)->iData == iData){DeleteEnd(pHead, pEnd);return *pHead;}else{//循环找节点struct Node* pTemp = *pHead;while (pTemp->pNext != NULL){if (pTemp->pNext->iData == iData)break;pTemp = pTemp->pNext;}//判断if (pTemp->pNext != NULL){struct Node* pT = pTemp->pNext; //记录pTemp->pNext = pT->pNext;free(pT);return *pHead; //return pTemp->pNext ----- pHead}else{printf("查无此节点\n");return NULL;}}
}
提醒一点哈,这里考虑到删除的节点可能是头结点,所有采用了返回值的方式
删除:4.根据数值删除此所有相同数据的节点
void DeleteAllDataByData(struct Node** pHead, struct Node** pEnd, int iData)
{if (NULL == *pHead)return;struct Node* pTemp = DeleteOneDataByData(pHead, pEnd, iData);while (pTemp != NULL){pTemp = DeleteOneDataByData(pHead, pEnd, iData);}
}
删除:5.根据下标删除此节点
void DeleteDataByIndex(struct Node** pHead, struct Node** pEnd, int iIndex)
{if (NULL == *pHead)return;if (0 == iIndex)DeleteHead(pHead, pEnd);else{//找前一个节点struct Node* pTemp = FindNodeByIndex(*pHead, iIndex - 1);if (pTemp != NULL){if (pTemp->pNext == *pEnd)DeleteEnd(pHead, pEnd);//记录被删除的节点struct Node* pT = pTemp->pNext;//链接pTemp->pNext = pT->pNext;//释放free(pT);}else{printf("查无此节点\n");}}
}
下面是一些其他简单操作方便大家更加熟悉链表
(1)获取节点个数
int GetListNodeCount(struct Node* pHead)
{int iCount = 0;while (NULL != pHead){iCount++;pHead = pHead->pNext;}return iCount;
}
(2)根据数值交换两个节点的数据
void SwapByData(struct Node* pHead, int iData1, int iData2)
{if (NULL == pHead)return;//查找struct Node* pT1 = FindNodeByData(pHead, iData1);struct Node* pT2 = FindNodeByData(pHead, iData2);//都找到才能交换if (pT1 != NULL && pT2 != NULL){//交换成员//struct Node p = *pT1;//*pT1 = *pT2;//*pT2 = p;//int temp = pT1->iData;//pT1->iData = pT2->iData;//pT2->iData = temp;struct Node p = *pT1;memcpy(pT1, pT2, 4);memcpy(pT2, &p, 4);}
}
(3)根据下标交换两个节点的数据
void SwapByIndex(struct Node* pHead, int iIndex1, int iIndex2)
{if (NULL == pHead)return;//查找struct Node* pT1 = FindNodeByIndex(pHead, iIndex1);struct Node* pT2 = FindNodeByIndex(pHead, iIndex2);//都找到才能交换if (pT1 != NULL && pT2 != NULL){//交换成员//int temp = pT1->iData;//pT1->iData = pT2->iData;//pT2->iData = temp;struct Node p = *pT1;memcpy(pT1, pT2, 4);memcpy(pT2, &p, 4);}
}
(4)交换指针指向节点
void SwapByChangePoint(struct Node** pHead, struct Node** pEnd, int iIndex1, int iIndex2)
{//参数合法性检测if (NULL == *pHead || NULL == (*pHead)->pNext || iIndex1 == iIndex2 || iIndex1 < 0 || iIndex2 < 0){return;}//确定大小关系int iMin = iIndex1;int iMax = iIndex2;if (iIndex1 > iIndex2){iMin = iIndex2;iMax = iIndex1;}//根据下标找节点struct Node* pMin = FindNodeByIndex(*pHead, iMin);struct Node* pMax = FindNodeByIndex(*pHead, iMax);//找不到就结束if (NULL == pMin || NULL == pMax){printf("查无此节点\n");return;}//头尾交换if (pMin == *pHead && pMax == *pEnd){if ((*pHead)->pNext == *pEnd) //两个节点{(*pEnd)->pNext = *pHead;(*pHead)->pNext = NULL;//交换指向*pHead = *pEnd;*pEnd = (*pHead)->pNext;}else //多个节点{//找到尾巴的前一个节点struct Node* pMaxPre = FindNodeByIndex(*pHead, iMax - 1);//尾巴变头(*pEnd)->pNext = (*pHead)->pNext;//头变尾巴pMaxPre->pNext = *pHead;//头下一个为NULL(*pHead)->pNext = NULL;//交换指向*pHead = *pEnd;*pEnd = pMaxPre->pNext;}}//头和中间交换else if (pMin == *pHead && pMax != *pEnd){//相邻if (pMin->pNext == pMax){pMin->pNext = pMax->pNext;pMax->pNext = pMin;*pHead = pMax;}//不相邻else {//找pMax的前一个指针struct Node* pMaxPre = FindNodeByIndex(*pHead, iMax - 1);//记录头的下一个节点 即链表第二个节点struct Node* pHeadNext = pMin->pNext;//头节点连在max的位置上pMin->pNext = pMax->pNext;pMaxPre->pNext = pMin;//pMax挪到头pMax->pNext = pHeadNext;//改变新的头*pHead = pMax;}}//尾和中间交换else if (pMin != *pHead && pMax == *pEnd){if (pMin->pNext == pMax) //相邻{//找到pMin的前一个struct Node* pMinPre = FindNodeByIndex(*pHead, iMin - 1);//先把尾巴放中间pMinPre->pNext = pMax;pMax->pNext = pMin;//pMin next = NULLpMin->pNext = NULL;*pEnd = pMin;}//不相邻else{//找到pMin的前一个struct Node* pMinPre = FindNodeByIndex(*pHead, iMin - 1);//找pMax的前一个指针struct Node* pMaxPre = FindNodeByIndex(*pHead, iMax - 1);//pmax放中间去pMinPre->pNext = pMax;pMax->pNext = pMin->pNext;//pMin放尾巴上去pMaxPre->pNext = pMin;pMin->pNext = NULL;*pEnd = pMin;}}//中间两个相互交换else if (pMin != *pHead && pMax != *pEnd){//相邻if (pMin->pNext == pMax){//找到pMin的前一个节点struct Node* pMinPre = FindNodeByIndex(*pHead, iMin - 1);struct Node* pMaxNext = pMax->pNext;//将pMax装在pMin 与pMinPre中间pMinPre->pNext = pMax;pMax->pNext = pMin;//把pMax拿下来pMin->pNext = pMaxNext;}//不相邻else{//找到pMin的前一个struct Node* pMinPre = FindNodeByIndex(*pHead, iMin - 1);struct Node* pMinNext = pMin->pNext;//找pMax的前一个指针struct Node* pMaxPre = FindNodeByIndex(*pHead, iMax - 1);struct Node* pMaxNext = pMax->pNext;//将pMin撞到pMax的位置pMaxPre->pNext = pMin;pMin->pNext = pMaxNext;//将pMax撞到pMin的位置pMinPre->pNext = pMax;pMax->pNext = pMinNext;}}
}
(5)根据数据翻转链表
void ReverseByData(struct Node* pHead)
{//参数合法性检测if (NULL == pHead || NULL == pHead->pNext){return;}int iCount = GetListNodeCount(pHead);int i = 0, j = iCount - 1;for (; i < j; i++, j--){SwapByIndex(pHead, i, j);}
}
(6)根据下标翻转链表
void ReverseByPoint(struct Node** pHead, struct Node** pEnd)
{//参数合法性检测if (NULL == *pHead || NULL == (*pHead)->pNext){return;}int iCount = GetListNodeCount(*pHead);int i = 0, j = iCount - 1;for (; i < j; i++, j--){SwapByChangePoint(pHead, pEnd, i, j);}
}
此时单向链表基本操作已经完成咯~
【数据结构基础_有[*pHead]和[*pEnd]的单向链表_(C语言实现)】相关推荐
- c语言单向链表经典,C语言基础 - 实现单向链表
写在前面 弄了下个人站...防止内容再次被锁定...所有东西都在这里面 welcome~ 个人博客 回归C基础 实现一个单向链表,并有逆序功能 (大学数据结构经常是这么入门的) //定义单链表结构体 ...
- 链表有环是什么意思_互联网大厂offer收割之单向链表的概念及面试题大全
链表是最基本的数据结构,面试官也常常用链表来考察面试者的基本能力,而且链表相关的操作相对而言比较简单,也适合考察写代码的能力.链表的操作也离不开指针,指针又很容易导致出错.综合多方面的原因,链表题目在 ...
- java简单单向链表_【新手自白书】简单单项链表的实现(JAVA)
复习一下简单单项链表的实现. 在动手写链表之前,需要思考链表是如何组成的,一般来说,一个简单的单项链表主要是由节点构成,由于链表的特性,头节点是一个十分重要的成员,所以,链表必须的成员是节点Node, ...
- java简单单向链表_用java简单的实现单链表的基本操作
packagecom.tyxh.link;//节点类 public classNode {protected Node next; //指针域 protected int data;//数据域 pub ...
- java 链表逆序代码_如何实现一个高效的单向链表逆序输出?(详解)
需要考虑因素,高效应权衡多方面因素 数据量是否会很大 空间是否有限制 原始链表的结构是否可以更改 时间复杂度是否有限制 一个链表节点需要输出的元素有多个,例如链表中存的是自定义对象,有多个字段 题目. ...
- c语言单链表功能,[数据结构]单链表(C语言)的各种功能
06-03阅读200,000 + 链表是一种常见的基本数据结构,在此充分利用了结构指针. 链表可以动态存储和分配,即链表是一个功能非常强大的数组. 他可以在节点中定义多种数据类型,并可以根据需要随意添 ...
- Algorithms_基础数据结构(04)_线性表之链表_单向循环链表约瑟夫环问题
文章目录 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 约瑟夫问题 结构 分析 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 tip:单向链表 约瑟夫问题 N个人围成一圈, ...
- Algorithms_基础数据结构(03)_线性表之链表_双向链表
文章目录 大纲图 双向链表 双向链表的基本结构 双向链表的基本操作 头插 尾插 中间部位插入 删除头部 删除尾部 删除中间位置的数据 查找 更新 Code 总结 大纲图 双向链表 Algorithms ...
- asp子窗口读取父窗口数据_算法与数据结构基础 - 数组(Array)
数组基础 数组是最基础的数据结构,特点是O(1)时间读取任意下标元素,经常应用于排序(Sort).双指针(Two Pointers).二分查找(Binary Search).动态规划(DP)等算法.顺 ...
- 在列表前方插入一个数据_通俗易懂的Redis数据结构基础教程
Redis有5个基本数据结构,string.list.hash.set和zset.它们是日常开发中使用频率非常高应用最为广泛的数据结构,把这5个数据结构都吃透了,你就掌握了Redis应用知识的一半了. ...
最新文章
- 批量启用lync用户-3
- Tomcat下使用Druid配置JNDI数据源
- SQL注入——报错注入
- android任务 进程 线程详解,Android任务、进程、线程详解
- 让ie8按照ie7 的方式来进行解析
- 如何屏蔽LOGD\LOGI等打印输出
- 微信小程序开发实战——模块化
- SmartFoxServer 2X 安装
- iOS视频直播初窥:高仿喵播APP
- List集合排序总结
- 推荐一个好用的论文助手工具
- layui数据表格实现快捷键切换编辑单元格
- python-字符串格式化(万古枯)
- NAND Flash SLC、MLC技术解析
- WinCE USB驱动CDevice::EnterOperationalState函数相关
- 微信公共服务平台开发(.Net 的实现)13-------网页授权(下 :C#代码的实现 )
- 前端开发:a标签的使用
- js获取当前月、上一月和下一月
- 自动化测试之 ddt 驱动 excel 文件
- 大数据架构之--Kappa架构