单链表 定义:链表就是通过一组任意的存储单元(可任意连续,可以不连续)来存储线性表中的数据元素
定义:链表就是通过一组任意的存储单元(可任意连续,可以不连续)来存储线性表中的数据元素
单链表的结构
每个数据元素AI:
数据域:用来存储结点地数据值
指针域: 用来存储数据元素的直接后继的地址(或位置)
单链表的存储
单链表:A B C D E F G H
元素间存储物理关系不紧邻,逻辑关系紧邻
头结点的数据域可以存储标题、表长等信息,也可以不存储任何信息,其指针域存储第一个结点的首地址。
单链表的建立
头插法
思想:首先申请一个头结点,并且将头结点指针域置空(NULL);然后每读入一个数据元素则申请一个结点,并插在链表的头结点之后。
由于是在头部插入,所以数据的读入顺序和线性表中的逻辑顺序是相反的
struct Node *creat()
{
int x;
struct Node *h,*p,*q;
h=(struct Node *)malloc(sizeof(struct Node));
h->next=NULL;
scanf("%d",&x);
while(x!=-1)
{
q=(struct Node *)malloc(sizeof(struct Node));
q->data=x;
q->next=h->next;
h->next=q;
scanf("%d",&x);
}
return h;
}
尾插法
思想:在单链表的尾部插入节点建立单链表,简称“尾插法”。由于每次是将新结点插入到链表的尾部,所以增加一个指针r来始终指向链表中的尾结点,以便能够将新结点插入到链表的尾部。
由于是在尾部插入的,所以数据的读入顺序和线性表的逻辑顺序是一致的
struct Node *creat()
{
int x;
struct Node *h,*p,*q;
h=(struct Node *)malloc(sizeof(struct Node));
h->next=NULL;
p=h;
q=(struct Node *)malloc(sizeof(struct Node));
scanf("%d",&x);
q->data=x;
while(x!=-1)
{
p->next=q;
p=p->next;
scanf("%d",&x);
q=(struct Node *)malloc(sizeof(struct Node));
q->data=x;
}
p->next=NULL;
return h;
}
单链表的基本运算
单链表地插入
和创建类似。
void ListInsert_L(LinkList &L,int i,ElemType e){
//在带头结点的单链线性表L中第i个位置之前插入元素e
LinkList p=L;int j=0;
while(p&&j<i-1){
p=p->next;++j;
}//寻找第i-1个节点
if(!p||j>i-1) return ERROR;
LinkList s;
s=(LinkList)malloc(sizeof(LNode));
s->data=e;s->next=p->next;
p->next=s;
return OK;
}//ListInsert_L
单链表删除
思想:先找到这个数据所在结点,是头结点修改头结点,删除头结点,free该结点;不是头节点,直接删除该结点(使此结点的前驱直接等于此结点的后继,此结点的后继结点的前驱等于此结点的前驱)
void ListDelete_L (LinkList &L,int i,ElemType &e){
//在带头结点的单链表L中,删除第i个元素,并由e返回其值
LinkList p;
LinkList q;
p=L; int j=0;
while(p->next&&j<i-1){//寻找第i个节点,并令p指向其前驱
p=p->next;++j;
}
if(!(p->next)||j>i-1) return ERROR; //删除位置不合理
q=p->next;p->next=q->next;//删除并释放节点
e=q->data; free(q);
return OK;
}//ListDelete_L
存储空间的分配和释放
malloc函数
malloc原型: void* malloc(unsigned int size);
malloc(动态内存分配):申请一块连续的指定大小的内存块区域以void*类型返回分配的内存区域地址,当无法知道内存的具体位置时,想要绑定真正的内存空间,就需要用到动态的分配内存,且分配的大小就是程序要求的大小。
使用方法:
p=(LinkList)malloc(sizeof(LNode))
malloc和new的区别
1、new返回指定类型的指针,并且可以自动计算所需要的大小。
malloc必须要由我们计算字节数,并且在返回后强行转换为实际类型的指针。
2、malloc只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存,其值将是随机的。
calloc函数
calloc原型:void* calloc(unsigned int num,unsigned int size);
**calloc(动态内存分配并做初始化):**在内存的动态存储区中分配num个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。
num:对象个数 size:对象占据的内存字节数 calloc会自动将内存初始化为0
与malloc的区别
calloc在动态分配内存后,自动初始化该内存为0,而malloc不做初始化,分配到空间中的数据是随机数据。
relloc
free函数
free函数原型:void free(void *ptr)
free:释放之前调用calloc、malloc所分配的内存空间
如果一个指针删除之后,不进行释放,内存块无法再被程序使用,如果耗尽了内存池,会导致以后的临时申请语句申请失败