带头结点单链表的翻转(递归)

前言:

    单链表是基础的数据结构, 分为有头结点和无头结点, 无头结点使用起来比较麻烦, 下面是有头结点的单链表操作, 重点是在于有头结点的单链表翻转操作。

代码:singlelist.c

/*
    带头结点head的单链表

*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "list.h"

NODE *head = NULL;

/*
翻转链表(递归方法)

*/
NODE* reverse_list_recursion(NODE *pNode)
{
    if(NULL == pNode || NULL == pNode->next)
        return pNode;

    NODE *newhead = reverse_list_recursion(pNode->next);
    if(pNode != head){
        pNode->next->next = pNode;
        pNode->next = NULL;
     return newhead; }
else { pNode->next = newhead;
return pNode; }
} /* 尾插法插入节点到链表 1:首先需要找到尾结点, 它的标志就是next域为NULL 2:创建新结点初始化 3:尾结点的next域指向新结点 */ void tail_insert_node(NODE *head, int data) { NODE *tail = head; while(tail->next != NULL) tail = tail->next; NODE *p = (NODE *)calloc(1, sizeof(struct list)); p->data = data; p->next = NULL; tail->next = p; } /* 头插法插入结点到链表, 比尾插法简单, 不需要找到尾结点 1:创建新结点, 新结点的next指向头结点的next 2:头结点的next域指向新结点 */ void head_insert_node(NODE *head, int data) { NODE *p = (NODE *)calloc(1, sizeof(struct list)); p->data = data; p->next = head->next; head->next = p; } /* 尾插法初始化链表 */ void init_list_tail(NODE *head) { int array[5] = {1, 2, 3, 4, 5}; int i; assert(head); for(i=0; i<(sizeof array)/(sizeof array[0]); i++) { tail_insert_node(head, array[i]); } } /* 头插法初始化链表 */ void init_list_head(NODE *head) { int array[5] = {1, 2, 3, 4, 5}; int i; assert(head); for(i=0; i<(sizeof array)/(sizeof array[0]); i++) { head_insert_node(head, array[i]); } } /* 删除一个结点 */ void remove_list_node(NODE *head, int data) { if(NULL == head || NULL == head->next){ printf("Already empty list "); return; } NODE *pNode = head; NODE *ptr = NULL; while(pNode->next != NULL){ if(pNode->next->data != data) { pNode = pNode->next; continue; } else { ptr = pNode->next; pNode->next = pNode->next->next; free(ptr); return; } } printf("no this node in list "); } void print_list(NODE *head) { NODE *p = head->next; int i = 0; while(p){ printf("list[%d]:%d ", i++, p->data); p = p->next; } } int main(int argc, char const *argv[]) { head = (NODE *)calloc(1, sizeof(struct list)); init_list_tail(NULL); print_list(head); reverse_list_recursion(head); print_list(head); remove_list_node(head, 5); head = reverse_list_recursion(head); print_list(head); return 0; }

list.h

#ifndef __LIST_H__
#define __LIST_H__

typedef struct list {
    int data;
    struct list *next;
}NODE;

NODE* reverse_list_recursion(NODE *pNode);
void tail_insert_node(NODE *head, int data);
void head_insert_node(NODE *head, int data);
void init_list_tail(NODE *head);
void init_list_head(NODE *head);
void print_list(NODE *head);

#endif

 翻转单链表的函数:

NODE* reverse_list_recursion(NODE *pNode)
{
    if(NULL == pNode || NULL == pNode->next)
        return pNode;

    NODE *newhead = reverse_list_recursion(pNode->next);
    if(pNode != head){
        pNode->next->next = pNode;
        pNode->next = NULL;
   return newhead; }
else { pNode->next = newhead;
return pNode; }
}

  使用了递归的思想, 可以把单链表看做只有左子树的树, 依次递归交换相邻两个树叶的指向。head是全局的头结点, 但是要判断一种特殊情况, 那就是pNode回归最后指向了head时(此时也是递归最后一次), 这时候就不要交换head和第一个结点的指向了, 只需要将head的next指向新的第一个结点newhead就可以了。

原文地址:https://www.cnblogs.com/Flychown/p/7851880.html