链表面试题

1. 从尾到头打印单链表

//时间复杂度O(N*N),空间复杂度O(1)
//非递归
void  SListPrintTailToHead(SListNode* pHead)
{
    SListNode* tail = NULL;

    while (tail != pHead)//非空
    {
        SListNode* cur = pHead;
        while (cur->_next != tail)
        {
            cur = cur->_next;
        }
        printf("%d ", cur->_data);
        tail = cur;
    }
    printf("\n");
}

//时间复杂度O(N),空间复杂度O(1)
//递归
void  SListPrintTailToHeadR(SListNode* pHead)//递归
{
    if (pHead == NULL)
        return;
    SListPrintTailToHeadR(pHead->_next);
    printf("%d ", pHead->_data);

}

void TestSListPrintTailToHead()
{
    SListNode* list = NULL;

    SListPushFront(&list, 4);
    SListPushFront(&list, 3);
    SListPushFront(&list, 2);
    SListPushFront(&list, 1);

    SListPrint(list);

    //SListPrintTailToHead(list);
    SListPrintTailToHeadR(list);
    printf("\n");
}

这里写图片描述

2. 删除一个无头单链表的非尾节点(不能遍历链表)

void DelNonTailNode(SListNode* pHead, SListNode* pos)
{
    //替换法
    SListNode* next = NULL;
    assert(pos&&pos->_next);
    next = pos->_next;
    pos->_data = next->_data;
    pos->_next = next->_next;
    free(next);
}

void TestDelNonTailNode()
{
    SListNode* list = NULL;
    SListNode* pos = NULL;

    SListPushFront(&list, 4);
    SListPushFront(&list, 3);
    SListPushFront(&list, 2);
    SListPushFront(&list, 1);

    SListPrint(list);

    pos = SListFind(list,3);
    DelNonTailNode(list, pos);

    SListPrint(list);
}

这里写图片描述

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

void InsertFrontNode(SListNode* pos,DataType x)
{
    //替换法插入
    SListNode* next = NULL;
    SListNode* newNode = NULL;
    assert(pos);
    next = pos->_next;

    newNode = BuySListNode(pos->_data);
    pos->_next = newNode;
    newNode->_next = next;
    pos->_data = x;
}

void TestInsertFrontNode()
{
    SListNode* list = NULL;
    SListNode* pos = NULL;

    SListPushFront(&list, 4);
    SListPushFront(&list, 3);
    SListPushFront(&list, 2);
    SListPushFront(&list, 1);

    SListPrint(list);
    pos = SListFind(list, 3);
    InsertFrontNode(pos,6);
    SListPrint(list);
}

这里写图片描述

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

SListNode* JosephCircle(SListNode* pHead, int k)
{
    SListNode* cur = pHead;
    SListNode* next = NULL;
    while (cur->_next != cur)//循环继续条件
    {
        int count = k;
        while (--count)
        {
            cur = cur->_next;
        }
        //替换法
        next = cur->_next;
        cur->_data = next->_data;
        cur->_next = next->_next;
        free(next);
    }
    return cur;
}
void TestJosephCircle()
{
    SListNode* list = NULL;
    SListNode* tail = NULL;

    SListPushBack(&list, 1);
    SListPushBack(&list, 2);
    SListPushBack(&list, 3);
    SListPushBack(&list, 4);

    SListPrint(list);
    tail = SListFind(list, 4);
    tail->_next = list;
    printf("最后的幸存者是:%d\n",JosephCircle(list,3)->_data);

}

这里写图片描述

5.逆置/反转单链表


void Reverselist(SListNode** ppList)
{
    SListNode* n1 = NULL;
    SListNode* n2 = NULL;
    SListNode* n3 = NULL;
    if (*ppList==NULL || (*ppList)->_next == NULL)
        return;
    n1 = *ppList;
    n2 = n1->_next;
    n3 = n2->_next;
    //逆置
    n1->_next = NULL;
    while (n2)
    {
        n2->_next = n1;
        n1 = n2;
        n2 = n3;

        if (n3!=NULL)
            n3 = n3->_next;
    }
    *ppList = n1;
}

//创建新节点
SListNode* Reverselist1(SListNode* list)
{
    SListNode* cur = list;
    SListNode* newList = NULL;
    while (cur)
    {
        SListNode* next = cur->_next;
        cur->_next = newList;
        newList = cur;
        cur = next ;
    }
    return newList;
}
void TestReverselist()
{
    SListNode* list = NULL;
    SListNode* newList = NULL;

    SListPushBack(&list, 1);
    SListPushBack(&list, 2);
    SListPushBack(&list, 3);
    SListPushBack(&list, 4);

    SListPrint(list);

    //Reverselist(&list);
    newList = Reverselist1(list);
    SListPrint(newList);
}

这里写图片描述

6.单链表排序(冒泡排序&快速排序)

//冒泡排序

void SListBubbleSort(SListNode* list)
{

    SListNode* tail = NULL;
    while (tail!=list)
    {
        SListNode* cur = list;
        SListNode* next = cur->_next;
        int exchange = 0;//判断是否进行交换,如果已经有序,直接退出
        while (next != tail)
        {

            if (cur->_data > next->_data)
            {
                DataType tmp = cur->_data;
                cur->_data = next->_data;
                next->_data = tmp;
                exchange = 1;
            }
            cur = cur->_next;
            next = next->_next;
        }
        if (exchange = 0)
        {
            break;
        }
        tail = cur;//打印结点
    }

}

void TestSListBubbleSort()
{
        SListNode* list = NULL;
        SListPushBack(&list, 10);
        SListPushBack(&list, 22);
        SListPushBack(&list, 3);
        SListPushBack(&list, 40);
        SListPushBack(&list, 5);

        SListBubbleSort(list);
        SListPrint(list);
}

7.合并两个有序链表,合并后依然有序

//升序
SListNode* SListMerge(SListNode* list1, SListNode* list2)
{
    //尾插
    SListNode* list = NULL;
    SListNode* tail = NULL;

    //去较小的一个节点做开头
    if (list1->_data < list2->_data)
    {
        tail = list = list1;
        list1 = list1->_next;
    }
    else
    {
        tail = list = list2;
        list1 = list2->_next;
    }

    //尾插
    while (list1&&list2)
    {
        if (list1->_data < list2->_data)
        {
            tail->_next = list1;
            list1 = list1->_next;
        }
        else
        {
            tail->_next = list2;
            list2 = list2->_next;
        }
        tail = tail->_next;
    }
    if (list1)
        tail->_next = list1;
    if (list2)
        tail->_next = list2;
    return list;
}

void TestSListMerge()
{
    SListNode* list1 = NULL;
    SListNode* list2 = NULL;
    SListNode* list = NULL;

    SListPushBack(&list1, 1);
    SListPushBack(&list1, 3);
    SListPushBack(&list1, 3);
    SListPushBack(&list1, 5);
    SListPushBack(&list1, 9);
    SListPrint(list1);

    SListPushBack(&list2, 2);
    SListPushBack(&list2, 3);
    SListPushBack(&list2, 4);
    SListPushBack(&list2, 6);
    SListPushBack(&list2, 8);
    SListPrint(list2);

    list = SListMerge(list1, list2);
    SListPrint(list);

}

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

//定义两个指针,slow,fastslow一次走一格,fast一次走两格当fast走到尾时,slow位于中间节点
SListNode* FindMidNode(SListNode* list)
{
    SListNode* fast = NULL;
    SListNode* slow = NULL;
    fast = slow = list;
    while (fast&&fast->_next)
    {
        slow = slow->_next;
        fast = fast->_next->_next;
    }
    return slow;

}

void TestFindMidNode()
{
    SListNode* list = NULL;
    SListNode* mid = NULL;

    SListPushBack(&list, 1);
    SListPushBack(&list, 2);
    SListPushBack(&list, 3);
    SListPushBack(&list, 4);
    SListPushBack(&list, 5);
    SListPrint(list);
    mid = FindMidNode(list);
    printf("中间节点是:%d\n", mid->_data);
}

这里写图片描述

9.查找单链表的倒数第k个节点,要求只能遍历一次链表

SListNode* FindTailKNode(SListNode* list, size_t k)
{
    SListNode* fast = NULL;
    SListNode* slow = NULL;
    fast = list;
    slow = list;
    while (k--)
    {
        if (fast==NULL)//判空
            return NULL;
        fast = fast->_next;
    }
    while (fast)
    {
        slow = slow->_next;
        fast = fast->_next;
    }
    return slow;

}

这里写图片描述
10.删除链表的倒数第K个结点

void DelTailKNode(SListNode* list)
{
    SListNode* Del = NULL;
    SListNode* prev = NULL;
    SListNode* next = NULL;

    Del = FindTailKNode(list, 2);
    prev = list;
    while (prev->_next != Del)
    {
        prev = prev->_next;
    }
    next = prev->_next;
    prev->_next = Del->_next;
    Del->_data = next->_data;
    free(Del);

}
void TestFindTailKNode()
{
    SListNode* list = NULL;
    SListNode* kNode = NULL;
    SListNode* Del = NULL;

    SListPushBack(&list, 1);
    SListPushBack(&list, 2);
    SListPushBack(&list, 3);
    SListPushBack(&list, 4);
    SListPushBack(&list, 5);
    SListPrint(list);
    DelTailKNode(list);
    SListPrint(list);

    //kNode = FindTailKNode(list, 2);

    //printf("倒数第k个节点: %d\n", kNode->_data);
}

11.判断单链表是否带环?

若带环,求环的长度?求环的入口点?并计算每个算法的时间复杂度&空间复杂度

SListNode* IsCycle(SListNode* list)
{
    SListNode* fast = NULL;
    SListNode* slow = NULL;
    fast = list;
    slow = list;
    while (fast&&fast->_next)
    {
        slow = slow->_next;
        fast = fast->_next->_next;
        if (slow == fast)
            return slow;
    }
    return NULL;
}

int GetCycleLen(SListNode* meet)
{
    int n = 1;
    SListNode* cur = meet;
    while (cur->_next != meet)
    {
        n++;
        cur = cur->_next;
    }
    return n;

}

SListNode* GetEntryNode(SListNode* list, SListNode* meet)
{
    while (list != meet)
    {
        list = list->_next;
        meet = meet->_next;
    }
    return list;
}
void TestIsCycle()
{
    SListNode* list = NULL;
    SListNode* meet = NULL;
    SListNode* tail = NULL;
    SListNode* entry = NULL;
    SListPushBack(&list, 1);
    SListPushBack(&list, 2);
    SListPushBack(&list, 3);
    SListPushBack(&list, 4);
    SListPushBack(&list, 5);
    SListPushBack(&list, 6);

    printf("IsCycle? %d\n",IsCycle(list));
    //构造环
    tail = SListFind(list, 6);
    entry = SListFind(list, 3);
    tail->_next = entry;
    meet = IsCycle(list);
    printf("IsCycle?:%d\n", meet->_data);
    printf("Cycle Len?:%d\n", GetCycleLen(meet));
    printf("Cycle Entry?:%d\n", GetEntryNode(list, meet)->_data);
}

这里写图片描述

12.判断两个链表是否相交

,若相交,求交点。(假设链表不带环)
//判断两个链表是否相交,若相交,求交点。(假设链表可能带环)

int IsCross(SListNode* list1, SListNode* list2)
{
    while (list1&&list1->_next)
    {
        list1 = list1->_next;
    }
    while (list2&&list2->_next)
    {
        list2 = list2->_next;
    }
    if (list1 == list2&&list1 != NULL)
    {
        return 1;
    }
    else
        return 0;
}
SListNode* GetCrossNode(SListNode* list1, SListNode* list2)
{
    SListNode* longlist = NULL;
    SListNode* shortlist = NULL;
    SListNode* cur1 = list1;
    SListNode* cur2 = list2;
    int n1 = 0;
    int n2 = 0;
    int gap = 0;
    while (cur1)
    {
        cur1 = cur1->_next;
        n1++;
    }
    while (cur2)
    {
        cur2 = cur2->_next;
        n2++;
    }
    longlist = list1;
    shortlist = list2;
    if (n1 < n2)
    {
        longlist = list2;
        shortlist = list1;
    }
    gap = abs(n1 - n2);//绝对值
    while (gap--)
    {
        longlist = longlist->_next;
    }
    while (shortlist != longlist)
    {
        shortlist = shortlist->_next;
        longlist = longlist->_next;
    }
    return shortlist;
}


void TestCrossNode()
{
    SListNode* node11, *node22;
    SListNode* node1 = BuySListNode(1);
    SListNode* node2 = BuySListNode(2);
    SListNode* node3 = BuySListNode(3);
    SListNode* node4 = BuySListNode(4);
    SListNode* node5 = BuySListNode(5);
    node1->_next = node2;
    node2->_next = node3;
    node3->_next = node4;
    node4->_next = node5;

    node11 = BuySListNode(11);
    node22 = BuySListNode(22);
    node11->_next = node22;
    node22->_next = node4;
    printf("Is Cross?%d\n", IsCross(node1, node11));
    printf("Cross Node?%d\n", GetCrossNode(node1, node11)->_data);
}

13.求两个已排序单链表中相同的数据。

void UnionSet(SListNode* list1, SListNode* list2)
{
    while (list1&&list2)
    {
        if (list1->_data > list2->_data)
        {
            list2 = list2->_next;
        }
        else if (list1->_data < list2->_data)
        {
            list1 = list1->_next;
        }
        else
        {
            printf("相同的数据:%d\n", list1->_data);

        list1 = list1->_next;
        list2 = list2->_next;
        }
    }
    printf("\n");
}
void TestUnionSet()
{
    SListNode* list1 = NULL;
    SListNode* list2 = NULL;
    SListPushBack(&list1, 1);
    SListPushBack(&list1, 3);
    SListPushBack(&list1, 4);
    SListPushBack(&list1, 5);
    SListPushBack(&list1, 6);

    SListPushBack(&list2, 2);
    SListPushBack(&list2, 3);
    SListPushBack(&list2, 5);
    SListPushBack(&list2, 7);
    SListPushBack(&list2, 9);

    UnionSet(list1, list2);
}

14.复杂链表的复制。

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

typedef struct ComplexNode
{
    int _data;
    struct ComplexNode* _next;
    struct ComplexNode* _random;
}ComplexNode;

ComplexNode* BuyComplexNode(int x)
{
    ComplexNode* node = (ComplexNode*)malloc(sizeof(ComplexNode));
    assert(node);
    node->_data = x;
    node->_next = NULL;
    node->_random = NULL;
    return node;
}

//理解难度较高**
ComplexNode* CopyComplexList(ComplexNode* list)
{
    //拷贝复杂链表,连接在原链表的后面
    ComplexNode* cur = list;
    ComplexNode* copylist = NULL;
    ComplexNode* tail = NULL;
    while (cur)
    {
        ComplexNode* next = cur->_next;
        ComplexNode*newNode = BuyComplexNode(cur->_data);
        cur->_next = newNode;
        newNode->_next = next;
        cur = next;
    }
    //置random
    cur = list;
    while (cur)
    {
        ComplexNode* next = cur->_next;
        if (cur->_random)
            next->_random = cur->_random->_next;
        cur = cur->_next->_next;

    }
    //拆解链表
    cur = list;
    while (cur)
    {
        ComplexNode* next = cur->_next;
        ComplexNode* nextNext = next->_next;

        cur->_next = nextNext;
        if (copylist == NULL)
        {
            copylist = tail = next;
        }
        else
        {
            tail->_next = next;
            tail = next;
        }

        cur = nextNext;
    }

    return copylist;
}

void PrintComplex(ComplexNode* list)
{
    while (list)
    {
        ComplexNode* random = list->_random;
        int data = random ? random->_data : 0;
        printf("%d:%d->", list->_data, data);
        list = list->_next;
    }
    printf("\n");
}
void TestCopyComplexList()
{
    ComplexNode*copylist = NULL;
    ComplexNode* n1 = BuyComplexNode(1);
    ComplexNode* n2 = BuyComplexNode(2);
    ComplexNode* n3 = BuyComplexNode(3);
    ComplexNode* n4 = BuyComplexNode(4);
    n1->_next = n2;
    n2->_next = n3;
    n3->_next = n4;
    n4->_next = NULL;

    n1->_random = n4;
    n2->_random = n1;
    n3->_random = NULL;
    n4->_random = n4;
    copylist = CopyComplexList(n1);
    PrintComplex(n1);
    PrintComplex(copylist);
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值