链表的概念
问题?
假如: 做一个班级信息管理系统, 统计班级学生的信息。而我们事先不知道班级人数, 或者知道人数,
但是中间人员可能发生变化: 比如有新同学加入, 有同学请假, 又或者我们需要统计班级的平均
成绩等等
假如: 要做一个类似 QQ、 飞秋类似的通信软件, 其中有一个功能, 类似用户上下线检测: 有新的
用户上线、 下线,实时更新显示, 可以实时查询在线状态、 按姓名排序等
以上问题如何使用学过的 C 语言知识处理呢?
使用数组远远不能达到我们的要求
因为数组必须实现确定大小, 不能实现动态申请、 释放
使用 malloc 动态内存分配也无法实现
malloc 申请的空间, 不能实现局部申请、 释放
这里我们学习一种很强大也很重要的数据结构——链表
1.1定义
链表是一种物理存储上非连续, 数据元素的逻辑顺序通过链表中的指针链接次序, 实现的一种线性存储结构。
1.2特点
链表由一系列节点(链表中每一个元素称为节点) 组成, 节点在运行时动态生成(malloc) , 每个节点包括两个部分:
一个是存储数据元素的数据域
另一个是存储下一个节点地址的指针域
![](https://img-blog.csdnimg.cn/img_convert/7131adbe15ff4c4d9ac7a35193d8fc68.png)
链表的构成
链表由一个个节点构成, 每个节点一般采用结构体的形式组织, 例如:
typedef struct student
{
int num;
char name[20];
struct student *next;
}STU;
2.1链表节点分为两个域
数据域: 存放各种实际的数据, 如: num、 score 等
指针域: 存放下一节点的首地址, 如: next 等.
![](https://img-blog.csdnimg.cn/img_convert/d8ed8586d96ba11ab164069900b8d7a0.png)
链表的创建
typedef struct student
{
int num;
int score;
char name[20];
struct srudent *next;
}STU;
vodi linkCreat(STU**p_head,STU*p_new)
{
STU *p_mov = *p_head;
if(*p_mov == NULL)
{
p_mov->next=p_new;
p_new->next = NULL;
}
else
{
while(p_mov->next!=NULL)
{
p_mov=p_mov->next;
}
p_mov->next=p_new;
p_new->next = NULL;
}
}
int main()
{
STU *head =NULL,*p_new=NULL;
int num,i;
printf("请输入链表的初始个数:\n");
scanf("%d",&num);
for(i=0;i<num;i++)
{
p_new = (STU*)(malloc(sizeof(STU)));
printf("请输入学号、分数、姓名:\n");
scanf("%d %d %s",&p_new->num,&p_new->score,&p_new->name );
link_creak(&head,p_new);
}
}
链表的遍历
void link_print(STU *head)
{
STU *p_mov = haed;
while(p_mov!=NULL)
{
printf("学号:%d,分数:%d,姓名:%s",p_mov->num,p_mov->score,p_mov->name);
p-mov=p_mov->next;
}
}
链表的释放
void link_free(STU*head)
{
STU*p_mov=head;
whlie(head!=NULL)
{
p_mov=head;
head=head->next;
free(p_mov);
}
}
链表节点的查找
STU * link_search_num(STU*head,int num)
{
STU*p_mov=head;
while(p_mov!=NULL)
{
if(p_mov->num==num)
{
return p_mov;
}
p_mov=p_mov->next;
}
return NULL;
}
链表节点的删除
void link_delete_num(STU**head , int num)
{
STU*p_mov=*head;
STU*pb=p_mov;
if(*p_head ==NULL)//链表为空,不用删
{
printf("链表为空,没有您要删的节点");\
return ;
}
if(p_mov->num==num)//要删除的是头节点
{
*head=*head->next;
}
else
{
p_mov=p_mov->next;
}
while(p_mov!=NULL)
{
if(p_mov->num==num)//找到要删除的节点
{
pb->next=p_mov->next;
free(p_mov);
}
pb=p_mov;
p_mov=p_mov->next;
}
}
链表中插入一个节点
头插法:
void link_insert(STU**head,STU*p_new)
{
STU*p_mov=*head;
if(*head==NULL)//空链表
{
*head=p_new;
p_new->next==NULL;
}
p_new->next=p_mov;
*p_head=p_new;
}
尾插法:
void link_insert(STU**head,STU*p_new)
{
STU*p_mov=*head;
if(*head==NULL)//空链表
{
*head=p_new;
p_nw->next==NULL;
}
while(p_mov->next=NULL)
{
p_mov=p_mov->next;
}
p_mov->next=p_new;
p_new->next=NULL:
}
链表排序
void link_order(STU*head)
{
STU*pb,*pf,temp;
pf=head;
if(head==NULL)//空链表
{
printf("空链表不用排序\n");
}
if(head->next==NULL)
{
printf("只有一个节点也不用排序\n")
}
while(pf->next!=NULL)
{
pb=pf->next;
while(bp!=NULL)
{
if(pf->num>pb->num)
{
temp=pb;
pb=pf;
pf=temp;
temp->next=pb->next;
pb->next=pf->next;
pf->next=temp->next;
}
pb=pb->next;
}
pf=pf->next;
}
}
链表逆序
STU* link_reverse(STU*head)
{
STU*pf,*pb,*r;
pf=head;
pb=pf->next;
while(head==NULL)printf("空链表\n");
while(pb!=NULL)
{
r=pb_next;
pb->next=pf;
pf=pb;
pb=r;
}
head->next=NULL;
head=pf;
return head;
}
双向链表的创建
typedef struct student
{
int num;
int score;
char name[20];
struct student *front;
struct student *next;
}STU;
void double_link_create(STU**head,STU*p_new)
{
STU *p_mov=*head;
if(*head==MULL)
{
*head = p_new;
p_new->next = NULL:
p_new->front=NULL;
}
else
{
while(p_mov->next!=NULL)
{
p_mov=p_mov->next;
}
p_mov->next=p_new;
p-new->next=NULL:
p_new->front=p_mov;
}
}
双向链表节点的删除
void double_link_delete_num(STU**head,int num)
{
STU*pb,*pf;
pb=*head;
if(*head == NULL)
{
printf("空链表\n");
return ;
}
while(pb->num==num&&pb->next!=NULL)
{
pb=pb->next;
}
if(pb->num==num)
{
if(pb==*head)
{
head=head->next;
head->front=NULL;
}
else
{
if(pb->next!=NULL)//要删除的是中间节点
{
pf=pb->front;
pf->next=pb->next;
(pb->next)->front=pf;
}
else//要删除的是尾节点
{
pf=pb->front;
pf->next=NULL;
}
}
}
}
双向链表插入节点
头插法:
void double_link_insert(STU**head,STU*p_new)
{
if(*head==NULL)
{
*head = p_new;
p_new>next=NULL;
p_new->front=NULL;
}
else
{
p_new->next = *head;
p_new->fornt=NULL;
*head = p_new;
}
}
尾插法:
void double_link_insert(STU**haed,STU*p_new)
{
STU*p_mov=*head;
if(*head==NULL)
{
*head = p_new;
p-new>next=NULL;
p_new->front=NULL;
}
while(p_mov->next!=NULL)
{
p_mov=p_mov->next;
}
p_mov->next=p_new;
p_new->front=p_mov;
p_new->next =NULL:
}