单链表链表面试题

.h

//链表面试题

 //打印无头单链表
void TailPrintSlist(SlistNode *pHead);
//删除非尾节点,不能遍历链表
void DeletingNonTailSlist(SlistNode **ppHead, SlistNode *pos);  
//无头单链表的某节点前插入一个节点,不能遍历链表
void PrevPosIsertSlist(SlistNode **ppHead, SlistNode *pos, DataType data);
//链表构环
void BuildCircleSlist(SlistNode **ppHead);
//约瑟夫环
DataType JosephCircleSlist(SlistNode **ppHead, DataType data);
//逆置单链表
void InverseSlist(SlistNode **ppHead);
//判断链表是否带环
SlistNode* IsCircleSlist(SlistNode *pHead);
//求环长
int RingLengthSlist(SlistNode *pHead);
//求环的入口点
SlistNode* SeekEnterSlist(SlistNode *pHead);
//查找单链表中的中间节点
SlistNode* FindMiddeNodeSlist(SlistNode *pHead);
//找到倒数第k个节点
SlistNode* FindCountDownKSlist(SlistNode *pHead, int k);
//删除倒数第k个节点
SlistNode* DeleteCountDownKSlsit(SlistNode **ppHead, int k);
//判断两个链表是否相交
int IsIntersectSlist(SlistNode *pHead1, SlistNode *pHead2);
//求两个相交链表的交点
SlistNode* IntersectionPointSlist(SlistNode *pHead1, SlistNode *pHead2);
//判断两个链表是否相交可能带环
int RingIntersectionSlist(SlistNode *pHead1, SlistNode *pHead2);
//求2个可能带环的链表的的交点
SlistNode* RingIntersectionPointSlist(SlistNode *pHead, SlistNode *pHead2);

//单链表排序(冒泡)
void BubbleSlsitNode(SlistNode **ppHead);
//合并2个有序单链表合并完仍有序
SlistNode* MergeTwoSlist(SlistNode **ppHead1, SlistNode **ppHed2);


//////////////////////////////////////////////////////////////////////////////////////////////////////
//创建复杂链表的节点
ComplexSlistNode* BuyComplexSlistNode(DataType data);
//复杂链表的尾插
void ComplexSlistPushBack(ComplexSlistNode **ppHead, DataType data);
//复杂链表的初始化
void InitComplexSlist(ComplexSlistNode **ppHead);
//寻找复杂链表中的节点
ComplexSlistNode* FindComplexSlistNode(ComplexSlistNode **ppHead, DataType data);
//复杂链表的复制
ComplexSlistNode* CopyComplexSlist(ComplexSlistNode *pHead);

.c

//从尾到头打印无头单链表
void TailPrintSlist(SlistNode *pHead)
{
    if ((pHead) == NULL)
        return;
    TailPrintSlist(pHead->_next);
    printf("<--%d ",pHead->_data);
}

//删除非尾节点,不能遍历链表
void DeletingNonTailSlist(SlistNode **ppHead, SlistNode *pos)
{
    SlistNode *del = NULL;
    assert(ppHead);
    if (*ppHead == NULL)
        printf("链表为空\n");
    else
    {
        if (pos->_next == NULL)
            printf("此为尾部节点不能删\n");
        else
        {
            del = pos->_next;
            pos->_data = del->_data;
            pos->_next = del->_next;
            free(del);
        }
    }
}

//无头单链表的某节点前插入一个节点,不能遍历链表
void PrevPosIsertSlist(SlistNode **ppHead, SlistNode *pos, DataType data)
{
    SlistNode *newnode = NULL;
    DataType tmp = 0;
    assert(ppHead);
    if (*ppHead == NULL)
        printf("链表为空\n");

    else
    {
        //先插在后面
        newnode = BuySlistNode(data);
        newnode->_next = pos->_next;
        pos->_next = newnode;
        //交换俩个的数据
        tmp = pos->_data;
        pos->_data = newnode->_data;
        newnode->_data = tmp;
    }
}

//链表构圆环
void BuildCircleSlist(SlistNode **ppHead)
{
    SlistNode *cur = NULL;
    assert(ppHead);
    if (*ppHead == NULL)
        return;
    cur = *ppHead;
    while (cur->_next)
    {
        cur = cur->_next;
    }
    cur->_next = *ppHead;
}

DataType JosephCircleSlist(SlistNode **ppHead, DataType data)
{
    //先构环
    BuildCircleSlist(ppHead);
    DataType n = data;
    while ((*ppHead)->_next != *ppHead)
    {
        n = data;
        while (--n) //走data-步
        {
            *ppHead = (*ppHead)->_next;
        }
        DeletingNonTailSlist(ppHead, *ppHead); 
    }
    //完成之后解开环
    (*ppHead)->_next = NULL;
    return (*ppHead)->_data;
}

逆置单链表
void InverseSlist(SlistNode **ppHead)
{
    SlistNode *prev = NULL, *tail = NULL, *centre = NULL;
    assert(ppHead);
    if (*ppHead == NULL)
        return;
    prev = *ppHead;
    centre = prev; 
    prev = prev->_next;
    while (centre) //中间指针作为判断条件
    {
        方法一:
        //centre->_next = tail;  //逆置
        //if (prev != NULL)
        //{
        //  tail = centre;
        //  centre = prev;
        //  prev = prev->_next;
        //}
        //else
        //{ 
        //  centre->_next = tail;//逆置
        //  return *ppHead = centre;
        //}

        //方法二:
        centre->_next = tail;  //逆置
        tail = centre;
        if (NULL == prev)              //if的判断条件不能换成别的
        {
            *ppHead = centre;  //逆置完将头更新
            return;
        }   
        centre = prev;
        prev = prev->_next; //当最后一个指针走到NULL的时候,就可以结束了
    }
}

//判断链表是否带环  (快慢指针法,快指针必须是走2步,慢指针必须是走1步)
SlistNode* IsCircleSlist(SlistNode *pHead)
{
    SlistNode *fast = pHead, *slow = pHead;

    //这里省略链表为空的情况
    while (fast && fast->_next)
    {
        slow = slow->_next;
        fast = fast->_next->_next;
        if (fast == slow)
            return slow;
    }
    return NULL;        //走到这肯定是不带环。这里连链表为空一块解决了
}

//求环长
int RingLengthSlist(SlistNode *pHead)
{
    int count = 1;   //起点是1个节点
    SlistNode *cur = NULL;
    SlistNode *meet = NULL;
    meet = IsCircleSlist(pHead);
    assert(meet);
    cur = meet;
    while (cur->_next != meet)
    {
        ++count;
        cur = cur->_next;
    }
    return count;
}

//求环的入口点  2(L+x) = L+n*c+x  
//先是快慢指针从头部走,快的走2步慢点走1步,当在环内相遇后。
//快指针从相遇点走,慢指针又从头部走。两个这次都是一次走一步。
//这样就会在入口点相遇
SlistNode* SeekEnterSlist(SlistNode *pHead)
{
    SlistNode *slow = NULL;  // 慢指针从头部走,一次走一步
    SlistNode *fast = IsCircleSlist(pHead);  //快指针从环内相遇点走,一次走1步,这样才能在入口点相遇
    slow = pHead;
    assert(slow && fast);

    while (fast != slow)
    {
        slow = slow->_next;
        fast = fast->_next; 
    }
    return fast;
}

//查找单链表中的中间节点
SlistNode* FindMiddeNodeSlist(SlistNode *pHead)
{
    SlistNode *fast = NULL, *slow = NULL;
    assert(pHead);
    fast = pHead;
    slow = pHead;
    if (fast->_next == NULL)
    {
        printf("该链表只有一个节点\n");
        return fast;
    }
    while (fast && fast->_next)
    {
        fast = fast->_next->_next;
        slow = slow->_next;
    }
    return slow;  //奇数数个节点返回的中间节点,偶数个节点返回的是中间的第二个节点
}

//找到倒数第k个节点
SlistNode* FindCountDownKSlist(SlistNode *pHead, int k)
{
    SlistNode *fast = NULL, *slow = NULL;
    int n = CountSlist(pHead);  //先计算链表中的节点个数
    assert(pHead && k && k <= n);  //k值过大也解决了
    fast = pHead;
    slow = pHead;
    while (k--)
    {
        fast = fast->_next;
    }
    //快指针走完k步后,两个指针一起走
    while (fast)
    {
        slow = slow->_next;
        fast = fast->_next;
    }
    return slow;
}

//删除倒数第k个节点
SlistNode* DeleteCountDownKSlsit(SlistNode **ppHead, int k)
{
    SlistNode *knode = NULL;
    assert(ppHead);
    knode = FindCountDownKSlist(*ppHead, k);
    if (knode == *ppHead)  //如果在头部调用头删函数
    {
        PopFrontSlist(ppHead);
        return *ppHead;
    }

    ErasePosSlist(ppHead, knode);  //调用任意位置删除函数
    return *ppHead;
}

//判断两个不带环链表是否相交
int IsIntersectSlist(SlistNode *pHead1, SlistNode *pHead2)
{
    assert(pHead1 && pHead2);
    //如果两个链表的尾部相同,则是相交
    while (pHead1->_next)
    {
        pHead1 = pHead1->_next;
    }
    while (pHead2->_next)
    {
        pHead2 = pHead2->_next;
    }
    if (pHead1 == pHead2)
        return 1;   //相交返回1
    return 0;  //不想交返回0
}

//求两个不带环链表的交点
SlistNode* IntersectionPointSlist(SlistNode *pHead1, SlistNode *pHead2)
{
    int n = 0;
    assert(IsIntersectSlist(pHead1, pHead2)); //检验2链表是否相交

    n = CountSlist(pHead1) - CountSlist(pHead2);
    //先让长的链表走
    if (n<0)
    {
        while (n++)
        {
            pHead2 = pHead2->_next;
        }
    }
    else
    {
        while (n--)
        {
            pHead1 = pHead1->_next;
        }
    }
    //2个一起走
    while(pHead1 != pHead2)
    {
        pHead1 = pHead1->_next;
        pHead2 = pHead2->_next;
    }
    return pHead1;
}

//判断两个链表是否相交可能带环
//不相交返回0,不带环相交返回1,都带环相交返回2
int RingIntersectionSlist(SlistNode *pHead1, SlistNode *pHead2)
{
    SlistNode *fast = NULL, *slow = NULL;
    //1.2个都不带环相交。 2.1个带环1个不带环不会相交。 3.2个都带环相交
    assert(pHead1 && pHead2);
    if (NULL == IsCircleSlist(pHead1) && NULL == IsCircleSlist(pHead2)) 
    {   
        if (IsIntersectSlist(pHead1, pHead2))
            return 1;   //2个都不带环相交

        return 0; // 2个都不带环不相交
    }
    //1个带环1个不带环不会相交
    else if (NULL == IsCircleSlist(pHead1) || NULL == IsCircleSlist(pHead2))
        return 0;
    //2个都带环相交
    else
    {
        //快慢指针
        fast = pHead1;
        slow = pHead2;
        while (fast != slow)
        {
            fast = fast->_next->_next;
            slow = slow->_next; 
        }
        return 2;
    }

    return 0;
}

//求2个可能带环的链表的的交点
SlistNode* RingIntersectionPointSlist(SlistNode *pHead1, SlistNode *pHead2)
{
    SlistNode *meet = NULL, *enter1 = NULL, *enter2 = NULL;
    assert(pHead1 && pHead2);

    //求2个环的入口点
    enter1 = SeekEnterSlist(pHead1);
    enter2 = SeekEnterSlist(pHead2);

    //判断是在环内还是环外相交 (利用2个环的入口点)
    if (enter1 == enter2)  
    {
        //在环外相交
        enter1->_next = NULL;  //以入口点断开环,就成了2个不带环求交点
        return IntersectionPointSlist(pHead1, pHead2);
    }
    //在环内相交, 则2个环的入口点都是交点
    return enter1; 
    //或者
    //return enter2;
}

//单链表排序(冒泡)
void BubbleSlsitNode(SlistNode **ppHead)
{
    SlistNode *cur = NULL, *prev = NULL, *end = NULL;
    DataType tmp = 0;
    int flag = 1;
    assert(ppHead);
    if (NULL == (*ppHead)->_next)  //只有一个节点
        return;

    flag = 1;   //优化
    while (end != *ppHead)
    {
        end = cur;
        cur = *ppHead;
        //冒一趟
        while (cur->_next && end != cur->_next)
        {
            if (cur->_data > cur->_next->_data)
            {
                tmp = cur->_data;
                cur->_data = cur->_next->_data;
                cur->_next->_data = tmp;

                flag = -1;  //优化
            }
            cur = cur->_next;
        }
        if (1 == flag)  //优化
            break;
    }
}

//合并2个有序单链表合并完仍有序
SlistNode* MergeTwoSlist(SlistNode **ppHead1, SlistNode **ppHead2)
{
    SlistNode *ph1 = NULL, *ph2 = NULL, *newnode = NULL;
    DataType tmp = 0;
    assert(ppHead1 && ppHead2);
    if (NULL == *ppHead1 || NULL == *ppHead2)  //若其中一个链表为空,则不需要排序
        return NULL;
    ph1 = *ppHead1;
    ph2 = *ppHead2;
    while (ph1 && ph2)
    {
        if (ph1->_data < ph2->_data)
            ph1 = ph1->_next;
        else
        {
            //将小的数插在大的后面,然后交换2个节点的数据
            //插在后面
            newnode = BuySlistNode(ph2->_data);
            newnode->_next = ph1->_next;
            ph1->_next = newnode;
            //交换
            tmp = ph1->_data;
            ph1->_data = newnode->_data;
            newnode->_data = tmp;

            ph1 = newnode;
            ph2 = ph2->_next;
        }   
    }

    if (NULL == ph1)
    {
        ph1 = *ppHead1;
        while (ph1->_next)
        {
            ph1 = ph1->_next;
        }
        ph1->_next = ph2;
        return *ppHead1;
    }
    else 
        return *ppHead1;
}






//创建复杂链表的节点
ComplexSlistNode* BuyComplexSlistNode(DataType data)
{
    ComplexSlistNode *node = NULL;
    node = (ComplexSlistNode*)malloc(sizeof(ComplexSlistNode));
    if (node == NULL)
    {
        printf("创建节点失败\n");
        return NULL;
    }
    else
    {
        node->_data = data;
        node->_next = NULL;
        node->_random = NULL;
        return node;
    }
}

//寻找复杂链表中的节点
ComplexSlistNode* FindComplexSlistNode(ComplexSlistNode **ppHead, DataType data)
{
    ComplexSlistNode *find = NULL;
    assert(ppHead);
    find = *ppHead;
    while (find)
    {
        if (find->_data == data)
            return find;
        find = find->_next;
    }
    return NULL;
}

//复杂链表的初始化
void InitComplexSlist(ComplexSlistNode **ppHead) //初始化链表
{
    ComplexSlistNode *cur;
    assert(ppHead);
    cur = *ppHead;
    while (cur)
    {
        cur->_data = 0;
        cur->_random = NULL;  //要先初始化random
        cur = cur->_next;

    }
}

//复杂链表的尾插
void ComplexSlistPushBack(ComplexSlistNode **ppHead, DataType data)
{
    ComplexSlistNode *tail = NULL, *cur = NULL;
    assert(ppHead);
    if (NULL == *ppHead) //链表为空
    {
        *ppHead = BuyComplexSlistNode(data);
        return;
    }

    tail = *ppHead;
    while (tail->_next)
    {
        tail = tail->_next; 
    }
    tail->_next = BuyComplexSlistNode(data);
}

//复杂链表的复制(O(n)的时间复杂度)
ComplexSlistNode *CopyComplexSlist(ComplexSlistNode *pHead)
{
    ComplexSlistNode *cur = NULL, *prev = NULL, *pHead2 = NULL;
    assert(pHead);
    cur = pHead;
    //在原链表的每个节点后面插入一个相同的节点
    while (cur)
    {
        prev = BuyComplexSlistNode(cur->_data);
        prev->_next = cur->_next;
        cur->_next = prev;
        cur = prev->_next;
    }
    //给新插入的节点的random赋值
    cur = pHead;
    prev = NULL;
    while (cur)
    {
        prev = cur->_next;

        if (NULL == cur->_random)   //如果原链表的random为空
            prev->_random = NULL;
        else
            prev->_random = cur->_random->_next;

        cur = prev->_next;
    }
    //将新链表和旧链表断开
    cur = pHead;
    prev = NULL;
    pHead2 = cur->_next;
    while (cur)
    {
        prev = cur->_next;
        cur->_next = prev->_next;
        if (cur->_next == NULL)
            break;

        cur = cur->_next;
        prev->_next = cur->_next;
    }
    return pHead2;
}

test.c

//测试环的问题,逆置,删非尾节点,约瑟夫环,从尾到头打印
//test4()
//{
//  SlistNode *list = NULL, *cur = NULL, *prev = NULL;
//  SlistNode *meet = NULL;
//  SlistNode* enter = NULL;
//
//      PushBackSlist(&list, 1);
//      PushBackSlist(&list, 2);
//      PushBackSlist(&list, 3);
//      PushBackSlist(&list, 4);
//      PushBackSlist(&list, 5);
//      PushBackSlist(&list, 6);
//      PushBackSlist(&list, 7);
//  
//      prev = FindNode(&list,7);
//      cur = FindNode(&list, 4);
//      prev->_next = cur;     //构建带环链表
//      
//      enter = SeekEnterSlist(list);
//      printf("环的入口点为: %d\n",enter->_data);

        //int n = RingLengthSlist(list);
        //printf("环长为:%d \n", n);

        //meet = IsCircleSlist(list);
        //printf("%d \n",meet->_data);
        //printf("%p\n",meet);

        //PrintSlist(list);
        //TailPrintSlist(list);

        //DeletingNonTailSlist(&list, FindNode(&list, 4));
        //PrevPosIsertSlist(&list, FindNode(&list, 6), 7);
        //BuildCircleSlist(&list);
        //printf("%d\n", JosephCircleSlist(&list, 3));
        //InverseSlist(&list);
        //PrintSlist(list);
//}

//测试找中间节点,寻找和删除倒数第k个节点,2链表是否相交,并求交点
//void test5()
//{
//  SlistNode *list1 = NULL, *list2 = NULL;
//  PushBackSlist(&list1, 1);
//  PushBackSlist(&list1, 2);
//  PushBackSlist(&list1, 3);
//  PushBackSlist(&list1, 4);
//  PushBackSlist(&list1, 5);
//  PushBackSlist(&list1, 6);
//  PushBackSlist(&list1, 7);
//
//  PushBackSlist(&list2, 1);
//  PushBackSlist(&list2, 2);
//  PushBackSlist(&list2, 3);
//  PushBackSlist(&list2, 4);
//  FindNode(&list2, 4)->_next = FindNode(&list1, 6); //构建相交
    //printf("%d\n",IsIntersectSlist(list1, list2));

    //printf("交点为:%d \n",IntersectionPointSlist(list1, list2)->_data);

    //PushBackSlist(&list2, 5);
    //PushBackSlist(&list2, 6);
    //PushBackSlist(&list2, 7);
    //PrintSlist(list);

    //printf("%d \n",FindMiddeNodeSlist(list)->_data);
    //printf("%d \n", FindCountDownKSlist(list, 7)->_data);
    //DeleteCountDownKSlsit(&list, 5);
    //PrintSlist(list);
//}

////测试2个可能带环链表的相交,求交点
//void test6()
//{
//  SlistNode *list1 = NULL, *list2 = NULL, *cur = NULL, *prev = NULL;
//  
//  PushBackSlist(&list1, 1);
//  PushBackSlist(&list1, 2);
//  PushBackSlist(&list1, 3);
//  PushBackSlist(&list1, 4);
//  PushBackSlist(&list1, 5);
//  PushBackSlist(&list1, 6);
//  PushBackSlist(&list1, 7);
//      
//  prev = FindNode(&list1,7);
//  cur = FindNode(&list1, 4);
//  prev->_next = cur;     //构建带环链表
//
//  PushBackSlist(&list2, 1);
//  PushBackSlist(&list2, 2);
//  PushBackSlist(&list2, 3);
//  PushBackSlist(&list2, 4);
//  FindNode(&list2, 4)->_next = FindNode(&list1, 6); //构建相交
//
//  //printf("%d \n", RingIntersectionSlist(list1, list2));
//  printf("%d \n",RingIntersectionPointSlist(list1, list2)->_data);
//}

////测试复杂链表的尾插,复制
//void test7()
//{
//  ComplexSlistNode *list = NULL, *list2;
//  InitComplexSlist(&list);
//
//  ComplexSlistPushBack(&list, 1);
//  ComplexSlistPushBack(&list, 2);
//  ComplexSlistPushBack(&list, 3);
//  ComplexSlistPushBack(&list, 4);
//  ComplexSlistPushBack(&list, 5);
//  
//  //设置复杂链表的random指针
//  FindComplexSlistNode(&list, 1)->_random = FindComplexSlistNode(&list, 3);
//  FindComplexSlistNode(&list, 2)->_random = FindComplexSlistNode(&list, 1);
//  FindComplexSlistNode(&list, 3)->_random = FindComplexSlistNode(&list, 4);
//  FindComplexSlistNode(&list, 4)->_random = NULL;
//  FindComplexSlistNode(&list, 5)->_random = FindComplexSlistNode(&list, 5);
//
//  list2 = CopyComplexSlist(list);
//  
//}

////测试冒泡排序
//void test8()
//{
//  SlistNode *list = NULL; 
//          
//  PushBackSlist(&list, 10);
//  PushBackSlist(&list, 1);
//  PushBackSlist(&list, 3);
//  PushBackSlist(&list, 5);
//  PushBackSlist(&list, 4);
//  PushBackSlist(&list, 3);
//  PushBackSlist(&list, 2);
//  PushBackSlist(&list, 6);
//  PushBackSlist(&list, 1);
//  PrintSlist(list);
//
//  BubbleSlsitNode(&list);
//  PrintSlist(list);
//}

//测试合并2个单链表
void test9()
{
    SlistNode *list1 = NULL, *list2 = NULL, *newlist;

    PushBackSlist(&list2, 1);
    //PushBackSlist(&list2, 3);
    //PushBackSlist(&list2, 5);
    //PushBackSlist(&list2, 7);
    //PushBackSlist(&list2, 7);
    //PushBackSlist(&list2, 9);
    //PushBackSlist(&list2, 10);
    PrintSlist(list2);

    PushBackSlist(&list1, 2);
    //PushBackSlist(&list1, 4);
    //PushBackSlist(&list1, 4);
    //PushBackSlist(&list1, 6);
    //PushBackSlist(&list1, 8);
    PrintSlist(list1);

    newlist = MergeTwoSlist(&list1, &list2);
    PrintSlist(newlist);
}

int main()
{
    //test1();
    //test2();
    //test3();
    //test4();
    //test5();
    //test6();
    //test7();
    //test8();
    test9();
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值