PTA 链表分段逆置问题【c语言版】 函数题

其实这篇文章在很久之前就应该发出了,但是当时在学校,上课之类的一系列事情耽误了,(最主要的是要陪别(dui)人(xiang),嘿嘿)但是这个是我写文章的第一篇,所以不想放弃,就填个坑,当时的我觉得这道题巨难,做出来贼nb,(现在看来贼简单)所以开了一个头,写文章的时候从草稿堆里翻出来的,就写一下
同时,告诉大家,坚持,回头看做过的路会感觉之前走过的路特别简单!!!


题目

给定一个带头结点的单链表和一个整数K,要求你将链表中的每K个结点做一次逆转。例如给定单链表 1→2→3→4→5→6 和 K=3,你需要将链表改造成 3→2→1→6→5→4;如果 K=4,则应该得到 4→3→2→1→5→6。


函数接口定义

void K_Reverse( List L, int K );

其中 List结构定义如下:

typedef struct Node *PtrToNode;
struct Node {
    ElementType Data; /* 存储结点数据 */
    PtrToNode   Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */

L是给定的带头结点的单链表,K是每段的长度。函数K_Reverse应将L中的结点按要求分段逆转。

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;

typedef struct Node *PtrToNode;
struct Node {
    ElementType Data; /* 存储结点数据 */
    PtrToNode   Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */

List ReadInput(); /* 裁判实现,细节不表 */
void PrintList( List L ); /* 裁判实现,细节不表 */
void K_Reverse( List L, int K );

int main()
{
    List L;
    int K;

    L = ReadInput();
    scanf("%d", &K);
    K_Reverse( L, K );
    PrintList( L );

    return 0;
}

/* 你的代码将被嵌在这里 */

一、输入

6
1 2 3 4 5 6
4

二、输出

4 3 2 1 5 6

三、思路

对于此题,最基础的是链表逆置算法
而有所改进的是:

1.了解逆置规则

对于最后输入的数字n,需要每隔n个数字进行逆置,如果剩余的数字个数小于n,则不足的部分并再在进行逆置

2.了解逆置算法

在这里,博主给出大家链表逆置算法
大家可以吧它背住,考试或者做题默写上去,很方便快捷:

    head=head->next;
    plist bt1=NULL,p=head;
    bt=head;

    while(p){
    p=p->next;
    bt->next=bt1;
    bt1=bt;
    bt=p;
    }

这是算法核心,基本思路是这样的:
用三个单元来完成,让第一个指向空(没有头指针),然后下面的一个指向第一个,这样一个一个逆置,最后 p 和 bt 都是空,bt1指向头
我写了一个完整的,大家可以运行一下试试:

#include<stdio.h>
#include<stdlib.h>
typedef struct list{
    int data;
    struct list *next;
}list,*plist;

int main(){
    plist bt=(plist)malloc(sizeof(list));
    int i;
    plist head=bt;
    for(i=0;i<10;i++){
        plist bt1=(plist)malloc(sizeof(list));
        bt1->data=i;
        bt1->next=NULL;
        bt->next=bt1;
        bt=bt1;
    }

    head=head->next;
    plist bt1=NULL,p=head;
    bt=head;

    while(p){
    p=p->next;
    bt->next=bt1;
    bt1=bt;
    bt=p;
    }

    while(bt1){
        printf("%d ",bt1->data);
        bt1=bt1->next;
    }
}

这个小程序可以自动赋值,初始数据是
0 1 2 3 4 5 6 7 8 9
运行结果是
9 8 7 6 5 4 3 2 1 0
(博主运行过了,可以正常运行)

在这里插入图片描述

四、程序代码

void K_Reverse( List L, int K ){
List p1,p2,p3=NULL,n,p,c;
int q=0,i,d;
p=p1=L->Next;
while(p){
    q++;
    p=p->Next;
}
q=q/K;
if(q!=0){
n=p1;
for(i=0;i<K;i++){
p2=p1->Next;
p1->Next=p3;
p3=p1;
p1=p2;}
}
if(q!=0)
L->Next=p3; 
for(d=0;d<q-1;d++){
p3=NULL;
c=p1;
for(i=0;i<K;i++){
p2=p1->Next;
p1->Next=p3;
p3=p1;
p1=p2;
}
n->Next=p3;
n=c;
}
if(q!=0)
n->Next=p1;
return L;
}

五、提交结果截图

在这里插入图片描述

总结

总的来说,首先得知道需要逆置几次,然后分段分进行逆置,最后如果还有剩余,就直接添加到链表末尾

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值