链表的插入操作_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

智能推荐

线程的概念和模型以及与进程的比较-程序员宅基地

本博客前面部分转自:http://c.biancheng.net/cpp/html/2593.html线程的基本概念引入进程的目的,是为了使多道程序并发执行,以提高资源利用率和系统吞吐量;而引入线程,则是为了减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能。线程最直接的理解就是“轻量级进程”,它是一个基本的CPU执行单元,也是程序执行流的最小单元,由线程ID、程

航电oj:Quicksum_不玩游戏的休比的博客-程序员宅基地

**航电oj:Quicksum**#题目描述#输入一个字符串 按照规则一一将字符化为数字再相加 输出总值#空格也是一个字符 数字表示为0#知识点字符串#代码#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;char str[256];int main(){ while(gets(str))

常见的反爬虫机制以及对应思路-程序员宅基地

应对反爬的主要思路就是:尽可能的去模拟浏览器,浏览器在如何操作,代码中就如何去实现。1.通过User-Agent反爬爬虫发送请求时,请求头中默认没有User-Agent,或者提供非正常的UA。应对思路:在请求时添加UA具体应对: requests模块发送请求时在headers参数中UA键值对 selenium默认自带被控制浏览器的UA,也可以替换UA随机User-Age...

java中进行https证书jks文件的验证,并取其中的信息_怎么确保jks证书正确-程序员宅基地

服务端进行私钥密码验证 public static void valid() throws FileNotFoundException { File pfx = new File("E:\\星巴克项目\\证书\\测试环境\\scada.stg.starbucks.net.jks"); String privKeyPswdString = "tnk1VeENiMLp"; FileInputStream fileInputStream = new FileI_怎么确保jks证书正确

【Vue.js】Vue官方文档学习-Vue实例-程序员宅基地

一、创建一个Vue实例var vm = new Vue({ // 选项})每个Vue应用程序都是通过Vue函数创建出一个新的Vue对象开始的。 通常我们使用变量 vm (ViewModel 的简称) 来表示 Vue 实例。 在创建一个 Vue 实例时,你会传入一个选项对象。 Vue 应用程序由「一个使用 new Vue 创建的 Vue 根实例」、「嵌套的树结构(可选)」和「...

mysql distinct 失效_DISTINCT关键字在mysql查询中不起作用-程序员宅基地

MySQL DISTINCT多列您可以将DISTINCT子句与多个列一起使用.在这种情况下,MySQL使用所有列的组合来确定结果集中行的唯一性.如果要解决问题,可以使用group_concat()函数,然后对所有联合查询按catnam进行分组:SELECT name ,GROUP_CONCAT(id)FROM your_tableGROUP BY name ;因此您的查询可以是:SELECT di..._mysql distinct 无效

随便推点

h5外卖源码php_从零搭建外卖CPS平台小程序开发-程序员宅基地

什么是CPS?简单点讲就是你帮助商家销售产品,商家给你结算一定的佣金。如何快速开发一个外卖CPS类型的小程序呢?当然是站在巨人的肩膀上会更快!你只需要会git使用,简单的小程序开发工具使用就可以快速搭建一个属于你自己的小程序。本文将教你如何快速搭建一个外卖CPS平台。使用源码为zwpro同学的 https://github.com/zwpro/coupons 项目。一、前期准备1. 小程...

javascript大文件上传解决方案支持分片断点上传_js 断点上传_Mr_Zang666的博客-程序员宅基地

第二步:调用RandomAccessFile的getChannel()方法,打开文件通道 FileChannel,这块逻辑可以优化,如果以后有分布式存储需求,可以改为分布式存储,减轻单台服务器的压力。/** * 文件在服务器中的相对路径。示例:/www/web/upload/md5.exe *//** * 数字化的文件长度。// /// 是否是文件夹中的子文件 /// _js 断点上传

解决mysql [1045] Access denied for user 'root'@'192.168.180.248' (using password: YES)-程序员宅基地

解决mysql远程连接1045Linux服务器上安装了msyql数据库,Linux下MySQL默认安装完成后只有本地访问的权限,没有远程访问的权限,需要你给指定用户设置访问权限才能远程访问该数据库,下面把我的做法记录一下:grant all privileges on *.* to 'root'@'%' identified by 'root'; 这里的root代表root用户,最后的root...

万里(挑一)开源GreatDB及其他介绍_greatdb收费么-程序员宅基地

万里开源不断丰富着自身的产品线,先后推出单机数据库管理系统系列产品(简称“GreatDB”)、分布式数据库管理系统系列产品(简称“GreatDB Cluster”)、安全数据库系列产品(简称“GreatDBSE”)、云数据库服务平台(简称“GreatDB RDS”)、时序数据库管理系统(简称“GreatTS”)、企业级服务器操作系统软件(简称“TLES”)等多类数据库、操作系统核心产品,万里开源全线产品兼容X86、龙芯、飞腾、鲲鹏、海光等国内外主流芯片,具有产品生态能力及广泛的市场应用前景。万里开源单机数_greatdb收费么

本地python连接虚拟机中的mongodb-程序员宅基地

本地python连接虚拟机中的mongodb1.修改配置虚拟机中mongodb的配置文件,让其允许远程访问(1)在虚拟机终端输入sudo vim /etc/mongodb.conf ,这是使用vim来打开mongoDB的配置文件,具体打开的配置文件位置以自己mongodb的安装位置为准(2)使用vim打开后,将bind_ip修改为0.0.0.0 ,表示允许远程主机登陆访问。然后单击esc...