链表相关面试题(一)
来源:互联网 发布:快手上的淘宝优惠群 编辑:程序博客网 时间:2024/06/05 07:58
当我对指针的使用感到很简单的时候,链表给了我一记重击。
在面试中,最经常被提及的就是链表,因为它简单,但又因为需要对指针进行操作,凡是涉及到指针的,都需要我们具有良好的编程基础才能确保代码没有任何错误。
所以,整理了一些面试题,特别记录下来。
注:本文是对上一篇文章的补充。(http://blog.csdn.net/qq_35524916/article/details/66296292)
另外:在对参数进行if判空还是assert判空上,我才用如下方法:若对参数的引用非法,使用assert,否则使用if。
附上,本文要解决的问题
// 使用递归实现从尾到头打印单链表void PrintFromTail2Head(PNode pHead);// 删除单链表的非尾结点(不能遍历链表)void DeleteNotTailNode(PNode pos);// 在单链表非头结点前插入结点datavoid InsertNotHeadNode(PNode pos, DataType data);//约瑟夫环问题void JosephCircle(PNode *pHead, size_t M);// 查找单链表的中间结点,要求只便利一次链表PNode FindMidNode(PNode pHead);// 查找单链表的倒数第K个结点,要求只遍历一次链表PNode FindLastKNode(PNode pHead, size_t k);// 使用冒泡排序对单链表进行排序void BubbleSort(PNode pHead);
下面一一分析:
1,利用递归逆序打印单链表
解析:利用递归思想,可以实现从后往前的打印。
注:参入参数为空的情况。
void PrintFromTail2Head(PNode pHead){if (NULL == pHead)return ;if (pHead->_pNext)PrintFromTail2Head(pHead->_pNext);printf("%d->", pHead->_data);}
2, 删除单链表的非尾结点(不能遍历单链表)
解析:如何在不知道链表节点的前一节点的情况下删除该节点?
可以遍历一次链表,然后保存两个节点的位置,再实现删除操作。
可是,当面试官要求不能遍历单链表呢?那就比较难了。
既然是非尾节点,那么可以激荡pos的下一节点,与当前节点的值互换,然后删除pos的下一节点即可。
注:链表为空或只有一个节点的情况。
void DeleteNotTailNode(PNode pos){PNode pDelNode = NULL;if ((NULL == pos) || (NULL == pos->_pNext))return ;pDelNode = pos->_pNext;pos->_data = pDelNode->_data;pos->_pNext = pDelNode->_pNext;free(pDelNode);pDelNode = NULL;}
3,在单链表非头结点前插入结点data
解析:和上面的思想差不多,先将节点插入到data后面,然后互换两个节点的值。
注:链表为空。
void InsertNotHeadNode(PNode pos, DataType data){PNode pNewNode = NULL;DataType temp_data = 0;if(NULL != pos)
return ;if (!(pNewNode = BuyNode(data)))return ;pNewNode->_pNext = pos->_pNext;pos->_pNext = pNewNode;temp_data = pos->_data;pos->_data = pNewNode->_data;pNewNode->_data = temp_data;}
4,约瑟夫环问题
解析:先将单链表的首尾相连,形成环。
然后设定一个计数器m,开始就遍历环,每遍历一个节点,m减1,同时删除该节点,直到链表只剩于一个链表。
注:链表传入的参数为空,无法解引用。
void JosephCircle(PNode *pHead, size_t M){PNode pTailNode = NULL; //用来指向最后一个节点PNode pCurNode = NULL;//用来指向数到M的节点size_t m = 0; assert(NULL != pHead); assert(0 != M); //M不能小于0pCurNode = *pHead;//pCurNode从首节点开始if (!(pTailNode = Back(*pHead))) //指向最后一个节点。return ;pTailNode->_pNext = *pHead;//首尾相连形成约瑟夫环while (pCurNode->_pNext != pCurNode) //当链表剩余不止一个节点时{PNode pDelNode = NULL;//用来删除的节点m = M;while (--m)pCurNode = pCurNode->_pNext;//pCurNode指向数到M的节点printf("%d->", pCurNode->_data);//打印节点信息//将下一节点的值赋给当前节点,删除下一节点。pDelNode = pCurNode->_pNext;//pDelNode指向下一节点pCurNode->_data = pDelNode->_data;//拷贝数据pCurNode->_pNext = pDelNode->_pNext;//跳过pDelNode,指向pDelNode的下一节点。free(pDelNode);//释放节点。pDelNode = NULL;}printf("%d-><null>\n", pCurNode->_data);//打印剩余节点信息free(pCurNode);//释放最后一个节点。pCurNode = NULL;*pHead = NULL;//链表为空}
5,查找单链表的中间结点,要求只遍历一次链表
解析:只遍历一次话,只利用一个节点遍历的话,实现比较麻烦。
所以采用两个节点遍历,一个快指针,一个慢指针。快指针一次走一步,慢指针一次走一步。
当快指针走到链表尾时,慢指针刚好指向链表额中间节点。返回慢指针即可。
注:链表为空的情况。
PNode FindMidNode(PNode pHead){//定义一个快指针,一次走两步,定义一个慢指针,一次走一步PNode pFast = NULL;PNode pSlow = NULL;//当链表为空,返回头指针if (NULL == pHead)return pHead;//都从pHead开始遍历pFast = pSlow = pHead;//当快指针走完后,返回慢指针的地址。while (NULL != pFast->_pNext){//快慢指针都先走一步pFast = pFast->_pNext;pSlow = pSlow->_pNext;//快指针多走一步if (NULL != pFast->_pNext)pFast = pFast->_pNext;}return pSlow;}
6,查找单链表的倒数第K个结点,要求只遍历一次链表
解析:类似利用了快慢指针方法,快指针先走k-1个几点,然后快慢指针一起走,直到快指针走完,返回慢指针。
注:链表为空。
PNode FindLastKNode(PNode pHead, size_t k){//利用快慢指针,快指针比慢指针先走(k-1)步。当快指针走完后,返回慢指针地址。PNode pAhead = NULL;PNode pBehind = NULL;if (NULL == pHead)//链表为空时返回NULLreturn NULL;pAhead = pBehind = pHead;//从头结点开始遍历while ((k-- > 1) && (NULL != pAhead->_pNext))//pFast先走k-1步pAhead = pAhead->_pNext;while (NULL != pAhead->_pNext){pAhead = pAhead->_pNext;pBehind = pBehind->_pNext;}return pBehind;}
7,使用冒泡排序对单链表排序
解析:定义一个开始节点pStart,从头开始遍历。每遍历一个几点,
在循环内定义一个当前节点pCurNode和pStart比较大小,判断是否需要交换值,若需要,跳出内循环,继续外循环
若不需要,继续内循环,直到pCurNode遍历完或满足交换条件。
void BubbleSort(PNode pHead){PNode pStart = NULL;//开始比较的节点指针if (NULL == pHead)return ;pStart = pHead;//从头结点开始遍历while (NULL != pStart->_pNext){PNode pCurNode = pStart->_pNext;//定义要比较的节点。while (NULL != pCurNode){if (pStart->_data > pCurNode->_data){DataType data = pCurNode->_data;pCurNode->_data = pStart->_data;pStart->_data = data;}pCurNode = pCurNode->_pNext;//要比较的节点往后移一步}pStart = pStart->_pNext;//开始比较节点往后移一步}}
- 链表相关面试题(一)
- 链表相关的热点面试题(一)
- 链表相关面试题(二)
- Hadoop相关面试题(一)
- 单链表相关热点面试题(一)
- 链表相关面试题
- 链表相关面试题
- 链表相关面试题
- 链表相关面试题
- 链表相关面试题
- 链表相关的热点面试题(二)
- 链表相关面试题(基础篇)
- 【C语言】单链表相关面试题(一)
- 链表相关面试题(zz)
- 常见的链表相关面试题
- 链表相关的面试题总结
- [各种面试题] 链表相关
- 链表的相关面试题
- View拖动实现
- C# 基于iTextSharp封装的PDF操作类
- 分析system_call中断处理过程
- CVPR2016代码合集
- pwnable.kr writeup hash
- 链表相关面试题(一)
- dfs-104. Maximum Depth of Binary Tree
- android UI 五大布局
- SSH实现批量删除
- 产品经理的要学习的知识
- Effective C++ 读书笔记
- Android设计模式(二)- 续:WindowManager
- 【Coursera Machine Learning】 Week2 学习笔记
- 哈希(散列)表之开放定址法的C++类模板实现