• 反转单链表的几种方法


    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt114

    最近试着做一些笔试面试题,既是为来年找工作做准备,也可以做为数据结构和算法的复习笔记,就陆续发在这里吧,有需要的朋友可以看一下,如果有没考虑周全的地方欢迎指正。

      先来一个最常见的题目:反转单链表。假设单链表的数据结构定义如下:

      

    typedef struct LNode
    {
        int     data;
        struct LNode    *next;
    }LNode, *LinkedList;

      并且这个单链表有一个头指针list指向第一个结点,最后一个结点指向NULL,很容易理解。

      最容易想到的第一种方法就是重新建立一个单链表newList,每次将list中的第一个结点放到newList后面。注释比较详细,所以就不具体说了,直接看代码吧:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    LinkedList ReverseSinglyLinkedList(LinkedList list)
    {
        LinkedList  newList;    //新链表的头结点
        LNode       *tmp;       //指向list的第一个结点,也就是要摘除的结点
     
        //
        //参数为空或者内存分配失败则返回NULL
        //
        if (list == NULL || (newList = (LinkedList)malloc(sizeof(LNode))) == NULL)
        {
            return NULL;
        }
     
        //
        //初始化newList
        //
        newList->data = list->data;
        newList->next = NULL;
     
        //
        //依次将list的第一个结点放到newList的第一个结点位置
        //
        while (list->next != NULL)
        {
            tmp = newList->next;         //保存newList中的后续结点
            newList->next = list->next;       //将list的第一个结点放到newList中
            list->next = list->next->next;     //从list中摘除这个结点
            newList->next->next = tmp;        //恢复newList中后续结点的指针
        }
     
        //
        //原头结点应该释放掉,并返回新头结点的指针
        //
        free(list);
        return newList;
    }

      第二种方法是每次都将原第一个结点之后的那个结点放在list后面,下图是原始的单链表。单链表反转示例图片

      为了反转这个单链表,我们先让头结点的next域指向结点2,再让结点1的next域指向结点3,最后将结点2的next域指向结点1,就完成了第一次交换,顺序就变成了Header-结点2-结点1-结点3-结点4-NULL,然后进行相同的交换将结点3移动到结点2的前面,然后再将结点4移动到结点3的前面就完成了反转,思路有了,就该写代码了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    LinkedList ReverseSinglyLinkedList(LinkedList list)
    {
        LNode   *tmp = NULL;
        LNode   *p = NULL;
     
        if (list == NULL)
        {
            return NULL;
        }
        tmp = list->next;
        while (tmp->next != NULL)
        {
            p = tmp->next;
            tmp->next = p->next;
            p->next = list->next;
            list->next = p;
        }
        return list;
    }

      第三种方法跟第二种方法差不多,第二种方法是将后面的结点向前移动到头结点的后面,第三种方法是将前面的结点移动到原来的最后一个结点的后面,思路跟第二种方法差不多,就不贴代码了。

      我只想到这三种方法,如果你还知道其它方法,欢迎留言告诉我,多谢。

  • 相关阅读:
    Yii 动作过滤的方法
    artdialog
    第一天:安装nodejs
    yii模块下面的组件
    总是容易忘记 jquery ajax POST
    【来自简书】浏览器~加载,解析,渲染
    【收藏】九个PHP很有用的功能
    从理论到实践,全方位认识DNS(实践篇)
    从理论到实践,全方位认识DNS(理论篇)
    DNS解析过程原理
  • 原文地址:https://www.cnblogs.com/grefr/p/6095049.html
Copyright © 2020-2023  润新知