1.什么是链表?
连表示结构体变量与结构变量连接在一起
链表结点中既要存储数据,也要存储下一个结点的地址
因此链表结点通常由若干个数据成员(数据域)和指针成员(指针域)组成
最简单的链表中只包含一个数据域和一个指针域
例1,创建一个包含3个结点的简单链表,每个节点包含一个整形数据成员和一个指针成员
编程思路
首先定义链表节点结构体
struct node//链表结点结构体类型
{int data;//数据域
struct node *next;//指针域
};
struct node a,b,c;//链表节点结构体变量
指针域的next类型是struct node*(指向struct node类型的指针类型),因为next要只想下一个结点(struct node 类型)
2. 有了链表结点 如何构成链表?
访问连表示总是从第一个开始顺序访问,因此需要定义一个专门的指针,用于指向链表的第一个结点,并称之为头指针
struct node *head;//定义指针变量
head=&a;//令头指针指向第一个结点
然后,依次在链表结点的数据域中存入数据,并通过指针域将链表结点连接起来
scanf("%d",&a.data);//把输入的数据存入到a结点中的数据域中
a.next=&b;//a的指针指向b结点的地址
scanf("%d",&b.data);
b.next=&c;
scanf("%d",&c.data);
c.next=Null;
链表的末结点没有后继结点,故其指针域赋值为空指针NULL,表示不指向任何结点
在上述程序段中,有意的对代码进行简化,再用定义变量(即静态内存分配)的方式创建链表结点。这种链表成为静态链表
由于静态链表相对于数组来说不具备多少优势,因而很少使用
在实际应用中,通常使用动态链表。即采用动态内存分配方式创建链表结点
3.怎么动态创建链表?
内存的动态分配:
是指在程序运行过程中随时地分配与回收内存
动态分配方式,是通过调用专门的函数来实现的
***c语言中提供了专门动态分配内存的函数——malloc 函数
原型:void *malloc(unsigned int n)
功能:申请分配长度为N字节的连续内存。
若成功,则返回分配内存的首地址;若失败,则返回空指针NULL。
在程序调用该函数时,失败几率非常低,故一般不需要判断是否分配成功
void*是一种通用指针类型,它与所有其他指针类型都是赋值兼容的
例2.利用动态内存分配方式分配一个整型数据的内存空间。
1,可以用malloc函数实现动态内存分配
2,一个int型数据在内存中是不是一定要占用4个字节呢? 不一定,在不用的c语言编译器中,同一种类型的数据其内存长度有可能不同
3,为了提高程序的通用性,可以利用sizeof运算符求出某种数据类型的内存长度。如sizeof(int)
#include
#include//调用malloc函数
int main(void)
{
int *p;
p=(int*)malloc(sizeof(int));//动态分配内存,,,在上面调用了malloc函数,malloc函数的返回值是一个void*,而我直接赋值给p为int型了,所以要加一个强制转换符(int*)
*p=100;//j=间接引用所分配的内存
printf("%d\n",*p);
free(p);
return 0;
}
动态内存申请+模块化设计
<1>创建链表(创建一个表头来表示一个链表)
链表其实就是将若干个结构体变量,通过指针连接起来构成的数据结构
链表中的结构体变量成为链表的结点
链表中的结点既要存储数据,也要存储下一个结点的地址。
创建头结点(链表表头)
结构体指针怎么变成结构体变量?
typedef语句
在c语言中,可以使用typedef语句为已存在的数据类型定义一个类型的别名
其一般形式为
typedef 类型说明符 类型别名
typedef unsigned int UINT;//定义类型别名
UINT a,b;
等效于 unsigned int a,b;
可以利用typedef语句为结构体类型等定义别名,从而简化代码,增强程序的可读性
struct node
{int data;
struct node *next;
};
typedef struct node NODE;//定义类型别名
//从而NODE a,b,*p;
将等效于struct node a,b,*p;
内存的两种访问方式
1.随机访问方式
对数组来说,它的所有元素在内存中是连续存储的,因而很容易计算出每个元素的地址,从而可以直接访问数组中的任意一个元素
2.顺序访问方式
对于链表来说,不同的结点在内存中的存储位置是随机的,因而无法计算出每个结点的内存地址,从而只能从第一个结点开始依次访问
不带头结点的链表
若是将第一个结点的地址存储到一个专门的指针变量中,那么这种链表成为不带头结点的链表,用于存放第一个节点地址的指针变量成为头指针。
带头结点的链表
若是将第一个节点的地址存储到一个专门的结点的指针域中,那么这种链表成为带头结点的链表
:通过动态内存申请
<2>创建结点
<3>插入结点
<4>删除结点
<5>打印遍历链表()