链表面试题

头文件定义及链表结构体声明

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>

typedef int DataType;
typedef struct SListNode
{
    struct SListNode *next;
    DataType data;
}SListNode, *pSListNode, **ppSListNode;

从尾到头打印单链表

void SListReverse(pSListNode head)//从尾到头打印单链表(逆序打印)
{
#if 1
    //方法1:递归  O(N) O(N)
    if (head == NULL)
    {
        printf(" NULL <-");
        return;
    }
    SListReverse(head->next);
    printf("%2d <-", head->data);
#else
    //方法:循环  O(N^2) O(1)
    pSListNode end = NULL; 
    printf(" NULL");
    while (end != head)
    {
        pSListNode node = head;
        while (node->next != end)
            node = node->next;
        printf(" <-%2d", node->data);
        end = node;
    }
    printf("\n");
#endif
}

逆置/反转单链表

pSListNode Reverse(ppSListNode head)//逆置链表
{
#if 1
    //头删头插法
    pSListNode node = NULL;
    pSListNode cur = *head;
    while (cur)
    {
        pSListNode tmp = cur;
        cur = cur->next;
        //头插
        tmp->next = node;
        node = tmp;
    }
    return node;
#else
    //改变指向法
    //前两个指指针负责翻转,第三个负责保存节点
    pSListNode p1 = NULL, p2 = *head , p3 = p2->next;
    if (*head == NULL || (*head)->next == NULL)
        return *head;
    while (p2 != NULL)
    {
        p2->next = p1;
        p1 = p2;
        p2 = p3;
        if (p3 != NULL)
            p3 = p3->next;
    }
    *head = p1;
    return *head;
#endif
}

任意位置删

void SListErase(ppSListNode head, pSListNode pos)
{
#if 1
    pSListNode node = *head;
    if (head == NULL)
        return;//非法输入
    if (*head == pos)//头删
    {
        SListPopFront(head);
        return;
    }
    while (node->next != pos)
        node = node->next;
    node->next = pos->next;
    free(pos);
#else
    //删除一个无头单链表的非尾节点(不能遍历链表) 时间复杂度O(1)
    //替换法删除----腾讯面试题
    if (head == NULL)//非法输入
        return;
    if (*head == NULL)//空链表
        return;
    if (pos != NULL && pos->next != NULL)
    {
        pSListNode node = pos->next;
        pos->data = pos->next->data;
        pos->next = node->next;
        free(node);
    }
#endif
}

任意位置插

void SListInsert(ppSListNode head,pSListNode pos,DataType x)
{
#if 0
    pSListNode node = *head;
    pSListNode newnode = BuySListNode(x);
    if (head == NULL)
        return;//非法输入
    if (*head == pos)//头插
        SListPushFront(head, x);
    while (node->next != pos)
        node = node->next;
    newnode->next = pos;
    node->next = newnode;
#else
//在无头单链表的一个节点前插入一个节点(不能遍历链表)
//创建一个节点(node)不赋值,将源位置节点(pos)的数赋值到该节点(node)处,将插入值赋值到源位置节点(pos)处
//断链(pos-1---pos)/(pos---pos+1),连链(pos-1---node)/(node---pos+1)
    pSListNode node=BuySListNode(x);
    if (head == NULL && pos == NULL)
        return;
    if (*head == NULL)
        return;
    node->data = pos->data;
    pos->data = x;
    node->next = pos->next;
    pos->next = node;
#endif
}

约瑟夫环

int JosephCircle(pSListNode head,size_t number)//约瑟夫环
{
    pSListNode node = head, cur = head;
    //空链表返回
    if (head == NULL)
        return 0;
    //非循环变化成循环
    while (node->next)
        node = node->next;
    node->next = head;
    //循环只剩一人
    while (cur->next != cur)
    {
        int count = number;
        //教号数循环number-1次
        while (--count)
            cur = cur->next;
        node = cur->next;
        cur->data = node->data;
        cur->next = node->next;
        free(node);
    }
    return cur->data;
}

单链表排序

pSListNode BubbleSort(pSListNode head)//冒泡
{
    pSListNode node = head;
    pSListNode newnode = head->next;
    pSListNode end = NULL;
    int flag = 0;
    if (head == NULL || head->next == NULL)
        return head;
    while (end != head->next)
    {
        node = head;
        newnode = head->next;
        while (newnode != end)
        {
            if (node->data > newnode->data)
            {
                DataType tmp = node->data;
                node->data = newnode->data;
                newnode->data = tmp;
                flag = 1;
            }
            node = node->next;
            newnode = newnode->next;
        }
        if (flag == 0)
            break;
        end = node;
    }
    return head;
}

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

pSListNode MergeList(pSListNode list1, pSListNode list2)//合并两个有序链表,合并后依然有序
{
    pSListNode list = NULL, node = NULL;
    //防止其中一个为空
    if (list1 == NULL)
        return list2;
    if (list2 == NULL)
        return list1;
    //准备头
    if (list1->data < list2->data)
    {
        list = list1;
        list1 = list1->next;
    }
    if (list1->data > list2->data)
    {
        list = list2;
        list2 = list2->next;
    }
    //链接
    node = list;//标记此时尾
    while (list1 && list2)//其中一个结束循环结束
    {
        if (list1->data < list2->data)
        {
            node->next = list1;
            list1 = list1->next;
        }
        else
        {
            node->next = list2;
            list2 = list2->next;
        }
        node = node->next;
    }
    if (list1)
        node->next = list1;
    if (list2)
        node->next = list2;
    return list;
}

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

pSListNode FindMiddle(pSListNode head)//查找中间节点,要求只能遍历一次链表
{
    pSListNode fast = head;
    pSListNode slow = head;
    while (fast != NULL && fast->next != NULL)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}

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

pSListNode FindDsp(pSListNode head,DataType k)
{
    pSListNode front = head;
    pSListNode back = head;
    assert(head);
    while (--k)
        front = front->next;
    while (front->next != NULL)
    {
        front = front->next;
        back = back->next;
    }
    return back;
}

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

pSListNode FindErase(pSListNode head, DataType k)//查找倒数第k个节点,并删除
{
    pSListNode fast = head;
    pSListNode slow = head;
    pSListNode node = NULL;
    assert(head);
    while (--k)
        fast = fast->next;
    while (fast->next != NULL)
    {
        fast = fast->next;
        slow = slow->next;
    }
    //如果slow==NULL就尾删,如果非NULL即非尾节点删
    SListErase(&head, slow);//任意位置删
    return head;
}

判断单链表是否带环?若带环,求环的长度?求环的入口点?并计算每个算法时间复杂度,空间复杂度?

pSListNode IsCycle(pSListNode head)//判断是否带环
{
    pSListNode fast = head, slow = head;
    assert(head);
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if (fast == slow)
            return fast;//返回相遇点
    }
    return NULL;
}
int GetCirclelen(pSListNode meet)//求环的节点数
{
    //从相遇点,绕一圈,就是环的长度
    pSListNode node = meet->next;
    size_t count = 1;
    while (node != meet)
    {
        node = node->next;
        count++;
    }
    return count;//返回环的节点数
}
//2(L+X)=L+X+nR
//L=nR-X
pSListNode GetEntry(pSListNode head, pSListNode meet)//找到带环的节点位置
{
    while (head != meet)
    {
        head = head->next;
        meet = meet->next;
    }
    return meet;//返回节点位置
}

判断两个链表是否相交,若相交,求交点

pSListNode GetCrossNode(pSListNode list1, pSListNode list2)
{
    DataType len1 = 0, len2 = 0;
    pSListNode cur1 = list1, cur2 = list2;
    pSListNode longlist = list1, shortlist = list2;
    size_t step = 0;
    while (cur1)//求list1长度
    {
        ++len1;
        cur1 = cur1->next;
    }
    while (cur2)//求list2长度
    {
        ++len2;
        cur2 = cur2->next;
    }
    if (len1 < len2)//保证longlist始终为长链表
    {
        longlist = list2;
        shortlist = list1;
    }
    step = abs(len1 - len2);
    while (step--)//对齐,让长链表先走差距步
        longlist = longlist->next;
    while (longlist != shortlist)
    {
        longlist = longlist->next;
        shortlist = shortlist->next;
    }
    return longlist;
}

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

pSListNode UnionSet(pSListNode list1, pSListNode list2)//求两个已排序单链表中相同的数据
{
    pSListNode node = NULL;
    while (list1 && list2)
    {
        if (list1->data < list2->data)
            list1 = list1->next;
        else if (list1->data > list2->data)
            list2 = list2->next;
        else
        {
            SListPushBack(&node, list1->data);
            list1 = list1->next;
            list2 = list2->next;
        }
    }
    return node;
}

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

void Print(pCList head)
{
    assert(head);
    pCList node = head;
    while (node)
    {
        printf("%d (%d) ->", node->data, node->random != NULL ? node->random->data : 0);
        node = node->next;
    }
    printf(" NULL\n");
}

pCList CopyCList(ppCList head)
{
    assert(head);
    if(*head==NULL)
        return NULL;
    pCList src = *head;
    pCList newlist = NULL;
    //拷贝插入节点
    while (src)
    {
        pCList node = (pCList)malloc(sizeof(pCList));
        node->data = src->data;
        node->next = src->next;
        src->next = node;
        src = src->next->next;
    }
    //置random
    for (src = *head; src; src = src->next->next)
    {
        if (src->random != NULL)
            src->next->random = src->random->next;
        else
            src->next->random=NULL;
    }
    printf("插入后链表:\n");
    Print(*head);
    newlist = (*head)->next;
    //拆
    for (src = *head; src; src = src->next)
    {
        pCList copy = src->next;
        pCList cur = copy->next;
        if (cur != NULL)
            copy->next = cur->next;
        else
            copy->next = NULL;
        src->next = cur;
    }
    return newlist;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值