PATb1015

博客围绕单链表每K个结点反转问题展开,给出题目描述、输入输出要求,指出题目存在除完整链表外有无关节点、K可能大于链表实际长度等坑,还介绍了memset函数相关知识,最后附上评论区代码、自己写的代码及个人补充代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

给定一个常数K以及一个单链表L,请编写程序将L中每K个结点反转。例如:给定L为1→2→3→4→5→6,K为3,则输出应该为
3→2→1→6→5→4;如果K为4,则输出应该为4→3→2→1→5→6,即最后不到K个元素不反转。

输入描述:

每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址、结点总个数正整数N(<= 105)、以及正整数K(<=N),即要求反转的
子链结点的个数。结点的地址是5位非负整数,NULL地址用-1表示。

接下来有N行,每行格式为:

Address Data Next

其中Address是结点地址,Data是该结点保存的整数数据,Next是下一结点的地址。

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

输出描述:

对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

题目的坑

除了给的完整链表还可能有无关节点:

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 -1
99999 5 68237
12309 2 33218

错以为只有完整一条
从而导致K可能大于链表实际长度

评论区copy代码

#include <stdio.h>
#include <memory.h>
 
#define LIMIT 100002
 
struct linknode {
    int data;
    int next;
}; 
int reversek(struct linknode *, int, int);
 
int main(void) {
    struct linknode list[LIMIT];     //静态链表 
    int faddr, n, k;
    int addr, data, next;
    int i, j, count = 0;
 
    scanf("%d %d %d", &faddr, &n, &k);
    memset(list, 0, LIMIT * sizeof(struct linknode));   //结构体数组清零初始化 
    list[LIMIT-1].next = faddr;       //head node    
    for(i = 0; i < n; ++i) {
        scanf("%d %d %d", &addr, &data, &next);
        list[addr].data = data;
        list[addr].next = next;
    }
    for(i = list[LIMIT-1].next; i != -1; i = list[i].next) 
        ++count; //count valid nodes    统计实际链表节点数 
    for(j = count / k, i = LIMIT - 1; j > 0 && i != -1; --j) //剩余反转数j     
        i = reversek(list, i, k); //reverse every k nodes  //未完成头节点地址i 
     //传输(虚拟)头节点地址而不是反转头地址,是为了防止无法与前面链表连接       
    for(i = list[LIMIT-1].next; list[i].next != -1; i = list[i].next) 
        printf("%05d %d %05d\n", i, list[i].data, list[i].next);
    printf("%05d %d %d\n", i, list[i].data, list[i].next);
    return 0;
}
 
int reversek(struct linknode *list, int head, int k) {
    int i, j, p;
    int nexthead;     //p!=-1 防止长度不够 
    for(j = 0, p = list[head].next; j < k && p != -1; ++j) //find tail
        p = list[p].next;
    nexthead = list[head].next;  //该小段头节点地址 
    list[head].next = p;  //剔除该小段 
    for(j = 0, i = nexthead; j < k && i != -1; ++j) {
        p = list[i].next;
        list[i].next = list[head].next; //insert at the head 头节点插入使该小段反转 
        list[head].next = i;
        i = p;
    }
    return nexthead;  //返回未完成节点前一个地址(作为未完成头节点) 
} 

附:

附解

1.void *memset(void *s, int ch, size_t n);

函数解释:将s中当前位置后面的n个字节 typedef unsigned int size_t 用 ch替换并返回 s 。
memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法 。
memset()函数原型是extern void *memset(void *buffer, int c, int count) buffer:为指针或是数组,c:是赋给buffer的值,count:是buffer的长度

2.memset函数按字节对内存块进行初始化,所以不能用它将int数组初始化为0和-1之外的其他值(除非该值高字节和低字节相同)
511的二进制码为(00000000 00000000 00000001 11111111)后八位为(11111111),
所以数组中每个字节,如a[0]含四个字节都被赋值为(11111111),其结果为a[0](11111111 11111111 11111111 11111111)
3.C里面数是以补码方式来储存的 -1为11111111 11111111 11111111 11111111

附自己写的 垃圾 代码

仅供自己反思:

#include<stdio.h>			//惨不忍睹001

int main()
{
    int N,K,i,*tadd=NULL,*padd=NULL,t=0,*tnext=NULL;
    struct POINT{
        int *address;
        int data;
        int *next;
    }a[100050],*pa=a;
    scanf("%d",&padd);
    scanf("%d",&N);
    scanf("%d",&K);
    for(i=0;i<N;i++)
    {
     scanf("%d",&a[i].address);
     scanf("%d",&a[i].data);
     scanf("%d",&a[i].next);
    }
    for(i=0;i<N-1;i++)
    {
        while(pa->address!=padd)
            pa++;
        tadd=a[i].address;
        a[i].address=pa->address;
        pa->address=tadd;
        
        tnext=a[i].next;
        a[i].next=pa->next;
        pa->next=tnext;
        
        t=a[i].data;
        a[i].data=pa->data;
        pa->data=t;
        
        padd=pa->next;
        pa=a+i+1;
    }
    pa=a+K-1;
    while(pa<a+N-1)
    {
        tnext=pa->next;
        for(i=0;i<K-1;i++)
        {
            (pa-i)->next=(pa-i-1)->address;
        }
        (pa-K+1)->next=tnext;
        for(i=0;i<4;i++)
            printf("%d %d %d\n",(pa-i)->address,(pa-i)->data,(pa-i)->next);
        pa+=K;
    }
    return 0;
}
#include<stdio.h>			//惨不忍睹010

int main()
{
    int N,K,i,*tadd=NULL,*padd=NULL,t=0,*tnext=NULL;
    struct POINT{
        int *address;
        int data;
        int *next;
    }a[100000],*pa=a;
    scanf("%d",&padd);
    scanf("%d",&N);
    scanf("%d",&K);
    for(i=0;i<N;i++)
    {
     scanf("%d",&a[i].address);
     scanf("%d",&a[i].data);
     scanf("%d",&a[i].next);
    }
    
    for(i=0;i<N-1;i++)
    {
        while(pa->address!=padd)
            pa++;
        tadd=a[i].address;
        a[i].address=pa->address;
        pa->address=tadd;
        
        tnext=a[i].next;
        a[i].next=pa->next;
        pa->next=tnext;
        
        t=a[i].data;
        a[i].data=pa->data;
        pa->data=t;
        
        padd=a[i].next;
        pa=a+i+1;
        if(a[i].next==NULL)
            break;
    }
    N=pa-a;
    pa=a+K-1;
    while(pa<a+N)
    {
        tnext=pa->next;
        for(i=0;i<K-1;i++)
        {
            (pa-i)->next=(pa-i-1)->address;
        }
        (pa-K+1)->next=tnext;
        for(i=0;i<K;i++)
            printf("%d %d %d\n",(pa-i)->address,(pa-i)->data,(pa-i)->next);
        pa+=K;
    }
    pa=pa-K+1;
    while(pa<a+N)
    {
        printf("%d %d %d\n",pa->address,pa->data,pa->next);
        pa+=1;
    }
 return 0; 
}

后个人补充代码

#include<stdio.h>

struct NODE{
    int data;
    int next;
};

int standard(struct NODE *a,int i,int k)
{
    int pnext=a[i].next,paddr=a[i].next,j,addr,head=i;
    for(j=0;j<k;j++)
        pnext=a[pnext].next;
    head=paddr;
    for(j=0;j<k;j++)
    {
        addr=a[paddr].next;
        a[paddr].next=pnext;
        a[i].next=paddr;
        pnext=paddr;
        paddr=addr;
    }
    return head;
}
int main()
{
    static struct NODE a[100002];
    int addr,data,next;
    int faddr,n,k;
    int i,num=0,j;
    scanf("%d %d %d",&faddr,&n,&k);
    a[100001].next=faddr;
    for(i=0;i<n;i++)
    {
        scanf("%d",&addr);
        scanf("%d",&a[addr].data);
        scanf("%d",&a[addr].next);
    }
    printf("static实验%d %d %d\n",5,a[5].data,a[5].next);
    i=100001;
    while(a[i].next!=-1)
    {
        num++;
        i=a[i].next;
        printf(" next address %05d\n",i);
    }
    n=num;        //链表实际长度
    printf("实际长度  %d \n",num);
    i=100001;
    for(j=0;j<n/k;j++)
    {
        i=standard(a,i,k);
    }
    printf("结果\n");
    faddr=a[100001].next; 
    for(j=0;j<n;j++)
    {
        printf("%05d %d %05d\n",faddr,a[faddr].data,a[faddr].next);
        faddr=a[faddr].next;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值