链表的常见面试题

链表的基本操作

逆序打印单链表
删除链表的非尾结点,要求:不能遍历链表
在链表pos位置前插入值到data的结点
查找链表的中间结点,要求只能遍历一次链表
查找链表的倒数第K个结点,要求只能遍历一次链表
删除链表的倒数第K个结点,要求只能遍历一次链表
用单链表实现约瑟夫环
链表的逆置–三个指针
链表的逆置–头插法
用冒泡排序思想对单链表进行排序
合并两个有序单链表,合并后依然有序
判断两个单链表是否相交—链表不带环
求两个单链表相交的交点—链表不带环
测试

判断链表是否带环,返回相遇点
获取环的入口点
获取环的长度
判断两个链表是否相交,链表可能带环
测试

复杂链表的复制

逆序打印单链表
void PrintSListFromTail2Head(PNode pHead)       
{
    PNode pTail = NULL;
    PNode pCur = pHead;
    PNode pPre = NULL;
    if (NULL == pHead)
        return;
    while (pCur)
    {
        pTail = pCur;
        pCur = pCur->_pNext;
    }
    while (pTail!=pHead)
    {
        pCur = pHead;
        while (pCur!=pTail)
        {
            pPre = pCur;
            pCur = pCur->_pNext;

        }
        printf("%d->", pTail->_data);
        pTail = pPre;
    }
    printf("%d->NULL\n", pTail->_data);

//递归实现
#if 0
    if(pHead->_pNext)
    {
        PrintSListFromTail2Head(pHead->_pNext);
    }
    printf("->%d", pHead->_data);

#endif
}

删除链表的非尾结点,要求:不能遍历链表
void DeleteListNotTailNode(PNode pos)
{
    PNode pNext = NULL;
    pNext = pos->_pNext;
    pos->_data = pNext->_data;
    pos->_pNext = pNext->_pNext;
    free(pNext);
    pNext = NULL;
}

在链表pos位置前插入值到data的结点
/*在链表后边插入,然后将pos的值给后边的,再将值给pos*/
void InesrtPosFront(PNode pos, DataType data)
{
    PNode pNext = BuySListNode(data);
    pNext->_pNext = pos->_pNext;
    pos->_pNext = pNext;
    pNext->_data = pos->_data;
    pos->_data = data;
}

查找链表的中间结点,要求只能遍历一次链表
/*定义两个指针,一个一次走两步,一个走一步*/
PNode FindMiddleNode(PNode pHead)
{
    PNode pFast = pHead;
    PNode pSlow = pHead;
    if (NULL == pHead)
    {
        return NULL;
    }
    else if (NULL == pHead->_pNext)
    {
        return pHead;
    }
    else
    {
        while (pFast&&pFast->_pNext)
        {
            pFast = pFast->_pNext->_pNext;
            pSlow = pSlow->_pNext;
        }
        return  pSlow;
    }
}

查找链表的倒数第K个结点,要求只能遍历一次链表
PNode FindLastKNode(PNode pHead, int K)
{
    PNode pSlow = pHead;
    PNode pFast = pHead;
    if (NULL == pHead || K <= 0)
    {
        return NULL;
    }
    while (K--)
    {
        pFast = pFast->_pNext;
    }
    while (pFast)
    {
        pFast = pFast->_pNext;
        pSlow = pSlow->_pNext;
    }

    return pSlow;
}

// 删除链表的倒数第K个结点,要求只能遍历一次链表

void DeleteLastKNode(PNode pHead, int K)
{
    PNode pSlow = pHead;
    PNode pFast = pHead;
    PNode pPre = NULL;
    if (NULL == pHead || K <= 0)
    {
        return;
    }
    while (K--)
    {
        pFast = pFast->_pNext;
    }
    while (pFast)
    {
        pFast = pFast->_pNext;
        pPre = pSlow;
        pSlow = pSlow->_pNext;
    }
    pPre->_pNext = pSlow->_pNext;
    free(pSlow);
    pSlow = NULL;

}

用单链表实现约瑟夫环
void JosephCircle(PNode* pHead, const int M)
{
    PNode pCur = NULL;
    PNode pDel = NULL;
    int count = 0 ;
    assert(pHead);
    if (NULL == *pHead|| M <= 0)
    {
        return;
    }
    pCur = *pHead;
    //先遍历链表,让尾指向头
    while (pCur->_pNext)
    {
        pCur = pCur->_pNext;
    }
    pCur->_pNext = *pHead;
    pCur = *pHead;
    while ((pCur)->_pNext != pCur)
    {
        count = M;
        while (--count)                     //为什么时--M
        {
            pCur = pCur->_pNext;
        }
        //删节点
        pDel = pCur->_pNext;
        pCur->_data = pDel->_data;
        pCur->_pNext = pDel->_pNext;
        free(pDel);
        pDel = NULL;

    }
    //解环
    pCur->_pNext = NULL;

    SListPrint(pCur);
}

链表的逆置–三个指针

void ReverseSList(PNode* pHead)
{
    PNode pPre = NULL;
    PNode pCur = NULL;
    PNode pNext = NULL;
    assert(pHead);
    pCur = *pHead;
    while (pCur)
    {
        pNext = pCur->_pNext;
        pCur->_pNext = pPre;
        pPre = pCur;
        pCur = pNext;
    }
    *pHead = pPre;
}

链表的逆置–头插法

PNode ReverseSListOP(PNode pHead)
{
    PNode pCur = NULL;
    PNode pNewNode= NULL;
    if (NULL == pHead || NULL == pHead->_pNext)
        return NULL;

    while (pHead)
    {   
        pCur = pHead;
        pHead = pCur->_pNext;
        pCur->_pNext = pNewNode;
        pNewNode = pCur;
    }
    pHead = pCur;

    return pHead;
}

用冒泡排序思想对单链表进行排序

void BubbleSort(PNode pHead)
{
    PNode pTail = NULL;
    PNode pCur = pHead;
    int flag = 0;
    if (pHead == NULL || pHead->_pNext == NULL) 
    {
        return;
    }
    while (pTail != pHead)
    {
        pCur = pHead;
        flag = 0;
//这里为pCur->_pNext是为了防止if语句的中pCur->_pNext为空,如果为空第一次比较程序就会崩溃
        while (pCur->_pNext != pTail)           
        {
            if (pCur->_data < pCur->_pNext->_data)
            {
                DataType temp = pCur->_data;
                pCur->_data = pCur->_pNext->_data;
                pCur->_pNext->_data = temp;
                flag = 1;
            }

            pCur = pCur->_pNext;
        }
        pTail = pCur;
        if (0 == flag)
            break;
    }
}

合并两个有序单链表,合并后依然有序
PNode MergeSList(PNode pHead1, PNode pHead2)
{
    PNode pNewHead = NULL;
    PNode pCur = NULL;

    if (!pHead1)
        return pHead2;
    if (!pHead2)
        return pHead1;
    if (pHead1->_data >= pHead2->_data)
    {
        pCur = BuySListNode(pHead2->_data);
        pHead2 = pHead2->_pNext;
        pNewHead = pCur;
    }
    else if (pHead1->_data < pHead2->_data)
    {
        pCur = BuySListNode(pHead1->_data);
        pHead1 = pHead1->_pNext;
        pNewHead = pCur;
    }

    while (pHead1&&pHead2)
    {
        if (pHead1->_data >= pHead2->_data)
        {
            pCur->_pNext = BuySListNode(pHead2->_data);
            pHead2 = pHead2->_pNext;
            pCur = pCur->_pNext;
        }
        else if (pHead1->_data < pHead2->_data)
        {
            pCur->_pNext = BuySListNode(pHead1->_data);
            pHead1 = pHead1->_pNext;
            pCur = pCur->_pNext;
        }
    }
    while (pHead1)
    {
        pCur->_pNext = BuySListNode(pHead1->_data);
        pHead1 = pHead1->_pNext;
        pCur = pCur->_pNext;
    }
    while (pHead2)
    {
        pCur->_pNext = BuySListNode(pHead2->_data);
        pHead2= pHead2->_pNext;
        pCur = pCur->_pNext;
    }

    return pNewHead;
}

判断两个单链表是否相交—链表不带环
int IsSListCross(PNode pHead1, PNode pHead2)
{
    if (NULL == pHead1 || NULL == pHead2)
        return 0;
    //找到链表的最后一个节点
    while (pHead1->_pNext)
    {
        pHead1 = pHead1->_pNext;
    }
    while (pHead2->_pNext)
    {
        pHead2 = pHead2->_pNext;
    }
    if (pHead1 == pHead2)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

求两个单链表相交的交点—链表不带环
/*先让长的链表遍历size1-size2,再让两个链表一起遍历,
            当pCur1==pCur2时,两链表相交*/
PNode GetCorssNode(PNode pHead1, PNode pHead2)
{
    if (NULL == pHead1 || NULL == pHead2)
        return NULL;
    int size1 = 0;
    int size2 = 0;
    int gap = 0;
    PNode pCur1 = pHead1;
    PNode pCur2 = pHead2;
    while (pCur1)
    {
        pCur1 = pCur1->_pNext;
        size1++;
    }
    while (pCur2)
    {
        pCur2 = pCur2->_pNext;
        size2++;
    }
    gap = size1 - size2;
    pCur1 = pHead1; pCur2 = pHead2;
    if (gap > 0)
    {
        while (gap--)
        {
            pCur1 = pCur1->_pNext;
        }
    }
    else
    {
        while (gap++)
        {
            pCur2 = pCur2->_pNext;
        }
    }
    while (pCur1 != pCur2)
    {
        pCur1 = pCur1->_pNext;
        pCur2 = pCur2->_pNext;
    }
    return pCur2;
}

测试程序
void TestInterview()
{
    PNode pHead1, pHead2,pCur;

    SListInit(&pHead1);
    SListPushBlack(&pHead1, 1);
    SListPushBlack(&pHead1, 5);
    SListPushBlack(&pHead1, 9);
    SListPushBlack(&pHead1, 3);
    SListPushBlack(&pHead1, 6);
    SListPushBlack(&pHead1, 34);
    SListPrint(pHead1);
    SListInit(&pHead2);
    SListPushBlack(&pHead2, 2);
    SListPushBlack(&pHead2, 4);

    pHead2->_pNext->_pNext = SListFind(pHead1,6);
    SListPrint(pHead2);
    pCur = GetCorssNode(pHead1, pHead2);
    //int ret = IsSListCross(pHead1, pHead2);


    //SListPushBlack(&pHead2, 6);
    //SListPushBlack(&pHead2, 34);
    //SListPrint(pHead2);


    //pCur = MergeSList(pHead1, pHead2);
    //SListPrint(pCur);

    //PrintSListFromTail2Head(pHead);
    //pCur = SListFind(pHead, 6);
    //DeleteListNotTailNode(pCur);
    //InesrtPosFront(pCur, 5);
    //SListPrint(pHead);

    /*pCur = FindMiddleNode(pHead);*/
    //pCur = FindLastKNode(pHead, 3);

    //DeleteLastKNode(pHead, 3);
    //SListPrint(pHead);

    //JosephCircle(&pHead, 3);

    //ReverseSList(&pHead);
    /*SListPrint(pHead);

    pHead = ReverseSListOP(pHead);
    SListPrint(pHead);*/

    /*BubbleSort(pHead);
    SListPrint(pHead);*/
}

判断两个链表是否相交,链表可能带环
PNode IsListWithCircle(PNode pHead1)
{
    PNode pFast = pHead1;
    PNode pSlow = pHead1;
    if (NULL == pHead1)
        return NULL;

    while (pFast && pFast->_pNext)
    {
        pFast = pFast->_pNext->_pNext;
        pSlow = pSlow->_pNext;

        if (pSlow == pFast)
            return pSlow;
    }

    return NULL;
}

获取环的入口点
PNode GetCircleEnter(PNode pHead1, PNode pMeetNode)
{
    PNode pH = pHead1;
    PNode pM = pMeetNode;
    if (NULL == pHead1 || NULL == pMeetNode)
    {
        return NULL;
    }
    else
    {
        while (pH != pM)
        {
            pH = pH->_pNext;
            pM = pM->_pNext;
        }
    }

    return pM;
}

获取环的长度
int GetCircleLen(PNode pMeetNode)
{
    PNode pCur = pMeetNode;
    int len = 1;
    if (NULL == pMeetNode)
    {
        return 0;
    }
    else
    {
        while (pCur->_pNext != pMeetNode)
        {
            pCur = pCur->_pNext;
            len++;
        }
    }

    return len;
}

判断两个链表是否相交,链表可能带环

int IsSListCrossWithCircle(PNode pHead1, PNode pHead2)
{
    PNode pSlow = NULL;
    PNode pFast = NULL;
    if (NULL == pHead1 || NULL == pHead2)
        return 0;

    pSlow = pHead1;
    pFast = pHead2;

    while (pFast&&pFast->_pNext)
    {
        pFast = pFast->_pNext->_pNext;
        pSlow = pSlow->_pNext;
        if (pFast == pSlow)
            return 1;
    }

    return 0;
}

测试
void TestInterview2()
{
    PNode pHead, pCur;

    SListInit(&pHead);
    SListPushBlack(&pHead, 1);
    SListPushBlack(&pHead, 3);
    SListPushBlack(&pHead, 6);
    SListPushBlack(&pHead, 9);
    SListPushBlack(&pHead, 7);
    SListPushBlack(&pHead, 4);
    SListPushBlack(&pHead, 8);
    SListPrint(pHead);

    pCur = pHead;
    while (NULL != pCur->_pNext)
        pCur = pCur->_pNext;
    pCur->_pNext = SListFind(pHead, 7);



    PNode pMeetNode = IsListWithCircle(pHead);
    PNode pEnterNode = GetCircleEnter(pHead, pMeetNode);
    int len = GetCircleLen(pMeetNode);

}

复杂链表的复制
PCSLNode CopyComplexList(PCSLNode pHead)
{
    PCSLNode pCur = pHead;
    PCSLNode pNewNode = NULL;
    PCSLNode pNewHead = NULL;
    if (NULL == pHead)
        return NULL;

    //1.在链表后面插入值相同的新节点
    while (pCur)
    {
        pNewNode = BuyCSNewNode(pCur->data);
        pNewNode->_pNext = pCur->_pNext;
        pCur->_pNext = pNewNode;
        pCur = pNewNode->_pNext;
    }
    pCur = pHead;

    //2.给新节点的随机指针域赋值
    //让随机指针域指向原节点随机指针指向的下个节点
    while (pCur)
    {
        pNewNode = pCur->_pNext;
        if (pCur->_pRandom)
        {
            pNewNode->_pRandom = pCur->_pRandom->_pNext;
        }
        pCur = pNewNode->_pNext;

    }

    //3.将新节点从原链表中拆下来
    pCur = pHead;
    pNewHead = pHead->_pNext;
    while (pCur->_pNext)
    {
        pNewNode = pCur->_pNext;
        pCur->_pNext = pNewNode->_pNext;
        pCur = pNewNode;

    }

    return pNewHead;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ArrayList 是 Java 中常用的动态数组,常见面试题有: 1. ArrayList 和普通数组的区别是什么? 答:ArrayList 是动态数组,它可以根据需要自动调整大小,而普通数组的大小是固定的。 2. 如何创建一个 ArrayList 对象? 答:可以使用无参构造函数创建一个空的 ArrayList 对象,或者使用带有初始容量参数的构造函数创建一个指定大小的 ArrayList 对象。 3. 如何向 ArrayList 中添加元素? 答:可以使用 add() 方法向 ArrayList 中添加元素,也可以使用 add(index, element) 方法在指定位置插入元素。 4. 如何从 ArrayList 中获取元素? 答:可以使用 get(index) 方法从 ArrayList 中获取指定位置的元素。 5. 如何在 ArrayList 中删除元素? 答:可以使用 remove(index) 方法删除指定位置的元素,或者使用 remove(element) 方法删除指定元素。 6. ArrayList 是否可以存储基本数据类型? 答:ArrayList 只能存储对象类型,不能直接存储基本数据类型。但是可以使用装箱和拆箱操作将基本数据类型转换为对应的包装类。 7. ArrayList 和 LinkedList 的区别是什么? 答:ArrayList 是基于动态数组实现的,支持随机访问,但插入和删除元素效率较低;LinkedList 是基于双向链表实现的,插入和删除元素效率较高,但随机访问效率较低。 8. ArrayList 如何进行遍历? 答:可以使用 for-each 循环或者使用普通的 for 循环配合 get() 方法进行遍历。 这些是常见的 ArrayList 面试题,希望能帮助到你!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值