单链表的面试题

本博客继上一篇的基本操作之后的一些比较复杂的问题解决
// 逆序打印单链表
void PrintSListFromTail2Head(PNode pHead);

// 删除链表的非尾结点,要求:不能遍历链表
void DeleteListNotTailNode(PNode pos);

// 在链表pos位置前插入值到data的结点
void InesrtPosFront(PNode pos, DataType data);

// 查找链表的中间结点,要求只能遍历一次链表
PNode FindMiddleNode(PNode pHead);

// 查找链表的倒数第K个结点,要求只能遍历一次链表
PNode FindLastKNode(PNode pHead, int K);

// 删除链表的倒数第K个结点,要求只能遍历一次链表
PNode DeleteLastKNode(PNode pHead, int K);

// 用单链表实现约瑟夫环
void JosephCircle(PNode* pHead, const int M);

// 链表的逆置–三个指针
void ReverseSList(PNode* pHead);

// 链表的逆置–头插法
PNode ReverseSListOP(PNode pHead);

// 用冒泡排序思想对单链表进行排序
void BubbleSort(PNode pHead);

// 合并两个有序单链表,合并后依然有序
PNode MergeSList(PNode pHead1, PNode pHead2);

// 判断两个单链表是否相交—链表不带环
int IsSListCross(PNode pHead1, PNode pHead2);

// 求两个单链表相交的交点—链表不带环
PNode GetCorssNode(PNode pHead1, PNode pHead2);

List.h

#include<stdio.h>
#pragma once
#include<assert.h>
#include<stdlib.h>


typedef int DataType;

typedef struct Node
{
    struct Node *Next;
    DataType data;
}Node,*PNode;


typedef struct SCListNode  //复杂链表  
{
    struct SCListNode* _pNext;
    struct SCListNode* _random;
    int _data;
}SCLNode;



// 链表的初始化 
void SListInit(PNode* pHead);
// 尾插 
void SListPushBack(PNode* pHead, DataType data);
// 尾删 
void SListPopBack(PNode* pHead);
// 头插 
void SListPushFront(PNode* pHead, DataType data);
// 头删 
void SListPopFront(PNode* pHead);
// 在链表中查找值为data的元素,找到后返回值为data的结点 
PNode SListFind(PNode pHead, DataType data);
// 在pos位置插入值为data的结点 
void SListInsert(PNode* pHead, PNode pos, DataType data);
// 删除pos位置额结点 
void SListErase(PNode* pHead, PNode pos);
// 获取链表中值data的结点 
int SListSize(PNode pHead);
// 判断链表是否为空 
int SListEmpty(PNode pHead);
// 销毁聊表 
void SListDestroy(PNode* pHead);
//创建新的节点
PNode NewNode(DataType data);
//打印链表
void SListPrint(PNode pHead);
// 逆序打印单链表 
void PrintSListFromTail2Head(PNode pHead);

// 删除链表的非尾结点,要求:不能遍历链表 
void DeleteListNotTailNode(PNode pos);

// 在链表pos位置前插入值到data的结点 
void InesrtPosFront(PNode pos, DataType data);

// 查找链表的中间结点,要求只能遍历一次链表 
PNode FindMiddleNode(PNode pHead);

// 查找链表的倒数第K个结点,要求只能遍历一次链表 
PNode FindLastKNode(PNode pHead, int K);

// 删除链表的倒数第K个结点,要求只能遍历一次链表 
PNode DeleteLastKNode(PNode pHead, int K);

// 用单链表实现约瑟夫环 
void JosephCircle(PNode* pHead, const int M);

// 链表的逆置--三个指针 
void ReverseSList(PNode* pHead);

// 链表的逆置--头插法 
PNode ReverseSListOP(PNode pHead);

// 用冒泡排序思想对单链表进行排序 
void BubbleSort(PNode pHead);

// 合并两个有序单链表,合并后依然有序 
PNode MergeSList(PNode pHead1, PNode pHead2);

// 判断两个单链表是否相交---链表不带环 
int IsSListCross(PNode pHead1, PNode pHead2);

// 求两个单链表相交的交点---链表不带环 
PNode GetCorssNode(PNode pHead1, PNode pHead2);
//复杂链表的复制
SCLNode* CopyComplexList(SCLNode* pHead);

List.c

#include"List.h"


void SListInit(PNode* pHead)
{
    assert(pHead);
    *pHead = NULL;
}
PNode NewNode(DataType data)
{
    PNode pnewNode = (PNode)malloc(sizeof(Node));
    if (NULL == pnewNode)
        return NULL;
    pnewNode->data = data;
    pnewNode->Next = NULL;
    return pnewNode;
}
void SListPushBack(PNode* pHead, DataType data)
{
    assert(pHead);
    PNode pnewNode = NULL;
    pnewNode = NewNode(data);
    if (pnewNode == NULL)
        return;
    if (*pHead == NULL)
        *pHead = pnewNode;
    else
    {
        PNode pCur = *pHead;
        while (pCur->Next != NULL)
        {
            pCur = pCur->Next;
        }
        pCur->Next = pnewNode;
    }
}
void SListPopBack(PNode* pHead)
{
    assert(pHead);
    if (NULL == *pHead)
        return;
    else if ((*pHead)->Next == NULL)
    {
        free(*pHead);
        *pHead = NULL;
    }
    else
    {
        PNode pCur = *pHead;
        while (pCur->Next != NULL)
        {
            pCur = pCur->Next;
        }
        free(pCur);
        pCur = NULL;
    }
}
void SListPrint(PNode pHead)
{
    PNode pCur = NULL;
    if (pHead == NULL)
        return;
    pCur = pHead;
    while (pCur->Next)
    {
        printf("%d---->", pCur->data);
        pCur=pCur->Next;
    }
    printf("NULL\n");
}
void SListPushFront(PNode* pHead, DataType data)
{
    assert(pHead);
    PNode newNode = NULL;
    newNode = NewNode(data);
    if (newNode == NULL)
        return;
    newNode->Next = *pHead;
    *pHead = newNode;
}
void SListPopFront(PNode* pHead)
{
    PNode pCur = NULL;
    assert(pHead);
    if (*pHead == NULL)
    {
        return;
    }
    else
    {
        pCur = (*pHead);
        *pHead = (*pHead)->Next;
        free(pCur);
    }
}
PNode SListFind(PNode pHead, DataType data)
{
    PNode pCur = NULL;
    if (pHead == NULL)
        return NULL;
    pCur = pHead;
    while (pCur)
    {
        if (pCur->data == data)
            return pCur;
        pCur = pCur->Next;
    }
    return NULL;
}
void SListInsert(PNode* pHead, PNode pos, DataType data)
{
    PNode pnewnode = NULL;
    assert(pHead);
    if (*pHead == NULL || pos == NULL)
        return;
    pnewnode=NewNode(data);
    if (NULL == pnewnode)
        return;
    pnewnode->Next = pos->Next;
    pos->Next = pnewnode;
}
void SListErase(PNode* pHead, PNode pos)
{
    PNode newnode = NULL;
    assert(pHead);
    if (*pHead == NULL || pos == NULL)
        return;
    else if ((*pHead)==pos)
        SListPopFront(pHead);
    else
    {
        newnode = *pHead;
        while (newnode->Next != pos)
        {
            newnode = newnode->Next;
        }
        newnode->Next = pos->Next;
        free(pos);
    }
}
int SListSize(PNode pHead)
{
    int count = 0;
    if (pHead == NULL)
        return 0;
    while (pHead)
    {
        count++;
        pHead = pHead->Next;
    }
    return count;
}
int SListEmpty(PNode pHead)
{
    return !pHead;
}
void SListDestroy(PNode* pHead)
{
    PNode pnew = NULL;
    assert(pHead);
    if (NULL == (*pHead))
        return;
    while (pnew)
    {
        pnew = *pHead;
        *pHead = pnew->Next;
        free(pnew);
    }
}
void PrintSListFromTail2Head(PNode pHead)
{
    if (pHead){

        PrintSListFromTail2Head(pHead->Next);
        printf("%d   ", pHead->data);
    }
}
//做法是将pos下一个节点删除,删除前将pos->Next->Data的值赋给pos->Data
void DeleteListNotTailNode(PNode pos)
{
    PNode pDel;
    if (pos == NULL || pos->Next == NULL)
        return;
    pDel = pos->Next;
    pos->Next= pDel->Next;
    pos->data = pDel->data;
    free(pDel);
}
void InesrtPosFront(PNode pos, DataType data)
{
    PNode pnew = NULL;
    if (NULL == pos)
        return;
    pnew = NewNode(data);
    if (NULL == pnew)
        return;
    pnew->Next = pos->Next;
    pos->Next = pnew;
    pnew->data = pos->data;
    pos->data = data;
}
PNode FindMiddleNode(PNode pHead)
{
    PNode pFast;
    PNode pSlow;
    if (NULL == pHead)
        return NULL;
    pFast = pHead;
    pSlow = pHead;
    while (pFast->Next&&pHead->Next->Next)
    {
        pFast = pFast->Next->Next;
        pSlow = pSlow->Next;
    }
    return pSlow;
}
PNode FindLastKNode(PNode pHead, int K)
{
    int count = 0;
    PNode pFast;
    PNode pSlow;
    if (NULL == pHead)
        return NULL;
    pFast = pHead;
    pSlow = pHead;
    count = K;
    while (count--)
    {
        pFast = pFast->Next;
    }
    while (pFast->Next)
    {
        pFast = pFast->Next;
        pSlow = pSlow->Next;
    }
    return pSlow;
}
PNode DeleteLastKNode(PNode pHead, int K)
{
    int count = 0;
    PNode pFast;
    PNode pSlow;
    if (NULL == pHead)
        return NULL;
    pFast = pHead;
    pSlow = pHead;
    count = K;
    while (count--)
    {
        pFast = pFast->Next;
    }
    while (pFast->Next)
    {
        pFast = pFast->Next;
        pSlow = pSlow->Next;
    }
    pFast = pSlow->Next;
    pSlow->Next = pFast->Next;
    pSlow->data = pFast->data;
    free(pFast);
}
void JosephCircle(PNode* pHead, const int M)
{
    PNode pcur = NULL;
    assert(pHead);
    pcur = *pHead;

    while (pcur!=pcur->Next)
    {
        int count = M;
        pcur = pcur->Next;
        PNode pDel = NULL;
        while (--count)//count--,count=3,后置--,先用M的值判断一次,一共走了3次,所以必须用前置--,走2次,到三的位置的结点  
        {
            pcur = pcur->Next;
        }
        //删除 (替换法删除:条件:非尾结点,因为是个环,所以没有尾结点)
        pDel = pcur->Next;
        pcur->Next = pDel->Next;
        pcur->data = pDel->data;
        free(pDel);
    }
    //如果把第一个结点删除了,把*ppHead的指向改一下
    *pHead = pcur;
}
void ReverseSList(PNode* pHead)
{
    PNode pcur = NULL;
    PNode pnext = NULL;
    PNode pre = NULL;
    assert(pHead);
    if (NULL == *pHead || NULL == (*pHead)->Next)//如果NULL == (*pHead)->Next,是一个节点的情况,不需要逆置
        return;
    pcur = *pHead;
    while (pcur)
    {
        pnext = pcur->Next;//让pnext标记pcur的下一个节点
        pcur->Next = pre;//pcur这个节点指向前一个节点
        pre = pcur;//将前一个节点往后移
        pcur = pnext;//将本节点往后移动
    }
    *pHead = pcur;
}
PNode ReverseSListOP(PNode pHead)
{
    PNode pCur = pHead;
    PNode pNext = NULL;
    PNode pNewHead = NULL;
    while (pCur)
    {
        pNext = pCur->Next;
        pCur->Next = pNewHead;
        pNewHead = pCur;
        pCur = pNext;
    }
    return pNewHead;
}
void BubbleSort(PNode pHead)
{
    PNode pCur = NULL;
    PNode pNext = NULL;
    PNode pTail = NULL;
    int Flag = 0;
    if (NULL == pHead || NULL == pHead->Next)
    {
        return;
    }
    while (pHead!=pTail)
    {
        pCur = pHead;
        pNext = pCur->Next;
        Flag = 0;
        while (pNext!=pTail)
        {
            if (pCur->data > pNext->data)
            {
                DataType temp = pCur->data;
                pCur->data = pNext->data;
                pNext->data = temp;
                Flag = 1;
            }
            pCur = pNext;
            pNext = pNext->Next;
        }
        if (!Flag)
        {
            return;
        }
        pTail = pCur;
    }
}
PNode MergeSList(PNode pHead1, PNode pHead2)
{
    PNode pl1 = pHead1;
    PNode pl2 = pHead2;
    PNode pnew = NULL;
    PNode pTail = NULL;
    //判断两链表是否为空  
    if (NULL == pHead1 || NULL == pHead2) //等效注释部分  
    {
        return (pHead1) ? pHead1 : pHead2;
    }
    //if (NULL == pHead1)  
    //{  
    //  return pHead2;  
    //}  
    //if (NULL == pHead2)  
    //{  
    //  return pHead1;  
    //}  
    if (pl1->data < pl2->data){
        pnew = pl1;
        pTail = pl1;
        pl1 = pl1->Next;
    }
    else{
        pnew = pl2;
        pTail = pl2;
        pl2 = pl2->Next;
    }
    while (pl1 && pl2)
    {
        if (pl1->data < pl2->data)
        {
            pTail->Next = pl1;
            pl1 = pl1->Next;
        }
        else
        {
            pTail->Next = pl2;
            pl2 = pl2->Next;
        }
        pTail = pTail->Next;
    }
    // 处理完两个链表,还剩下一个链表里有数据
    if (pl1)
    {
        pTail->Next = pl1;
    }
    if (pl2)
    {
        pTail->Next = pl2;
    }
    return pnew;
    }
// 判断单链表是否带环
PNode HasCircle(PNode pHead)
{
    PNode pSlow = pHead;
    PNode pFast = pHead;

    while (pFast && pFast->Next)
    {
        pFast = pFast->Next->Next; //要先走,不能先判断  
        pSlow = pSlow->Next;

        if (pFast == pSlow)
        {
            return pSlow; //返回相遇点  
        }
    }
    return NULL;
}
int IsSListCross(PNode pHead1, PNode pHead2)
{
    PNode pTail1 = pHead1;
    PNode pTail2 = pHead2;

    if (NULL == pHead1 || NULL == pHead2)
    {
        return 0;
    }

    while (pTail1->Next == NULL)
    {
        pTail1 = pTail1->Next;
    }
    while (pTail2->Next == NULL)
    {
        pTail2 = pTail2->Next;
    }
    return pTail1 == pTail2;
}
PNode GetCorssNode(PNode pHead1, PNode pHead2)
{
    size_t size1 = 0;
    size_t size2 = 0;

    PNode pCur1 = pHead1;
    PNode pCur2 = pHead2;

    int div = 0;

    if (NULL == pHead1 || NULL == pHead2)
    {
        return NULL;
    }

    while (pCur1) //求两个链表的长度  
    {
        size1++;
        pCur1 = pCur1->Next;
    }
    while (pCur2) //求两个链表的长度  
    {
        size2++;
        pCur2 = pCur2->Next;
    }

    div = size1 - size2; //求两链表哪个长  

    if (div > 0) //长链表的头指针先走长的减去短的长度  
    {
        while (div--) //后置-- 走了div步,需要走div步  
        {
            pCur1 = pCur1->Next;
        }
    }
    else
    {
        while (div++)
        {
            pCur2 = pCur2->Next;
        }
    }

    while (pHead1 && pHead2) //两个头指针再一起走  
    {
        if (pCur1 == pCur2) ////在 第一个链表 中找到 第一个 在 第二个链表 中出现的 结点  
        {
            return pCur1;
        }

        pCur1 = pCur1->Next;
        pCur2 = pCur2->Next;
    }

    return NULL;
}
SCLNode* BuySCLNode(int data)
{
    SCLNode* pNewNode = (SCLNode*)malloc(sizeof(SCLNode));
    pNewNode->_data = data;
    pNewNode->_pNext = NULL;
    pNewNode->_random = NULL;

    return pNewNode;
}

SCLNode* CopyComplexList(SCLNode* pHead)
{
    //1.在原链表每个结点后插入新结点  
    SCLNode* p1 = pHead;
    SCLNode* pNewNode = NULL;
    SCLNode* pNewHead = NULL;
    if (pHead)
    {
        return NULL;
    }
    while (p1)
    {
        pNewNode = BuySCLNode(p1->_data);
        pNewNode->_pNext = p1->_pNext;
        p1->_pNext = pNewNode;
        p1 = pNewNode->_pNext;
    }

    //2.给新插入结点的随机指针域赋值  
    p1 = pHead;
    while (p1)
    {
        pNewNode = p1->_pNext;
        if (NULL == p1->_random)
        {
            pNewNode->_random = NULL;
        }
        else if (p1->_random == p1)
        {
            pNewNode->_random = pNewNode;
        }
        else
        {
            pNewNode->_random = p1->_random->_pNext;
        }
        p1 = pNewNode->_pNext;
    }

    //3.将新结点从链表中拆下来  
    p1 = pHead;
    pNewHead = p1->_pNext;
    pNewNode = pNewHead;
    while (pNewNode != NULL)
    {
        p1->_pNext = pNewNode->_pNext;
        p1 = pNewNode;
        pNewNode = pNewNode->_pNext;
    }
    return pNewHead;
}









void Test()
{
    PNode list;
    SListInit(&list);
    SListPushBack(&list, 1);
    SListPushBack(&list, 2);
    SListPushBack(&list, 3);
    SListPushBack(&list, 4);
    SListPushBack(&list, 5);
    SListPushBack(&list, 6);
    SListPopFront(&list);
    SListPushFront(&list, 1);
    SListFind(list, 1);
    //SListErase(&list, SListFind(list, 1));
    SListPrint(list);
    SListDestroy(&list);
}
void Test1()
{
    PNode list;
    SListInit(&list);
    SListPushBack(&list, 1);
    SListPushBack(&list, 2);
    SListPushBack(&list, 3);
    SListPushBack(&list, 4);
    SListPushBack(&list, 5);
    SListPushBack(&list, 6);
    //DeleteListNotTailNode(SListFind(list, 1));
    //InesrtPosFront(SListFind(list, 1), 0);
    //InesrtPosFront(FindLastKNode(list,6), 0);

    SListPrint(list);

}

test.c

#include"List.h"



int main()
{
    Test1();
}

猜你喜欢

转载自blog.csdn.net/weixin_40909099/article/details/80063151