链表相关面试题(一)

来源:互联网 发布:快手上的淘宝优惠群 编辑:程序博客网 时间: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;//开始比较节点往后移一步}}

0 0
原创粉丝点击