小甲鱼链表插入:
对链表的插入是指将一个结点插入到一个已有的链表中。
为了能做到正确插入,必须解决两个问题:
①怎样找到插入的位置;
②怎样实现插入。
我们可以先用指针变量p0指向待插入的结点,p1指向第一个结点,将p0->num与p1->num相比较,如果p0->num > p1->num,此时将p1后移,并使p2指向刚才p1所指的结点。
流程图如下,左边三个都是插入到链表中间(不是表头或表尾),右上角是插入到表头,右下角是插入到表尾。
流程图如下:
源码:
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#define LEN sizeof(struct student)//student结构的大小
struct student *creat();//创建链表
struct student *del(struct student *head,int num);//del函数用于删除结点,*head即链表
//的头指针,num是要删除的结点num。
struct student *insert (struct student *head,struct student *stu_2);//第一个参数需要被插入的链表
//第二个参数待插入的结构的地址
void print(struct student *head);//打印链表
struct student
{
int num;
float score;
struct student *next;
};
int n;//全局变量,用来记录存放了多少数据。
void main()
{
struct student *stu,*p,stu_2;
int n;
stu = creat();//返回head指针
p = stu;
print(p);//打印输出
printf("\nPls input the num to delete: ");
scanf("%d",&n);
print(del(p,n));//把head指针和n传进去del函数里面,调用完后再次打印,
//提示:每当调用完删除或者插入函数后,都要返回head重新打印一次
printf("\nPls input the num to insert: ");
scanf("%d",&stu_2.num);
printf("Pls input the score: ");
scanf("%f",&stu_2.score);
p=insert(stu,&stu_2);//调用插入函数,把head和stu_2的地址传进insert函数里面
print(p);
printf("\n\n");
system("pause");
}
struct student *creat()//把数据调进仓库里面
{
struct student *head;
struct student *p1,*p2;
p1 = p2 = (struct student *)malloc(LEN);//LEN是student结构的大小
printf("Pls enter the num: ");
scanf("%d",&p1->num);
printf("Pls enter the score: ");
scanf("%f",&p1->score);
head = NULL;
n = 0;
while(p1->num)
{
n++;
if(1 == n)
{
head = p1;
}
else
{
p2->next = p1;
}
p2 = p1;
p1 = (struct student *)malloc(LEN);//->
//新建一个student数据结构的对象,为其分配student结构所占用的内存空间。
//sizeof(struct student)为求该对象在内存中占用多少内存空间,然后用malloc函数分配同样大小的空间。
//将指针p1指向该对象,即新分配出的空间。
printf("\nPls enter the num: ");
scanf("%d",&p1->num);
printf("Pls enter the score: ");
scanf("%f",&p1->score);
}
p2->next = NULL;
return head;
}
void print(struct student *head)//把数据从仓库调出,此时无需要p1、p2等指针,直接用p
{
struct student *p;
printf("\nThere are %d records!\n\n",n);
p = head;
if(head)//如果输入的第一个学号就是0,既直接把NULL赋给head
{
do
{
printf("学号为 %d 的成绩是:%f\n",p->num,p->score);
p = p->next;//直接用p顺延下去
}while(p);//倘若p的next为NULL,既p=0,结束循环
}
}
struct student *del(struct student *head ,int num)
{
struct student *p1,*p2;
if(NULL == head)//如果头指针指向NULL,这是一个空链表。
{
printf("\nThis list is NULL\n");
goto end;
}
p1 = head;//从头结点开始寻找
while(p1->num != num && p1->next != NULL)//如果第一个结点的学号不是要删除的学号,而且存在第二个结点
//则使p2指向p1,再让p1顺延下去,直到找到要删除的数据为止。
{
p2 = p1;
p1 = p1->next;
}
if(num == p1->num)
{
if(p1 == head) //当将要删除的结点位于头结点的时候
{
head = p1->next;//直接跳过p1(head)指向的数据,让head指向p1的next
}
else //一般情况:如果要删除的数据不是头结点的数据
{
p2->next = p1->next;//跳过p1当前指向的数据,直接让p2的next指向p1的next
}
printf("\nDelete No: %d succeed!\n",num);
n = n-1;//n是作为一个全局变量,用来记录链表的数据数。
}
else
{
printf("%d not been found!\n",num);
}
end:
return head;
}
struct student *insert(struct student *head,struct student *stu_2)
{
struct student *p0,*p1,*p2;
p1=head;
p0=stu_2;
if(NULL==head)//如果是空表的话
{
head=p0;
p0->next = NULL;
}
else //如果不是空表的话
{
while((p0->num > p1->num) && (p1->next != NULL))//两种情况退出while,如果是要插入的
//元素p0比链表中任何一个元素都要大,既
//要插到表尾,则退出while,因为此时p1的
//next是空指针NULL。
{
p2=p1;
p1=p1->next;
}
if(p0->num <= p1->num)
{
if(head == p1) //p1是头结点,插入头部
{
head = p0;
}
else //普通情况,插入中间
{
p2->next=p0;//在p1指向了p1的next以后,p2的next要指向新插入的元素
}
p0->next = p1;
}
else //p0->num > p1->num,既p0的num最大,插入到末尾
{
p1->next = p0;
p0->next = NULL;
}
}
n=n+1; //由于插入了,所以增加了一位数据成员到链表中
return head;
}