首页 > 其他分享 >C语言链表通关文牒3.0

C语言链表通关文牒3.0

时间:2024-12-31 23:56:08浏览次数:3  
标签:NODE pC2 next 链表 pC 3.0 C语言 节点

经典链表,经典上工,经典数据结构考试

例题

创建一个链表,把偶数节点单拿出来组成一个新的链表

思路

总体

首先还是老三样,创建一个单向链表节点,创建单向链表,遍历函数(地地道道)

忘了或者不知道怎么回事的可以看我的刷题专栏,里面零基础链表开教

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

typedef struct node
{
    int n;
    struct node *next;
}NODE;

NODE *init()    //初始化链表
{
    NODE *h = (NODE*)malloc(sizeof(NODE));  //创建一个头节点(方便指示指针回到开头和整体引用),后面一切操作不改变头节点
    h->n = -1;
    h->next = NULL;

    //尾部指针
    NODE *pR = h;
    
    int val = -1;
    while(1)
    {
        printf("Enter a number(-1 to End):\n");
        scanf("%d",&val);
        if(val==-1)
        {
            break;
        }

        //先创建新节点,再往里面填数据
        NODE *new = (NODE*)malloc(sizeof(NODE));
        new->n = val;
        new->next = NULL;

        //新节点插入到链表中
        pR->next = new;
        //更新尾部指针指向
        pR = new;   //pR这个帽子被新创建的结构体抢走了,这样才能让下一个更新的再抢走帽子
        
    }
    return h;
}
void Foreach(NODE *h)
{
    NODE *pC = h->next;
    if(h == NULL)
    {
        return;
    }
    while(pC != NULL)
    {
        printf("%d ",pC->n);
        pC = pC->next;
    }
}

 然后需要创建另一个函数,函数中创建另一个开头,这个函数就是帮助我们选出偶数项节点的,并且把他们弄成一个新链表,取名就叫Select吧

函数应该是什么类型的?和init一样,还是NODE*类型的(函数类型如果是个*代表返回的是个什么类型的指针,比如char* Function就是返回一个字符串,开坑),这里我们要return一个链表,所以返回的指针类型是NODE*,括号里面要加工一个NODE*类型的变量(就是加工一个链表)

就是这样

接下来就是函数里面写什么

首先需要创建一个新链表(新头节点)

链表整活儿用什么来着?那我问你。

啊对了是脚标,链表怎么尖尖的

需要几个?那我问你。

链表2.0里面讲过想要孤立(这里挑出来也是孤立,只不过不free),一个链表里需要两个脚标,一个pC还有一个是pC的前一个取名pP(这样才能孤立),可是我们还有一个链表,为了重复操作,参考遍历函数,L链表也需要一个脚标进行尾插法操作(有脚标才方便重复操作)

让我们找偶数,怎么弄?计数器!

计数器

计数器配合取余数,可以找到偶数,或者几的倍数,是个挺重要的编程小工具 

接下来就是怎么处理偶数项了,不过先看一眼,一个if肯定不行,非偶数项也有脚标上面的操作,不然脚标就无法遍历了,所有框架应该是这样的

 

好,奇数就是两个脚标移动遍历,所有else后面就写出来了

 

接下来就是连、串(纯串子) 

首先如果pC是偶数项,pC2的下一项应该也是pC(C语言从上到下执行熬憋忘喽)

pC2->next = pC;

然后记得更新变量,这样才能在下次也可以操作

pC2 = pC;

然后是孤立,跳过pC2(哎,我跳)绿色的

pP->next = pC2->next;

然后就是pC要往后移一个(不能把pC顺走,没人要我就拿走了,这个脚标在上面链表还得用)

pC = pC->next;

接下来就是断舍离,断开pC2和后面联系

pC2->next = NULL;

再把这些操作写入循环就可以了 (别忘了循环外return l)

完整代码如下

NODE *Select(NODE *h)
{
    NODE *l = (NODE*)malloc(sizeof(NODE)); // 创建新链表的头节点
    l->n = -1;
    l->next = NULL;
    
    NODE *pC2 = l; // pC2 用于构建新链表的尾部
    NODE *pP = h; // pP 指向原始链表的头节点
    NODE *pC = h->next; // pC 指向原始链表的第一个实际节点
    
    int index = 1; // 初始化节点索引

    while (pC != NULL)
    {
        if(index%2 == 0)
        {
            pC2->next = pC;
            pC2 = pC;
            pP->next = pC2->next;
            pC = pC->next;
            pC2->next = NULL;

        }else{
            pP = pC;
            pC = pC->next;
        }
        
        index++; // 增加节点索引
    }

    return l;
}
#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
    int n;
    struct node *next;
}NODE;

NODE *init()    //初始化链表
{
    NODE *h = (NODE*)malloc(sizeof(NODE));  //创建一个头节点(方便指示指针回到开头和整体引用),后面一切操作不改变头节点
    h->n = -1;
    h->next = NULL;

    //尾部指针
    NODE *pR = h;
    
    int val = -1;
    while(1)
    {
        printf("Enter a number(-1 to End):\n");
        scanf("%d",&val);
        if(val==-1)
        {
            break;
        }

        //先创建新节点,再往里面填数据
        NODE *new = (NODE*)malloc(sizeof(NODE));
        new->n = val;
        new->next = NULL;

        //新节点插入到链表中
        pR->next = new;
        //更新尾部指针指向
        pR = new;   //pR这个帽子被新创建的结构体抢走了,这样才能让下一个更新的再抢走帽子
        
    }
    return h;
}

NODE *Select(NODE *h)
{
    NODE *l = (NODE*)malloc(sizeof(NODE)); // 创建新链表的头节点
    l->n = -1;
    l->next = NULL;
    
    NODE *pC2 = l; // pC2 用于构建新链表的尾部
    NODE *pP = h; // pP 指向原始链表的头节点
    NODE *pC = h->next; // pC 指向原始链表的第一个实际节点
    
    int index = 1; // 初始化节点索引

    while (pC != NULL)
    {
        if(index%2 == 0)
        {
            pC2->next = pC;
            pC2 = pC;
            pP->next = pC2->next;
            pC = pC->next;
            pC2->next = NULL;

        }else{
            pP = pC;
            pC = pC->next;
        }
        
        index++; // 增加节点索引
    }

    return l;
}





void Foreach(NODE *h)
{
    NODE *pC = h->next;
    if(h == NULL)
    {
        return;
    }
    while(pC != NULL)
    {
        printf("%d ",pC->n);
        pC = pC->next;
    }
}

int main()
{
    NODE *h = init();
    Foreach(h);
    NODE *l = Select(h);
    printf("\n");
    Foreach(h);
    printf("\n");
    Foreach(l);

    return 0;
}

效果

 

这里来个引申,上面不是说index%2==0吗,如果%n,就是第n的倍数项拿出来,也好理解,不多赘述

总结

经典文牒(折叠屏要是折了会流液体吗?)

我们有一些学到的知识

1、 *函数,返回一个类型的指针

2、计数器

3、画图思考

4、针对特定项有操作,还要思考非特定项有没有相关操作,考虑一下if else语句

以上均是本人理解,如有错误欢迎各位大佬评论区指出~

标签:NODE,pC2,next,链表,pC,3.0,C语言,节点
From: https://blog.csdn.net/dyudbegdu/article/details/144742939

相关文章

  • C语言一维数组与指针运算
    今天来着重讲解一下指针运算的方法遍历一维数组基本原理数组就是第一个数的地址,等价于一个指针,但是是开辟了空间的我就可以除了数组[]写法操作,也可以用指针指着操作,这里语法也十分重要,通过一道题咱们都领略一遍指针运算例题任务描述本关任务:编写程序,用指针实现以下功......
  • Linux第一课:c语言 学习记录day01
    0、大纲1、Linux命令2、基础内容:进制转换、词法符号、变量常量、输入输出3、语句:分支语句、循环语句、循环控制语句4、数组:一维数组、字符数组、排序、二维数组5、指针:一级指针、二级指针、指针和数组、指针数组、数组指针6、函数:函数基本用法、string函数族、开辟堆区空......
  • C语言插入排序及其优化
    插入排序算法详解插入排序是一种简单直观的排序算法。它通过构建有序序列,将未排序部分的元素插入到已排序部分的正确位置,直到所有元素排序完成。下面是插入排序的关键点及其实现细节。算法思想从第二个元素(下标为1)开始,假定左侧的子数组已排序。将当前元素与已排序部分逐一......
  • C语言数组名的理解
    一维数组intmain(){ inta[]={1,2,3,4}; printf("%zu\n",sizeof(a)); printf("%zu\n",sizeof(a+0)); printf("%zu\n",sizeof(*a)); printf("%zu\n",sizeof(a+1)); printf("%zu\n",sizeof(a[1])); prin......
  • OpenEuler23.03中磁盘挂载
    OpenEuler23.03中磁盘挂载一、fdisk磁盘分区(fdisk工具小于2T硬盘可用)参考:https://blog.csdn.net/changzhaohui/article/details/1401031671.查看分区情况1.1查看当前系统分区情况lsblk1.2查看当前磁盘数量情况fdisk-l2.创建磁盘挂载点mkdir-p/mnt/sdc3.创......
  • 链表移动:将前m个结点移动到链尾
     (......
  • 【北大计算概论A】【期末复习】专题1:链表
    链表的基本结构:单链表(1)单链表的创建#include<iostream>usingnamespacestd;structNode{intdata;Node*next;};Node*head,*p,*tail;intx;intmain(){cin>>x;head=newNode;//申请头结点tail=head;while(x!=-1){......
  • C语言里面的size_t是什么意思
    size_t是C语言中一个非常常用的数据类型,主要用于表示对象的大小或计数。它定义在<stddef.h>、<stdio.h>、<stdlib.h>等标准头文件中。以下是对size_t的详细解释:size_t的定义和用途定义:size_t是一个无符号整数类型(typedef定义),其具体大小依赖于编译器和平台。通......
  • 万字带你彻底搞懂 C语言| 文件IO还不懂?看这篇就够了
    目录一、前言(必看)文件访问方式对比二、系统调用接口2.1打开文件:open函数示例代码一:以只读方式打开test.txt文件,文件不存在则报错示例代码二:以只写方式打开文件test.txt,文件不存在则创建,文件存在则清空示例代码三:验证一个进程(现在可以理解成一个程序)能打开的最大文件......
  • c语言 - 如何安全返回局部变量的地址
    c语言返回局部变量的地址在C语言中,返回局部变量的地址是不安全的行为,因为一旦函数执行完毕,局部变量的内存将被释放,返回的地址将指向未定义的内存区域,这将导致不可预知的行为。以下是一个返回局部变量引用的例子,这是错误的做法:#include<stdio.h>int*getVarAddr()......