单链表的基本操作的相关题目

链表:

一种链式存储的线性表,用一组地址任意的存储单元存放线性表的 数据元素,称存储单元为一个节点。链表可以分为带头结点的单链表和不带头结点的单链表。此片文章是不带头结点的单链表

上图为单链表结构,每个节点均有数据域data和指向下一个节点的指针域pNext。

链表优缺点:在执行插入和删除操作是不需要移动元素,但在查询时必须通过头结点进行查询比较麻烦。由于存放元素的地址不连续。因此有可能造成空间浪费。

链表结构c语言描述

typedef int DataType;
typedef struct SList
{
    DataType data;
    struct SList* pNext;

}SList;
函数声明:

void Init(SList **ppHead);//初始化
SList* BuyNewNode(DataType data);//申请新节点
void PushBack(SList **ppHead, DataType data);//头插
void myprintf(SList *ppHead);//打印函数
void DestroyLinkList(SList **ppHead);//销毁
void SListPopBack(SList** pHead);//尾删
void SListPushFront(SList** pHead, DataType data);//头插
void SListPopFront(SList** pHead);//头删

//面试题

void PrintListFromTail2Front(SList* pHead);// 从尾到头打印单链表 

void DeleteListNotTail(SList* pos);// 删除单链表的非尾结点,不能遍历链表 
void InsertPosFront(SList* pos, DataType data);// 在单链表非头结点前插入新节点,要求不能遍历链表 
SList* JosephCircle(SList* pHead, int M);// 用单链表模拟实现约瑟夫环 
void BubbleSort(SList* pHead);// 用冒泡排序对单链表进行排序 
SList* FindMiddleNode(SList* pHead);// 查找单链表的中间结点,要求只能遍历一次链表
SList* FindLastKNode(SList* pHead, int K);// 查找单链表的倒数第K个结点,要求只能遍历一次链表 
void ReverseList(SList** pHead);// 单链表的逆置尾插
SList* ReverseListOP(SList* pHead);//头插
SList* MergeList(SList* pHead1, SList* pHead2);// 合并两个有序链表,合并成功后依然有序 
SList* HasListCircle(SList* pHead);// 检测单链表是否带环 
int GetCircleLen(SList* pHead);// 求环的长度
SList* GetEnterNode(SList* pHead, SList* pMeetNode);// 求环的入口点 
int IsListCross(SList* pHead1, SList* pHead2);// 判断两个单链表是否相交(链表不带环) 
SList* GetCrossNode(SList* pHead1, SList* pHead2);// 若相交,求交点
int IsListCrossWithCircle(SList* pHead1, SList* pHead2);// 检测两个链表是否相交,链表可能带环

函数的实现:

#include"SList.h"
#include<stdio.h>
#include<malloc.h>
void Init(SList **ppHead)//初始化
{
    *ppHead = NULL;
}
SList* BuyNewNode(DataType data)//申请新节点
{
    SList *pNewNode = (SList*)malloc(sizeof(SList));
    if (pNewNode == NULL)
    {
        assert(0);
        return NULL;
    }
    assert(pNewNode);
    pNewNode->data = data;
    pNewNode->pNext = NULL;
    return pNewNode;


}
void PushBack(SList **ppHead, DataType data)//尾插
{
    SList *pNewNode = BuyNewNode(data);//如果头结点不存在用申请的节点来创建头结点
    if (*ppHead == NULL)
    {
        *ppHead = pNewNode;

    }
    else
    {
        SList *pCur = *ppHead;
        while (pCur->pNext != NULL)
        {
            pCur = pCur->pNext;
        }
        pCur->pNext = pNewNode;
        pNewNode->pNext = NULL;
    }

}
void DestroyLinkList(SList **ppHead)//销毁
{
    SList *Cur = *ppHead;
    SList *Pre = NULL;
    while (Cur)

    {
        Pre = Cur->pNext;
        free(Cur);
        Cur = Pre;
        
    }
    ppHead = NULL;


}
void SListPopBack(SList** ppHead)//尾删
{
    assert(ppHead);
    if (*ppHead == NULL)
    {
        return;

    }
    SList* cur = *ppHead;
    SList* pre = NULL;
    while (cur->pNext!=NULL)
    {
        pre = cur;
        cur = cur->pNext;

    }
    free(cur);
    cur=NULL;
    pre->pNext = NULL;


}
void SListPushFront(SList** ppHead, DataType data)//头插
{

    SList *pNewNode = BuyNewNode(data);
    if (ppHead == NULL)
    {
        *ppHead = pNewNode;

    }
    else
    {
        pNewNode->pNext = *ppHead;
        *ppHead = pNewNode;
    }

}
void SListPopFront(SList** ppHead)//头删
{
    SList* pDel = NULL;
    assert(ppHead);
    if (NULL == *ppHead)
        return;

    pDel = *ppHead;
    *ppHead = pDel->pNext;
    free(pDel);
    

}
SList* SListFind(SList* pHead, DataType data)//查找某个节点
{
    SList* pCur = pHead;
    while (pCur)
    {
        if (data == pCur->data)
            return pCur;

        pCur = pCur->pNext;
    }

    return NULL;
}

SList* SListBack(SList* pHead)//获取最后一个节点
{
    SList* pPreCur = NULL;
    SList* pCur = pHead;
    while (pCur)
    {
        pPreCur = pCur;
        pCur = pCur->pNext;
    }

    return pPreCur;
}
void PrintListFromTail2Front(SList* ppHead)// 从尾到头打印单链表 
{
    
    if (ppHead != NULL)
    {
        PrintListFromTail2Front(ppHead->pNext);
        printf("%d", ppHead->data);
    }

}
void DeleteListNotTail(SList* pos)// 删除单链表的非尾结点,不能遍历链表
{
    assert(pos);
    if (pos == NULL || pos->pNext == NULL)//该节点和下一个节点不能为空
    {
        return;
    }
    SList*cur = NULL;
    cur = pos->pNext;
    pos->data = cur->data;
    pos->pNext = cur->pNext;
    free(cur);

}void InsertPosFront(SList* pos, DataType data)// 在单链表非头结点前插入新节点,要求不能遍历链表 
{
    SList*pNewNode = NULL;
    if (pos ==NULL)
        return;
    pNewNode = BuyNewNode(pos->data);
    pNewNode->pNext = pos->pNext;
    pos->pNext = pNewNode;
    pos->data = data;
}
SList* JosephCircle(SList* pHead, int M)// 用单链表模拟实现约瑟夫环 
{
    SList*Tail = pHead;
    SList*cur = NULL;
    while (Tail->pNext != NULL)
    {
        Tail = Tail->pNext;

    }
    Tail->pNext =pHead;
    cur = pHead;
    while (cur->pNext != cur)
    {
        int k = M;
        SList*next = NULL;
        while (--k)
            cur = cur->pNext;
        
        next = cur->pNext;//伪删除是指并不是将这个节点删除,而是将该节点的data改为下一个节点的data.
        cur->data = next->data;
        cur->pNext = next->pNext;
        free(next);

    }
    return cur;
}
void BubbleSort(SList* pHead)// 用冒泡排序对单链表进行排序 

    {
        SList* pTailNode = NULL;
        int isChange = 0;
        if (NULL == pHead || NULL == pHead->pNext)//链表为空或只有一个节点不同排序
            return;

        while (pHead != pTailNode)//排序轮数
        {
            SList* pPre = pHead;
            SList* pCur = pPre->pNext;
            isChange = 0;

            // 冒泡方法
            while (pCur != pTailNode)//每一轮需要进行的排序次数
            {
                if (pPre->data > pCur->data)
                {
                    DataType temp = pPre->data;
                    pPre->data = pCur->data;
                    pCur->data = temp;
                    isChange = 1;
                }

                pPre = pCur;
                pCur = pCur->pNext;
            }

            if (!isChange)//如果次序正常则不进行这次排序
                return;

            pTailNode = pPre;//当一遍排序结束后最后一个节点不同在排序将为指针向前移动
        }
}
SList* FindMiddleNode(SList* pHead)// 查找单链表的中间结点,要求只能遍历一次链表
{
    SList *slow = pHead;
    SList*fast = pHead;
    while (fast&&fast->pNext)
    {
        slow = slow->pNext;
        fast = fast->pNext->pNext;
    }
    return slow;
}
SList* FindLastKNode(SList* ppHead, int K)// 查找单链表的倒数第K个结点,要求只能遍历一次链表 
{
    SList  *pFast = ppHead;
    SList *pSlow = ppHead;
    if (ppHead == NULL || K <= 0)
        return 0;
    while (--K)
    {
        if (pFast == NULL)
            return NULL;
        pFast = pFast->pNext;
    }
    while (pFast->pNext!=NULL)
    {
        pFast = pFast->pNext;
        pSlow = pSlow->pNext;
    }
    return pSlow;


}
void ReverseList(SList** ppHead)// 单链表的逆置
{
    SList *pCur = NULL;
    SList *pPre = NULL;
    SList *pNext = NULL;
    pCur = *ppHead;
    while (pCur)
    {
        pNext = pCur->pNext;
        pCur->pNext = pPre;//将取下来的节点直接连在pPre的前面
        pPre = pCur;
        pCur = pNext;

    }
    *ppHead = pPre;
}
SList* MergeList(SList* pHead1, SList* pHead2)// 合并两个有序链表,合并成功后依然有序
{
    SList *pNewNode = NULL;
    SList *pTail = NULL;//用来保证新节点不用动因此先插一个节点;
    SList*pL1 = pHead1;
    SList*pL2 = pHead2;
    if (pHead1 == NULL)
        return pHead2;
    if (pHead2 == NULL)
        return pHead2;
    if (pL1->data <= pL2->data)//先存放一个节点
    {
        pNewNode = pTail = pL1;
        pL1 = pL1->pNext;
    }
    else
    {
        pNewNode = pTail = pL2;
        pL2 = pL2->pNext;
    }
    while (pL1&&pL2)
    {
        if (pL1->data <= pL2->data)
        {
             pTail->pNext = pL1;
            pL1 = pL1->pNext;
        }
        else
        {
             pTail->pNext= pL2;
            pL2 = pL2->pNext;
        }
        pTail = pTail->pNext;
        
    }
    if (pL1)
        pTail->pNext = pL1;
    else
        pTail->pNext = pL2;
    return pNewNode;
}

SList* HasListCircle(SList* ppHead)// 检测单链表是否带环 
{
    SList *pFast = ppHead;
    SList *pSlow = ppHead;
    while (pFast&&pFast->pNext)//肯定会在环内相遇
    {
        pFast = pFast->pNext->data;
        pSlow = pSlow->pNext;
        if (pFast == pSlow)
            return pFast;
    }
    return NULL;
}
int GetCircleLen(SList* pMeetNode)// 求环的长度
{
    int count = 1;
    SList *pCur = pMeetNode;
    if (pMeetNode == NULL)
        return 0;
    while (pCur->pNext != pMeetNode)
    {
        count++;
        pCur = pCur->pNext;
    }
    return count;

}
SList* GetEnterNode(SList* ppHead, SList* pMeetNode)// 求环的入口点 
{
    SList *pH = ppHead;
    SList *pM = pMeetNode;
    if (ppHead == NULL || pMeetNode == NULL)
        return NULL;
    while (pH!=pM)//相遇点和从头开始的节点一定会在入口点相交
    {
        pH = pH->pNext;
        pM = pM->pNext;
    }
    return pM;
}
int IsListCross(SList* pHead1, SList* pHead2)// 判断两个单链表是否相交(链表不带环) 
{
    SList*pH1 = pHead1;
    SList*pH2 = pHead2;
    if (pHead1 == NULL || pHead2 == NULL)
        return 0;
    while (pH1)
        pH1 = pH1->pNext;
    while (pH2)
        pH2 = pH2->pNext;
    return pH1 == pH2;

}
SList* GetCrossNode(SList* pHead1, SList* pHead2)// 若相交,求交点
{
    SList *pH1 = pHead1;
    SList *pH2 = pHead2;
    int count = 0;
    int size1 = 0;
    int size2 = 0;
    while (pH1 != NULL)
    {
        pH1 = pH1->pNext;
        size1++;
    }
    while (pH2 != NULL)
    {
        size2++;
        pH2 = pH2->pNext;
    }
    count = size1 - size2;
    if (count > 0)
    {
        while (count--)
            pH1 = pH1->pNext;
    }
    else
    {
        while (count++)
            pH2 = pH2->pNext;
    }
    while (pH1 != pH2)
    {
        pH1 = pH1->pNext;
        pH2 = pH2->pNext;

    }
    return pH1;
}
int IsListCrossWithCircle(SList* pHead1, SList* pHead2)
{
    SList* pMeetNode1 = NULL;
    SList* pMeetNode2 = NULL;
    if (NULL == pHead1 || NULL == pHead2)
        return 0;

    pMeetNode1 = HasListCircle(pHead1);
    pMeetNode2 = HasListCircle(pHead2);
    if (NULL == pMeetNode1 && NULL == pMeetNode2)//不带环相交
    {
        SList* pTailNode1 = pHead1;
        SList* pTailNode2 = pHead2;
        while (pTailNode1->pNext)
            pTailNode1 = pTailNode1->pNext;

        while (pTailNode2->pNext)
            pTailNode2 = pTailNode2->pNext;

        if (pTailNode1 == pTailNode2)
            return 1;
    }
    else if (pMeetNode1 && pMeetNode2)//带还相交
    {
        SList* pCur = pMeetNode1;
        while (pCur->pNext != pMeetNode1)
        {
            if (pCur == pMeetNode2)
                return 2;

            pCur = pCur->pNext;
        }

        if (pCur == pMeetNode2)
            return 2;
    }

    return 0;
}
void myprintf(SList *ppHead)


{
    SList *pCur = ppHead;
    while (pCur != NULL)
    {
        printf("%d", pCur->data);
        pCur = pCur->pNext;
    }
}

 


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值