当前位置: 首页 > news >正文

0.单向链表的创建

链表是数据结构的基础内容,希望这篇文章尽量做到事无巨细,还请大家多多斧正。

1.链表的组成原理

2.单向链表的创建

3.链表的函数实现需要注意的问题


1.链表的组成原理 

想想一下一群人排成一条对,后面的人的手搭在前面的人的肩上。

这就构成了一条单向链表。(黑人问号脸???)

解释一下:

这里有四个小朋友编号为1,2,3,4

1把手搭2肩上依次向后然后4的手在空中

这样每个小朋友都有一个编号并且可以知道自己摸的小朋友的编号,除了最后一个小朋友外(指向NULL)

再来看看链表的原理图是不是好理解些了

总结一下单向链表的结构特点(划重点!!)

1.单向链表由多个相互联系的结点(Node)构成

2.每个结点由值和指向下一个结点的指针构成

3.有一个head指针作为标记指向初结点,最后一个结点中的指针指向NULL

是不是很好理解呢?嘿嘿嘿

2.单向链表的创建

啥也不说先上一段代码

typedef struct _node{
    int value;
    struct _node *next;
}Node;

 知识点:结构类型

创建了一个结构类型名字叫Node,这个结构中含有链表节点中的指针两个部分,我们以int类型的值举例

好了,我们创建好了单个节点了,现在我们要做的就是要把这些节点连起来!

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 typedef struct _node{
 5     int value;
 6     struct _node *next;
 7 }Node;
 8 
 9 int main(int argc, char const *argv[])
10 {
11     Node * head=NULL;
12     int number;
13     do{
14         scanf("%d",&number);
15         if(number!=-1){
16             //将number插入linklist
17             Node *p =(Node*)malloc(sizeof(Node));
18             //相当于创建了一个指向Node类型的指针并且开辟了一块空间储存Node结构所含变量
19             //malloc 返回结果为void*而需要Node*需要强制类型转换
20             p->value = number;
21             p->next = NULL;
22             
23             Node *last=head;
24             if(last){
25             while(last->next){
26                 last = last->next;
27             }
28             last->next = p;
29             }else{
30                 head = p;
31             }
32         }
33     }while(number!=-1);
34     return 0;
35 }

我们打算创建一个由从键盘中读取的整数组成的链表,每个新数据储存在上一个数据后面,直到读到-1结束。

下面我分行来解释一下。

基础知识点:动态分配内存,结构指针

11:声明一个指向Node的指针作为head    注意:这里head=NULL是必须的,未赋值的指针是很危险的,将随机指向任何一内存。

13:do-while循环很好理解,连续从键盘读取数字,然后执行循环体,直到-1时结束,-1将被抛弃。

17-21:敲黑板!重点来了。我们现在读取了一个number的量,我们需要把这个量放到一个节点Node里面,我们怎么办呢?

第一步:创造一个节点

  我们这里是用的是为指针动态分配内存的形式创造的结点,你可能说为什么不像下面写,一定要用到malloc

Node a;
Node *p=a;

原因就是动态!动态!动态!链表的最大特点就是其动态性,以后的删除就依赖这一特性,如果你没用malloc,就无法free掉这块内存,那你声明的这个结点未来就会永远存在,就算删除了也依旧会占据内存。

第二步:为这个节点赋值

这个容易理解,用刚声明的指针为这个结点的value和next赋值,由于我们是从末尾添加结点,所以next指向NULL

23-31:制造出了一个含有数据的结点然后我们需要干嘛?是这些结点形成关联,这是链表的核心。这里我的想法是,每要添加一个结点时,做一遍结点的遍历,找到最后的一个结点,然后把最后一个结点的next从NULL指向新的结点就可以了。

灵魂画师出场解释一下:

再敲黑板!!!这里尤其要注意第一个结点添加的情况 

1             Node *last=head;
2             if(last){
3             while(last->next){
4                 last = last->next;
5             }
6             last->next = p;
7             }else{
8                 head = p;
9             }

第一步:声明一个指针等于head,指向这个链表的第一个结点。

注意:当创建第一个结点时,我们的head实际上指向的是NULL,记得最开始创建head时候说的话吗。

这个时候我们是无法对一个空指针进行操作(->)的,所以我们用if(last)判断last是否为空,如果是的话就执行else中的head=p,让head指向了我们的第一个结点

第二步:从读入第二个数据开始,就可以开始遍历啦

刚才的last指向的是第一个结构,如果last->next不为NULL那么他就不是最后一个结构

那么就让last=last->next,指向下一个结构,直到last->next为NULL时,使Last->next=p,就完成了新增结点的链接。

 

链表创建大概就是这样啦!

撒花撒花,给灵魂画师点个赞,是不是很好理解呢~~~

3.链表创建的函数实现需要注意的问题

函数实现的意义我就不多说了,这里尤其要注意传址与传值的问题。

先上代码好喽

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 typedef struct _node{
 5     int value;
 6     struct _node *next;
 7 }Node;
 8 
 9 typedef struct _list
10 {
11     Node *head;
12 }List;
13 void creat_node(List *plist,int number);
14 
15 int main(int argc, char const *argv[])
16 {
17     List list1;//为链表1单独创建了一个结构
18     list1.head=NULL;
19 
20     int number;
21     do{
22         scanf("%d",&number);
23         if(number!=-1)
24         creat_node(&list1,number);//传入链表1的地址,指针指向该地址
25     }while(number!=-1);
26 }
27 void creat_node(List *plist,int number)
28 {
29             
30             Node *p=(Node *)malloc(sizeof(Node));
31             p->value=number;
32             p->next=NULL;
33             
34             Node *last=plist->head;
35             if(last)
36             {
37                 while(last->next)
38                     last=last->next;
39                 last->next=p;
40             }            
41             else
42                 plist->head=p;
43 }

 

还是刚才那个情景哈,读入数字直到-1。

怎么看起来变复杂了,不怕不怕,其实没啥。

typedef struct _list
 {
     Node *head;
 }List;

这一步是给每个链表定义了一个结构类型List,也就是说链表终于有自己的名字啦,以后可以定义List1 List2 List小王八等等等了

每个List类型里面包含了这个链表的head指针,确定了链表的身份。

void creat_node(List *plist,int number);

想用一个函数完成结点的创建和链接,这个函数需要什么参数呢?

很容易想到,需要一个链表,和希望写入结点的值。

我们知道,c语言函数传值的时候是拷贝传值,就是说将原值拷贝一份传入这个函数进行操作,我们是无法改变原值的,而我们现在是要改变原来的链表,就不能使用传值这种方式,所以我们得向这个函数传入原链表的地址。再用一个指针指向这个地址,完成对链表的修改。

 1 void creat_list(List *plist,int number)
 2 {
 3             
 4             Node *p=(Node *)malloc(sizeof(Node));
 5             p->value=number;
 6             p->next=NULL;
 7             
 8             Node *last=plist->head;
 9             if(last)
10             {
11                 while(last->next)
12                     last=last->next;//链接
13                 last->next=p;
14             }            
15             else
16                 plist->head=p;
17 }

既然传来了的是地址,那么函数中也要发生相应变化。

指针plist指向链表list1

创造结点过程还是没有变。

由于我们新建了一个链表的类型

所以原来Node*last=head变成了Node*last=plist->head。

后面遍历结点的过程就和前文的过程一样了。

 

传址是后续添加删除查找等操作的基础,后面的操作都会用函数的方式写了。


以上

 

转载于:https://www.cnblogs.com/clclcl/p/9834501.html

相关文章:

  • ×××计算机信息系统安全保护条例
  • 索引切片步长
  • DataGridView 密码列(显示为*号)的设置
  • Yeslab华为安全HCIE七门之--防火墙高级技术(17篇)
  • 七日瘦身汤
  • BZOJ 1022(博弈论)
  • 已经阅读过的Ajax文章资源
  • Linux10 ----------------进程 定时任务 僵尸进程
  • 过程决定质量——清华郑人杰教授谈软件测试
  • luigi 学习
  • oracle的substr函数的用法
  • 博客索引
  • 刚登录,有点感觉就想写下来
  • ubuntu 14.04 添加、删除用户,修改用户名称,修改主机名
  • 本博客迁移到 http://www.cleocn.com , 该站使用SharePoint 2007 Blog模板架设
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • [译]前端离线指南(上)
  • css的样式优先级
  • Fundebug计费标准解释:事件数是如何定义的?
  • Go 语言编译器的 //go: 详解
  • Linux快速复制或删除大量小文件
  • Map集合、散列表、红黑树介绍
  • text-decoration与color属性
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • Twitter赢在开放,三年创造奇迹
  • Windows Containers 大冒险: 容器网络
  • 如何进阶一名有竞争力的程序员?
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • #QT(一种朴素的计算器实现方法)
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • ( 10 )MySQL中的外键
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (编译到47%失败)to be deleted
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (初研) Sentence-embedding fine-tune notebook
  • (二)springcloud实战之config配置中心
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (新)网络工程师考点串讲与真题详解
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)Linux整合apache和tomcat构建Web服务器
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • *上位机的定义
  • .describe() python_Python-Win32com-Excel
  • .equals()到底是什么意思?
  • .net framework profiles /.net framework 配置
  • .net项目IIS、VS 附加进程调试
  • [ 蓝桥杯Web真题 ]-布局切换
  • [Angular] 笔记 16:模板驱动表单 - 选择框与选项
  • [C++] 多线程编程-thread::yield()-sleep_for()
  • [C++][数据结构][算法]单链式结构的深拷贝
  • [iOS]GCD(一)