数组在存储好多数时不够灵活,但是用链表则会快很多。
那么如何实现链表,在c语言中可以使用指针和动态分配内存函数malloc来实现。
int *p
指针的作用:存储一个内存空间的地址,简单地说指针就是用来存储地址的。
整型指针p存储整型变量a的地址
p=&a;
&是取地址符,这样整型指针p就获得了整型变量a的地址,我们可以形象的理解为整型指针p指向整型变量a。
#include<stdio.h>
int main()
{
int a=10;
int *p;
p=&a;
printf("%d",*p);
rreturn 0;
}
printf中的* p的星号叫做间接访问运算符,作用是取得指针p所指向的内存中的值。
malloc函数的作用是从内存中申请分配指定字节大小的内存空间。
malloc(sizeof(int));//从内存中申请了4个字节的空间来准备存放一个整数
int *p;
p=(int *)malloc(sizeof(int));//储存这个空间的首地址
链表的每一个结点都由两部分组成。左边部分用来存放具体数值,右边部分需要存储下一个节点的地址,可以用指针实现
struct node
{
int data;
struct node *next;
}
这个结构体类型有两个成员。第一个成员是整型data,用来储存具体的数值;第二个成员是一个指针,用来存储下一个结点的地址。
建立链表,首先需要一个头指针head指向链表的开始。当链表还没有建立时头指针head为空
struct node *head;
head=NULL;//头结点初始为空
现在创建第一个结点,并用临时指针p指向这个结点
struct node *p;
p=(struct node *)malloc(sizeof(struct node));//动态申请一个空间,用来存放一个结点,并用临时指针p指向这个结点
接下来分别设置新创建的这个结点的左半部分和右半部分
scanf("%d",&a);
p->data=a;
p->next=NULL;
下面来设置头指针,方便以后从头遍历整个链表
if(head==NULL)
{
head=p;//如果这是第一个创建的结点,则将头指针指向这个结点
}
else
q->next=p; //如果这不是第一个创建的结点,则将上一个结点的后继指针指向当前的结点
完整代码如下
#include<stdio.h>
#include<stdlib.h>
//这里创建一个结构体用来表示链表的节点类型
struct node
{
int data;
struct node *next;
};
int main()
{
struct node *head,*p,*q,*t;
int i,n,a;
scanf("%d",&n);
head=NULL;//头指针初始为空
for(i=1;i<=n;i++)//循环读入n个数
{
scanf("%d",&a);
//动态申请一个空间用来存放一个节点,并用临时指针p指向这个结点
p=(struct node *)malloc(sizeof(struct node));
p->data=a;//将数据存储在data中
p->next=NULL;//设置当前结点的后继指针指向空
if(head==NULL)
{
head=p;//如果这是第一个创建的结点,则将头指针指向这个结点
}
else
q->next=p; //如果这不是第一个创建的结点,则将上一个结点的后继指针指向当前的结点
q=p;//指针q也指向当前结点
}
//输出链表中的所有数
t=head;
while(t!=NULL)
{
printf("%d ",t->data);
t=t->next;//继续下一个结点
}
return 0;
}
当要在链表中插入6时
首先用一个临时指针t从链表的头部开始遍历
t=head;
当指针指向的下一个结点比6大时,将6插入到中间。即t->next->data大与6时进行插入,
scanf("%d",&a);//读入待插入的数
while(t!=NULL)//当没有到达链表尾部时循环
{
if(t->next->data>a||t->next==NULL)
{
p=(struct node *)malloc(sizeof(struct node));//动态申请一个空间,用来存放新增节点
p->data=a;
p->next=t->next;//新增结点的后继指针指向当前结点的后继指针所指向的结点
t->next=p;//当前结点的后继指针指向新增结点
break;
}
t=t->next;//继续下一个结点
}