1,为什么要用到链表

数组作为存放同类数据的集合,给我们在程序设计时带来很多的方便,增加了灵活性。但数组也同样存在一些弊病。如数组的大小在定义时要事先规定,不能在程序中进行调整,这样一来,在程序设计中针对不同问题有时需要3 0个大小的数组,有时需要5 0个数组的大小,难于统一。我们只能够根据可能的最大需求来定义数组,常常会造成一定存储空间的浪费。

我们希望构造动态的数组,随时可以调整数组的大小,以满足不同问题的需要。链表就是我们需要的动态数组。它是在程序的执行过程中根据需要有数据存储就向系统要求申请存储空间,决不构成对存储区的浪费。

链表是一种复杂的数据结构,其数据之间的相互关系使链表分成三种:单链表、循环链表、双向链表,下面将逐一介绍。

2,单向链表

单链表有一个头节点head,指向链表在内存的首地址。链表中的每一个节点的数据类型为结构体类型,节点有两个成员:整型成员(实际需要保存的数据)和指向下一个结构体类型节点的指针(它是节点类型)即下一个节点的地址(事实上,此单链表是用于存放整型数据的动态数组)。链表按此结构对各节点的访问需从链表的头找起,后续节点的地址由当前节点给出。无论在表中访问那一个节点,都需要从链表的头开始,顺序向后查找。链表的尾节点由于无后续节点,其指针域为空,写作为NULL

如图所示

上图还给出这样一层含义,链表中的各节点在内存的存储地址不是连续的,其各节点的地址是在需要时向系统申请分配的,系统根据内存的当前情况,既可以连续分配地址,也可以跳跃式分配地址。

3,单向链表程序的实现

(1),链表节点的数据结构定义

struct node
{
int num;
struct node *p;
} ;

在链表节点的定义中,除一个整型的成员外,成员p是指向与节点类型完全相同的指针。

在链表节点的数据结构中,非常特殊的一点就是结构体内的指针域的数据类型使用了未定义成功的数据类型。这是在C中唯一规定可以先使用后定义的数据结构。

(2),链表的创建、输出步骤

单链表的创建过程有以下几步:

1 ) 定义链表的数据结构(即定义节点的数据结构);

2 ) 创建一个空表;

3 ) 利用malloc ( )函数向系统申请分配一个节点;

4 ) 将新节点的指针成员赋值为空。若是空表,将新节点连接到表头;若是非空表,将新

节点接到表尾;

5 ) 判断一下是否有后续节点要接入链表,若有转到3 ),否则结束;

单链表的输出过程有以下几步

1) 找到表头;

2) 若是非空表,输出节点的值成员,是空表则退出;

3 ) 跟踪链表的增长,即找到下一个节点的地址;

4) 转到2 ).

(3),程序代码例子:

创建一个存放正整数单链表,输入0或小于0的数,结束创建链表,并打印出链表中的值,程序如下:

#include <stdlib.h> /*含ma l l o c ( ) 的头文件*/
#include <stdio.h>
struct node //①定义链表数据结构
{
int num;
struct node *next;
};
main( )
{
struct node *creat();
void print();
struct node *head;
head=NULL; //②建一个空表
head=creat(head);/*创建单链表*/
print(head);/*打印单链表*/
}
/******************************************/
struct node*creat(struct node *head)/*返回的是与节点相同类型的指针*/
{
struct node*p1,*p2;
//③利用malloc ( )函数向系统申请分配一个节点
p1=p2=(struct node*)malloc(sizeof(struct node));/*新节点*/
printf("p1= %d\n",p1);
scanf("%d",&p1->num);/*输入节点的值*/
p1->next=NULL;/*将新节点的指针置为空*/
while(p1->num>0)/*输入节点的数值大于0*/
{
//④将新节点的指针成员赋值为空。若是空表,将新节点连接到表头;若是非空表,将新
//节点接到表尾;
if(head==NULL)
head=p1;/*空表,接入表头*/
else
p2->next=p1;/*非空表,接到表尾*/
p2=p1;
p1=(struct node*)malloc(sizeof(struct node));/*下一个新节点*/
printf("p2= %d\n",p2);
scanf("%d",&p1->num);/*输入节点的值*/
//⑤判断一下是否有后续节点要接入链表,若有转到3 ),否则结束;
}
printf("p2->next=%d\n",p2->next);
return head;/*返回链表的头指针*/
}
/*******************************************/
void print(struct node*head)/*出以head为头的链表各节点的值*/
{
struct node *temp;
temp=head;/*取得链表的头指针*/
while(temp!=NULL)/*只要是非空表*/
{
printf("%6d",temp->num);/*输出链表节点的值*/
temp=temp->next;/*跟踪链表增长*/
}
}

编译后执行:

p1= 140660744  //链表头

1

p2= 140660760

45

p2= 140660776

6

p2= 140660792

77

p2= 140660808

88

p2= 140660824

0                               //输入0结束增加链表

p2->next=0       //链表结尾

1       45    6    77    88          //输出链表的值。

在链表的创建过程中,链表的头指针是非常重要的参数。因为对链表的输出和查找都要从链表的头开始,所以链表创建成功后,要返回一个链表头节点的地址,即头指针

程序执行流程:

C语言单向链表的更多相关文章

  1. c语言单向链表逆转实现方法

    自己理解的思路如下所示: 从第二个节点开始,先记录下一个节点,把第二个节点移到头节点之前,头节点变为移动的这个节点之前记录的节点变为接下来要移动的节点用for循环重复最后把原来头节点变成尾节点(*ne ...

  2. C语言通讯录系统——C语言单向链表实现

    实现的通讯录功能有:查看通讯录.添加联系人.删除联系人.查询联系人.保存并退出. 通过txt文件保存和读取通讯录数据. #include <stdio.h> #include <st ...

  3. ZT C语言链表操作(新增单向链表的逆序建立)

    这个不好懂,不如看 转贴:C语言链表基本操作http://www.cnblogs.com/jeanschen/p/3542668.html ZT 链表逆序http://www.cnblogs.com/ ...

  4. C语言实现单向链表及其各种排序(含快排,选择,插入,冒泡)

    #include<stdio.h> #include<malloc.h> #define LEN sizeof(struct Student) struct Student / ...

  5. C语言基础 - 实现单向链表

    回归C基础 实现一个单向链表,并有逆序功能 (大学数据结构经常是这么入门的) //定义单链表结构体 typedef struct Node{ int value; struct Node *next; ...

  6. C语言:创建动态单向链表,创建完成后,输出每一个节点的数据信息。

    // //  main.c //  dynamic_link_list // //  Created by ma c on 15/8/5. //  Copyright (c) 2015. All ri ...

  7. C语言实现简单的单向链表(创建、插入、删除)及等效STL实现代码

    实现个算法,懒得手写链表,于是用C++的forward_list,没有next()方法感觉很不好使,比如一个对单向链表的最简单功能要求: input: 1 2 5 3 4 output: 1-> ...

  8. C语言:将ss所指字符串中所有下标为奇数位上的字母转换成大写,若不是字母,则不转换。-删除指针p所指字符串中的所有空白字符(包括制表符,回车符,换行符)-在带头结点的单向链表中,查找数据域中值为ch的结点,找到后通过函数值返回该结点在链表中所处的顺序号,

    //将ss所指字符串中所有下标为奇数位上的字母转换成大写,若不是字母,则不转换. #include <stdio.h> #include <string.h> void fun ...

  9. C语言:将带头节点的单向链表结点域中的数据从小到大排序。-求出单向链表结点(不包括头节点)数据域中的最大值。-将M*N的二维数组中的数据,按行依次放入一维数组,

    //函数fun功能是将带头节点的单向链表结点域中的数据从小到大排序. //相当于数组的冒泡排序. #include <stdio.h> #include <stdlib.h> ...

随机推荐

  1. nginx php上传配置

    .file_uploads 设为On,允许通过HTTP上传文件 2.upload_tmp_dir 文件上传至服务器时用于临时存储的目录,如果没指定,系统会使用默认的临时文件夹(我的机器是/tmp). ...

  2. ArcGIS API for Javascript 加载天地图(墨卡托投影)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  3. golang社区

    a development list for Go Programming Language https://groups.google.com/forum/#!forum/golang-dev a ...

  4. a:hover标签已经定义了text-decoration:none,并且生效,但是还是有下划线

    a标签在F12计算出来的样式里 text-decoration:none; 确实有被应用到.但是链接的下划线并没有被去掉... 解决办法:p:commandLink <p:commandLink ...

  5. 视觉SLAM的方案总结

    MoNoSLAM:https://github.com/hanmekim/SceneLib2 以扩展卡尔曼滤波为后端,追踪前端非常稀疏的特征点,以相机的当前状态和所有路标点为状态量,更新其均值和协方差 ...

  6. MySQL字符串相关函数学习二

    ① LOWER(str):将字符串转为小写:与此函数具有相同作用的函数有LCASE() 如果参数是小写.数字或其他特殊字符,则返回原数据 ② LEFT(str, len):返回字符串str左边的len ...

  7. Java笔记:开发环境

    Java开发环境 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称.由James Gosling和同事们共同研发,并在1995年正 ...

  8. VMware虚拟机下为Ubuntu添加磁盘

    20G的磁盘还是不够用啊,正好复习下磁盘分区和逻辑卷. 关闭虚拟机,打开VMware,右键虚拟机点击设置,点下下方的添加,就可以添加磁盘了. 进入虚拟机,查看: root@ubuntu:/# fdis ...

  9. 微信支付接口开发之---微信支付之JSSDK(公众号支付)步骤

    1.准备     1.1.公众号为服务号,开通微信支付功能     1.2.为了方便调试微信后台的回调URL(必须为外网),我用了nat123软件来做一个映射     1.3.官方微信开发的示例WxP ...

  10. 深入设计电子计算器(一)——CPU指令集设计

    版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖.如要转贴,必须注明原文网址 http://www.cnblogs.com/Colin-Cai/p/8254096.html 作者:窗户 Q ...