12 链表
12.1 链表概述
1.采用动态存储分配的一种重要数据结构,一个链表中存储的是一批同类型的相关联数据
2.动态分配时,每个结点之间可以不连续,结点之间的联系可以用指针实现,每个结点分两个域:数据域和指针域
12.2 处理动态链表所需函数(需要包含头文件stdlib.h)
1.分配内存空间函数malloc()
(1)函数调用形式:(类型说明符*)malloc(size)
(2)malloc函数要求系统在内存分配一块长度为size字节的连续区域,函数返回值为区域首地址
(3)函数返回的指针是无类型的,(类型说明符*)表示把返回值强制转换为该类型指针
(4)例如,p=(char*)malloc(100); //表示分配100个字节的内存空间,强制转换为字符数组类型,函数返回值为指向该字符数组的指针,把该指针赋给指针变量p
2.分配内存空间函数calloc()
(1)函数调用形式:(类型说明符*)calloc(n,size)
(2)calloc函数要求系统在内存动态存储区分配n块长度为size字节的连续区域
(3)例如,ps=(struct stu *)calloc(2,sizeof(struct stu));
3.释放内存空间函数free()
(1)函数调用形式:free§
(2)释放指针变量p所指向的一块内存区域
12.3 单链表基本操作
1.建立链表
(1)调用malloc()函数向系统申请一个结点的存储空间
(2)输入该结点的值,并把该节点的指针成员设置为0
(3)把该结点加入链表中,如果链表为空,则该结点为链表头结点,否则该结点加入表尾
2.链表查找
3.插入结点
(1)调用malloc()函数分配一个结点空间,并输入新节点的值
(2)查找合适的插入位置
(3)修改相关节点的指针域
4.删除结点
(1)从表头结点开始,确定要删除结点的地址q,以及q的前一个结点p的地址
(2)如果q为头结点,删除后应修改表头指针head,否则修改结点p的指针域
(3)回收结点q的空间
代码:
#include<stdio.h>
#include<stdlib.h>
struct node //定义结点结构
{
int num;
int score;
struct node *next;
};
//1.创建链表
struct node *creat(struct node *head,int n)
{
struct node *p,*q;
for(int i=1; i<=n; i++)
{
q=(struct node *)malloc(sizeof(struct node)); //申请结点空间
scanf("%d%d",&q->num,&q->score); //输入结点值
q->next=NULL; //指针成员设为NULL
if(head==NULL) //如果链表为空,该结点为链表头结点
{
head=q;
}
else //否则加入表尾
{
p->next=q;
}
p=q; //q赋给p,为下一次q开辟空间保留上一次结点地址
}
return head;
};
//2.输出链表
void print(struct node *head)
{
struct node *p;
p=head;
while(p!=NULL)
{
printf("%d %d\n",p->num,p->score);
p=p->next;
}
}
//3.链表查找
void find(struct node *head)
{
int x;
printf("请输入要查找的序号:\n");
scanf("%d",&x);
struct node *p;
p=head;
while(p!=NULL&&p->num!=x)
{
p=p->next;
}
if(p)
{
printf("num=%d\tscore=%d\n",p->num,p->score);
}
else
{
printf("%d not be found!\n",x);
}
}
//4.插入结点
struct node *insert(struct node *head)
{
struct node *p,*q,*p1;
q=(struct node*)malloc(sizeof(struct node)); //为新结点申请空间
printf("请输入要插入的结点(序号、分数):\n");
scanf("%d%d",&q->num,&q->score);
//在空表中插入
if(head==NULL)
{
q->next=NULL;
head=q;
return head;
}
//新结点插入表头之前
if(head->num > q->num)
{
q->next=head;
head=q;
return head;
}
//在链表中查找插入位置
p=head;
p1=head->next;
while(p1!=NULL&&p1->num < q->num)
{
p=p1; //循环结束后p是上一结点
p1=p1->next; //循环结束后p1是插入位置下一结点
}
q->next=p1;
p->next=q;
return head;
};
//5.删除结点
struct node *dele(struct node *head)
{
int i,x;
printf("请输入要删除的序号:\n");
scanf("%d",&x);
struct node *p,*q;
q=head;
while(q!=NULL&&q->num!=x)
{
p=q; //保留上一结点地址
q=q->next;
}
if(q==NULL)
{
printf("not found!");
}
else
{
if(q==head)
{
head=q->next;
}
else
{
p->next=q->next;
}
free(q);
}
return head;
};
int main()
{
struct node *head=NULL; //定义表头指针
head=creat(head,5);
print(head);
find(head);
head=insert(head);
print(head);
head=dele(head);
print(head);
return 0;
}