单链表的建立(头插法、尾插法)(数据结构与算法)

在这里插入图片描述

如果要把很多个数据元素存到一个单链表中,如何操作?
1.初始化一个单链表
2. 每次取一个数据元素,插入到表尾/表头

1. 尾插法建立单链表

尾插法建立的单链表元素顺序与输入数据集合的顺序相同,即按照输入数据的顺序排列。

使用尾插法建立单链表的一个常见应用是在计算机科学中进行数据输入。通过将用户输入的数据逐个添加到链表的尾部,可以方便地保存输入的数据,并在后续处理中使用。

  1. 初始化单链表
  2. 设置变量length纪录链表长度
  3. while循环{
  4. 每取一个元素e;
  5. ListInsert(L, length+1, e) 插入到尾部;
  6. length++;}
    在这里插入图片描述

尾插法(尾部插入法)是一种建立单链表的常用方法,与头插法相反,它会将新节点插入到链表的尾部位置。以下是使用尾插法建立单链表的步骤:

  1. 首先定义一个头节点,并将其初始化为空指针。
  2. 遍历需要转化为链表的数据集合。
  3. 对于数据集合中的每一个元素,创建一个新的节点,并设置其数据域为该元素的值。
  4. 若链表为空,将新节点直接设置为头节点。
  5. 若链表非空,则遍历到链表的最后一个节点,并将其指针域指向新节点。
  6. 更新链表的最后一个节点为新节点。
typedef struct LNode      //定义单链表结点类型
{ElemType data;		  //每个结点存放一个数据元素struct LNode *next;   //指针指向下一个节点
}
//初始化一个单链表(带头结点)
bool InitList(LinkList &L)  
{L = (LNode *)  malloc(sizeof(LNode)); //分配一个头结点if (L == NULL) 		 //内存不足, 分配失败return false;L->next = NULL; 		//头结点之后暂时还没有节点return true;	
}
void test()
{LinkList L;   //声明一个指向单链表的指针//初始化一个空表InitList(L);//......后续代码......
}//在第i个位置处插入元素e(带头结点)
bool ListInsert(LinkList &L, int i, ElemType e)
{if(i<1)return false;LNode *p;		//指针p指向当前扫描到的节点int j = 0; 		//指针p指向的是第几个结点p = L;		//L指向头结点 头结点是第0个结点,不存数据while( p != NULL && j < i-1) //循环找到第i-1个结点{p = p->next;j++;}if( p==NULL)	//i值不合法return false;LNode *s = (LNode *) malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;		//将结点s连到p之后return true;		//插入成功
}

当插入1个元素时,while需要循环一次,插入2个元素,while循环1此…插入n个元素,while循环n-1次。 每次都从开头开始之后遍历,循环次数为1+2+3+…+(n-1)。时间复杂度为0(n^2)

这种操作,时间复杂度太大,并不是最佳方案。

其实根本没必要每次都从头开始往后寻找, 我们可以设置一个指针r,指向表尾,当要在尾部插入一个新的数据元素时,就只需要对r结点做一个后插操作就行了。

//后插操作: 在p结点之后插入元素e
bool InsertNode(LNode *p, ElemType e)
{if(p == NULL)return false;LNode *s = (LNode *)malloc(sizeof(LNode));if(s==NULL)		//内存分配失败return false;s->data = e;		//用结点s保存数据元素s->next = p->next;   p->next = s; 		//将结点s连到p之后    后插操作return true;				
}

在这里插入图片描述

插入数据元素40

在这里插入图片描述

尾部插入一个元素,表尾指针后移一位,仍然指向最后一个元素,方便下一次插入

在这里插入图片描述

示例:尾插法建立单链表

设此次输入的整数是10,while循环检测,循环中前两句,会申请一个新的结点,然后让s这个指针指向新结点,并且把输入的x = 10放入新结点中,接下来把 r结点的next指针指向s结点。最后,再让r指针指向s结点,接下来就可以输入下一个元素x,继续插入。

时间复杂度:O(n)

LinkList List_TailInsert(LinkList &L)
{int x;		//设ElemType为整型L = (LinkList)malloc(sizeof(LNode));	//建立头结点LNode *s, *r = L;	//r为表尾指针scanf("%d", &x);	//输入结点的值while(x != 9999)    //该数是随便取的 ,输入9999表示结束{s = (LNode *) malloc(sizeof(LNode));  //简历一个结点ss->data = x; 	//将x存放到s数据域中r->next = s; //将表尾指针指向s结点r = s;	//r指向新的表尾结点scanf("%d",&x);}r->next = NULL; 	//尾结点指针置空return L;
}

LNode *s, *r = L; //r为表尾指针

在这里插入图片描述

申请一个新的结点,然后让s这个指针指向新结点,并且把输入的x = 10放入新结点中

在这里插入图片描述

接下来把 r 结点的next指针指向s结点

在这里插入图片描述

最后,再让r指针指向s结点, 接下来就可以输入下一个元素x,继续插入

在这里插入图片描述

假设继续输入 x = 16。那么会再申请一个新的结点s,让s指针指向新节点, 并把16放入新结点, 接下来把r结点的指针指向s结点, 最后…

在这里插入图片描述

将 r 指针指向s结点,再输入下一个元素27 。 以此类推完成插入操作。

在这里插入图片描述

如果x输入的是9999, 那么就可以跳过while循环,执行r->next = NULL; 让r结点的next指向NULL。
在这里插入图片描述

2. 头插法建立单链表

头插法建立单链表的特点是:新节点插入到链表的头部位置,因此建立完成的链表元素顺序是和输入数据集合的顺序相反的,即倒序排列。

对头结点的后插操作,如下图所示:

  1. 首先定义一个头节点,并将其初始化为空指针。
  2. 遍历需要转化为链表的数据集合。
  3. 对于数据集合中的每一个元素,创建一个新的节点,并设置其数据域为该元素的值。
  4. 将新节点的指针域指向当前头节点,即将新节点插入到链表的头部。
  5. 更新头节点为新节点。

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

//后插操作:在p结点之后插入元素e
bool InsertNextNode(LNode *p, ElemType e)
{if(p == NULL)return false;LNode *s = (LNode *)malloc(sizeof(LNode));if(s == NULL)	//内存分配失败return false;	s->data = e;		//用结点s保存数据元素es->next = p->next;p->next = s;		//将结点s连接到p之后return true;
}

在这里插入图片描述

  • 如上图所示,此处,尾插法中是没有 L->next = NULL 这一句的,但在头插法中,这句非常必要。由于是动态分配,如果头结点指向没有被初始化为NULL,那头结点L->next 很有可能指向了内存中某一神秘区域,从而形成脏数据,影响后面的插入操作。

养成好习惯,只要是初始化单链表,都先把头指针指向NULL

  • 按照头插法形成的规则,最终形成的单链表刚好是输入元素的逆序,这种性质非常重要!!!
    很多题目中都用得到单链表的逆置。
    在这里插入图片描述

3. 知识点回顾

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/161668.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java连接Redis并操作Redis中的常见数据类型

目录 一. Java连接Redis 1. 导入依赖 2. 建立连接 二. Java操作Redis的常见数据类型存储 1. Redis字符串(String) 2. Redis哈希(Hash) 3. Redis列表&#xff08;List&#xff09; 4. Redis集合&#xff08;Set&#xff09; 一. Java连接Redis 1. 导入依赖 pom依赖…

爬虫项目-爬取股吧(东方财富)评论

1.最近帮别人爬取了东方财富股吧的帖子和评论&#xff0c;网址如下&#xff1a;http://mguba.eastmoney.com/mguba/list/zssh000300 2.爬取字段如下所示&#xff1a; 3.爬虫的大致思路如下&#xff1a;客户要求爬取评论数大于5的帖子&#xff0c;首先获取帖子链接&#xff0c…

以太网【FPGA】

1物理&#xff1a; 2接线&#xff1a; 信号名 信号类型 对应引脚 备注 sys_clk Input B5 系统晶振输入时钟&#xff0c;频率 50MHz sys_rst_n Input E8 系统复位信号&#xff0c;低有效 eth_rxc Input E17 PHY 输入时钟&#xff0c;频率 125MHz eth_rx_ctl Inpu…

arduino - NUCLEO-H723ZG - test

文章目录 arduino - NUCLEO-H723ZG - test概述笔记物理串口软串口备注END arduino - NUCLEO-H723ZG - test 概述 准备向NUCLEO-H723ZG上移植西门子飞达控制的Arduino程序. 先确认一下知识点和效果. 笔记 物理串口 NUCLEO-H723ZG在STM32 Arduino 库中, 只提供了一个串口 Se…

Canvas 梦幻树生长动画

canvas可以制作出非常炫酷的动画&#xff0c;以下是一个梦幻树的示例。 效果图 源代码 <!DOCTYPE> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /> <title>梦幻数生长动画</title&…

【51单片机】蜂鸣器(学习笔记)

一、蜂鸣器 1、蜂鸣器介绍 鸣器是一种将电信号转换为声音信号的器件&#xff0c;常用来产生设备的按键音、报警音等提示信号 有源蜂鸣器&#xff1a;内部自带振荡源&#xff0c;将正负极接上直流电压即可持续发声&#xff0c;频率固定无源蜂鸣器&#xff1a;内部不带振荡源&…

【漏洞复现】Apache_HTTP_2.4.50_路径穿越漏洞(CVE-2021-42013)

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证方式一 curl方式二 bp抓捕 1.5、修复建议 说明内容漏洞编号CVE-2021-42013漏洞名称…

【MySQL】用户管理权限控制

文章目录 前言一. 用户管理1. 创建用户2. 删除用户3. 修改用户密码 二. 权限控制1. 用户授权2. 查看权限3. 回收权限 结束语 前言 MySQL的数据其实也以文件形式保存&#xff0c;而登录信息同样保存在文件中 MySQL的数据在Linux下默认路径是/var/lib/mysql 登录MySQL同样也可以…

HDFS 读写架构

一、组成架构 1、NameNode(NN) : 集群的Master&#xff0c;它是一个主管&#xff0c;管理者 (1) 管理HDFS的命名空间 (2) 配置副本策略 (3) 管理数据块(Block)映射信息 (4) 处理客户端读写请求 2、DataNode(DN) : 集群的Slave。NN下达命令&#xff0c;DataNode执行实际操作。…

vue基于ElementUI/Plus自定义的一些组件

vue3-my-ElementPlus 源码请到GitHub下载使用MyTable、MySelect、MyPagination 置顶|Top | 使用案例&#xff1a; 1.0 定义表格数据&#xff08;测试使用&#xff09; data() {return {tableData: [],value:[],valueList: [],}; },// 构造表格测试数据// 1 第一行&#xf…

如何去除视频水印?三种简便有效的方法解决视频水印问题

在当今社交媒体时代&#xff0c;视频分享已成为一种流行趋势。然而&#xff0c;很多人在分享自己的作品时却苦于视频上存在的水印&#xff0c;水印通常是出于版权保护或品牌推广的目的而添加到视频中的&#xff0c;但有时它们可能会对用户体验造成负面影响。 如果您正在寻找如何…

基础课18——智能客服系统架构

1.基础设施层 基础设施主要包括以下几点&#xff1a; 1. 硬件设施&#xff1a;包括服务器、存储设备、网络设备等&#xff0c;这是整个系统运行的物理基础。 2. 软件设施&#xff1a;包括操作系统、数据库管理系统、自然语言处理(NLP)工具和机器学习算法等&#xff0c;这些是…