单链表的常见笔试题(1)

        在之前的“单链表基本操作”博客中,介绍了一些关于单链表的增删查改等基本操作。在本文中,对单链表的操作升级,列举一些常见的有关单链表的常见笔试题。

        注意:该单链表还是无头结点,单向,无环的。有关链表的信息与“单链表基本操作中”相同。

1. 逆序打印单链表

        链表正常的输出顺序是从头开始输出,如果逆序的话,最后输出的是头结点,先输出的是最后一个节点,此过程可以通过递归来实现:在打印上一个节点之前,先打印下一个节点,依次往后。递归的终止条件是节点为NULL

void LinkListReversePrint(LinkListNode* head)                                                                                                                           
{
    if(head == NULL)
    {
        //链表为空
        return;
    }
    LinkListReversePrint(head->next);//在输出该上个节点之前,先输出下个结点
    printf("%c ",head->data);
}

2. 在指定位置pos前插入节点,不允许遍历链表

         在单链表的基本操作中,也实现了该算法。不过在任意位置之前插入结点要找到该位置的上一个节点。这样可以比较麻烦,因为之前已经编写过在任意位置之后插入节点,所以可以利用该算法来实现。

        首先可以在指定位置之后插入节点,使该节点的数据域为指定位置的数据域,而将指定位置的数据域改为要插入的元素值value,这样就可以与在指定位置之前插入节点达到同样的效果。如图所示:


        代码如下:

//在任意位置pos之前插入节点,数据域为value
void LinkListInsertEx(LinkListNode** phead,LinkListNode* pos,LinkListType value)
{
    if(phead == NULL || pos == NULL)
    {    
        //非法输入
        return;
    }    
    if(*phead == NULL)
    {    
        //空链表
        return;
    }    
    if(*phead == pos) 
    {    
        //指定位置为头节点,相当于头插
        LinkListPushFront(phead,value);//调用头插函数
        return;
    }    
    LinkListInsertAfter(phead,pos,pos->data);//在指定位置之后插入节点,数据域为指定位置的数据
    pos->data = value;//将指定位置的数据替换为value                                                                                                                     
    return;
}

        该算法的时间复杂度和空间复杂度分别为O(n)和O(1)。

        注意:当链表节点的数据较复杂时,该方法就不适用了。

3. 删除指定位置pos处(非尾节点)的节点,不能遍历链表

        与上述在指定位置插入节点类似。要删除pos处的节点就要从头开始遍历链表找到删除位置的前一个节点。但是,题目要求不能遍历链表,pos之前的节点需遍历找到,而pos之后的结点则不用遍历。

        所以该问题可以转化为:先将pos处的数据域替换为pos之后结点的数据域。再删除pos之后的结点,这样,便可以达到相同的效果。

        因为要删除的结点是最后一个结点时,在它之后没有节点,所以该方法不适用于删除尾节点的情形。而题目又正好指定删除的位置不是为节点。所以:

(1)如果是空链表,则删除失败

(2)如果是非空链表,替换数据域后,直接删除pos之后的结点即可。

 void LinkListErase2(LinkListNode** phead, LinkListNode* pos) 
    {    
        if(phead == NULL || pos ==NULL)
        {    
            //非法输入
            return;
        }    
        if(*phead == NULL)
        {    
            //空链表
            return;
        }       
        LinkListNode* to_delete = pos->next;//保存pos之后的结点即要删除的结点
        pos->data = to_delete->data;//进行数据域的替换
        pos->next = to_delete->next;//使pos指向to_delete之后的结点
        LinkListNodeDestory(to_delete);//销毁pos之后的结点                                                                                                                                 
        return; 
    }

4. 单链表实现约瑟夫环

        首先,需要了解一下约瑟夫环。以5个结点的带环单链表(此时,最后一个节点指向第一个节点)为例,指定数字2。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值