热门标签 | 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;
}

推荐阅读
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本文探讨了如何在模运算下高效计算组合数C(n, m),并详细介绍了乘法逆元的应用。通过扩展欧几里得算法求解乘法逆元,从而实现除法取余的计算。 ... [详细]
  • 本文详细介绍了 Apache Jena 库中的 Txn.executeWrite 方法,通过多个实际代码示例展示了其在不同场景下的应用,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 本文详细探讨了VxWorks操作系统中双向链表和环形缓冲区的实现原理及使用方法,通过具体示例代码加深理解。 ... [详细]
  • Codeforces Round #566 (Div. 2) A~F个人题解
    Dashboard-CodeforcesRound#566(Div.2)-CodeforcesA.FillingShapes题意:给你一个的表格,你 ... [详细]
  • 火星商店问题:线段树分治与持久化Trie树的应用
    本题涉及编号为1至n的火星商店,每个商店有一个永久商品价值v。操作包括每天在指定商店增加一个新商品,以及查询某段时间内某些商店中所有商品(含永久商品)与给定密码值的最大异或结果。通过线段树分治和持久化Trie树来高效解决此问题。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • 本文详细介绍了Java中org.w3c.dom.Text类的splitText()方法,通过多个代码示例展示了其实际应用。该方法用于将文本节点在指定位置拆分为两个节点,并保持在文档树中。 ... [详细]
  • 文件描述符、文件句柄与打开文件之间的关联解析
    本文详细探讨了文件描述符、文件句柄和打开文件之间的关系,通过具体示例解释了它们在操作系统中的作用及其相互影响。 ... [详细]
  • Linux设备驱动程序:异步时间操作与调度机制
    本文介绍了Linux内核中的几种异步延迟操作方法,包括内核定时器、tasklet机制和工作队列。这些机制允许在未来的某个时间点执行任务,而无需阻塞当前线程,从而提高系统的响应性和效率。 ... [详细]
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社区 版权所有