链表面试题(一)

先定义链表结构为:

typedef int DataType;
typedef struct SListNode
{
    struct  SListNode* _next;
    DataType           _data;
}SListNode;

1. 从尾到头打印单链表
1)定义end先走到空,通过第一层循环先找到第1个要打印的数,每次找end的前一个数打印。再定义cur,end中的数据打印完后,把cur赋给end,让cur从头走

void PrintTailToHead(SListNode* head)
{
    SListNode* end = NULL;

    while (end != head)
    {
        SListNode* cur = head;
        while (cur->_next != end)
        {
            cur = cur->_next;
        }

        //此时cur走到end的前一个位置
        printf("%d", cur->_data);

        end = cur;
    }
    printf("\n");
}

2)采用递归的方式,如果当前节点不为空,就继续打印函数传递过去的参数的下一个节点

void PrintTailToHeadR(SListNode* head)//递归
{
    if (head == NULL)//不能用assert,它会终止程序
        return;

    PrintTailToHeadR(head->_next);
    printf("%d ", head->_data);
}

2. 删除无头单链表的非尾节点(不能遍历链表)
用替换法,让当前位置的下一个节点覆盖当前节点,再free掉当前节点的下一个节点

void DelNode(SListNode* pos)
{
    SListNode* next;
    assert(pos && pos->_next);

    //替换法删除
    next = pos->_next;
    pos->_data = next->_data;
    pos->_next = next->_next;
    free(next);
}

3. 在无头单链表的一个节点前插入一个节点(不能遍历链表)
因为只知道当前节点的下一个节点的位置,所以在当前节点后先把这个节点插入,再交换一下这两个节点的位置

void InsertNode(SListNode* pos, DataType x)
{
    assert(pos);
    SListNode* tmp = BuySListNode(pos->_data);
    tmp->_next = pos->_next;
    pos->_next = tmp;
    pos->_data = x;
}

4. 单链表实现约瑟夫环(JosephCircle)
给定k值表示走到k就删掉k的位置上的数
先把链表的尾链上头形成一个环,使用替换法删除节点,返回最后剩下的这个节点。

SListNode* JosephCycle(SListNode* head, int k)//数到k就删掉
{
    SListNode* tail = head, *cur = head;
    if (head == NULL)
        return NULL;

    //构成环
    while (tail->_next)
        tail = tail->_next;
    tail->_next = head;

    while (cur->_next != cur)
    {
        SListNode* next;
        int count = k;
        while (--count)//走k-1次
            cur = cur->_next;

        next = cur->_next;
        cur->_data = next->_data;
        cur->_next = next->_next;
        free(next);
    }

    return cur;
}

5. 逆置/反转单链表
用头插法

SListNode* ReverseList2(SListNode* head)
{
    SListNode* newhead = NULL;
    SListNode* cur = head;
    while (cur)
    {
        SListNode* tmp = cur;
        cur = cur->_next;

        //头插
        tmp->_next = newhead;
        newhead = tmp;
    }

    return newhead;
}

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

void BubbleSortList(SListNode* head)
{
    SListNode* cur, *next;
    SListNode* tail = NULL;
    if (head == NULL || head->_next == NULL)
        return;

    while (tail != head->_next)
    {
        int flag = 0;
        cur = head;
        next = cur->_next;
        while (next != tail)
        {
            if (cur->_data > next->_data)
            {
                DataType tmp = cur->_data;
                cur->_data = next->_data;
                next->_data = tmp;

                flag = 1;
            }

            cur = cur->_next;
            next = next->_next;
        }

        if (flag == 0)
            break;

        tail = cur;
    }
}

7. 合并两个有序链表,合并后依然有序
用尾插法,每走一步都做一次比较,用小的数当作新表需要尾插的数,定义list头指向第一次尾插的数

SListNode* MergeList(SListNode* list1, SListNode* list2)
{
    SListNode* list, *tail;
    if (list1 == NULL)
        return list2;

    if (list2 == NULL)
        return list1;

    if (list1->_data < list2->_data)
    {
        list = list1;
        list1 = list1->_next;
    }
    else
    {
        list = list2;
        list2 = list2->_next;
    }

    tail = list;
    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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值