简单的链表(输入并输出)

(阅读友情提示,将节点,结点看成同一个概念 输入法变来变去的 懒得改)
众所周知,单单的数组没有办法达到动态分配的效果。
因此,链表就产生了,来满足人们的欲望
我今天被链表折磨的简直难以想象
单单是见到这张图在这里插入图片描述
就已经心有余悸,一个下午不知见了多少次。
最终在他人的帮助,百度的查询(百度其实没啥鸟用)的艰难环境下
终于完成了最简单的单向链表
对链表或是结构体的概念让我有了更深一步的理解

As everyone knows
C语言或他弟 都是比较自由的语言 语法上不管咋写,咋缩进,if(不非法)都是可以的; 所以,对他的理解也是如此,只要对的,不管咋理解都是可以的(换而言之下面对链表的理解可能不对,请各位大佬以特别简单的方法指出。让在下好生研究研究)

首先完成咱们的头文件

#pragma once
#include<stdio.h>
#include<malloc.h>
struct student{
		int num;
		struct student* next;
};
typedef struct student stu;
stu* create();

#pragma once 这句表示防止重复包含头文件
这句以下都是对需要用到的头文件和函数 结构体的声明
typedef struct student stu;这句的关键字typedef 本来可以直接加在结构体前面
但是我觉得看着太麻烦就分开写了
这个头文件名为 list.h

接下来是名为create.cpp的文件

#include<list.h>
int n;
stu* create()
{
		n=0;
		stu* head,*p1,*p2;
		p1=p2=(stu*)malloc(sizeof(stu*));
		scanf_s("%d",&p1->num);
		head=NULL;
		while(1)
		{
			n++;
			if(n==1)
			{
					head=p1;
			}
			p2->next=p1;
			p2=p1;
			p1=(stu*)malloc(sizeof(stu*));
			scanf_s("%d",&p1->num);	
		}
   p2->next=NULL;	
		return head;
}

C语言中,要使用sizeof()不需要包含头文件,因为sizeof实际是C语言的一种单目运算符,也是关键字之一,可以直接使用。
sizeof 是运算符,而不是函数。虽然我们习惯sizeof(…),但( )并不是必需的,它只是表示优先级。我们把sizeof后面的目标叫对象或者操作数。本文约定就叫sizeof对象。(这段话百度找的,我以为sizeof用来计算数据长度,因此认为包含在string.h头文件中)
首先解释一下让我困惑很久,甚至在写这篇博客写到这里的时候还是想了许久的地方

p2->next=p1;
p2=p1;

首先,此处的p1已经不是上边的p1了,因为p2->next这个地方为p1,可以看做是将p1以前的值覆盖了(本人说法)
就像是把p1放在了p2的后面,就是创建了一个新的节点把上边的p1不管他是啥,覆盖了。然后p2=p1 p2通过创建的节点来跑到下一个位置
总而言之,便是 p2->next =p1 首先p2刚开始并没有下一个节点 因此将p2的下一个节点变成p1 不管p1是什么,都让p2有了下一个位置 通过p2=p1将p2移动到下一个位置,因为在循环中,不断的使用这样的方法,就可以不断的输入新的值。一直到最后p1为p2开辟新的节点是,我们假定新开的节点是有什么在的,因为p1是上一个节点的指针。因此让p2->next=NULL 输入结束后让最后一个节点的next为NULL保证这是最后一个节点。
然后 实际上在利用p1开辟新的节点的时候确实是没有什么的,这是我多疑了。因为用的是指针。因此,指针就像针一样插在哪个地方再拔出来,实际上根本什么都带不走。
所以,这个问题就这么解决了。
(同时让我明白了写博客确实可以让人进步不少,许多本来不知道或者是疑惑的地方,写着写着就明白了。)
又同时,我认为这个地方如果在加一个指针可能就不会出现我那种认为p1会带有上一个节点什么的情况了。

接下来是使我们的主函数所在的文件,名为源.cpp(本人比较懒,创建项目的时候懒得改)
主函数部分主要是对链表的遍历
当然也可以分成多个文件或函数写,但是本人比较懒
这个遍历就后好几种写法

#include<list.h>
int main()
{
		stu* p;
		p=create();
		while(1)
		{
				printf("\n%d",p->num);
				if(p->next !=NULL)
					p=p->next;
				else
					break;
		}
		return 0;
}

此代码首先做了一个恒真循环,p=create() 这里,因为这个函数返回了head的地址,所以p指向头结点(前提是头结点是要有数据的,有些人写链表就喜欢没有数据的头结点)
循环里的第一句输出了头结点的数据 如果头结点没有数据可能就要第一一个变量,通过分支不输出头结点
if分支里判断这个结点是不是还有下一个,如果有就跳到下一个节点,如果没有就break;
另外的写法

#include<list.h>
int main()
{
		stu* p;
		p=create();
		while(p!=NULL)
		{
				printf("\n%d",p->num);
					p=p->next;
		}
		return 0;
}

此处,循环是有条件的,如果p指向了空,就结束。我们都知道,链表的最后都是空指针
如果语句发现p是空指针了,就停止循环
如果不是空的就输出num 并且p跳到下一个节点。
这个地方我犯了一个错误,将判断条件写成了p->num
其实没有必要检查num是不是空的因为这个语句并不是检查下一个结点,而是在目前的结点检查,所以这个语句没有任何意义。

经群友的友情告知 链表是这个结点

这个节点就像是两条线交叉在一起形成的一个节点

而结点就像是树的分支的结点 (此处为本人理解,群友只是告知了链表是这个结点)

以上是对链表的概述 链表是个好东西 但是一错吓死人

(在下C语言小萌新 有什么不对的 希望用友好且极其极其简单的语言表达)两个极其是重点,圈起来要考的!!!

最后就是我们的镇店之图:
在这里插入图片描述

  • 25
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值