链表的基本操作——以及链表面试题

#define _CRT_SECURE_NO_WARNINGS

#include"list.h"
#include<assert.h>

void SListInit(PNode* pHead)  //链表初始化
{
    assert(pHead);
    *pHead = NULL;
}

PNode BuySListNode(DataType data)//申请一个结点
{
    PNode PNewNode = (PNode )malloc(sizeof(Node));
    if (PNewNode == NULL)
    {
        return NULL;
    }
    PNewNode->_pNext = NULL;
    PNewNode->_data = data;
    return PNewNode;
}

void SListPushBack(PNode* pHead, DataType data)// 尾插 
{
    assert(pHead);
    if (NULL == pHead)
    {
        /*pHead = BuySListNode(data);*/
        return;
    }
    else
    {
        PNode pCur = NULL;
        pCur = *pHead;
        while (pCur->_pNext)
        {
            pCur = pCur->_pNext;
        }
        pCur->_pNext = BuySListNode(data);
    }
}

void SListPopBack(PNode* pHead) // 尾删 
{
    assert(pHead);
    if (NULL == *pHead) //空链表
        return ;

    else if (NULL == (*pHead)->_pNext) //只有一个节点
    {
        PNode TmpNode = *pHead;
        free(TmpNode);
        TmpNode = NULL;
        *pHead = NULL;
    }
    else
    {
        PNode pCur = *pHead;
        while (pCur->_pNext->_pNext)
        {
            pCur = pCur->_pNext;
        }
        pCur->_pNext = NULL;
    }
}

void SListPushFront(PNode* pHead, DataType data)// 头插 
{
    PNode PNewNode = NULL;
    assert(pHead);

    PNewNode = BuySListNode(data);
    if (NULL == PNewNode)
        return;
    PNewNode->_pNext = *pHead;
    *pHead = PNewNode;

}

void SListPopFront(PNode* pHead)// 头删 
{
    PNode pDelNode = NULL;
    assert(pHead);
    if (NULL == pHead) //空链表
        return ;
    pDelNode = *pHead;
    *pHead = pDelNode->_pNext;
    free(pDelNode);
}

// 查找值为data的结点,返回该结点在链表中的位置 
PNode SListFind(PNode pHead, DataType data)
{
    PNode pCur = pHead;
    while (pCur)
    {
        if (pCur->_data == data)
        {
            return pCur;
        }
        pCur = pCur->_pNext;
    }
    return NULL;
}

// 在链表pos位置后插入结点data 
void SListInsert(PNode* pHead, PNode pos, DataType data)
{
    PNode PNewNode = NULL;
    assert(pHead);
    if (NULL == *pHead || NULL == pos)
        return;

    PNewNode = BuySListNode(data);
    PNewNode->_pNext = pos->_pNext;
    pos->_pNext = PNewNode;

}

// 删除链表pos位置上的结点 
void SListErase(PNode* pHead, PNode pos)
{
    assert(pHead);
    if (NULL == *pHead || NULL == pos)
        return;
    if (pos == *pHead)
    {
        SListPopFront(pHead);
    }
    else
    {
        PNode pCur = *pHead;
        while (pCur && pCur->_pNext != pos)
        {
            pCur = pCur->_pNext;
        }
            if (pCur)
        {
            pCur->_pNext = pos->_pNext;
            free(pos);
        }
    }
}

void SListClear(PNode* pHead)// 将链表中的结点清空
{
    PNode pDelNode = NULL;
    assert(pHead);
    while (*pHead)
    {
        pDelNode = *pHead;
        *pHead = pDelNode->_pNext;
        free(pDelNode);
    }
}

void SListDestroy(PNode* pHead)// 销毁单链表 
{
    SListClear(pHead);
}

int SListSize(PNode pHead)  // 求链表中结点的个数 
{
    int count = 0;
    PNode pCur = pHead;
    assert(pHead);
    if (NULL == pHead)
        return 0;
    pCur = pHead;
    while (pCur)
    {
        count++;
        pCur = pCur->_pNext;
    }
    return count;
}

// 获取链表中的最后一个结点,返回该结点的地址 
PNode SListBack(PNode pHead)
{
    PNode pCur = pHead;
    assert(pHead);
    while (pCur->_pNext)
    {
        pCur = pCur->_pNext;
    }
    return pCur;
}

void PrintList(PNode* pHead)//打印单链表  
{
    PNode pCur = *pHead;
    while (pCur)
    {
        printf("%d->", pCur->_data);
        pCur = pCur->_pNext;
    }
    printf("NULL\n");
}

以下为链表面试题

// 从尾到头打印单链表 
void PrintListFromTail2Head(PNode pHead)
{
    if (pHead)
    {
        PrintListFromTail2Head(pHead->_pNext);
        printf("%d--", pHead->_data);
    }
}

// 删除无头单链表的非尾结点,要求:不能遍历链表 
void DeleteNotTailNode(PNode pos)
{
    PNode pDelNode = NULL;
    if (NULL == pos&&NULL == pos->_pNext)
        return;

    pDelNode = pos->_pNext;
    pos->_data = pDelNode->_data;
    pos->_pNext = pDelNode->_pNext;
    free(pDelNode);
}

// 在无头单链表pos位置前插入值为结点data的结点 (不能遍历链表)
void InsertPosFront(PNode pos, DataType data)
{
    PNode pNewNode = NULL;
    if (NULL == pos)
        return;
    pNewNode = BuySListNode(pos->_data);
    pNewNode->_pNext = pos->_pNext;
    pos->_pNext = pNewNode;
    pos->_data = data;
}

// 用单链表模拟实现约瑟夫环 
void JosephCircle(PNode* pHead, const int M)
{
    assert(pHead);
    PNode pCur = *pHead;
    if (NULL == pHead)
        return;

    while (pCur->_pNext != pCur)
    {
        ///报数
        int count = M;
        while (--count)
        {
        pCur = pCur->_pNext;
        }
            //删除--替换法删除
        PNode pDelNode = pCur->_pNext;
        pCur->_data = pDelNode->_data;
        pCur->_pNext = pDelNode->_pNext;
        free(pDelNode);
    }
    *pHead = pCur;
}

// 使用冒泡排序方法对单链表进行排序 
void BubbleSort(PNode pHead)
{
    PNode pPreCur = NULL;
    PNode pCur = NULL;
    PNode pTail = NULL;
    if (NULL == pHead || NULL == pHead->_pNext)
        return;
    while (pHead != pTail)
    {
        int IsChange = 0;
        pPreCur = pHead;
        pCur = pPreCur->_pNext;
        while (pCur != pTail)
        {
            if (pPreCur->_data > pCur->_data)
            {
                int tmp = pPreCur->_data;
                pPreCur->_data = pCur->_data;
                pCur->_data = tmp;
                IsChange = 1;
            }
            pPreCur = pCur;
            pCur = pPreCur->_pNext;
        }
        if (!IsChange)
            return;
        pTail = pPreCur;
    }
}


// 单链表的逆置--三个指针 
void ReverseSList(PNode* pHead)
{
    PNode pPre = NULL;
    PNode pCur = NULL;
    PNode pNext = NULL;
    assert(pHead);
    if (NULL == *pHead || NULL == (*pHead)->_pNext)
        return;
    pCur = *pHead;
    while (pCur)
    {
        pNext = pCur->_pNext;
        pCur->_pNext = pPre;
        pPre = pCur;
        pCur = pNext;
    }
    *pHead = pPre;
}

// 单链表的逆置--头插法 
PNode ReverseSListOP(PNode pHead)
{
    PNode pNewHead = NULL;
    PNode pCur = pHead;
    PNode pNext = NULL;

    if (NULL == pHead || NULL == pHead->_pNext)
        return pHead;

    while (pCur)
    {
        pNext = pCur->_pNext;
        pCur->_pNext = pNewHead;
        pNewHead = pCur;
        pCur = pNext;
    }
    return pNewHead;
}

// 合并两个有序链表,合并之后依然有序 
PNode MergeSList(PNode pHead1, PNode pHead2)
{
    PNode pNewHead = NULL;
    PNode pTailNode = NULL;
    PNode pL1 = pHead1;
    PNode pL2 = pHead2;
    if (NULL == pHead1)
        return pHead2;
    if (NULL == pHead2)
        return pHead1;
    //两个链表都不为空,确定第一个节点
    if (pL1->_data < pL2->_data)
    {
        pNewHead = pL1;
        pL1 = pL1->_pNext;
    }
    else
    {
        pNewHead = pL2;
        pL2 = pL2->_pNext;
    }
    //向新链表中插入值
    pTailNode = pNewHead;
    while (pL1 && pL2)
    {
        if (pL1->_data < pL2->_data)
        {
            pTailNode->_pNext = pL1;
            pL1 = pL1->_pNext;
        }
        else
        {
            pTailNode->_pNext = pL2;
            pL2 = pL2->_pNext;
        }
        pTailNode = pTailNode->_pNext;
    }
    //若一个链表有剩余,放在新链表后面
        if (pL1)
            pTailNode->_pNext = pL1;
        else
            pTailNode->_pNext = pL2;
    return pNewHead;
}

// 查找链表的中间结点,要求只能遍历一次链表 
PNode FindMiddleNode(PNode pHead)
{
    PNode pFast = pHead;
    PNode pSlow = pHead;
    /*PNode pPre = pHead;*/
    while (pFast && pFast->_pNext)
    {
        /*pPre = pSlow;*/
        pFast = pFast->_pNext->_pNext;
        pSlow = pSlow->_pNext;
    }

    //求奇数个节点的中间节点前一个节点
    /*if (NULL == pFast)
    return pPre;*/
    return pSlow;
}

// 查找链表的倒数第K个结点,要求只能遍历链表一次 
PNode FindLastKNode(PNode pHead, int K)
{
    PNode pFast = pHead;
    PNode pSlow = pHead; 
    if (NULL == pHead || K < 0)
        return NULL;
    //让pFast先走K步
    while (K--)
    {
        if (NULL == pFast)//K大于节点个数
            return NULL;
        pFast = pFast->_pNext;
    }
    //两指针同时往后走
    while (pFast)
    {
        pFast = pFast->_pNext;
        pSlow = pSlow->_pNext;
    }
    return pSlow;
}

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

    if (NULL == pHead || K <= 0)
        return NULL;
    int count = K;
    //快的指针先走K步
    while (count--)
    {
        if (NULL == pFast)
            return NULL;
        pFast = pFast->_pNext;
    }
    //然后快慢指针一起走,慢指针指向的就是倒数第K个节点
    while (pFast)
    {
        pPre = pSlow;
        pFast = pFast->_pNext;
        pSlow = pSlow->_pNext;
    }
    //删除
    pPre->_pNext = pSlow->_pNext;
    free(pSlow);

    return pHead;
}

// 判断单链表是否相交?链表不带环 
int IsCrossWithoutCircle(PNode pHead1, PNode pHead2)
{
    PNode pTail1 = pHead1;
    PNode pTail2 = pHead2;
    if (NULL == pHead1 || NULL == pHead2)
        return 0;
    //找第一个链表的最后一个节点
    while (pTail1)
        pTail1 = pTail1->_pNext;
    //找第二个链表的最后一个节点
    while (pTail2)
        pTail2 = pTail2->_pNext;
    return pTail1 == pTail2;
}

// 求不带环单链表相交交点 
PNode GetCrossNode(PNode pHead1, PNode pHead2)
{
    int size1 = 0, size2 = 0, gap;
    PNode pCur1 = pHead1, pCur2 = pHead2;
    if (!(IsCrossWithoutCircle(pHead1, pHead2)))
        return NULL;
    //求交点
    while (pCur1)
    {
        size1++;
        pCur1 = pCur1->_pNext;
    }
    while (pCur2)
    {
        size2++;
        pCur2 = pCur2->_pNext;
    }
    //让长的链表先走差值这么多
    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 pCur1;
}

// 判断链表是否带环 
PNode IsCircle(PNode pHead)
{
    PNode pFast = pHead;
    PNode pSlow = pHead;
    while (pFast&&pFast->_pNext)
    {
        pFast = pFast->_pNext->_pNext;
        pSlow = pSlow->_pNext;
        if (pFast == pSlow)     //带环
            return pFast;
    }
    return 0;
}

// 求环的长度 
int GetCircleLen(PNode pHead)
{
    PNode pMeetNode = IsCircle(pHead);
    PNode pCur = pMeetNode;
    int count = 1;
    if (NULL == pMeetNode)
        return 0;
    while (pCur->_pNext != pMeetNode)
    {
        count++;
        pCur = pCur->_pNext;
    }
    return count;
}

// 求环的入口点--注意推断过程 
PNode GetEnterNode(PNode pHead, PNode pMeetNode)
{
    PNode PH = pHead;
    PNode PM = pMeetNode;
    if (NULL == pHead || NULL == pMeetNode)
        return NULL;
    while (PH != PM)
    {
        PH = PH->_pNext;
        PM = PM->_pNext;
    }
    return PM;
}

// 判断链表是否带环,链表可能带环 
int IsListCrossWithCircle(PNode pHead1, PNode pHead2)
{
    PNode pMeetNode1 = NULL;
    PNode pMeetNode2 = NULL;
    if (NULL == pHead1 || NULL == pHead2)
        return 0;
    //判断两个链表是否带环
    pMeetNode1 = IsCircle(pHead1);
    pMeetNode2 = IsCircle(pHead2);
    //两个链表都不带环
    if (NULL == pMeetNode1&&NULL == pMeetNode2)
    {
        //求两个链表的最后一个元素,若最后一个元素相等则相交
        PNode pTail1 = pHead1;
        PNode pTail2 = pHead2;
        while (pTail1->_pNext)
            pTail1 = pTail1->_pNext;
        while (pTail2->_pNext)
            pTail2 = pTail2->_pNext;

        if (pTail1 == pTail2)
            return 1;
    }
    //两个链表都带环
    else if (pMeetNode1 && pMeetNode2)
    {
        PNode pCur = pMeetNode1;
    /*  do
        {
            if (pCur == pMeetNode2)
                return 2;
            pCur = pCur->_pNext;
        } while (pCur != pMeetNode1);*/
        while (pCur->_pNext != pMeetNode1)
        {
            if (pCur == pMeetNode2)
                return 2;
            pCur = pCur->_pNext;
        }
        if (pCur == pMeetNode2)
            return 2;
    }
    return 0;
}

// 复杂链表的复制 
PCListNode CopyComplexList(PCListNode pHead)
{
    PCListNode pOldNode = pHead;
    PCListNode pNewNode = NULL;
    PCListNode pNewHead = NULL;
    if (NULL == pHead)
        return NULL;
    //在原链表的每个节点后插入值相同的新节点
    while (pOldNode)
    {
        pNewHead = (PCListNode)malloc(sizeof(CListNode));
        pNewHead->_data = pOldNode->_data;
        pNewNode->_pNext = NULL;
        pNewNode->_pRandom = NULL;
        if (NULL == pNewNode)
            return NULL;

        pNewNode->_pNext = pOldNode->_pNext;
        pOldNode->_pNext = pNewNode;
        pOldNode = pNewNode->_pNext;
    }
    //给新插入的节点的随机指针域赋值
    pOldNode = pHead;
    while (pOldNode)
    {
        pNewNode = pOldNode->_pNext;
        if (NULL == pOldNode->_pRandom)
            pNewNode->_pRandom = NULL;
        else
            pNewNode->_pRandom = pOldNode->_pRandom->_pNext;
        pOldNode = pNewNode->_pNext;
    }
    //将插入的新节点从链表中拆下来
    pOldNode = pHead;
    pNewHead = pOldNode->_pNext;
    while (pOldNode->_pNext)
    {
        pNewNode = pOldNode->_pNext;
        pOldNode->_pNext = pNewNode->_pNext;
        pOldNode = pNewNode;
    }
    return pNewHead;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章