数据结构_链表问题(倒序打印、相交、带环)

问题集锦

从尾到头打印单链表
删除一个无头单链表的非尾节点(不能遍历链表)
在无头单链表的一个节点前插入一个节点(不能遍历链表)
单链表实现约瑟夫环(JosephCircle)
逆置/反转单链表
单链表排序(冒泡排序&快速排序)
合并两个有序链表,合并后依然有序
查找单链表的中间节点,要求只能遍历一次链表
查找单链表的倒数第k个节点,要求只能遍历一次链表
删除链表的倒数第K个结点
判断单链表是否带环?若带环,求环的长度?求环的入口点?并计算
每个算法的时间复杂度&空间复杂度。
判断两个链表是否相交,若相交,求交点。(假设链表不带环)
判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
复杂链表的复制。一个链表的每个节点,有一个指向next指针指向
下一个节点,还有一个random指针指向这个链表中的一个随机节点
或者NULL,现在要求实现复制这个链表,返回复制后的新链表。
求两个已排序单链表中相同的数据。

头文件代码

#ifndef __CODE_H__
#define __CODE_H__

#include 
#include 


typedef int DataType;

typedef struct SListNode
{
    DataType _a;
    struct SListNode* _next;
}SListNode;


void SListPushBack(SListNode* pHead, DataType x);
void SListPrint(SListNode* pHead);

void SLitsPrintTailToHead(SListNode* pHead);
void SListPrintTailToHeadR(SListNode* pHead);

void SListDelNonTailNode(SListNode* pos);
void SListInsertFrontNode(SListNode* pos, DataType x);
SListNode* SListJosephCircle(SListNode* pHead, int k);
SListNode* SListReverse(SListNode* list);

// 升序
void SListBubbleSort(SListNode* list); 
SListNode* SListMerge(SListNode* list1, SListNode* list2);

SListNode* SListFindMidNode(SListNode* list);
SListNode* SListFindTailKNode(SListNode* list, size_t k);

// 链表带环问题 
SListNode* SListIsCycle(SListNode* list);
int SListCycleLen(SListNode* meetNode);
SListNode* SListEntryNode(SListNode* list, SListNode* meetNode);

// 链表相交问题 
SListNode* SListIsCrossNode(SListNode* list1, SListNode* list2);
SListNode* SListCrossNode(SListNode* list1, SListNode* list2);

// 复杂链表复制 
typedef struct ComplexListNode
{
    int _data;
    struct ComplexListNode* _next;
    struct ComplexListNode* _random;
}ComplexListNode;

ComplexListNode* CopyComplexList(ComplexListNode* list);

void UnionSet(SListNode* l1, SListNode* l2);



#endif//__CODE_H__

函数功能实现代码

#include <stdio.h>
#include "code.h"

void SListPushBack(SListNode* pHead, DataType x)
{
    assert(pHead);
    while (pHead->_next != NULL)
    {
        pHead = pHead->_next;
    }
    pHead->_next = (SListNode*)malloc(sizeof(SListNode));
    pHead = pHead->_next;
    pHead->_a = x;
    pHead->_next = NULL;
}
void SListPrint(SListNode* pHead)
{
    //assert(pHead);
    while (pHead != NULL)
    {
        printf("%d ", pHead->_a);
        pHead = pHead->_next;
    }
    printf("\n");
}

void SLitsPrintTailToHead(SListNode* pHead)
{
    assert(pHead);

    SListNode* start = pHead;
    if (start->_next == NULL)
    {
        printf("%d ", start->_a);
        return;
    }
    else
    {
        SLitsPrintTailToHead(start->_next);
        printf("%d ", start->_a);
    }
}

void SListPrintTailToHeadR(SListNode* pHead)
{
    assert(pHead);

    SListNode* p1 = pHead;
    SListNode* p2 = p1->_next;

}

void SListDelNonTailNode(SListNode* pos)
{
    assert(pos);

    if (NULL == pos->_next)
    {
        return;
    }
    else
    {
        SListNode* pNode=pos->_next;
        pos->_a = pos->_next->_a;
        pos->_next = pNode->_next;
        free(pNode);
        pNode = NULL;
    }
}

void SListInsertFrontNode(SListNode* pos, DataType x)
{
    assert(pos);

    SListNode* pNode=(SListNode*)malloc(sizeof(SListNode));
    pNode->_a = pos->_a;
    pNode->_next = pos->_next;
    pos->_next = pNode;
    pos->_a = x;
}

SListNode* SListJosephCircle(SListNode* pHead, int k)
{
    assert(pHead);
    assert(k > 0);

    SListNode* p1 = pHead;
    SListNode* p2 = pHead;
    while (p2 != p2->_next)
    {
        for (int i = 0; i < k-1; i++)
        {
            p1 = p2;
            p2 = p2->_next;
        }
        p1->_next = p2->_next;
        free(p2);
        p2 = p1->_next; 
    }
    return p2;
}

SListNode* SListReverse(SListNode* list)
{
    assert(list);
    assert(list->_next);

    SListNode* p1 = list;
    SListNode* p2 = p1->_next;
    SListNode* p3 = p2->_next;

    p1->_next = NULL;
    while (p2 != NULL)
    {
        p2->_next = p1;
        p1 = p2;
        p2 = p3;
        if (p3 != NULL)
        {
            p3 = p3->_next;
        }
    }
    return p1;
}




SListNode* SListFindMidNode(SListNode* list)
{
    assert(list);

    SListNode* pfast = list;
    SListNode* pslow = list;
    while (pfast->_next != NULL && pfast!=NULL)
    {
        pfast = pfast->_next->_next;
        pslow = pslow->_next;
    }
    return pslow;
}

SListNode* SListFindTailKNode(SListNode* list, size_t k)    //找倒数第K个结点
{
    assert(list);

    SListNode* pfast = list;
    SListNode* pslow = list;
    for (size_t i = 0; i < k - 1; i++)
    {
        pfast = pfast->_next;
    }
    while (pfast->_next != NULL)
    {
        pfast = pfast->_next;
        pslow = pslow->_next;
    }
    return pslow;
}

SListNode* SListIsCycle(SListNode* list)      //判断是否带环并找相遇结点
{
    assert(list);
    SListNode* pfast = list;
    SListNode* pslow = list;
    while (pfast->_next != NULL && pfast != NULL)
    {
        pfast = pfast->_next->_next;
        pslow = pslow->_next;
        if (pfast == pslow)
        {
            return pslow;
        }
    }
    return NULL;
}

int SListCycleLen(SListNode* meetNode)  //求环的长度
{
    assert(meetNode);

    int i = 1;
    SListNode* cur = meetNode->_next;
    while (cur != meetNode)
    {
        cur = cur->_next;
        i++;
    }
    return i;
}
//2l+2x=l+nq+x
//l = nq - x
SListNode* SListEntryNode(SListNode* list, SListNode* meetNode)  //求入口点  
{
    assert(list);
    assert(meetNode);
    while (list != meetNode)
    {
        list = list->_next;
        meetNode = meetNode->_next;
    }
    return list;
}


SListNode* SListIsCrossNode(SListNode* list1, SListNode* list2)  //假设链表不带环
{
    assert(list1);
    assert(list2);

    SListNode* tail1 = list1;
    SListNode* tail2 = list2;
    SListNode* meetNode = NULL;
    if (list1 == list2)
    {
        return NULL;
    }
    while (tail1->_next != NULL)
    {
        tail1 = tail1->_next;
    }
    tail1->_next = list1;
    meetNode = SListIsCycle(list2);
    tail2 = SListEntryNode(list2, meetNode);
    return tail2;
}

SListNode* SListCrossNode(SListNode* list1, SListNode* list2)  //假设链表带环,则都带环
{
    assert(list1);
    assert(list2);

    SListNode* tail1 = list1;
    SListNode* tail2 = list2;
    SListNode* start = list2;
    int temp = 0;
    tail1 = SListEntryNode(list1, SListIsCycle(list1));
    tail2 = SListEntryNode(list2, SListIsCycle(list2));
    while (tail1 != start)
    {
        start = start->_next;
        if (start == tail2)
        {
            temp++;
        }
        if (temp == 2)
        {
            return NULL;
        }
    }
    if (tail1 != tail2)
    {
        return tail1;
    }
    tail1->_next = list1;
    tail2 = SListEntryNode(list2, SListIsCycle(list2));
    return tail2;
}

ComplexListNode* CopyComplexNode(ComplexListNode* list)   //复制结点
{
    assert(list);

    ComplexListNode* tail = (ComplexListNode*)malloc(sizeof(ComplexListNode));
    tail->_data = list->_data;
    tail->_next = list->_next;
    tail->_random = list->_random;
    return tail;
}

void ChangeComplexList(ComplexListNode* list)    //把每个复制的结点放在相同结点后面组成新的链表
{
    assert(list);

    ComplexListNode* temp = NULL;
    ComplexListNode* tail1 = list;
    ComplexListNode* tail2 = tail1->_next;
    while (tail1 != NULL)
    {
        temp = CopyComplexNode(tail1);
        tail1->_next = temp;
        temp->_next = tail2;
        tail1 = tail2;
        if (tail2 != NULL)
        {
            tail2 = tail2->_next;
        }
    }
}

ComplexListNode* CopyComplexList(ComplexListNode* list)
{
    assert(list);

    ComplexListNode* tail = NULL;
    ComplexListNode* list1 = list;
    ComplexListNode* list2 = NULL;
    ComplexListNode* temp = NULL;
    ChangeComplexList(list1);

    list2 = list1->_next;
    temp = list2;

    while (list2 != NULL)             //让复制的结点随机指针指向对应复制的结点
    {
        if (list2->_random != NULL)
        {
            list2->_random = list2->_random->_next;
        }

        list2 = list2->_next;
    }
    list2 = temp;

    while (list2->_next != NULL)      //分开两个链表
    {
        tail = list2->_next;
        list1->_next = tail;
        list2->_next = tail->_next;
        list1 = tail;
        list2 = tail->_next;
    }
    list1->_next = NULL;   //最后只要断开最后两个结点就可以了
    return temp;
}


void UnionSet(SListNode* list1, SListNode* list2)
{
    assert(list1);
    assert(list2);

    while (list1 != NULL && list2 != NULL)
    {
        if (list1->_a == list2->_a)
        {
            printf("%d ", list1->_a);
            list1 = list1->_next;
            list2 = list2->_next;
        }
        else if (list1->_a > list2->_a)
        {
            list2 = list2->_next;
        }
        else
        {
            list1 = list1->_next;
        }
    }
}

测试用例

#include <stdio.h>
#include "code.h"

SListNode* pHead = NULL;
SListNode* pHead2 = NULL;
ComplexListNode* pNode = NULL;

void test(void)
{
    pHead = (SListNode*)malloc(sizeof(SListNode));
    pHead->_a = 0;
    pHead->_next = NULL;

    SListPushBack(pHead, 1);
    SListPushBack(pHead, 2);
    SListPushBack(pHead, 3);
    SListPushBack(pHead, 4);
    SListPushBack(pHead, 5);
    SListPushBack(pHead, 6);
}

void test1(void)
{
    SListNode* pos = pHead->_next->_next;

    SListPrint(pHead);
    SLitsPrintTailToHead(pHead);
    printf("\n");

    SListDelNonTailNode(pos);
    SListPrint(pHead);
    SListInsertFrontNode(pos, 0);
    SListPrint(pHead);
}

void test2(void)
{
    SListNode* start = pHead;
    while (start->_next != NULL)
    {
        start = start->_next;
    }
    start->_next = pHead;
    start=SListJosephCircle(pHead, 3);
    printf("%d\n", start->_a);
}

void test3(void)
{
    pHead=SListReverse(pHead);
    SListPrint(pHead);
}


void test5(void)
{
    SListNode* start = SListFindMidNode(pHead);
    printf("%d\n", start->_a);
    start=SListFindTailKNode(pHead, 3);
    printf("%d\n", start->_a);
}

void test6(void)
{
    int size = 0;
    SListNode* tail = pHead;
    SListNode* meetNode = NULL;
    SListPushBack(pHead, 7);
    SListPushBack(pHead, 8);
    SListPushBack(pHead, 9);
    SListPushBack(pHead, 10);

    meetNode = SListIsCycle(pHead);
    if (meetNode == NULL)
        printf("不带环\n");

    while (tail->_next != NULL)
    {
        tail = tail->_next;
    }
    tail->_next = pHead->_next->_next->_next;
    meetNode = SListIsCycle(pHead);
    size = SListCycleLen(meetNode);
    tail = SListEntryNode(pHead, meetNode);
    printf("%d %d\n", size, tail->_a);
}

void test7(void)
{
    SListNode* tail = pHead;
    SListNode* temp = NULL;
    pHead2 = (SListNode*)malloc(sizeof(SListNode));
    pHead2->_a = 10;
    pHead2->_next = NULL;

    SListPushBack(pHead, 7);
    SListPushBack(pHead, 8);
    SListPushBack(pHead, 9);
    SListPushBack(pHead, 10);

    SListPushBack(pHead2, 11);
    SListPushBack(pHead2, 12);
    SListPushBack(pHead2, 13);

    pHead2->_next->_next->_next->_next = pHead->_next->_next;
    while (tail->_next != NULL)
    {
        tail = tail->_next;
    }
    tail->_next = pHead->_next->_next->_next;
    temp = SListCrossNode(pHead, pHead2);
    if (temp != NULL)
    {
        printf("%d\n", temp->_a);
    }
}

void test8(void)
{
    pNode = (ComplexListNode*)malloc(sizeof(ComplexListNode));
    pNode->_data = 0;
    ComplexListNode* pNode1 = (ComplexListNode*)malloc(sizeof(ComplexListNode));
    pNode1->_data = 1;
    ComplexListNode* pNode2 = (ComplexListNode*)malloc(sizeof(ComplexListNode));
    pNode2->_data = 2;
    ComplexListNode* pNode3 = (ComplexListNode*)malloc(sizeof(ComplexListNode));
    pNode3->_data = 3;
    ComplexListNode* pNode4 = (ComplexListNode*)malloc(sizeof(ComplexListNode));
    pNode4->_data = 4;
    ComplexListNode* pNewNode = NULL;
    pNode->_next = pNode1;
    pNode->_random = pNode2;
    pNode1->_next = pNode2;
    pNode1->_random = pNode4;
    pNode2->_next = pNode3;
    pNode2->_random = NULL;
    pNode3->_next = pNode4;
    pNode3->_random = pNode1;
    pNode4->_next = NULL;
    pNode4->_random = pNode2;

    pNewNode = CopyComplexList(pNode);

    while (pNode != NULL)
    {
        if (pNode->_random != NULL)
        {
            printf("%d ", pNode->_random->_data);
        }
        printf("%d\n", pNode->_data);
        pNode = pNode->_next;
    }

    while (pNewNode != NULL)
    {

        if (pNewNode->_random != NULL)
        {
            printf("%d ", pNewNode->_random->_data);
        }
        printf("%d\n", pNewNode->_data);
        pNewNode = pNewNode->_next;
    }

}

void test9(void)
{
    pHead2 = (SListNode*)malloc(sizeof(SListNode));
    pHead2->_a = 1;
    pHead2->_next = NULL;

    SListPushBack(pHead2, 3);
    SListPushBack(pHead2, 5);
    SListPushBack(pHead2, 7);

    UnionSet(pHead, pHead2);
}

int main()
{
    //test();

    //test1();

    //test2();

    //test3();

    //test5();

    //test6();

    //test7();

    //test8();

    //test9();
    return 0;
}

你可能感兴趣的:(数据结构)