单链表经典面试题

从尾到头打印单链表

  使用递归从后往前打印

在无头单链表的一个结点前插入一个结点(不能遍历链表)

描述

单链表实现约瑟夫环(JosephCircle)

描述

逆置单链表

方法一:
描述

方法二:
描述

单链表排序(冒泡排序)

  类似于普通数组冒泡排序

合并两个有序链表,合并后任然有序

描述

查找单链表的中间节点,要求只能遍历一次链表

描述

查找单链表的倒数第K个结点,要求只能遍历一次链表

描述

删除链表的倒数第K个结点

描述

判断单链表是否带环?若带环求环的长度和入口

描述

环入口:
描述

判断两链表是否相交(假设链表不带环)

描述

判断两链表是否相交(假设链表可能带环)

描述

求两个已排序单链表中相同数据

描述

复杂链表的复制。一个链表的每个结点,有一个next指针指向下一个结点,还有一个random指针指向链表的一个随机节点或者NULL,要求实现这个复杂链表的复制,返回复制后的新链表

方法一:
描述

方法二:
描述

具体实现代码如下:

部分代码请参照 >单链表基础操作<

①linklist.h

#pragma once

#include <stddef.h>
#include <stdio.h>

typedef char LinkType;

typedef struct LinkNode{
    LinkType data;
    struct LinkNode* next;
}LinkNode;

void LinkListInit(LinkNode** head);            //初始化

void LinkListPrintChar(LinkNode* head, const char* msg);    //打印链表

LinkNode* LinkListPushBack(LinkNode** head, LinkType value);   //尾插

void LinkListPopBack(LinkNode** head);        //尾删

void LinkListPushFront(LinkNode** head, LinkType value);    //头插

void LinkListPopFront(LinkNode** head);     //头删

LinkNode* LinkListFind(LinkNode* head, LinkType to_find);     //查找元素在链表中的位置

void LinkListInsert(LinkNode** head, LinkNode* pos, LinkType value);       //在pos之前插入元素

void LinkListInsertAfter(LinkNode** head, LinkNode* pos, LinkType value);       //在pos之后插入元素

void LinkListErase1(LinkNode** head, LinkNode* pos);           //删除指定位置的元素

void LinkListErase2(LinkNode** head, LinkNode** pos);

void LinkListRemove1(LinkNode** head, LinkType value);          //删除指定值的元素

void LinkListRemove2(LinkNode** head, LinkType value);         

void LinkListRemoveAll(LinkNode** head, LinkType value);          //删除指定值的所有元素

int LinkListEmpty(LinkNode* head);          //判断链表是否为空,为空返回1,否则返回0

size_t LinkListSize(LinkNode* head);        //求链表元素个数


//经典面试题
void LinkListReversePrint(LinkNode* head);      //逆序打印单链表

void LinkListInsertBefore(LinkNode** head, LinkNode* pos, LinkType value);   //不允许遍历链表, 在 pos之前插入

LinkNode* JosephCycle(LinkNode* head, size_t food);     //约瑟夫环

void LinkListReverse(LinkNode** head);     //单链表逆置
void LinkListReverse2(LinkNode** head);

void LinkListBubbleSort(LinkNode* head);     //单链表的冒泡排序

LinkNode* LinkListMerge(LinkNode* head1, LinkNode* head2);     //将两个有序链表, 合并成一个有序链表

LinkNode* FindMidNode(LinkNode* head);      //找到中间节点

LinkNode* FindLastKNode(LinkNode* head, size_t K);       //找到倒数第 K 个节点

void EraseLastKNode(LinkNode** head, size_t K);      //删除倒数第K个节点

LinkNode* HasCycle(LinkNode* head);      //判定单链表是否带环. 如果带环返回1

size_t GetCycleLen(LinkNode* head);       //如果链表带环, 求出环的长度

LinkNode* GetCycleEntry(LinkNode* head);       //如果链表带环, 求出环的入口

LinkNode* HasCross(LinkNode* head1, LinkNode* head2);       //判定两个链表是否相交, 并求出交点(假设链表不带环)

LinkNode* HasCrossWithCycle(LinkNode* head1, LinkNode* head2);       //判定两个链表是否相交(假设链表可能带环)

LinkNode* UnionSet(LinkNode* head1, LinkNode* head2);           //求两个已排序单链表中相同的数据

typedef struct ComplexNode{
    LinkType data;
    struct LinkNode* next;
    struct LinkNode* random;
}ComplexNode;
ComplexNode* CreateComplexNode(LinkType value);

ComplexNode* CopyComplex(ComplexNode* head);          //拷贝复杂链表
ComplexNode* CopyComplex2(ComplexNode* head);          //拷贝复杂链表

②linklist.c

//经典面试题
#include "linklist.h"

#include <stdlib.h>

void LinkListReversePrint(LinkNode* head)      //逆序打印单链表
{
    if (head == NULL)
    {
        return;
    }
    LinkListReversePrint(head->next);
    printf("[%c:%p] ", head->data, head);
}

void LinkListInsertBefore(LinkNode** head, LinkNode* pos, LinkType value)   //不允许遍历链表, 在 pos之前插入
{
    if (head == NULL || pos == NULL)
    {
        return;     //非法输入
    }
    LinkNode* new_node = LinkListCreateNode(pos->data);
    pos->data = value;
    new_node->next = pos->next;
    pos->next = new_node;
    return;
}

LinkNode* JosephCycle(LinkNode* head, size_t food)     //约瑟夫环
{
    if (head == NULL)
    {
        return NULL;
    }
    if (food == 0)
    {
        return NULL;
    }
    LinkNode* cur = head;
    while (cur != cur->next)
    {
        size_t i = 0;
        for (; i < food - 1; ++i)
        {
            cur = cur->next;
        }
        printf("food:[%c]\n", cur->data);
        cur->data = cur->next->data;
        LinkNode* to_delete = cur->next;
        cur->next = to_delete->next;
        LinkListDestroyNode(to_delete);
    }
    return cur;
}

void LinkListReverse(LinkNode** head)     //单链表逆置
{
    if (head == NULL)
    {
        return;   //非法输入
    }
    if (*head == NULL)
    {
        return;     //空链表
    }
    if ((*head)->next == NULL)
    {
        return;     //只有一个元素
    }
    LinkNode* cur = *head;
    while (cur->next != NULL)
    {
        LinkNode* to_delete = cur->next;
        //将当前结点删除
        cur->next = to_delete->next;
        //将这个被删除的结点插入到链表头部
        to_delete->next = *head;
        *head = to_delete;
    }
    return;
}

void LinkListReverse2(LinkNode** head)
{
    if (head == NULL)
    {
        return;   //非法输入
    }
    if (*head == NULL)
    {
        return;     //空链表
    }
    if ((*head)->next == NULL)
    {
        return;     //只有一个元素
    }
    LinkNode* pre = *head;
    LinkNode* cur = (*head)->next;
    pre->next = NULL;
    while (cur != NULL)
    {
        LinkNode* next = cur->next;
        cur->next = pre;        //重置了当前结点的next
        pre = cur;
        cur = next;
    }
    *head = pre;
    return;
}

void Swap(LinkType* a, LinkType* b)
{
    LinkType tmp = *a;
    *a = *b;
    *b = tmp;
}
void LinkListBubbleSort(LinkNode* head)     //单链表的冒泡排序(升序)
{
    if (head == NULL)
    {
        return;
    }
    LinkNode* count = head;
    LinkNode* tail = NULL;
    for (; count != NULL; count = count->next)
    {
        LinkNode* cur = head;
        for (; cur->next != tail; cur = cur->next)
        {
            if (cur->data > cur->next->data)
            {
                Swap(&cur->data, &cur->next->data);
            }
        }
        tail = cur;
    }
}

LinkNode* LinkListMerge(LinkNode* head1, LinkNode* head2)     //将两个有序链表, 合并成一个有序链表
{
    LinkNode* cur1 = head1;
    LinkNode* cur2 = head2;
    LinkNode* new_head = NULL;
    LinkNode* new_tail = NULL;
    while (cur1 != NULL && cur2 != NULL)
    {
        if (cur1->data < cur2->data)
        {
            if (new_head == NULL)
            {
                new_head = new_tail = cur1;
            }
            else
            {
                new_tail->next = cur1;
                new_tail = new_tail->next;
            }
            cur1 = cur1->next;
        }
        else if (cur1->data >= cur2->data)
        {
            if (new_head == NULL)
            {
                new_head = new_tail = cur2;
            }
            else
            {
                new_tail->next = cur2;
                new_tail = new_tail->next;
            }
            cur2 = cur2->next;
        }
    }
    if (cur1 != NULL)
    {
        new_tail->next = cur1;
    }
    else
    {
        new_tail->next = cur2;
    }
    return new_head;
}

LinkNode* FindMidNode(LinkNode* head)      //找到中间节点
{
    LinkNode* slow = head;
    LinkNode* fast = head;
    while (fast != NULL && fast->next != NULL)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}

LinkNode* FindLastKNode(LinkNode* head, size_t K)       //找到倒数第 K 个节点
{
    LinkNode* slow = head;
    LinkNode* fast = head;
    size_t i = 0;
    for (; i < K && fast != NULL; ++i)
    {
        fast = fast->next;
    }
    if (i < K)
    {
        //这种情况表示链表结点小于K,直接返回NULL
        return NULL;
    }
    while (fast != NULL)
    {
        fast = fast->next;
        slow = slow->next;
    }
    return slow;
}

void EraseLastKNode(LinkNode** head, size_t K)      //删除倒数第K个节点
{
    if (head == NULL)
    {
        return;   //非法输入
    }
    if (*head == NULL)
    {
        return;     //空链表
    }
    size_t size = LinkListSize(*head);
    if (size < K)
    {
        //要删除的结点不存在
        return;
    }
    if (size == K)
    {
        //要删除的是头结点
        LinkNode* to_delete = *head;
        *head = (*head)->next;
        LinkListDestroyNode(to_delete);
        return;
    }
    LinkNode* cur = *head;
    size_t i = 0;
    for (; i < size - (K + 1); ++i)
    {
        cur = cur->next;
    }
    LinkNode* to_delete = cur->next;
    cur->next = to_delete->next;
    LinkListDestroyNode(to_delete);
    return;
}

LinkNode* HasCycle(LinkNode* head)      //判定单链表是否带环. 如果带环返回1
{
    LinkNode* slow = head;
    LinkNode* fast = head;
    while (fast != NULL && fast->next != NULL)
    {
        fast = fast->next->next;
        slow = slow->next;
        if (fast == slow)
        {
            return fast;
        }
    }
    return NULL;
}

size_t GetCycleLen(LinkNode* head)       //如果链表带环, 求出环的长度
{
    LinkNode* meet_node = HasCycle(head);
    if (meet_node == NULL)
    {
        return 0;    //链表无环
    }
    size_t count = 1;
    LinkNode* cur = meet_node;
    for (; cur->next != meet_node; cur = cur->next)
    {
        ++count;
    }
    return count;
}

LinkNode* GetCycleEntry(LinkNode* head)       //如果链表带环, 求出环的入口
{
    LinkNode* meet_node = HasCycle(head);
    if (meet_node == NULL)
    {
        return NULL;        //无环,直接返回
    }
    LinkNode* cur1 = head;
    LinkNode* cur2 = meet_node;
    while (cur1 != cur2)
    {
        cur1 = cur1->next;
        cur2 = cur2->next;
    }
    return cur1;
}

LinkNode* HasCross(LinkNode* head1, LinkNode* head2)       //判定两个链表是否相交, 并求出交点
{
    if (head1 == NULL || head2 == NULL)
    {
        return NULL;
    }
    size_t size1 = LinkListSize(head1);
    size_t size2 = LinkListSize(head2);
    LinkNode* cur1 = head1;
    LinkNode* cur2 = head2;
    if (size1 < size2)
    {
        size_t i = 0;
        for (; i < size2 - size1; ++i)
        {
            cur2 = cur2->next;
        }
    }
    else
    {
        size_t i = 0;
        for (; i < size1 - size2; ++i)
        {
            cur1 = cur1->next;
        }
    }
    while (cur1 != cur2)
    {
        cur1 = cur1->next;
        cur2 = cur2->next;
    }
    return cur1;
}

LinkNode* HasCrossWithCycle(LinkNode* head1, LinkNode* head2)       //判定两个链表是否相交(假设链表可能带环)
{
    if (head1 == NULL || head2 == NULL)
    {
        return NULL;
    }
    LinkNode* entry1 = GetCycleEntry(head1);
    LinkNode* entry2 = GetCycleEntry(head2);
    if (entry1 == NULL && entry2 == NULL)
    {
        //1.两个链表都不带环
        return HasCross(head1, head2) != NULL ? 1 : 0;
    }
    else if (entry1 != NULL && entry2 != NULL)
    {
        //2.两链表都带环
        if (entry1 == entry2)
        {
            //相交在环外
            return 1;
        }
        LinkNode* cur = entry1;
        while (cur->next != entry1)
        {
            //相交在环上
            if (cur == entry2)
            {
                return 1;
            }
            cur = cur->next;
        }
        return 0;   //不相交
    }
    else
    {
        //3.一个带环,一个不带环,一定不相交
        return 0;
    }
    return 0;
}

LinkNode* UnionSet(LinkNode* head1, LinkNode* head2)            //求两个已排序单链表中相同的数据
{
    if (head1 == NULL || head2 == NULL)
    {
        return NULL;
    }
    LinkNode* cur1 = head1;
    LinkNode* cur2 = head2;
    LinkNode* new_head = NULL;
    LinkNode* new_tail = NULL;
    while (cur1 != NULL && cur2 != NULL)
    {
        if (cur1->data < cur2->data)
        {
            cur1 = cur1->next;
        }
        else if (cur1->data > cur2->next)
        {
            cur2 = cur2->next;
        }
        else
        {
            //cur1的值与cur2的值相等,将这个元素放到结果中去
            LinkNode* new_node = LinkListCreateNode(cur1->data);
            if (new_head == NULL)
            {
                new_head = new_tail = new_node;
            }
            else
            {
                new_tail->next = new_node;
                new_tail = new_tail->next;
            }
            cur1 = cur1->next;
            cur2 = cur2->next;
        }
    }
    return new_head;
}

ComplexNode* CreateComplexNode(LinkType value)
{
    ComplexNode* ptr = (ComplexNode*)malloc(sizeof(ComplexNode));
    ptr->data = value;
    ptr->next = NULL;
    ptr->random = NULL;
    return ptr;
}

size_t Diff(ComplexNode* src, ComplexNode* dest)
{
    if (src == NULL || dest == NULL)
    {
        return (size_t)-1;
    }
    size_t count = 0;
    while (src != NULL)
    {
        if (src == dest)
        {
            return count;
        }
        ++count;
        src = src->next;
    }
    return (size_t)-1;
}
ComplexNode* Step(ComplexNode* pos, size_t offset)
{
    size_t i = 0;
    for (; i < offset; ++i)
    {
        if (pos == NULL)
        {
            return NULL;
        }
        pos = pos->next;
    }
    return pos;
}
ComplexNode* CopyComplex(ComplexNode* head)          //拷贝复杂链表
{
    if (head == NULL)
    {
        return NULL;        //空链表
    }
    //1.先把链表进行简单复制
    ComplexNode* new_head = NULL;
    ComplexNode* new_tail = NULL;
    ComplexNode* cur = head;
    for (; cur != NULL; cur = cur->next)
    {
        ComplexNode* new_node = CreateComplexNode(cur->data);
        if (new_head == NULL)
        {
            new_head = new_tail = new_node;
        }
        else
        {
            new_tail->next = new_node;
            new_tail = new_tail->next;
        }
    }
    //2.再去依次求每个random指针相对头结点的偏移量
    ComplexNode* new_cur = new_head;
    for (cur = head; cur != NULL && new_cur != NULL; cur = cur->next, new_cur = new_cur->next)
    {
        if (cur->random == NULL)
        {
            new_cur->random = NULL;
            continue;
        }
        //3.根据偏移量,修改每个新链表结点的random指针
        size_t offset = Diff(head, cur->random);
        new_cur->random = Step(head, offset);
    }
    return new_head;
}

ComplexNode* CopyComplex2(ComplexNode* head)          //拷贝复杂链表
{
    //1.遍历旧链表,给每一个结点都创建一个对应的新结点
    //   并将新结点插入到旧结点之后
    ComplexNode* cur = head;
    for (; cur != NULL; cur = cur->next->next)
    {
        ComplexNode* new_node = CreateComplexNode(cur->data);
        new_node->next = cur->next;
        cur->next = new_node;
    }
    //2.再遍历链表,更新每个新结点的random指针
    for (cur = head; cur != NULL; cur = cur->next->next)
    {
        ComplexNode* cur_next = cur->next;
        cur_next->random = cur->random->next;
    }
    //3.再遍历链表,把新结点依次拆下来,组成一个新的链表
    ComplexNode* new_head = NULL;
    ComplexNode* new_tail = NULL;
    for (cur = head; cur != NULL; cur = cur->next)
    {
        ComplexNode* to_delete = cur->next;
        //将结点拆下来
        cur->next = to_delete->next;
        //将这个结点安装到新链表的末尾
        if (new_head == NULL)
        {
            new_head = new_tail = to_delete;
        }
        else
        {
            new_tail->next = to_delete;
            new_tail = new_tail->next;
        }
    }
    return new_head;
}

③test.c

//经典面试题
#include "linklist.h"

#include <windows.h>

#define TEST_HEADER printf("\n========================================%s===========================================\n",__FUNCTION__)

void TestReversePrint()
{
    TEST_HEADER;
    LinkNode* head = NULL;
    LinkListInit(&head);
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'b');
    LinkListPushBack(&head, 'c');
    LinkListPushBack(&head, 'd');
    LinkListPrintChar(head, "尾插四个元素");
    printf("[逆序打印]:");
    LinkListReversePrint(head);
    printf("\n");
}

void TestInsertBefore()
{
    TEST_HEADER;
    LinkNode* head = NULL;
    LinkListInit(&head);
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'b');
    LinkNode* pos_c = LinkListPushBack(&head, 'c');
    LinkListPushBack(&head, 'd');
    LinkListPrintChar(head, "尾插四个元素");
    LinkListInsertBefore(&head, pos_c, 'x');
    LinkListPrintChar(head, "在c之前插入元素x");
}

void TestJosephCycle()
{
    TEST_HEADER;
    LinkNode* head = NULL;
    LinkListInit(&head);
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'b');
    LinkListPushBack(&head, 'c');
    LinkListPushBack(&head, 'd');
    LinkListPushBack(&head, 'e');
    LinkListPushBack(&head, 'f');
    LinkListPushBack(&head, 'g');
    LinkNode* pos = LinkListPushBack(&head, 'h');
    pos->next = head;
    pos = JosephCycle(head, 5);
    printf("JosephCycle: %c\n", pos->data);
}

void TestReverse()
{
    TEST_HEADER;
    LinkNode* head = NULL;
    LinkListInit(&head);
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'b');
    LinkListPushBack(&head, 'c');
    LinkListPushBack(&head, 'd');
    LinkListPushBack(&head, 'e');
    LinkListPushBack(&head, 'f');
    LinkListPrintChar(head, "尾插六个元素");
    LinkListReverse(&head);
    LinkListPrintChar(head, "逆置后的结果");
}

void TestReverse2()
{
    TEST_HEADER;
    LinkNode* head = NULL;
    LinkListInit(&head);
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'b');
    LinkListPushBack(&head, 'c');
    LinkListPushBack(&head, 'd');
    LinkListPushBack(&head, 'e');
    LinkListPushBack(&head, 'f');
    LinkListPrintChar(head, "尾插六个元素");
    LinkListReverse2(&head);
    LinkListPrintChar(head, "逆置后的结果");
}

void TestBubbleSort()
{
    TEST_HEADER;
    LinkNode* head = NULL;
    LinkListInit(&head);
    LinkListPushBack(&head, 'b');
    LinkListPushBack(&head, 'd');
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'f');
    LinkListPushBack(&head, 'e');
    LinkListPushBack(&head, 'c');
    LinkListPrintChar(head, "尾插六个元素");
    LinkListBubbleSort(head);
    LinkListPrintChar(head, "排序后的结果");
}

void TestMerge()
{
    TEST_HEADER;
    LinkNode* head1 = NULL;
    LinkListInit(&head1);
    LinkListPushBack(&head1, 'a');
    LinkListPushBack(&head1, 'd');
    LinkListPushBack(&head1, 'e');
    LinkListPushBack(&head1, 'h');
    LinkListPrintChar(head1, "尾插四个元素");

    LinkNode* head2 = NULL;
    LinkListInit(&head2);
    LinkListPushBack(&head2, 'b');
    LinkListPushBack(&head2, 'c');
    LinkListPushBack(&head2, 'f');
    LinkListPrintChar(head2, "尾插三个元素");

    LinkNode* new_head = LinkListMerge(head1, head2);
    LinkListPrintChar(new_head, "合并后的结果");
}

void TestMidNode()
{
    TEST_HEADER;
    LinkNode* head = NULL;
    LinkListInit(&head);
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'b');
    LinkListPushBack(&head, 'c');
    LinkListPushBack(&head, 'd');
    LinkListPushBack(&head, 'e');
    LinkListPrintChar(head, "尾插五个元素");
    LinkNode* mid = FindMidNode(head);
    printf("mid expect c, actual %c\n", mid->data);
}

void TestLastK()
{
    TEST_HEADER;
    LinkNode* head = NULL;
    LinkListInit(&head);
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'b');
    LinkListPushBack(&head, 'c');
    LinkListPushBack(&head, 'd');
    LinkListPushBack(&head, 'e');
    LinkListPrintChar(head, "尾插五个元素");
    LinkNode* node = FindLastKNode(head, 2);
    printf("last 2 node expect d,actual %c\n", node->data);
}

void TestEraseLastK()
{
    TEST_HEADER;
    LinkNode* head = NULL;
    LinkListInit(&head);
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'b');
    LinkListPushBack(&head, 'c');
    LinkListPushBack(&head, 'd');
    LinkListPushBack(&head, 'e');
    LinkListPrintChar(head, "尾插五个元素");
    EraseLastKNode(&head, 2);
    LinkListPrintChar(head, "删除d 后结果");
}

void TestHasCycle()
{
    TEST_HEADER;
    LinkNode* head = NULL;
    LinkListInit(&head);
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'b');
    LinkListPushBack(&head, 'c');
    LinkListPushBack(&head, 'd');
    LinkNode* pos = LinkListPushBack(&head, 'e');
    pos->next = head;
    printf("list has cycle: expect 1, actual %p\n", HasCycle(head));
}

void TestCycleLen()
{
    TEST_HEADER;
    LinkNode* head = NULL;
    LinkListInit(&head);
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'b');
    LinkListPushBack(&head, 'c');
    LinkListPushBack(&head, 'd');
    LinkNode* pos = LinkListPushBack(&head, 'e');
    pos->next = head;
    printf("cycle len expect 5, actual %lu\n", GetCycleLen(head));
}

void TestGetEntry()
{
    TEST_HEADER;
    LinkNode* head = NULL;
    LinkListInit(&head);
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'b');
    LinkNode* pos_c = LinkListPushBack(&head, 'c');
    LinkListPushBack(&head, 'd');
    LinkListPushBack(&head, 'e');
    LinkListPushBack(&head, 'f');
    LinkNode* pos_g = LinkListPushBack(&head, 'g');
    pos_g->next = pos_c;
    printf("cycle entry expect c,actual %c\n", GetCycleEntry(head)->data);
}

void TestHasCross()
{
    TEST_HEADER;
    LinkNode* head1 = NULL;
    LinkListInit(&head1);
    LinkListPushBack(&head1, 'a');
    LinkNode* pos_d = LinkListPushBack(&head1, 'd');
    LinkListPushBack(&head1, 'e');
    LinkListPushBack(&head1, 'h');

    LinkNode* head2 = NULL;
    LinkListInit(&head2);
    LinkListPushBack(&head2, 'b');
    LinkListPushBack(&head2, 'c');
    LinkNode* pos_f = LinkListPushBack(&head2, 'f');
    pos_f->next = pos_d;

    LinkNode* cross = HasCross(head1, head2);
    printf("cross expect d, actual %c\n", cross->data);
}

void TestHasCrossWithCycle()
{
    TEST_HEADER;
    LinkNode* head1 = NULL;
    LinkListInit(&head1);
    LinkNode* pos_a = LinkListPushBack(&head1, 'a');
    LinkNode* pos_b = LinkListPushBack(&head1, 'b');
    LinkListPushBack(&head1, 'c');
    LinkNode* pos_d = LinkListPushBack(&head1, 'd');
    pos_d->next = pos_b;

    LinkNode* head2 = NULL;
    LinkListInit(&head2);
    LinkListPushBack(&head2, 'e');
    LinkListPushBack(&head2, 'f');
    LinkNode* pos_g = LinkListPushBack(&head2, 'g');
    pos_g->next = pos_a;

    int ret = HasCrossWithCycle(head1, head2);
    printf("ret expect 1, actual %d\n", ret);
}

void TestUnionSet()
{
    TEST_HEADER;
    LinkNode* head1 = NULL;
    LinkListInit(&head1);
    LinkListPushBack(&head1, 'a');
    LinkListPushBack(&head1, 'd');
    LinkListPushBack(&head1, 'e');
    LinkListPushBack(&head1, 'h');
    LinkListPrintChar(head1, "创建链表一");

    LinkNode* head2 = NULL;
    LinkListInit(&head2);
    LinkListPushBack(&head2, 'b');
    LinkListPushBack(&head2, 'c');
    LinkListPushBack(&head2, 'd');
    LinkListPushBack(&head2, 'e');
    LinkListPushBack(&head2, 'f');
    LinkListPushBack(&head2, 'h');
    LinkListPrintChar(head2, "创建链表二");

    LinkNode* new_head = UnionSet(head1, head2);
    LinkListPrintChar(new_head, "两链表交集");
}

void TestComplexCopy()
{
    TEST_HEADER;
    ComplexNode* a = CreateComplexNode('a');
    ComplexNode* b = CreateComplexNode('b');
    ComplexNode* c = CreateComplexNode('c');
    ComplexNode* d = CreateComplexNode('d');
    a->next = a;
    b->next = c;
    c->next = d;
    d->next = NULL;
    a->random = c;
    b->random = a;
    c->random = NULL;
    d->random = d;

    ComplexNode* new_head = CopyComplex2(a);
    printf("new_head:%p\n", new_head);
}

int main()
{
    //经典面试题
    TestReversePrint();
    TestInsertBefore();
    TestJosephCycle();
    TestReverse();
    TestReverse2();
    TestBubbleSort();
    TestMerge();
    TestMidNode();
    TestLastK();
    TestEraseLastK();
    TestHasCycle();
    TestCycleLen();
    TestGetEntry();
    TestHasCross();
    TestHasCrossWithCycle();
    TestUnionSet();
    TestComplexCopy();
    system("pause");
    return 0;
}

结果:

描述
描述
描述
描述

顺序表与链表比较:

  • 顺序表支持随机访问,单链表不支持随机访问
  • 顺序表插入/删除数据效率很低,时间复杂度为O(N)(除尾插尾删),单链表插入/删除效率更高,时间复杂度为O(1)
  • 顺序表的CPU高速缓存效率更高,单链表CPU高速缓存效率低

猜你喜欢

转载自blog.csdn.net/adorable_/article/details/79609513