热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

链表的基本操作——以及链表面试题

#define_CRT_SECURE_NO_WARNINGS#includelist.h#includevoidSListInit(PNode*pHead

#define _CRT_SECURE_NO_WARNINGS#include"list.h"
#include<assert.h>void SListInit(PNode* pHead) //链表初始化
{assert(pHead);*pHead &#61; NULL;
}PNode BuySListNode(DataType data)//申请一个结点
{PNode PNewNode &#61; (PNode )malloc(sizeof(Node));if (PNewNode &#61;&#61; NULL){return NULL;}PNewNode->_pNext &#61; NULL;PNewNode->_data &#61; data;return PNewNode;
}void SListPushBack(PNode* pHead, DataType data)// 尾插
{assert(pHead);if (NULL &#61;&#61; pHead){/*pHead &#61; BuySListNode(data);*/return;}else{PNode pCur &#61; NULL;pCur &#61; *pHead;while (pCur->_pNext){pCur &#61; pCur->_pNext;}pCur->_pNext &#61; BuySListNode(data);}
}void SListPopBack(PNode* pHead) // 尾删
{assert(pHead);if (NULL &#61;&#61; *pHead) //空链表return ;else if (NULL &#61;&#61; (*pHead)->_pNext) //只有一个节点{PNode TmpNode &#61; *pHead;free(TmpNode);TmpNode &#61; NULL;*pHead &#61; NULL;}else{PNode pCur &#61; *pHead;while (pCur->_pNext->_pNext){pCur &#61; pCur->_pNext;}pCur->_pNext &#61; NULL;}
}void SListPushFront(PNode* pHead, DataType data)// 头插
{PNode PNewNode &#61; NULL;assert(pHead);PNewNode &#61; BuySListNode(data);if (NULL &#61;&#61; PNewNode)return;PNewNode->_pNext &#61; *pHead;*pHead &#61; PNewNode;}void SListPopFront(PNode* pHead)// 头删
{PNode pDelNode &#61; NULL;assert(pHead);if (NULL &#61;&#61; pHead) //空链表return ;pDelNode &#61; *pHead;*pHead &#61; pDelNode->_pNext;free(pDelNode);
}// 查找值为data的结点&#xff0c;返回该结点在链表中的位置
PNode SListFind(PNode pHead, DataType data)
{PNode pCur &#61; pHead;while (pCur){if (pCur->_data &#61;&#61; data){return pCur;}pCur &#61; pCur->_pNext;}return NULL;
}// 在链表pos位置后插入结点data
void SListInsert(PNode* pHead, PNode pos, DataType data)
{PNode PNewNode &#61; NULL;assert(pHead);if (NULL &#61;&#61; *pHead || NULL &#61;&#61; pos)return;PNewNode &#61; BuySListNode(data);PNewNode->_pNext &#61; pos->_pNext;pos->_pNext &#61; PNewNode;}// 删除链表pos位置上的结点
void SListErase(PNode* pHead, PNode pos)
{assert(pHead);if (NULL &#61;&#61; *pHead || NULL &#61;&#61; pos)return;if (pos &#61;&#61; *pHead){SListPopFront(pHead);}else{PNode pCur &#61; *pHead;while (pCur && pCur->_pNext !&#61; pos){pCur &#61; pCur->_pNext;}if (pCur){pCur->_pNext &#61; pos->_pNext;free(pos);}}
}void SListClear(PNode* pHead)// 将链表中的结点清空
{PNode pDelNode &#61; NULL;assert(pHead);while (*pHead){pDelNode &#61; *pHead;*pHead &#61; pDelNode->_pNext;free(pDelNode);}
}void SListDestroy(PNode* pHead)// 销毁单链表
{SListClear(pHead);
}int SListSize(PNode pHead) // 求链表中结点的个数
{int count &#61; 0;PNode pCur &#61; pHead;assert(pHead);if (NULL &#61;&#61; pHead)return 0;pCur &#61; pHead;while (pCur){count&#43;&#43;;pCur &#61; pCur->_pNext;}return count;
}// 获取链表中的最后一个结点&#xff0c;返回该结点的地址
PNode SListBack(PNode pHead)
{PNode pCur &#61; pHead;assert(pHead);while (pCur->_pNext){pCur &#61; pCur->_pNext;}return pCur;
}void PrintList(PNode* pHead)//打印单链表
{PNode pCur &#61; *pHead;while (pCur){printf("%d->", pCur->_data);pCur &#61; pCur->_pNext;}printf("NULL\n");
}


以下为链表面试题

// 从尾到头打印单链表
void PrintListFromTail2Head(PNode pHead)
{if (pHead){PrintListFromTail2Head(pHead->_pNext);printf("%d--", pHead->_data);}
}// 删除无头单链表的非尾结点&#xff0c;要求&#xff1a;不能遍历链表
void DeleteNotTailNode(PNode pos)
{PNode pDelNode &#61; NULL;if (NULL &#61;&#61; pos&&NULL &#61;&#61; pos->_pNext)return;pDelNode &#61; pos->_pNext;pos->_data &#61; pDelNode->_data;pos->_pNext &#61; pDelNode->_pNext;free(pDelNode);
}// 在无头单链表pos位置前插入值为结点data的结点 (不能遍历链表)
void InsertPosFront(PNode pos, DataType data)
{PNode pNewNode &#61; NULL;if (NULL &#61;&#61; pos)return;pNewNode &#61; BuySListNode(pos->_data);pNewNode->_pNext &#61; pos->_pNext;pos->_pNext &#61; pNewNode;pos->_data &#61; data;
}// 用单链表模拟实现约瑟夫环
void JosephCircle(PNode* pHead, const int M)
{assert(pHead);PNode pCur &#61; *pHead;if (NULL &#61;&#61; pHead)return;while (pCur->_pNext !&#61; pCur){///报数int count &#61; M;while (--count){pCur &#61; pCur->_pNext;}//删除--替换法删除PNode pDelNode &#61; pCur->_pNext;pCur->_data &#61; pDelNode->_data;pCur->_pNext &#61; pDelNode->_pNext;free(pDelNode);}*pHead &#61; pCur;
}// 使用冒泡排序方法对单链表进行排序
void BubbleSort(PNode pHead)
{PNode pPreCur &#61; NULL;PNode pCur &#61; NULL;PNode pTail &#61; NULL;if (NULL &#61;&#61; pHead || NULL &#61;&#61; pHead->_pNext)return;while (pHead !&#61; pTail){int IsChange &#61; 0;pPreCur &#61; pHead;pCur &#61; pPreCur->_pNext;while (pCur !&#61; pTail){if (pPreCur->_data > pCur->_data){int tmp &#61; pPreCur->_data;pPreCur->_data &#61; pCur->_data;pCur->_data &#61; tmp;IsChange &#61; 1;}pPreCur &#61; pCur;pCur &#61; pPreCur->_pNext;}if (!IsChange)return;pTail &#61; pPreCur;}
}// 单链表的逆置--三个指针
void ReverseSList(PNode* pHead)
{PNode pPre &#61; NULL;PNode pCur &#61; NULL;PNode pNext &#61; NULL;assert(pHead);if (NULL &#61;&#61; *pHead || NULL &#61;&#61; (*pHead)->_pNext)return;pCur &#61; *pHead;while (pCur){pNext &#61; pCur->_pNext;pCur->_pNext &#61; pPre;pPre &#61; pCur;pCur &#61; pNext;}*pHead &#61; pPre;
}// 单链表的逆置--头插法
PNode ReverseSListOP(PNode pHead)
{PNode pNewHead &#61; NULL;PNode pCur &#61; pHead;PNode pNext &#61; NULL;if (NULL &#61;&#61; pHead || NULL &#61;&#61; pHead->_pNext)return pHead;while (pCur){pNext &#61; pCur->_pNext;pCur->_pNext &#61; pNewHead;pNewHead &#61; pCur;pCur &#61; pNext;}return pNewHead;
}// 合并两个有序链表&#xff0c;合并之后依然有序
PNode MergeSList(PNode pHead1, PNode pHead2)
{PNode pNewHead &#61; NULL;PNode pTailNode &#61; NULL;PNode pL1 &#61; pHead1;PNode pL2 &#61; pHead2;if (NULL &#61;&#61; pHead1)return pHead2;if (NULL &#61;&#61; pHead2)return pHead1;//两个链表都不为空&#xff0c;确定第一个节点if (pL1->_data < pL2->_data){pNewHead &#61; pL1;pL1 &#61; pL1->_pNext;}else{pNewHead &#61; pL2;pL2 &#61; pL2->_pNext;}//向新链表中插入值pTailNode &#61; pNewHead;while (pL1 && pL2){if (pL1->_data < pL2->_data){pTailNode->_pNext &#61; pL1;pL1 &#61; pL1->_pNext;}else{pTailNode->_pNext &#61; pL2;pL2 &#61; pL2->_pNext;}pTailNode &#61; pTailNode->_pNext;}//若一个链表有剩余&#xff0c;放在新链表后面if (pL1)pTailNode->_pNext &#61; pL1;elsepTailNode->_pNext &#61; pL2;return pNewHead;
}// 查找链表的中间结点&#xff0c;要求只能遍历一次链表
PNode FindMiddleNode(PNode pHead)
{PNode pFast &#61; pHead;PNode pSlow &#61; pHead;/*PNode pPre &#61; pHead;*/while (pFast && pFast->_pNext){/*pPre &#61; pSlow;*/pFast &#61; pFast->_pNext->_pNext;pSlow &#61; pSlow->_pNext;}//求奇数个节点的中间节点前一个节点/*if (NULL &#61;&#61; pFast)return pPre;*/return pSlow;
}// 查找链表的倒数第K个结点&#xff0c;要求只能遍历链表一次
PNode FindLastKNode(PNode pHead, int K)
{PNode pFast &#61; pHead;PNode pSlow &#61; pHead; if (NULL &#61;&#61; pHead || K < 0)return NULL;//让pFast先走K步while (K--){if (NULL &#61;&#61; pFast)//K大于节点个数return NULL;pFast &#61; pFast->_pNext;}//两指针同时往后走while (pFast){pFast &#61; pFast->_pNext;pSlow &#61; pSlow->_pNext;}return pSlow;
}// 删除链表的倒数第K个结点&#xff0c;要求只能遍历链表一次
PNode DeleteLastKNode(PNode pHead, int K)
{PNode pFast &#61; pHead;PNode pSlow &#61; pHead;PNode pPre &#61; NULL;if (NULL &#61;&#61; pHead || K <&#61; 0)return NULL;int count &#61; K;//快的指针先走K步while (count--){if (NULL &#61;&#61; pFast)return NULL;pFast &#61; pFast->_pNext;}//然后快慢指针一起走&#xff0c;慢指针指向的就是倒数第K个节点while (pFast){pPre &#61; pSlow;pFast &#61; pFast->_pNext;pSlow &#61; pSlow->_pNext;}//删除pPre->_pNext &#61; pSlow->_pNext;free(pSlow);return pHead;
}// 判断单链表是否相交&#xff1f;链表不带环
int IsCrossWithoutCircle(PNode pHead1, PNode pHead2)
{PNode pTail1 &#61; pHead1;PNode pTail2 &#61; pHead2;if (NULL &#61;&#61; pHead1 || NULL &#61;&#61; pHead2)return 0;//找第一个链表的最后一个节点while (pTail1)pTail1 &#61; pTail1->_pNext;//找第二个链表的最后一个节点while (pTail2)pTail2 &#61; pTail2->_pNext;return pTail1 &#61;&#61; pTail2;
}// 求不带环单链表相交交点
PNode GetCrossNode(PNode pHead1, PNode pHead2)
{int size1 &#61; 0, size2 &#61; 0, gap;PNode pCur1 &#61; pHead1, pCur2 &#61; pHead2;if (!(IsCrossWithoutCircle(pHead1, pHead2)))return NULL;//求交点while (pCur1){size1&#43;&#43;;pCur1 &#61; pCur1->_pNext;}while (pCur2){size2&#43;&#43;;pCur2 &#61; pCur2->_pNext;}//让长的链表先走差值这么多gap &#61; size1 - size2;pCur1 &#61; pHead1; pCur2 &#61; pHead2;if (gap > 0){while (gap--)pCur1 &#61; pCur1->_pNext;}else{while (gap&#43;&#43;)pCur2 &#61; pCur2->_pNext;}while (pCur1 !&#61; pCur2){pCur1 &#61; pCur1->_pNext;pCur2 &#61; pCur2->_pNext;}return pCur1;
}// 判断链表是否带环
PNode IsCircle(PNode pHead)
{PNode pFast &#61; pHead;PNode pSlow &#61; pHead;while (pFast&&pFast->_pNext){pFast &#61; pFast->_pNext->_pNext;pSlow &#61; pSlow->_pNext;if (pFast &#61;&#61; pSlow) //带环return pFast;}return 0;
}// 求环的长度
int GetCircleLen(PNode pHead)
{PNode pMeetNode &#61; IsCircle(pHead);PNode pCur &#61; pMeetNode;int count &#61; 1;if (NULL &#61;&#61; pMeetNode)return 0;while (pCur->_pNext !&#61; pMeetNode){count&#43;&#43;;pCur &#61; pCur->_pNext;}return count;
}// 求环的入口点--注意推断过程
PNode GetEnterNode(PNode pHead, PNode pMeetNode)
{PNode PH &#61; pHead;PNode PM &#61; pMeetNode;if (NULL &#61;&#61; pHead || NULL &#61;&#61; pMeetNode)return NULL;while (PH !&#61; PM){PH &#61; PH->_pNext;PM &#61; PM->_pNext;}return PM;
}// 判断链表是否带环&#xff0c;链表可能带环
int IsListCrossWithCircle(PNode pHead1, PNode pHead2)
{PNode pMeetNode1 &#61; NULL;PNode pMeetNode2 &#61; NULL;if (NULL &#61;&#61; pHead1 || NULL &#61;&#61; pHead2)return 0;//判断两个链表是否带环pMeetNode1 &#61; IsCircle(pHead1);pMeetNode2 &#61; IsCircle(pHead2);//两个链表都不带环if (NULL &#61;&#61; pMeetNode1&&NULL &#61;&#61; pMeetNode2){//求两个链表的最后一个元素&#xff0c;若最后一个元素相等则相交PNode pTail1 &#61; pHead1;PNode pTail2 &#61; pHead2;while (pTail1->_pNext)pTail1 &#61; pTail1->_pNext;while (pTail2->_pNext)pTail2 &#61; pTail2->_pNext;if (pTail1 &#61;&#61; pTail2)return 1;}//两个链表都带环else if (pMeetNode1 && pMeetNode2){PNode pCur &#61; pMeetNode1;/* do{if (pCur &#61;&#61; pMeetNode2)return 2;pCur &#61; pCur->_pNext;} while (pCur !&#61; pMeetNode1);*/while (pCur->_pNext !&#61; pMeetNode1){if (pCur &#61;&#61; pMeetNode2)return 2;pCur &#61; pCur->_pNext;}if (pCur &#61;&#61; pMeetNode2)return 2;}return 0;
}// 复杂链表的复制
PCListNode CopyComplexList(PCListNode pHead)
{PCListNode pOldNode &#61; pHead;PCListNode pNewNode &#61; NULL;PCListNode pNewHead &#61; NULL;if (NULL &#61;&#61; pHead)return NULL;//在原链表的每个节点后插入值相同的新节点while (pOldNode){pNewHead &#61; (PCListNode)malloc(sizeof(CListNode));pNewHead->_data &#61; pOldNode->_data;pNewNode->_pNext &#61; NULL;pNewNode->_pRandom &#61; NULL;if (NULL &#61;&#61; pNewNode)return NULL;pNewNode->_pNext &#61; pOldNode->_pNext;pOldNode->_pNext &#61; pNewNode;pOldNode &#61; pNewNode->_pNext;}//给新插入的节点的随机指针域赋值pOldNode &#61; pHead;while (pOldNode){pNewNode &#61; pOldNode->_pNext;if (NULL &#61;&#61; pOldNode->_pRandom)pNewNode->_pRandom &#61; NULL;elsepNewNode->_pRandom &#61; pOldNode->_pRandom->_pNext;pOldNode &#61; pNewNode->_pNext;}//将插入的新节点从链表中拆下来pOldNode &#61; pHead;pNewHead &#61; pOldNode->_pNext;while (pOldNode->_pNext){pNewNode &#61; pOldNode->_pNext;pOldNode->_pNext &#61; pNewNode->_pNext;pOldNode &#61; pNewNode;}return pNewHead;
}

推荐阅读
  • 使用QT构建基础串口辅助工具
    本文详细介绍了如何利用QT框架创建一个简易的串口助手应用程序,包括项目的建立、界面设计与编程实现、运行测试以及最终的应用程序打包。 ... [详细]
  • 在Qt框架中,信号与槽机制是一种独特的组件间通信方式。本文探讨了这一机制相较于传统的C风格回调函数所具有的优势,并分析了其潜在的不足之处。 ... [详细]
  • 本文将深入探讨 Unreal Engine 4 (UE4) 中的距离场技术,包括其原理、实现细节以及在渲染中的应用。距离场技术在现代游戏引擎中用于提高光照和阴影的效果,尤其是在处理复杂几何形状时。文章将结合具体代码示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 小编给大家分享一下Vue3中如何提高开发效率,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获, ... [详细]
  • linux网络子系统分析(二)—— 协议栈分层框架的建立
    目录一、综述二、INET的初始化2.1INET接口注册2.2抽象实体的建立2.3代码细节分析2.3.1socket参数三、其他协议3.1PF_PACKET3.2P ... [详细]
  • Logging all MySQL queries into the Slow Log
    MySQLoptionallylogsslowqueriesintotheSlowQueryLog–orjustSlowLog,asfriendscallit.However,Thereareseveralreasonstologallqueries.Thislistisnotexhaustive:Belowyoucanfindthevariablestochange,astheyshouldbewritteninth ... [详细]
  • c语言二元插值,二维线性插值c语言
    c语言二元插值,二维线性插值c语言 ... [详细]
  • 嵌套列表的扁平化处理
    本文介绍了一种方法,用于遍历嵌套列表中的每个元素。如果元素是整数,则将其添加到结果数组中;如果元素是一个列表,则递归地遍历这个列表。此方法特别适用于处理复杂数据结构中的嵌套列表。 ... [详细]
  • 本文详细介绍了如何在循环双链表的指定位置插入新元素的方法,包括必要的步骤和代码示例。 ... [详细]
  • 编译原理中的语法分析方法探讨
    本文探讨了在编译原理课程中遇到的复杂文法问题,特别是当使用SLR(1)文法时遇到的多重规约与移进冲突。文章讨论了可能的解决策略,包括递归下降解析、运算符优先级解析等,并提供了相关示例。 ... [详细]
  • 题目编号:2049 [SDOI2008]Cave Exploration。题目描述了一种动态图操作场景,涉及三种基本操作:断开两个节点间的连接(destroy(a,b))、建立两个节点间的连接(connect(a,b))以及查询两节点是否连通(query(a,b))。所有操作均确保图中无环存在。 ... [详细]
  • 在Java开发中,保护代码安全是一个重要的课题。由于Java字节码容易被反编译,因此使用代码混淆工具如ProGuard变得尤为重要。本文将详细介绍如何使用ProGuard进行代码混淆,以及其基本原理和常见问题。 ... [详细]
  • 题目描述:计算从起点到终点的最小能量消耗。如果下一个单元格的风向与当前单元格相同,则消耗为0,否则为1。共有8个可能的方向。 ... [详细]
  • 本文介绍如何手动实现一个字符串连接函数,该函数不依赖于C语言的标准字符串处理函数,如strcpy或strcat。函数原型为void concatenate(char *dest, char *src),其主要作用是将源字符串src追加到目标字符串dest的末尾。 ... [详细]
  • 在现代Web开发中,HTML5 Canvas常用于图像处理和绘图任务。本文将详细介绍如何将Canvas中的图像导出并上传至服务器,适用于拼图、图片编辑等场景。 ... [详细]
author-avatar
actthank90909
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有