链表逆序总结

所谓链表逆序,是把诸如 1->2->3->4->null 的链表变换为 4->3->2-1->null。假设链表节点定义如下:

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};
解法一:

新建临时节点tmp_head,遍历原始链表,将原始链表头插入tmp_head之后,最后返回tmp_head。如是则返回了逆序后的链表。

ListNode * reverseList(ListNode *head)
{
    if (head == NULL || head->next == NULL)
        return head;
     
    ListNode *tmp_head, *next;
    tmp_head = new ListNode(-1);    //create a temporary head Node, notice that tmp_head->next is NULL
    next = head->next;
    while (head != NULL){
        next = head->next;
        head->next = tmp_head->next;
        tmp_head->next = head;
        head = next;
    }
    head = tmp_head->next;
    delete tmp_head;                //free the temporary head Node
    return head;       
}

解法二:

利用三个指针p、q、n,三个指针初试时如下图所示:

然后变换指针:

然后将p、q、n向后挪动一个位置:

如是反复,直到n的值为空,此时链表如下图所示:

程序代码如下:

ListNode * reverseList(ListNode *head)
{
    if (head == NULL || head->next == NULL)
        return head;
     
    ListNode *p, *q, *n;
    p = head, q = p->next, n = q->next;
    p->next = NULL;//notice that initially we should set the next filed of the first node to NULL
    while (n != NULL) {
        q->next = p;
        p = q; q = n;
        n = n->next;
    }
    q->next = p;
    
    head = q;
    return head;       
}


接下来是两种递归实现。但链表的处理不宜使用递归,因为当链表过长的时候,容易导致栈溢出。

解法三:

ListNode * recursiveReverseList(ListNode *p, ListNode *last)
{
    if (p->next == NULL){
        p->next = last;
        return p;
    }
    
    ListNode *tmp = p->next;
    p->next = last;
    return recursiveReverseList(tmp, p);
}


ListNode * reverseList(ListNode *head)
{
    if (head == NULL || head->next == NULL)
        return head;
        
    return recursiveReverseList(head, NULL);       
}

解法四:

ListNode * recursiveReverseList(ListNode *p)
{
    if (p->next == NULL)
        return p;

    ListNode *new_head = recursiveReverseList(p->next);
    p->next->next = p;
    return new_head;
}


ListNode * reverseList(ListNode *head)
{
    if (head == NULL || head->next == NULL)
        return head;

    ListNode *new_head = recursiveReverseList(head);
    head->next = NULL;
    return new_head;       
}

由上可见,解法三和解法四并没有本质的不同。但相对而言,无论是函数递归调用还是代码结构,解法三更好一些。下述代码是我测试以上函数时用到的代码。建议通过如下命令编译程序:

g++ filename.cpp -std=c++11

ListNode * reverseList(ListNode *head)
{
    return NULL;
}

ListNode * genList()
{
    vector<int> data = {1, 2, 3, 4};
    ListNode * head, *tmp;
    head = tmp = new ListNode(0);
    for (int j = 0; j < data.size(); ++j){
            tmp->next = new ListNode(data[j]);
            tmp = tmp->next;
    }
    tmp->next = NULL;
    tmp = head->next;
    delete head;
    return tmp;
}

void print_list(ListNode *head)
{
    cout << "print_list :" << endl;
    if (head == NULL){
        cout << endl;
        return;
    }
    ListNode *tmp = head;
    while(tmp != NULL){
        cout << tmp->val << " ";
        tmp = tmp->next;
    }
    cout << endl;
}
int main()
{

    ListNode * head = genList();
    print_list(head);
    head = reverseList(head);
    print_list(head);
    head = reverseList(head);
    print_list(head);
    
    return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值