链表的翻转

160 阅读2分钟

问题

定义一个方法(函数),实现输入一个链表的头结点,然后可以反转这个链表的方向,并输出反转之后的链表的头结点

解决方案

链表的翻转常见的解决方法为递归和非迭代法

迭代法

迭代的方式是从链头结点开始处理,如下图

首先对链表设置两个指针NewH,P

我们需要一个临时结点tmp保存要迭代的结点,防止找不到下一个结点。 在把当前结点指向新结点NewH(p->next=newH),然后让新结点前进(newH=p), P指针继续向后移动,直到P指针指向NULL停止迭代.

最后一步

代码示例:

typedef struct Node {
    int data;
    struct Node *next;
} Node, List;

List *reverseList(List *Head) {

    if (Head == NULL || Head->next == NULL)
        return Head;

    Node *p = Head;
    Node *newH = NULL;

    while (p->next != NULL) { //一直迭代到链尾
        Node *tmp = p->next; //暂存p下一个地址,防止变化指针指向后找不到后续的数
        p->next = newH; //p.next指向前一个空间
        newH = p; //新链表的头移动p, 扩长一步链表
        p = tmp; //p指向原始链表p指向的下一个空间
    }

    return newH;
}

递归

迭代是从前向后开始依次反转,递归则是先循环到最后一个元素,从后开始反转。

直接上代码

typedef struct Node {
    int data;
    struct Node *next;
} Node, List;

List *reverseList(List *p) {

    if (p == NULL || p->next == NULL) {
        return p; //链表为空直接返回,而p->next为空是递归基
    }

    Node *newH = reverseList(p->next); //一直循环到链尾
    p->next->next = p; //翻转链表的指向
    p->next = null; //记得赋值NULL,防止链表错乱
    return newH; //新链表头永远指向的是原链表的链尾
}

参考

链表的翻转

end

个人公众号:技术源区

欢迎扫描下图关注公众号:技术源区,分享一些有深度的文章!