链表的插入操作_Joaquin233的博客-程序员宅基地

小甲鱼链表插入:
对链表的插入是指将一个结点插入到一个已有的链表中。

为了能做到正确插入,必须解决两个问题:
①怎样找到插入的位置;
②怎样实现插入。

我们可以先用指针变量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;
}				

在这里插入图片描述
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Joaquin233/article/details/111072748

智能推荐

Doc批量转成Docx_c++ doc转docx-程序员宅基地

Doc批量转成Docx在工作中遇到需要将word文档中的doc转换成docx的需求,一共有大几百个文件,这种就不太可能一个个去转换了,文件太多效率太低了。VBA环境经过一顿查找之后确定使用Office的VBA(Microsoft Visual Basic for Applications)去做相应转换,它是Office自带的,一般不需要额外安装,转换之后兼容性也比较好。VBA环境开启步骤:打开任意一个word文档,Office版本按下Alt+F11快捷键即可看到VBA的编译环境语法这里需要_c++ doc转docx

Java中break,continue,return的用法_java continue和break和return正确的是_胖阿全的博客-程序员宅基地

JAVA中break,continue,return的用法1.break用于中断break所在的循环,执行后续语句2.continue用于中断本次循环,进入下一次循环,不会执行本次循环中continue之后的语句3.加上标识符aa:中断循环,返回aa处4.return用于中断方法的执行,立即返回调用处,不会执行当前方法中后续的所有操作。break中断public class Test {public static void main(String[] args) {for(int i=1;i_java continue和break和return正确的是

C++ 开发SOAP服务端和SOAP客户端_soap开源cpp client-程序员宅基地

C++ 开发SOAP服务端和SOAP客户端作者:flyfish 2012-5-12目的:利用gSOAP自带的Calc例子 仿写一个 网络中使用计算器客户端通过http发送xml格式的数据请求,服务端计算完之后,将结果以xml格式返回给客户端。编写之后 我们的服务端可独立使用。像在安装了IIS或者用Apache配置的Web服务器。gSoap版本 2.8.8 编译环境为_soap开源cpp client

qss设置平面按钮_Qt5.9中QSS(qt Style Sheet)用法之一设置按钮颜色和背景色(设置按钮间相互间隔、设置按钮与周围边缘间隔)..._杨真直的博客-程序员宅基地

本博客主要总结用QSS(qt Style Sheet/qt样式表)来设置QPushButton的背景色和字体颜色用法。在Qt中,常用控件都可以用QSS来设置颜色和背景,下面本文将举一个实例,示范QSS用法。本文实例的主要内容是,设置两个pushbutton按钮的字体颜色和背景色。同时,本文也总结了利用布局管理器,设置两个按钮跟上下空间距离,以及两个按钮相互之间距离,具体的实例如下代码所示:小结::..._qss 按钮样式

论文常用词汇i.e.,e.g.,etc.,viz.,et al.的前世今生 薛动谔的喵-程序员宅基地

转载:https://zhuanlan.zhihu.com/p/63640148前言:今天写英文论文,刚好用到that is to say(也就是说),突然想起平时阅读文献时的表达方式i.e.,就想着查一下它的词源,一查之下,才知道i.e.是拉丁文的缩写,原词为拉丁语id est。而且,无独有偶,像平时文献中遇到的e.g.,etc.,viz.,et al.等『注意是缩写,有.号』,也都是拉...

机器学习(3)——无监督学习_Fo*(Bi)的博客-程序员宅基地

什么是无监督学习?顾名思义,无监督学习就是不受监督的学习。同监督学习建立在人类标注数据的基础上不同,无监督学习不需要人类进行数据标注,而是通过模型不断地自我认知、自我巩固,最后进行自我归纳来实现其学习过程。虽然目前无监督学习的使用不如监督学习广泛,但这种独特的方法论为机器学习的未来发展方向给出了很多启发和可能性,正在引起越来越多的关注。2015年,深度学习“三巨头”——YannLeCun、Yoshua Bengio、Geoffrey Hinton首次合作在Nature上撰文,在对深度学习未来展望写道:“无

随便推点

Binder相关面试总结(五):为什么Activity间传递对象需要序列化_binder数据为什么需要序列化-程序员宅基地

前言我们都知道进行Android 开发的时候,跳转到Activity和Fragment的时候,传递对象是通过Intent或者bundle 进行传递。当这个对象没有实现序列化的时候 当你通过Inetnt传递的时候会报红,系统会提示你将这个对象实现序列化。不同 Activity 之间传输数据可以通过 Intent 对象的 putExtra 方法传递,对于 java 的八大基本数据类型(char int float double long short boolean byte)传递是没有问题的,但是如果传递比_binder数据为什么需要序列化

vr视频六面体变换-程序员宅基地

本文会对facebook的开源filter:vf_transform.c 做代码级分析,解释vr视频是如何做六面体转换的。转换的关键其实就是输入vr视频到六面体的映射(也就是下图中蓝色图像映射到红色图像):假设每个正方形的像素是512x512个,那么对于(x, y)这个像素值来说,想得到这个值,我只需要从原点,拉一条直线连接到(x, y)并沿着这条直线一直打到球面上,得到的像素值就

测量设备自动化-AK协议-程序员宅基地

1.AK协议定义AK协议是控制器和测量设备之间通信的方式,广泛应用于整车耐久转毂等测试中,如AVL VECON。人们通常都是用VECON界面设置试验曲线,但通过AK可以实现设备的自动化。如下图所示:集合INCA和AK,实现了闭环控制,可用于重复的试验,如失火等。关于AK协议的文档不多,本文收集了一些,回复”AK文档“获取。更多需要参考设备文档。2.AK报文格式按字节顺序..._ak协议mcu要配置成什么性质

字符串大小的比较_字符串如何比较大小-程序员宅基地

字符串大小比较的步骤:从左至右一位一位比较,如果相同,则继续下一位,如果不同,则谁的ASCII大谁的字符串就大如果比较到其中一者已经结束了,还没有分出大小,则长度长的字符串大..._字符串如何比较大小

宏的编写技巧_写宏-程序员宅基地

宏的编写技巧声明:整理来自开源项目json-tutoriallink.有些同学可能不了解 EXPECT_EQ_BASE 宏的编写技巧,简单说明一下。反斜线代表该行未结束,会串接下一行。而如果宏里有多过一个语句(statement),就需要用 do { /…/ } while(0) 包裹成单个语句,否则会有如下的问题:只用 { } 也不行:用 do while 就行了:..._写宏

11--黑马程序员--技术总结之字符串-程序员宅基地

一.基本概念 字符串或串(String)是由数字、字母、下划线组成的一串字符。一般记为s=“a1a2···an”(n>=0)。它是编程语言中表示文本的数据类型。 Java使用java.lang包中的String类来创建一个字符串变量,因此字符串变量是一个对象。 1.字符串常量 如,“你好”,“1234.987”,“weqweo”

推荐文章

热门文章

相关标签