链表的面试题(一)
来源:互联网 发布:js正则表达式 冒号 编辑:程序博客网 时间:2024/06/17 13:05
题目:
// 逆向打印单链表
void PrintListFromTail2Head(PNode pHead);
// 逆向销毁单链表
void DestroyListFromTail2Head(PNode* pHead);
// 删除单链表的非尾结点
void DeleteNotTailNode(PNode pos);
// 非头结点前插入data
void InsertNotHead(PNode pos, DataType data);
// 单链表实现约瑟夫环
PNode JosephCircle(PNode pHead, size_t M);
// 单链表的逆置–前后指针
PNode ReverseList(PNode pHead);
// 单链表的逆置–头插法
PNode ReverseList(PNode pHead);
// 查找链表的中间结点—要求不能遍历单链表
PNode FindMidNode(PNode pHead);
源程序:
void PrintListFromTail2Head(PNode pHead)//逆向打印{ if (pHead) { PrintListFromTail2Head(pHead->next);//运用递归的思想,找出最后一个节点,打印 printf("%d->", pHead->data); }}
void DestroyListFromTail2Head(PNode* pHead)//逆向销毁{ if (*pHead) { DestroyListFromTail2Head(&((*pHead)->next)); free(*pHead); *pHead = NULL; }}
图解:
void DeleteNotTailNode(PNode pos){ if (pos == NULL || pos->next == NULL) return; else //让pos保存pos下个节点的值,然后删除pos的下个节点 { PNode pTemp = pos->next; pos->data = pTemp->data; pos->next = pTemp->next; free(pTemp); }}
图解:
void InsertNotHeadNode(PNode pos, DataType data){ PNode PNewnode = NULL; assert(pos); PNewnode = ByeNode(data); PNewnode->next = pos->next; pos->next = PNewnode; PNewnode->data=pos->data; pos->data = data;}
约瑟夫环是一个自杀环,是约瑟夫和他的朋友为了活下来而想出的一种办法: 包括他和他的朋友在内的41个犹太人,为了不成为敌方的俘虏而相约自杀,自杀的顺序是这样产生的,他们41个人围成一个圈,从其中任意位置开始报数,每次报到3的人自杀,然后从下一个人又开始从1报数。直到最后就会剩下1个人,约瑟夫和他的朋友就站在了最后剩下的两个位置,从而生存下来。
我们可以使用单链表来实现,先将单链表构建成一个环,每次删除掉第M个元素,直到链表只剩下一个节点,那么就返回这个节点。
需要考虑:链表为空—-直接返回
链表不空时:
①报数
②删节点
还需要特别注意是头结点,因为在删除的过程中,你可能删除掉头结点,所以最好接收最后剩下的一个节点,因为此时phead保存的节点
已经可能被释放掉了,所以不能再使用phead,而是使用pCur,因为pCur始终指向的是链表中可以访问到的当前节点。
图形解析:
PNode JosephCircle(PNode pHead, size_t M){ if (NULL == pHead) { return NULL; } PNode pCur = pHead; PNode prev = pCur; while (pCur != pCur->next) { size_t k = M; while (--k) { pCur = pCur->next; } PNode pDel = pCur->next; pCur->data = pDel->data; pCur->next = pDel->next; free(pDel); } return pCur;}
第一种方法–三个指针
首先考虑的还是链表为空和只有一个节点的情况—-直接返回。
还有链表中只有两个节点时,这种情况刚好在循环外可以处理。
在逆置的过程中肯定要进行循环,找到最后一个节点。
第二种方法–头插法:
简单说明:
就是每次将原链表的头节点摘下来(pHead->next = newnode),然后头插在新链表中(此时需要更新新链表的头结点),然后原来的头结点继续向后走,因为之前已经将头结点后的节点保存下来了;循环执行,直到原链表只剩下一个节点时,直接将最后这个节点头插在新链表即可。
PNode ReverseList(PNode pHead)//指针法{ if (NULL == pHead || NULL == pHead->next) { return pHead; } PNode prev = pHead; PNode pCur = prev->next; PNode pnext = pCur->next; while (pnext) { pCur->next = prev; prev = pCur; pCur = pnext; pnext = pnext->next; } pCur->next = prev; pHead->next = NULL; return pCur;}PNode ReverseList1(PNode pHead)//头插法{ if (NULL == pHead || NULL == pHead->next) { return pHead; } PNode pCur = pHead->next; PNode newNode = NULL; while (pCur) { pHead->next = newNode; newNode = pHead; pHead = pCur; pCur = pCur->next; } pHead->next = newNode; newNode = pHead; return newNode;}
首先考虑:链表为空——返回NULL;
分为两种情况:
链表中有奇数个节点时,分析如图示:
链表中有偶数个节点时:
PNode FindMidNode(PNode pHead){ if (NULL == pHead || NULL == pHead->next) { return pHead; } PNode pSlow = pHead; PNode pFast = pHead; while (pFast && pFast->next) { pSlow = pSlow->next; pFast = pFast->next->next; } return pSlow;}
- 链表的面试题(一)
- 链表相关的热点面试题(一)
- 链表相关面试题(一)
- android的面试题(一)
- 链表的面试题
- 经典的面试题:链表的相交与环问题 (一)
- 链表常见面试题一:基本问题
- 【每日一题-2】链表基础面试题
- 一公司的oracle sql面试题
- 百度的面试题《卷一》
- 经典的SQL面试题(一)
- 不错的SQL面试题(一)
- 一道面试题的探讨(一)
- 一公司的牛面试题
- 一关于引用的面试题
- java常见的面试题(一)
- 关于数组的面试题总结(一)
- 【javascript】关于正则的面试题一
- 读写excel文件
- Hadoop学习笔记(二)HDFS
- 用可重用的链表模块来实现命令行菜单小程序V2.5
- MySQL优化必须调整的10项配置
- 快速解决vs2017应用C++ windows desktop application模板时中文乱码问题
- 链表的面试题(一)
- android 通过Banner实现 录播图的效果(和OkHttp3)结合
- 535. Encode and Decode TinyURL(C++)
- angularjs 猜数
- 无人机驾驶员培训学习记录(五)
- 网易2018校园招聘编程题真题-[编程题] 魔法币
- 观察者模式(一)
- python第三方库之numpy
- 【SHOI2012】魔法树