单链表的面试题总结--------图形解析
2017-01-02 00:57
239 查看
1.// 删除无头单链表的非尾结点,要求:不能遍历单链表
因为没有头结点,所以不能用固有的思维去考虑这个问题,因为是单链表,所以不能由链表中的后一个节点去找前一个节点,
所以这时需要转化一种思维,不能删除一个节点的前一个节点,但是可以去删除一个节点的后一个节点,
首先应该判断pos是否为空,如果为空,直接返回,如果不为空,分析如图示(利用转换思想)
在这里还应该思考:为什么是删除非尾节点?—-如果是删除最后一个节点,那么这里的pDel就为空了,
那么如果使用下面的方法,运行pDel->next时程序就会崩溃。所以就没办法删除这个节点了。
图形解析:
![](http://img.blog.csdn.net/20170102003841726?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQ5OTI4NDU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
代码实现:
2.// 在无头单链表非头结点前插入新节点
使用上一题的思想,可以转换,可以在这个节点的后面插入这个节点,然后将需要插入节点的值赋给这个节点即可:
分析如图示:
![](http://img.blog.csdn.net/20170102003931728?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQ5OTI4NDU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
代码实现:
3.// 用单链表实现约瑟夫环
首先需要构建一个环,这个很容易,只要将单链表的尾节点的next指向phead即可。
约瑟夫环是一个自杀环,是约瑟夫和他的朋友为了活下来而想出的一种办法:
包括他和他的朋友在内的41个犹太人,为了不成为敌方的俘虏而相约自杀,自杀的顺序是这样产生的,他们41个人围成一个圈,从其中任意位置开始报数,每次报到3的人自杀,然后从下一个人又开始从1报数。直到最后就会剩下1个人,约瑟夫和他的朋友就站在了最后剩下的两个位置,从而生存下来。
我们可以使用单链表来实现,先将单链表构建成一个环,每次删除掉第M个元素,直到链表只剩下一个节点,那么就返回这个节点。
需要考虑:链表为空—-直接返回
链表不空时:
①报数
②删节点
还需要特别注意是头结点,因为在删除的过程中,你可能删除掉头结点,所以最好接收最后剩下的一个节点,因为此时phead保存的节点
已经可能被释放掉了,所以不能再使用phead,而是使用pCur,因为pCur始终指向的是链表中可以访问到的当前节点。
图形解析:
![](http://img.blog.csdn.net/20170102004121246?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQ5OTI4NDU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
代码实现:
4.// 逆置单链表
第一种方法–三个指针
首先考虑的还是链表为空和只有一个节点的情况—-直接返回。
还有链表中只有两个节点时,这种情况刚好在循环外可以处理。
在逆置的过程中肯定要进行循环,找到最后一个节点。
![](http://img.blog.csdn.net/20170309121819626?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQ5OTI4NDU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
代码实现:
// 逆置单链表
第二种方法–头插法:
简单说明:
就是每次将原链表的头节点摘下来(pHead->next = newnode),然后头插在新链表中(此时需要更新新链表的头结点),然后原来的头结点继续向后走,因为之前已经将头结点后的节点保存下来了;循环执行,直到原链表只剩下一个节点时,直接将最后这个节点头插在新链表即可。
代码实现:
5.// 查找单链表的中间结点,要求只能够遍历一次链表
首先考虑:链表为空——返回NULL;
分为两种情况:
①链表中有奇数个节点时,分析如图示:
![](http://img.blog.csdn.net/20170102004521814?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQ5OTI4NDU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
②链表中有偶数个节点时:
![](http://img.blog.csdn.net/20170102004607352?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQ5OTI4NDU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
代码实现:
6.// 查找单链表的倒数第K个结点,只能够遍历一次链表
![](http://img.blog.csdn.net/20170102004657696?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQ5OTI4NDU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
代码实现:
7.// 删除单链表的倒数第K个结点
PNode DeleteLastKNode(PNode pHead, size_t K);
由上一题可以很容易的得到第k个节点,然后调用删除的函数即可。
代码实现:
8.// 合并两个已序单链表,合并之后依然有序
PNode MergeList(PNode pHead1, PNode pHead2);
考虑以下因素:
pHead1为空—–返回pHead2
pHead2为空—–返回pHead1
当pHead1和pHead2都不为空时,分析如图示:
![](http://img.blog.csdn.net/20170102004800650?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQ5OTI4NDU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
代码实现:
9.// 对单链表进行冒泡排序–升序
相信大家对冒泡排序的思想已经很熟悉了吧,如果真的有需要,可以去看一下我的冒泡排序的图形解析~当然了,如果有兴趣的话。
这里我就直接贴代码啦
上面的代码都是我验证过的,我的编译器是vs2010,当然啦,因为能力有限,上面的算法或许不是最优的,可能你还有更好的方法,欢迎评论探讨,共同学习,一起进步。
最近一直在考试,忙着复习,所以只能在这个时间点来总结学习的内容,赶紧得休息啦,明天继续复习。
因为没有头结点,所以不能用固有的思维去考虑这个问题,因为是单链表,所以不能由链表中的后一个节点去找前一个节点,
所以这时需要转化一种思维,不能删除一个节点的前一个节点,但是可以去删除一个节点的后一个节点,
首先应该判断pos是否为空,如果为空,直接返回,如果不为空,分析如图示(利用转换思想)
在这里还应该思考:为什么是删除非尾节点?—-如果是删除最后一个节点,那么这里的pDel就为空了,
那么如果使用下面的方法,运行pDel->next时程序就会崩溃。所以就没办法删除这个节点了。
图形解析:
代码实现:
void DeleteNotTailNode(PNode pos) { if (NULL == pos) { return ; } PNode pDel = pos->next; pos->data = pDel->data; pos->next = pDel->next; free(pDel); }
2.// 在无头单链表非头结点前插入新节点
使用上一题的思想,可以转换,可以在这个节点的后面插入这个节点,然后将需要插入节点的值赋给这个节点即可:
分析如图示:
代码实现:
void InsertNotHeadNode(PNode pos, DataType _data) { if (NULL == pos) { return ; } PNode newNode = BuyNode(pos->data); if (newNode) { newNode->next = pos->next; pos->next = newNode; pos->data = _data; } }
3.// 用单链表实现约瑟夫环
首先需要构建一个环,这个很容易,只要将单链表的尾节点的next指向phead即可。
约瑟夫环是一个自杀环,是约瑟夫和他的朋友为了活下来而想出的一种办法:
包括他和他的朋友在内的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; }
4.// 逆置单链表
第一种方法–三个指针
首先考虑的还是链表为空和只有一个节点的情况—-直接返回。
还有链表中只有两个节点时,这种情况刚好在循环外可以处理。
在逆置的过程中肯定要进行循环,找到最后一个节点。
代码实现:
逆置单链表--三个指针 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; }
// 逆置单链表
第二种方法–头插法:
简单说明:
就是每次将原链表的头节点摘下来(pHead->next = newnode),然后头插在新链表中(此时需要更新新链表的头结点),然后原来的头结点继续向后走,因为之前已经将头结点后的节点保存下来了;循环执行,直到原链表只剩下一个节点时,直接将最后这个节点头插在新链表即可。
代码实现:
PNode ReverseList(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; }
5.// 查找单链表的中间结点,要求只能够遍历一次链表
首先考虑:链表为空——返回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; }
6.// 查找单链表的倒数第K个结点,只能够遍历一次链表
代码实现:
PNode FindLastKNode(PNode pHead, size_t K) { if (NULL == pHead || K == 0) { return NULL; } PNode pSlow = pHead; PNode pFast = pHead; while (--K) { if (NULL == pFast) { return NULL; } pFast = pFast->next; } while (pFast->next) { pSlow = pSlow->next; pFast = pFast->next; } return pSlow; }
7.// 删除单链表的倒数第K个结点
PNode DeleteLastKNode(PNode pHead, size_t K);
由上一题可以很容易的得到第k个节点,然后调用删除的函数即可。
代码实现:
PNode DeleteLastKNode(PNode pHead, size_t K) { if (NULL == pHead || K == 0) { return NULL; } PNode pos = FindLastKNode(pHead,K); Erase(&pHead,pos); }
8.// 合并两个已序单链表,合并之后依然有序
PNode MergeList(PNode pHead1, PNode pHead2);
考虑以下因素:
pHead1为空—–返回pHead2
pHead2为空—–返回pHead1
当pHead1和pHead2都不为空时,分析如图示:
代码实现:
PNode MergeList(PNode pHead1, PNode pHead2) { if (NULL == pHead1) { return pHead2; } if (NULL == pHead2) { return pHead1; } PNode newNode = NULL; PNode pTail = NULL; if (pHead1->data < pHead2->data) { pTail = pHead1; pHead1 = pHead1->next; } else { pTail = pHead2; pHead2 = pHead2->next; } newNode = pTail; while (pHead1 && pHead2) { if (pHead1->data < pHead2->data) { pTail->next = pHead1; pTail = pHead1; pHead1 = pHead1->next; } else { pTail->next = pHead2; pTail = pHead2; pHead2 = pHead2->next; } } if (pHead1) { pTail->next = pHead1; } else { pTail->next = pHead2; } return newNode; }
9.// 对单链表进行冒泡排序–升序
相信大家对冒泡排序的思想已经很熟悉了吧,如果真的有需要,可以去看一下我的冒泡排序的图形解析~当然了,如果有兴趣的话。
这里我就直接贴代码啦
void BubbleSort(PNode pHead) { if (NULL == pHead || NULL == pHead->next) { return ; } PNode pCur = pHead; PNode pTail = NULL; int flag = 0; while (pTail != pHead) { pCur = pHead; while (pCur->next != pTail) { if (pCur->data > pCur->next->data) { DataType tmp = pCur->data; pCur->data = pCur->next->data; pCur->next->data = tmp; flag = 1; } pCur = pCur->next; if (!flag) { return ; } } pTail = pCur; } }
上面的代码都是我验证过的,我的编译器是vs2010,当然啦,因为能力有限,上面的算法或许不是最优的,可能你还有更好的方法,欢迎评论探讨,共同学习,一起进步。
最近一直在考试,忙着复习,所以只能在这个时间点来总结学习的内容,赶紧得休息啦,明天继续复习。
相关文章推荐
- 在单链表的第i个位置后插入一个节点(阿里+腾讯等面试题总结)
- 剑指offer代码解析——面试题16反转单链表
- 20110530-Day02 Xml的解析,dom4j + 平面图形面试题
- 剑指offer代码解析——面试题16反转单链表
- 深入理解 js this 绑定 (尾部有总结和面试题解析 )
- 单链表删除(Delete)或者去除(Remove)节点面试题总结
- 年总结2015前端面试题集锦及答案解析
- 单链表相关面试题总结
- 【单链表经典面试题解析三】在无头单链表的一个非头节点前插入一个节点(要求不能遍历单链表)
- 【单链表经典面试题解析一】从尾到头打印单链表
- 从头到尾彻底解析Hash表算法十道海量数据处理面试题与十个方法大总结
- 在单链表的第i个位置后插入一个节点(阿里+腾讯等面试题总结)
- 多种单链表反转面试题总结
- 笔试面试题总结之单链表(Linked List)
- HP面试题总结(六)
- sax解析xml文件过程总结
- XML文件解析技术总结(一)
- HP面试题总结(五)
- C/C++ 面试题总结
- HTMLParser(一个比较流行的html代码解析、处理开源项目)学习,总结