链表的面试题(一)

题目:

// 逆向打印单链表
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;
分为两种情况:
链表中有奇数个节点时,分析如图示:

这里写图片描述
链表中有偶数个节点时:
<code>这里写图片描述</code>

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值