链表相关练习

链表练习题

  • 创建链表
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef struct SListNode
{
    int data;
    struct SListNode *pNext;
}SList;
  • 初始化头部
void Init(SList **pphead)
{
    *pphead = NULL;
}
  • 输出链表
void Print(SList *pHead)
{
    assert(pHead);
    if(pHead == NULL)
    {
        printf("链表为空\n");
        return;
    }
    while(pHead != NULL)
    {
        printf("%d -> ",pHead->data);
        pHead = pHead->pNext;
    }
    printf("NULL\n");
}
  • 尾插
void SListPushBack(SList **ppHead, int data)
{
    SList *pNode; 
    SList *pNew = (SList *)malloc(sizeof(SList));
    if(*ppHead == NULL)
    {
        *ppHead = pNew;
        pNew->data = data;
        pNew->pNext = NULL;
        return;
    }
    pNode = *ppHead;
    while(pNode->pNext != NULL)
    {
        pNode = pNode->pNext;
    }
    pNode->pNext = pNew;
    pNew->data = data;
    pNew->pNext = NULL;
}
  • 头部插入
void SListPushFront(SList **ppHead, int data)
{
    SList *pNew = (SList *)malloc(sizeof(SList));
    if(*ppHead == NULL)
    {
        *ppHead = pNew;
        pNew->data = data;
        pNew->pNext = NULL;
        return;
    }
    pNew->pNext = *ppHead;
    pNew->data = data;
    *ppHead = pNew;
}
  • 尾删
void SListPopBack(SList **ppHead)
{
    SList *pHead = *ppHead;
    SList *pNode;
    if(*ppHead == NULL)
    {
        printf("链表为空\n");
        return;
    }
    if(pHead->pNext == NULL)
    {
        free(pHead);
        *ppHead = NULL;
        return;
    }
    while(pHead->pNext != NULL)
    {
        pNode = pHead;
        pHead = pHead->pNext;
    }
    free(pHead);
    pNode->pNext = NULL;
}
  • 头删
void SListPopFront(SList **ppHead)
{
    SList *pHead = *ppHead;
    if(pHead->pNext == NULL)
    {
        free(pHead);
        *ppHead = NULL;
        return;
    }
    *ppHead = pHead->pNext;
    free(pHead);
}
  • 随机插
void SListInsert(SList **ppHead, int x, int data)
{
    SList *pHead;
    SList *pNew = (SList *)malloc(sizeof(SList));
    pHead = *ppHead;
    if(pHead->data == x)
    {
        pNew->pNext = pHead;
        pNew->data = data;
        *ppHead = pNew;
        return;
    }
    while(pHead->pNext->data != x)
    {
        pHead = pHead->pNext;
    }
    pNew->pNext = pHead->pNext;
    pHead->pNext = pNew;
    pNew->data = data;
}
  • 删除
void SListDel(SList **ppHead, int data)
{
    SList *pHead = *ppHead;
    SList *pNode;
    if(pHead->data == data)
    {
        SListPopFront(ppHead);
        return;
    }
    while(pHead != NULL)
    {
        if(pHead->data == data)
        {
            pNode->pNext = pHead->pNext;
            free(pHead);
            return;
        }
        pNode = pHead;
        pHead = pHead->pNext;
    }
}
  • 按值删除所有
void SListRemoveAll(SList **ppHead, int data)
{
    SList *pNode = *ppHead;
    SList *pNode1;
    while(pNode->pNext != NULL)
    {
        if(pNode->pNext->data == data)
        {
            pNode1 = pNode->pNext;
            pNode->pNext = pNode1->pNext;
            free(pNode1);
        }else
        {
            pNode = pNode->pNext;
        }
    }
    if((*ppHead)->data == data)
    {
        SListPopFront(ppHead);
    }
}
  • 查找
SList *SListFind(SList *pHead, int data)
{
    SList *pNode = pHead;
    while(pNode != NULL)
    {
        if(pNode->data == data)
        {
            return pNode;
        }
        pNode = pNode->pNext;
    }
    return NULL;
}
  • 销毁
void SListDestroy(SList **ppHead)
{
    SList *pNode;
    assert(ppHead);
    while(*ppHead != NULL)
    {
        pNode = *ppHead;
        *ppHead = (*ppHead)->pNext;
        free(pNode);
    }
}
  • 删除一个无头单链表的非尾节点(不能遍历链表)
//换船上的人,不换船本体
void DelSList(SList **ppHead,int data)
{
    SList *pHead = *ppHead;
    assert(ppHead);
    while(pHead->data != data)
    {
        pHead = pHead->pNext;
    }
    while(pHead->pNext->pNext != NULL)
    {
        pHead->data = pHead->pNext->data;
        pHead = pHead->pNext;
    }
    pHead->data = pHead->pNext->data;
    free(pHead->pNext);
    pHead->pNext = NULL;
}
  • 反转链表
void SListRever(SList **ppHead)
{
    SList *p1,*p2,*p3;
    assert(ppHead);
    p1 = NULL;
    p2 = *ppHead;
    p3 = p2->pNext;
    while(p2 != NULL)
    {
        p2->pNext = p1;
        p1 = p2;
        p2 = p3;
        if(p3 != NULL)
        {
            p3 = p3->pNext;
        }
    }
    *ppHead = p1;
}
  • 在无头单链表的一个节点前插入一个节点(不能遍历链表)
void InsertNoFirstNode(SList **ppPos, int data)
{
    SList *pPos = *ppPos;
    SList *pNode;
    assert(ppPos);
    if(*ppPos == NULL)
    {
        SListPushBack(ppPos, data);
        return;
    }
    pNode = (SList *)malloc(sizeof(SList));
    pNode->data = data;
    pNode->pNext = NULL;

    pNode->pNext = pPos->pNext;
    pPos->pNext = pNode;
    pNode->data = pPos->data;
    pPos->data = data;
}
  • 单链表实现约瑟夫环
void SListJosephCircle(SList **ppHead, int n)
{
    SList *pHead = *ppHead;
    SList *pNode;
    int i;
    while(pHead->pNext != NULL)
    {
        pHead = pHead->pNext;
    }
    pHead->pNext = *ppHead;
    pHead = *ppHead;
    while(pHead->pNext != pHead)
    {
        i = n;
        while((--i)>0)
        {
            pNode = pHead;
            pHead = pHead->pNext;
        }

        pNode->pNext = pHead->pNext;
        free(pHead);

        pHead = pNode->pNext;
    }
    pHead->pNext = NULL;
    *ppHead = pHead;
}
  • 逆向打印链表
void PrintFail(SList *pHead)
{
    if(pHead == NULL)
    {
        return;
    }
    else
    {
        PrintFail(pHead->pNext);
        printf("->%d",pHead->data);

    }
}
  • 排序链表
//遍历链表,每次遍历删除值最大的链子,然后再创建到另一个链表上。
void SListSort(SList **ppHead)
{
    SList *pHead = *ppHead;
    SList *pNode = *ppHead;
    SList *First = NULL;
    int i = 0;
    while(pHead != NULL)
    {
        pNode = pHead;
        i = 0;
        while(pNode != NULL)
        {
            if(pNode->data > i)
            {
                i = pNode->data;
            }
            pNode = pNode->pNext;
        }
        SListPushBack(&First, i);
        SListDel(&pHead, i);
    }
    *ppHead = First;
}
  • 合并有序链表
//遍历两个链表,创建一个新的链表,两个链表中较小的放入新链表,最后将多余的放入新链表中
SList *SListmerge(SList **ppHead, SList **pptwo)
{
    SList *pone = *ppHead;
    SList *ptwo = *pptwo;
    SList *merge = NULL;
    SList *ptmp = NULL;
    while(pone != NULL && ptwo != NULL)
    {
        if(pone->data < ptwo->data)
        {
            SListPushBack(&merge, pone->data);
            pone = pone->pNext;
        }else
        {
            SListPushBack(&merge, ptwo->data);
            ptwo = ptwo->pNext;
        }
    }
    if(pone == NULL)
    {
        ptmp = ptwo;
    }else
    {
        ptmp = pone;
    }
    while(ptmp != NULL)
    {
        SListPushBack(&merge, ptmp->data);
        ptmp = ptmp->pNext;
    }
    return merge;
}
  • 求两个链表的交集
//遍历链表相同的放在新链表中
SList *SListintersection(SList **ppone, SList **pptwo)
{
    SList *pone = *ppone;
    SList *ptwo = *pptwo;
    SList *pnew = NULL;
    while(pone != NULL)
    {
        ptwo = *pptwo;
        while(ptwo != NULL)
        {
            if(pone->data == ptwo->data)
            {
                SListPushBack(&pnew, pone->data);
            }
            ptwo = ptwo->pNext;
        }
        pone = pone->pNext;
    }
    return pnew;
}
  • 求两个链表的并集
//先让新链表等于其中一个链表,然后用一个链表遍历另一个,
//如果链表里没有另一个链表里的数,保存并将状态置1,然后加入到新链表中,然后将状态置0,
//遍历过程中及时修改状态值,决定是否将其加入并集中。
SList * SListUnion(SList **ppone, SList **pptwo)
{
    SList *pone = *ppone;
    SList *ptwo = *pptwo;
    SList *pnew = pone;
    int stract = 0;
    int tmp = 0;
    if(pone == NULL && ptwo != NULL)
        return ptwo;
    if(ptwo == NULL && pone != NULL)
        return pone;
    assert(ppone&&pptwo);
    while(ptwo != NULL)
    {
        pone = *ppone;
        while(pone != NULL)
        {
            if(pone->data != ptwo->data)
            {
                stract = 1;
                tmp = ptwo->data;
                //SListPushBack(&pnew, 1);
            }
            if(pone->data == ptwo->data)
            {
                stract = 0;
                //SListPopBack(&pnew);
                break;
            }
            pone = pone->pNext;
        }
        if(stract == 1)
        {
            SListPushBack(&pnew, tmp);
            stract = 0;
        }
        ptwo = ptwo->pNext;
    }
    return pnew;
}
  • 求链表长度
int SListstrlen(SList *pHead)
{
    int count = 0;
    SList *str = pHead;
    while(str != NULL)
    {
        count++;
        str = str->pNext;
    }
    return count;
}
  • 两个链表是否相交,求交点
//链表如果相交,终点肯定是一致的,比较他们的末尾节点的地址,相等则相交。
//如果相交,求出俩链表长度,让长的先走链表长度差的步数,
//然后两链表同时向后走,地址相等时,两个链表相交
SList *SListIsintersect(SList *pHead, SList *ptwo1)
{
    SList *pone = pHead;
    SList *ptwo = ptwo1;
    SList *Long = NULL;
    SList *Short = NULL;
    int n = 0;
    int x = SListstrlen(pone);
    int y = SListstrlen(ptwo);
    if(x > y)
    {
        Long = pone;
        Short = ptwo;
        n = x-y;
    }
    else
    {
        Long = ptwo;
        Short = pone;
        n = y-x;
    }
    for(n; n>0; n--)
    {
        Long = Long->pNext;
    }
    while(Long != Short)
    {
        Long = Long->pNext;
        Short = Short->pNext;
    }
    return Long;
}
  • 删除倒数第K个节点
//定义两个指针,其中一个先走k-1步,然后两个同时遍历,
//先走的走完链表时,后走的刚好走到倒数第k个点上
void SListDelK(SList **pptwo, int k)
{
    SList *pfast = *pptwo;
    SList *pslow = *pptwo;
    SList *Del = NULL;
    assert(pptwo);
    while(k-1)
    {
        k--;
        pfast = pfast->pNext;
    }
    if(pfast->pNext == NULL)
    {
        SListPopFront(pptwo);
        return;
    }
    while(pfast->pNext != NULL)
    {
        Del = pslow;
        pfast = pfast->pNext;
        pslow = pslow->pNext;
    }
    Del->pNext = pslow->pNext;
}
  • 计算相遇点
//判断链表是否有环,定义两个指针,一个每次走两步,一个每次走一步,
//如果最后两个指针能指向同一个点,说明链表有环。
SList *SListmeet(SList *ptwo)
{
    SList *fast = ptwo;
    SList *slow = ptwo;
    if(ptwo == NULL)
    {
        return NULL;
    }
    while(1)
    {
        if(fast->pNext == NULL || fast->pNext->pNext == NULL)
        {
            return NULL;
        }
        fast = fast->pNext->pNext;
        slow = slow->pNext;
        if(fast == slow)
        {
            return slow;
        }
    }
}
  • 计算环的入口
//两个指针,一个从链表开始部分走,一个从相遇的点开始走,当两个指针相等的时候,就是环的入口点
SList *SListCircle(SList *ptwo, SList *meet)
{
    SList *first = ptwo;
    SList *pMeet = meet;
    assert(ptwo && meet);
    while(first != pMeet)
    {
        first = first->pNext;
        pMeet = pMeet->pNext;
    }
    return first;
}
  • 环的长度
int SListlen(SList *meet)
{
    int count = 1;
    SList *pMeet = meet->pNext;
    while(pMeet != meet)
    {
        count++;
        pMeet = pMeet->pNext;
    }
    return count;
}
  • 复杂链表的拷贝
/*
void CListCopy(CList **ppHead, SList **ppCopy)
{
    CList *pHead = *ppHead;
    CList *Copy = *ppCopy;
    CList *pNode = NULL;
    Clist *Next = NULL;
    CList *pNew = NULL;
    assert(ppHead);
    while(pHead != NULL)
    {
        pNode = pHead->pNext;
        pNew = (CList *)malloc(sizeof(CList));
        pNew->data = pHead->data;
        pNew->Rom = NULL;
        pNew->pNext = pNode;
        pHead->pNext = pNew;
        pHead = pHead->pNext-pNext;
    }
    pHead = *ppHead;
    while(pHead != NULL)
    {
        Next = pHead->Rom;
        if(Next != NULL)
        {
            pHead->pNext->Rom = Next->pNext;
            pHead = pHead->pNext->pNext;
        }
    }
    pHead = *ppHead;
    Copy = pHead->pNext;
    while(pHead != NULL)
    {
        Next = pHead->pNext->pNext;
        if(Next != NULL)
        {
            Copy->pNext = Next->pNext;
        }
        else
        {
            Copy->pNext = NULL;
        }
        pHead->pNext = Next;
        pHead = pHead->pNext;
    }
}
*/
int main()
{
    SList *pHead;
    SList *ptwo = NULL;
    SList *pNode = NULL;
    SList *pNode2 = NULL;
    SList *pCP = NULL;
    SList *meet = NULL;
    SList *circle = NULL;
    int c = 0;
    //SList *merge;
    //初始化头部
    //交集并集指针变量
    //SList *intersection;
    //SList *Union;
    Init(&pHead);
    //尾部插入
    SListPushBack(&pHead, 1);
    SListPushBack(&pHead, 2);
    SListPushBack(&pHead, 3);
    SListPushBack(&pHead, 4);
    SListPushBack(&pHead, 6);
    SListPushBack(&pHead, 9);
    SListPushBack(&pHead, 1);
    SListPushBack(&pHead, 8);
    SListPushBack(&pHead, 5);
    //头部插入
    //SListPushFront(&pHead, 5);
    //尾删
    //SListPopBack(&pHead);
    //头删
    //SListPopFront(&pHead);
    //在哪个数前插入
    //SListInsert(&pHead, 5, 4);
    //按值删除
    //SListDel(&pHead, 6);
    //按值删除所有
    //SListRemoveAll(&pHead, 2);
    //查找
    //pNode = SListFind(pHead, 6);
    //printf("%d\n",pNode->data);
    //销毁
    //SListDestroy(&pHead);
    //删除一个无头单链表的非尾节点(不能遍历链表)
    //DelSList(&pHead,1);
    //在无头单链表的一个节点前插入一个节点(不能遍历链表)
    //InsertNoFirstNode(&pNode, 9);
    //翻转链表
    //SListRever(&pHead);
    //单链表实现约瑟夫环
    ////SListJosephCircle(&pHead,3);
    //逆向打印
    //PrintFail(pHead);
    //printf("\n");
    //排序链表
    //SListSort(&pHead);
    //输出
    //Print(pHead);
    //链表二
    SListPushBack(&ptwo, 2);
    SListPushBack(&ptwo, 4);
    SListPushBack(&ptwo, 7);
    SListPushBack(&ptwo, 5);
    SListPushBack(&ptwo, 3);
    SListPushBack(&ptwo, 1);

    //连接两个链表
    //pNode = SListFind(ptwo, 7);
    //pNode2 = SListFind(pHead, 6);
    //pNode->pNext = pNode2;
    //制造一个链表环,如果链表带环,则打印链表会出现死循环。
    pNode = SListFind(ptwo, 7);
    pNode2 = SListFind(ptwo, 1);
    pNode2->pNext = pNode;
    //Print(ptwo);

    //计算相遇点
    meet = SListmeet(ptwo);
    if(meet != NULL)
    {
        //printf("是带环的,相遇点的值为%d\n",meet->data);
    }
    //计算环的入口
    circle = SListCircle(ptwo, meet);
    //printf("环入口处的值为%d\n",circle->data);
    //环的长度
    c = SListlen(meet);
    //printf("环的长度为%d\n",c);

    //合并有序链表
    //merge = SListmerge(&pHead, &ptwo);
    //Print(merge);
    //交集
    //intersection = SListintersection(&pHead, &ptwo);
    //Print(intersection);
    //并集
    //Union = SListUnion(&pHead, &ptwo);
    //Print(Union);
    //两个链表是否相交,求交点
    //pCP = SListIsintersect(pHead, ptwo);
    //printf("相交点的值为%d\n", pCP->data);

    //删除倒数第K个节点
    //SListDelK(&ptwo, 6);
    //Print(ptwo);
    //输出
    //Print(pHead);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41804778/article/details/80569506