C语言—链表的逆置

C语言—链表的逆置

组里考核题有这么一道题:创建一个链表,链表里的数据取随机数,现在要求把链表逆置,写出实现代码。

刚看到这道题的时候我第一想到的是交换指针实现,但是画了半天想不出来,为了过审核就用了最笨的值交换。就是把头和尾的值交换,头向后移,尾向前移,直到相遇。

后来组长除了这个值交换还说了两种方法:迭代逆置链表和递归逆置链表。

  • 迭代逆置链表:从第一个节点开始依次改变节点指针,把原来链表里的下一个节点插在前面,从而实现逆置。

  • 递归逆置指针:先递归到链表的最后一个节点,再从后往前改变。


1.值交换

没什么好说的,直接上代码。

注意:这里的函数的参数是指向结构体指针的指针!!!!

void listReverse(LinkList *L)
{
    int index = 0;
    LinkList temp = (*L)->next;
    for(; temp != NULL; index++)            //遍历出节点个数index 
    {
        temp = temp->next;
    }

    for(int i = 0; i < index/2; i++)        //外层循环 index/2 次 
    {
        LinkList pre = (*L)->next,aft = (*L)->next;
        for(int j = 0; j < i; j++)                  //前面的节点 
        {
            pre = pre->next;
        }
        for(int k = 0; k < index-i-1; k++)          //后面的节点 
        {
            aft = aft->next;
        }
        int temp = pre->data;                   //交换前后节点的数据 
        pre->data = aft->data;
        aft->data = temp;
    }
}

2.迭代逆置链表

迭代和递归逆置链表的代码块都很小,但是需要深刻理解,我先贴上代码,然后通过画图重现过程。

void listReverse2(LinkList L)
{
    printf("迭代逆置:\n");
    if(L->next == NULL || L->next->next == NULL)
    {
        return;
    } 
    LinkList temp = L->next;
    L->next = NULL;
    LinkList tail;
    while(temp)
    {
        tail = temp;
        temp = temp->next;
        tail->next = L->next;
        L->next = tail;
    }
}

首先,我们有一条已创建好的链表:
这里写图片描述

然后我们开始执行函数:
这里写图片描述
这些做完之后开始第一次循环:
这里写图片描述
再是第二次:
这里写图片描述
这下是不是看懂了?
紧接着第三次第四次循环之后 退出循环,迭代完成。
这里写图片描述
这里写图片描述


3.递归逆置链表

思想:迭代是从第一个节点开始改变指针指向,而递归是先找到最后的节点,从后往前走。

代码:
注意:调用时参数为头节点的下一个节点的指针。如果没有头节点就不用管

LinkList listReverse2(LinkList L)
{
    if(L->next == NULL)
    {
        return L;
    }
    LinkList newhead = listReverse2(L->next); 
    L->next->next = L;
    L->next = NULL;
    return newhead;
}

首先是我们本来给定的链表:
这里写图片描述
开始递归,到最深处,newhead有值了
这里写图片描述
然后开始回溯,L向前移动
这里写图片描述
继续回溯,最终完成逆置(注意:如果链表有头节点,千万不能以头节点作为参数,否则头节点会被逆置成新链表的最后一个节点,而这个节点里的值是不可预料的。)
这里写图片描述
这里写图片描述
这样就用递归完成了链表的逆置。

猜你喜欢

转载自blog.csdn.net/wintershii/article/details/80470271
今日推荐