单链表翻转

单链表的翻转也算是面试中常见的面试题目了,本文根据网上查阅的资料给大家总结了两种方法。

准备:

首先,我们先来看我们节点和函数的定义,以及客户端应用:

#include <stdio.h>
#include <stdlib.h> //提供malloc()
//节点结构
struct Node{
    int val;
    struct Node * next;
};
typedef struct Node node,* list;

//单链表翻转函数
//一、新建链表,头结点插入法
list func1(list head);
//二、就地翻转,改变原链表
list func2(list head);

//客户端
int main(void){
    //带翻转链表
    list mylist = (list)malloc(sizeof(node));
    mylist -> val = 1;
    mylist -> next = NULL;
    int i = 2;
    node * cur = mylist;
    while(i < 6){
        node * pnode = (node *)malloc(sizeof(node));
        pnode -> val = i;
        cur -> next = pnode;
        cur = cur -> next;
        i ++;
    }
    //函数调用
    //cur = func1(mylist);
    cur = func2(mylist);
    while(cur){
        printf("%d ",cur -> val);
        cur = cur -> next;
    }
    return 0;
}

接下来我们来看我们的两个单链表翻转方法:

一、新建链表,头结点插入法:

该方法的思想是:新建链表,遍历原链表,将每个节点逐一插入到新建链表的头部,最后新建链表就是原链表的翻转形式。

代码:

list func1(list head){
    //新链表
    list newList = (list)malloc(sizeof(node));
    if(head == NULL || newList == NULL){
        return NULL;
    }

    node * pnew = newList;    //新链表头结点指针
    node * pold = head;    //原链表遍历节点指针
    node * tmp;
    //初始化
    pnew -> val = pold -> val;
    pnew -> next = NULL;

    pold = pold -> next;
    while(pold){
        tmp = (node *)malloc(sizeof(node));
        tmp -> val = pold -> val;
        tmp -> next = pnew;
        pnew = tmp;    //在新链表头部插入
        pold = pold -> next;
    }
    return pnew;    //返回新链表
}

二、就地翻转

就地翻转就是改变原来的链表,不增加新链表。

思想:每次都将原第一个节点之后的那个节点放在链表的开头处,我们来看看一个例子:
原序列是 1 2 3 4 5 ,原第一个节点是 1 ,将 1 后的 2 放在链表的开头处,变成 2 1 3 4 5 ,再将 1 后面的 3 放在链表的开头处,变成 3 2 1 4 5 ……..直到 1 后面没有元素,翻转结束。

代码:

list func2(list head){
    if(head == NULL){
        return NULL;
    }
    node * pone = head;    //这个指针指向原来的第一个节点,该指针保持不变
    node * p1 = pone -> next;    //原第一个节点后面的第一个元素
    node * p2;
    while(p1){    //原第一个节点后面的第一个元素为空时翻转完成
        p2 = p1 -> next;
        p1 -> next = head;
        head = p1;
        pone -> next = p2;
        p1 = pone -> next;
    }
    return head;    //返回翻转后的头指针
}

结尾:

网上还有提供其他的方法如:

  1. 类似第二个方法,我们可以将前面的节点移动到原来的最后一个节点的后面。
  2. 遍历链表,将节点放到数组中,然后逆序遍历数组输出的新的链表中。

后面提到的方法大家可以试试。

关于这个问题的资源网上好多,这里仅仅做记录,大神勿喷。

扫描二维码关注公众号,回复: 1452359 查看本文章

猜你喜欢

转载自blog.csdn.net/baidu_30000217/article/details/64536815
今日推荐