单向链表的介绍及创建
链表的定义:
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。有时使用数组时显得不灵活,这时候使用链表,比如插入,删除等时比较好用。
链表的实现
C语言中可以使用指针和动态分配内存函数 malloc 来实现。
#include<stdio.h>
int main()
{
int a=100;
int *p;//定义一个指针p
p=&a;//指针p获取变量a的地址
printf("%d",*p);//输出指针p所指向的内存中的值
return 0;
}
运行结果
10
指针及动态空间的申请
指针的作用:存储一个地址。确切的说是存储一个内存空间的地址。比如说整型变量 a 的地址。严格的说这里的指针 p 也只能存储“一个存放整数内存空间”的地址,在前面定义的时候已经限制了这一点(即定义的时候 p 前面的是int)。
这里printf语句里的 * 号叫做间接访问运算符,作用是取得指针p所指向的内存中的值。
在C语言中*号有三个用途:
1.乘号,用作乘法运算。例如:5*6;
2.声明一个指针变量,在定义时指针变量是使用。例如 int *p;
3.间接访问运算符,取得指针所指向的内存中的值,例如 printf("%d",*p).
在程序中存储一个整数10,除了使用 int a;这种方式在内存中申请一块区域存储,还有另外一种动态存储方法
malloc(4);
molloc函数的作用是从内存中申请分配指定大小的内存空间,上面表示申请了4个字节,也可以如下写:
malloc(sizeof(int));
现在需要指针来指向这个空间,即存储空间的首地址。
int *p;
p=(int *)malloc(sizeof(int));
**malloc函数的返回值是void *类型,void 表示未确定类型的指针。在C或C++中,void 可以强制转化为任何其他类型的指针。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *p;//定义一个指针p
p=(int *)malloc(sizeof(int));//指针p获取动态分配的内存空间地址
*p=10;//向指针p所指向的内存空间存储10
printf("%d",*p);//输出指针p所指向的内存中的值
return 0;
}
运行结果
10
链表中结点的存储
每个结点都由两部分组成,左边的部分用来存放具体的数值,那么用一个整型变量就可以。右边的部分需要存储下一个结点的地址,可以用指针来实现(也称后继指针)。
struct node
{
int data;
struct node *next;
};
定义一个叫做node 的结构体类型,这个结构体有两个成员,第一个成员是整型data,用来存储具体的数值;第二个成员是一个指针,用来存储下一个结点的地址。因为下一个结点的类型为struct node ,所以这个指针的类型必须为struct student 类型的指针。
建立链表需要一个头指针 head指向链表最开始。当链表没有建立时头指针为空。
struct node *head;
head=NULL;//头指针指向为空
现在创建第一个结点,并用临时指针p指向这个结点。
struct node *p;
p=(struct node *)malloc(sizeof(struct node));
scanf("%d",&a);
p->data=a;//数据存储到当前的data域
p->next=NULL;//设置当前结点的后继指针指向空
上面的代码中的 “->”:结构体指针运算符,也是用来访问结构体内部成员的。此处p是一个指针,不能用 . 来访问内部成员,所以要使用->。
链表的创建
#include<stdio.h>
#include<malloc.h>
struct node
{
int data;
struct node *next;
};
int icount;
struct node *creat()//链表的创建
{
struct node *pnew,*pend,*phead=NULL;
pend=pnew=(struct node *)malloc(sizeof(struct node));
printf("data:");
scanf("%d",&pnew->data);
icount=0;
while(pnew->data!=0)
{
++icount;
if(icount==1)
{
phead=pnew;//若为第一个创造的结点,则头指针指向这个结点
}
else
{
pnew->next=NULL;//新结点的指针指向为空
pend->next=pnew;//上一个结点的后继指针指向当前的结点
pend=pnew;//指针pend指向当前结点
}
pnew=(struct node *)malloc(sizeof(struct node));
printf("data:");
scanf("%d",&pnew->data);
}
free(pnew);//释放结点
return phead;//返回头指针,找到头指针就可以遍历链表
}
void print(struct node *phead)
{
struct node *ptemp;
ptemp=phead;
printf("output:\n");
while(ptemp!=NULL)
{
printf("%d\n",ptemp->data);
ptemp=ptemp->next;
}
}
int main()
{
struct node *phead;
phead=creat();
print(phead);
}
运行结果
data:23
data:34
data:45
data:78
data:0
output:
23
34
45
78