一、问题描述
数组的插入与删除是不灵活的,比如要给一串数字的中间插入一个数,那么数组至少一半的数得移动,才能插入这个数到正确的位置。这样的操作明显是费时间的。
相比之下,链表的操作很简单。
如何实现链表:指针+动态内存函数malloc()。
malloc()函数的作用:从内存中申请分配指定字节大小的内存空间。可以在程序运行的过程中根据实际情况来申请空间。
malloc(4)代表了申请了4个字节。int恰好是4个字节。
malloc()函数的返回类型是void类型。void表示没有确定指针类型,可以强制类型转换为任何其他类型的指针。
如下边就是强制类型转换为整型指针:
int *p;
p=(int *)malloc(sizeof(int));
使用malloc()要包含库stdlib.h
二、思路解析以及链表
1.指针定义:
int a;//定义了一个整型变量a
int *p; //定义了一个整型指针p
2.指针作用:
存储一个地址。
具体来说就是存储一个内存空间的地址,比如说变量a的地址。(严格的来说这里存储的是一个整数的内存空间)
整型指针p如何才能存储变量a的地址。可以形象的理解为整型指针p指向了整型变量a。
p=&a;
这样我们就可以用指针p来操作变量a了。
3.为什么区分指针类型:
因为指针变量存储的是一个内存空间的首地址(第一个字节的地址);
但是这个空间占用了多少字节,用来存储什么类型的数,则是由指针的类型来标明的。
4.链表中的每一个结点应该如何存储:
每一个结点都是由两个部分组成:
左边部分用来存储具体的数值(用一个整型变量就可以),
右边的部分存储下一个结点的地址,可以用指针来实现。(也称为后继指针)
这里我们用结构体类型来村春这个结点:
struct node{
int data;
struct node *next;
};
三、代码复现
1.通过操作指针来输出变量a的值。
#include<stdio.h>
int main(){
int a=10;
int *p;
p=&a;
printf("%d",*p);//输出指针p所指向的内存中的值
getchar();
getchar();
return 0;
}
2.如何建立链表
#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;//继续下一个结点
}
getchar();
getchar();
return 0;
}
//说明,这里么有动态free空间,理论上来说是错误的。