翻转链表算法和实现


写个翻转链表算法,刚开始想到一个不错的思路。这个思路运行效率不低,时间复杂度为O(n);可以不用分配额外的节点空间,空间复杂度为O(0)。现在把思路整理一下,并实现代码,测试运行结果。

1、 翻转思路

1-1 整体的思路

用一个while顺序遍历这个链表,然后把遍历到每个节点插入到链表头部。

这里写图片描述

1-2 详细的思路

蓝色箭头即赋值符号,比如在第2个结点的操作:

  • step 2.1:front指针前移一位;
  • step 2.2:把head节点的next值(即指向节点1的地址)赋给节点2;
  • step 2.3:把节点2的地址赋给head节点的next;
  • step 2.4:back指针前移一位;

while遍历条件可根据back不为空,即while(back)

这里写图片描述

2、 代码实现

#include<stdio.h>       // NULL
#include<stdlib.h>      // malloc
#define ElemType int

typedef struct LNode{   // 定义单链表结点类型
    ElemType data;      // 数据域
    struct LNode *next; // 指针域
}LNode, *LinkList;      // LinkList相当于LNode*,即:struct LNode*

// 尾插法建立单链表L
LinkList listcreat_fromtail(LinkList L);
// 翻转链表L的算法
LinkList reverse_linklist(LinkList L);
// 把节点Node插入链表L头部
LinkList insert_head(LinkList L, LNode * Node);
// 输出链表L元素, flag=0为链表翻转前,flag=1为链表翻转后
void print_linklist(LinkList L, int flag);

int main(int argc, char *argv[])
{
    LinkList L;

    // 尾插法建立单链表L
    L = listcreat_fromtail(L);

    // 输出翻转前(flag=0)链表元素
    print_linklist(L, 0);

    // 翻转链表L
    L = reverse_linklist(L);

    // 输出翻转后(flag=1)链表元素
    print_linklist(L, 1);

    return 0;
}

// 翻转链表L的算法
LinkList reverse_linklist(LinkList L)
{
    LNode *back, *front;

    back = L->next; // step 0.1, init 
    L->next = NULL; // step 0.2, init

    while(back){
        front = back->next;      // step x.1
        L = insert_head(L, back);// step x.2, step x.3
        back = front;            // step x.4
    }
    //back = front = NULL;         // for secure

    return L;
}

// 把节点Node插入链表L头部
LinkList insert_head(LinkList L, LNode * node)
{
    node->next = L->next; // step x.2
    L->next = node;       // step x.3

    return L;
}

// 输出链表L元素, flag=0为链表翻转前,flag=1为链表翻转后
void print_linklist(LinkList L, int flag)
{
    printf(flag ? "翻转后:\n" : "翻转前:\n");

    printf("单链表元素个数:%d, 分别是:", L->data);
    for(LNode* N = L->next; N; N = N->next){
        printf("%d ",N->data);
    }

    puts("\n");
}

//尾插法建立单链表L
LinkList listcreat_fromtail(LinkList L)
{
    int len, data;
    LNode *r;

    L = (LinkList)malloc(sizeof(LNode));
    L->data = 0; L->next = NULL; // L->data为链表长度
    r = L;                       // r为表尾指针

    printf("请输入插法建立单链表长度:");
    scanf("%d", &len);
    printf("请逐个输入链表元素:");
    while(len--){
        scanf("%d",&data);
        LNode *s=(LNode*)malloc(sizeof(LNode));
        s->data = data; s->next = NULL;
        r->next = s;
        r = r->next;
        L->data++;    // 链表长度+1
    }
    return L;
}

3、 运行结果

huashidazhongbeitushuguandeiMac-2:Wu_Being duzhe$ vim reverse_linklist.c
huashidazhongbeitushuguandeiMac-2:Wu_Being duzhe$ gcc reverse_linklist.c 
huashidazhongbeitushuguandeiMac-2:Wu_Being duzhe$ ./a.out 
请输入插法建立单链表长度:5
请逐个输入链表元素:1 2 3 4 5
翻转前:
单链表元素个数:5, 分别是:1 2 3 4 5 

翻转后:
单链表元素个数:5, 分别是:5 4 3 2 1 

huashidazhongbeitushuguandeiMac-2:Wu_Being duzhe$ ./a.out 
请输入插法建立单链表长度:3
请逐个输入链表元素:1 2 3 4
翻转前:
单链表元素个数:3, 分别是:1 2 3 

翻转后:
单链表元素个数:3, 分别是:3 2 1 

huashidazhongbeitushuguandeiMac-2:Wu_Being duzhe$ 


Wu_Being博客声明:本人博客欢迎转载,请标明博客原文和原链接!谢谢!
《翻转链表算法和实现》:
http://blog.csdn.net/u014134180/article/details/78423589

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页