链表(Linked List)之单链表

原文地址:传送门

链表(Linked List)介绍

链表是有序的列表,但是它在内存中是存储如下

img

小结:

链表是以节点的方式来存储,是链式存储

每个节点包含 data 域, next 域:指向下一个节点.

如图:发现链表的各个节点不一定是连续存储.

链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定

结合一个实际的工作案例, 说明链表的实用价值

单链表

单链表(带头结点) 逻辑结构示意图如下

img

哔哩哔哩动画

单链表的应用实例

使用带head头的单向链表实现 –水浒英雄排行榜管理 完成对英雄人物的增删改查操作, 注: 删除和修改,查找可以考虑学员独立完成,也可带学员完成 第一种方法在添加英雄时,直接添加到链表的尾部 第二种方式在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)

img

单链表的常见面试题有如下:

求单链表中有效节点的个数

查找单链表中的倒数第k个结点 【新浪面试题】

单链表的反转【腾讯面试题,有点难度】

从尾到头打印单链表 【百度,要求方式1:反向遍历 。 方式2:Stack栈】

合并两个有序的单链表,合并之后的链表依然有序【课后练习.】

直接看老师代码演示 。

package com.atguigu.linkedlist;import java.util.Stack;public class SingleLinkedListDemo {public static void main(String[] args) {//进行测试//先创建节点HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");HeroNode hero3 = new HeroNode(3, "吴用", "智多星");HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");//创建要给链表SingleLinkedList singleLinkedList = new SingleLinkedList();//加入singleLinkedList.add(hero1);singleLinkedList.add(hero4);singleLinkedList.add(hero2);singleLinkedList.add(hero3);// 测试一下单链表的反转功能System.out.println("原来链表的情况~~");singleLinkedList.list();//        System.out.println("反转单链表~~");
//        reversetList(singleLinkedList.getHead());
//        singleLinkedList.list();System.out.println("测试逆序打印单链表, 没有改变链表的结构~~");reversePrint(singleLinkedList.getHead());/*        //加入按照编号的顺序singleLinkedList.addByOrder(hero1);singleLinkedList.addByOrder(hero4);singleLinkedList.addByOrder(hero2);singleLinkedList.addByOrder(hero3);//显示一把singleLinkedList.list();//测试修改节点的代码HeroNode newHeroNode = new HeroNode(2, "小卢", "玉麒麟~~");singleLinkedList.update(newHeroNode);System.out.println("修改后的链表情况~~");singleLinkedList.list();//删除一个节点singleLinkedList.del(1);singleLinkedList.del(4);System.out.println("删除后的链表情况~~");singleLinkedList.list();//测试一下 求单链表中有效节点的个数System.out.println("有效的节点个数=" + getLength(singleLinkedList.getHead()));//2//测试一下看看是否得到了倒数第K个节点HeroNode res = findLastIndexNode(singleLinkedList.getHead(), 3);System.out.println("res=" + res);
*/        }//方式2://可以利用栈这个数据结构,将各个节点压入到栈中,然后利用栈的先进后出的特点,就实现了逆序打印的效果public static void reversePrint(HeroNode head) {if(head.next == null) {return;//空链表,不能打印}//创建要给一个栈,将各个节点压入栈Stack<HeroNode> stack = new Stack<HeroNode>();HeroNode cur = head.next;//将链表的所有节点压入栈while(cur != null) {stack.push(cur);cur = cur.next; //cur后移,这样就可以压入下一个节点}//将栈中的节点进行打印,pop 出栈while (stack.size() > 0) {System.out.println(stack.pop()); //stack的特点是先进后出}}//将单链表反转public static void reversetList(HeroNode head) {//如果当前链表为空,或者只有一个节点,无需反转,直接返回if(head.next == null || head.next.next == null) {return ;}//定义一个辅助的指针(变量),帮助我们遍历原来的链表HeroNode cur = head.next;HeroNode next = null;// 指向当前节点[cur]的下一个节点HeroNode reverseHead = new HeroNode(0, "", "");//遍历原来的链表,每遍历一个节点,就将其取出,并放在新的链表reverseHead 的最前端//动脑筋while(cur != null) { next = cur.next;//先暂时保存当前节点的下一个节点,因为后面需要使用cur.next = reverseHead.next;//将cur的下一个节点指向新的链表的最前端reverseHead.next = cur; //将cur 连接到新的链表上cur = next;//让cur后移}//将head.next 指向 reverseHead.next , 实现单链表的反转head.next = reverseHead.next;}//查找单链表中的倒数第k个结点 【新浪面试题】//思路//1. 编写一个方法,接收head节点,同时接收一个index //2. index 表示是倒数第index个节点//3. 先把链表从头到尾遍历,得到链表的总的长度 getLength//4. 得到size 后,我们从链表的第一个开始遍历 (size-index)个,就可以得到//5. 如果找到了,则返回该节点,否则返回nulllpublic static HeroNode findLastIndexNode(HeroNode head, int index) {//判断如果链表为空,返回nullif(head.next == null) {return null;//没有找到}//第一个遍历得到链表的长度(节点个数)int size = getLength(head);//第二次遍历  size-index 位置,就是我们倒数的第K个节点//先做一个index的校验if(index <=0 || index > size) {return null; }//定义给辅助变量, for 循环定位到倒数的indexHeroNode cur = head.next; //3 // 3 - 1 = 2for(int i =0; i< size - index; i++) {cur = cur.next;}return cur;}//方法:获取到单链表的节点的个数(如果是带头结点的链表,需求不统计头节点)/*** * @param head 链表的头节点* @return 返回的就是有效节点的个数*/public static int getLength(HeroNode head) {if(head.next == null) { //空链表return 0;}int length = 0;//定义一个辅助的变量, 这里我们没有统计头节点HeroNode cur = head.next;while(cur != null) {length++;cur = cur.next; //遍历}return length;}}//定义SingleLinkedList 管理我们的英雄
class SingleLinkedList {//先初始化一个头节点, 头节点不要动, 不存放具体的数据private HeroNode head = new HeroNode(0, "", "");//返回头节点public HeroNode getHead() {return head;}//添加节点到单向链表//思路,当不考虑编号顺序时//1. 找到当前链表的最后节点//2. 将最后这个节点的next 指向 新的节点public void add(HeroNode heroNode) {//因为head节点不能动,因此我们需要一个辅助遍历 tempHeroNode temp = head;//遍历链表,找到最后while(true) {//找到链表的最后if(temp.next == null) {//break;}//如果没有找到最后, 将将temp后移temp = temp.next;}//当退出while循环时,temp就指向了链表的最后//将最后这个节点的next 指向 新的节点temp.next = heroNode;}//第二种方式在添加英雄时,根据排名将英雄插入到指定位置//(如果有这个排名,则添加失败,并给出提示)public void addByOrder(HeroNode heroNode) {//因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助找到添加的位置//因为单链表,因为我们找的temp 是位于 添加位置的前一个节点,否则插入不了HeroNode temp = head;boolean flag = false; // flag标志添加的编号是否存在,默认为falsewhile(true) {if(temp.next == null) {//说明temp已经在链表的最后break; //} if(temp.next.no > heroNode.no) { //位置找到,就在temp的后面插入break;} else if (temp.next.no == heroNode.no) {//说明希望添加的heroNode的编号已然存在flag = true; //说明编号存在break;}temp = temp.next; //后移,遍历当前链表}//判断flag 的值if(flag) { //不能添加,说明编号存在System.out.printf("准备插入的英雄的编号 %d 已经存在了, 不能加入\n", heroNode.no);} else {//插入到链表中, temp的后面heroNode.next = temp.next;temp.next = heroNode;}}//修改节点的信息, 根据no编号来修改,即no编号不能改.//说明//1. 根据 newHeroNode 的 no 来修改即可public void update(HeroNode newHeroNode) {//判断是否空if(head.next == null) {System.out.println("链表为空~");return;}//找到需要修改的节点, 根据no编号//定义一个辅助变量HeroNode temp = head.next;boolean flag = false; //表示是否找到该节点while(true) {if (temp == null) {break; //已经遍历完链表}if(temp.no == newHeroNode.no) {//找到flag = true;break;}temp = temp.next;}//根据flag 判断是否找到要修改的节点if(flag) {temp.name = newHeroNode.name;temp.nickname = newHeroNode.nickname;} else { //没有找到System.out.printf("没有找到 编号 %d 的节点,不能修改\n", newHeroNode.no);}}//删除节点//思路//1. head 不能动,因此我们需要一个temp辅助节点找到待删除节点的前一个节点//2. 说明我们在比较时,是temp.next.no 和  需要删除的节点的no比较public void del(int no) {HeroNode temp = head;boolean flag = false; // 标志是否找到待删除节点的while(true) {if(temp.next == null) { //已经到链表的最后break;}if(temp.next.no == no) {//找到的待删除节点的前一个节点tempflag = true;break;}temp = temp.next; //temp后移,遍历}//判断flagif(flag) { //找到//可以删除temp.next = temp.next.next;}else {System.out.printf("要删除的 %d 节点不存在\n", no);}}//显示链表[遍历]public void list() {//判断链表是否为空if(head.next == null) {System.out.println("链表为空");return;}//因为头节点,不能动,因此我们需要一个辅助变量来遍历HeroNode temp = head.next;while(true) {//判断是否到链表最后if(temp == null) {break;}//输出节点的信息System.out.println(temp);//将temp后移, 一定小心temp = temp.next;}}
}//定义HeroNode , 每个HeroNode 对象就是一个节点
class HeroNode {public int no;public String name;public String nickname;public HeroNode next; //指向下一个节点//构造器public HeroNode(int no, String name, String nickname) {this.no = no;this.name = name;this.nickname = nickname;}//为了显示方法,我们重新toString@Overridepublic String toString() {return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";}}

运行结果

原来链表的情况~~
HeroNode [no=1, name=宋江, nickname=及时雨]
HeroNode [no=4, name=林冲, nickname=豹子头]
HeroNode [no=2, name=卢俊义, nickname=玉麒麟]
HeroNode [no=3, name=吴用, nickname=智多星]
测试逆序打印单链表, 没有改变链表的结构~~
HeroNode [no=3, name=吴用, nickname=智多星]
HeroNode [no=2, name=卢俊义, nickname=玉麒麟]
HeroNode [no=4, name=林冲, nickname=豹子头]
HeroNode [no=1, name=宋江, nickname=及时雨]Process finished with exit code 0

原文地址:传送门

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

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

相关文章

有字符csv文件导入matlab_Matlab:如何读取CSV文件以及如何读取带有字符串数据项的CSV文件...

CSV&#xff0c;逗号分开的文件&#xff0c;如果能快速的读取这些文件中的数据&#xff0c;无疑会帮助我们解决很多问题。1、 只有数据的CSV文件&#xff0c;CSV file that includes only numbers.As an example, create a text file, named as data.csv if you prefer, which …

xchg_mb_border()

顾名思义&#xff0c; xchg_mb_border() 交换 MB 边界的像素。阅读代码可知&#xff0c;交换双方为边界缓存 (left_border,top_borders) 与重建图象中的相应数据。其中 xchg 参数是否为 1 决定&#xff0c;在从边界缓存赋值到重建图象的同时&#xff0c;是否保存重建图象的数据…

Introduction to the Optimizer --cbo

http://docs.oracle.com/cd/B10500_01/server.920/a96533/optimops.htm

统计字符串中某个字出现的次数

package ch11;import java.util.Scanner;/** * Created by liwenj on 2017/7/21. */public class T6 { public static void main(String[] args) { String w "我爱你中国&#xff0c;我爱你故乡"; String a "爱"; int k0; …

jedispool redis哨兵_通过java哨兵JedisSentinelPool代码示例连接对配置的redis哨兵主从模式进行测试验证...

一、前言本文章通过关于java的jedis(2.6.0)的redis客户端连接驱动包&#xff0c;对配置的redis哨兵主从读写模式配置进行示例代码验证&#xff0c;详细参见具体配置步骤&示例代码说明部分。二、配置步骤1. 安装redis(参考其他文章教程),并配置主从模式(参考其他相关文章&am…

链表(Linked List)之双向链表

双向链表应用实例 使用带head头的双向链表实现 –水浒英雄排行榜 管理单向链表的缺点分析: 单向链表&#xff0c;查找的方向只能是一个方向&#xff0c;而双向链表可以向前或者向后查找。 单向链表不能自我删除&#xff0c;需要靠辅助节点 &#xff0c;而双向链表&#xff…

H264 解码耗时分析

在数字基带处理器上代码的最佳放置 美国模拟器件公司 Jose Fridman   在手机等嵌入式系统中&#xff0c;除了处理器执行时间外&#xff0c;最重要的资源就是设备总线和存储器接口。本文将介绍一种在使用指令高速缓存时其带宽消耗的基础上&#xff0c;统计分析高速缓存所采用…

CentOS 7 使用iptables防火墙

# 停止firewalld服务 systemctl stop firewalld systemctl mask firewalld # 安装iptables-services yum install iptables-services Enable the service at boot-time: # 启动iptables服务 systemctl enable iptables # 管理iptables systemctl [stop|start|restart] ip…

Linux命令之useradd和userdel(添加、删除用户)

一、【useradd】&#xff1a;添加用户命令 1.作用useradd或adduser命令用来建立用户帐号和创建用户的起始目录&#xff0c;使用权限是超级用户。 2.格式 useradd [-d home] [-s shell] [-c comment] [-m [-k template]] [-f inactive] [-e expire ] [-p passwd] [-r] name 3.主…

链表(Linked List)之环形链表

原文地址:传送门 单向环形链表应用场景 Josephu(约瑟夫、约瑟夫环) 问题 Josephu 问题为&#xff1a;设编号为1&#xff0c;2&#xff0c;… n的n个人围坐一圈&#xff0c;约定编号为k&#xff08;1<k<n&#xff09;的人从1开始报数&#xff0c;数到m 的那个人出列&…

springboot 单测加入参数_spring-boot-单元测试参数数

简单案例RunWith(Parameterized.class)public class ParameterTest {// 2.声明变量存放预期值和测试数据private String firstName;private String lastName;//3.声明一个返回值 为Collection的公共静态方法&#xff0c;并使用Parameters进行修饰Parameterized.Parameterspubli…

H.264/AVC 标准中CAVLC 和CABAC 熵编码算法研究

http://www.paper.edu.cn/index.php/default/releasepaper/downPaper/200903-146

python ==》 元组

为何要有元组 &#xff0c;() 可存放多个值 元组不可变 更多的是用来查询t (1,[1,3],sss,(1,2)) #t tuple(1,[1,3],sss,(1,2))print (type(t))元组可以作为字典的keyd{(1,2,3):zcx}print(d,type(d),d[(1,2,3)])索引取值d (1,2,3,4,5)print(d[1])切片goods (iphone,lenove,…

免费SSL证书(支持1.0、1.1、1.2)

由于公司要开发微信小程序&#xff0c;而微信小程序的接口需要https协议的&#xff0c;并且要支持TLS1.0、TLS1.1、TLS1.2。如果仅仅是为了开发小程序&#xff0c;安全等级又不用太高&#xff0c;可以选择免费的SSL证书 在这里选择腾讯云的证书&#xff0c;申请在 https://cons…

viewsource和viewparsed_Network Panel说明

一、chrome Developer Tools&#xff1a;Network Panel从网络面板中可以获取很多有用信息&#xff0c;如详细的时间数据&#xff0c;http请求头响应头&#xff0c;cookies&#xff0c;WebSocket数据。通过分析这些数据&#xff0c;可以知道哪个资源加载耗时最久&#xff0c;谁发…

使用栈来完成一个表达式的结果

原文地址:传送门 使用栈来完成一个表达式的结果 使用栈完成计算 一个表达式的结果 7*2*2-51-53-4 &#xff1f; 32*6-2[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XzPnJzRe-1614845779689)(https://victorfengming.gitee.io/data_algorithm/i…

JM与h264标准中的关键字说明

有些乱&#xff0c;先存着&#xff0c;留着看 如何结合H.264标准看JM代码》这个web文件&#xff0c;大家都应该有了吧。不过&#xff0c;那个web文档是“H.264乐园”群中聊天的内容 1、一个sps后&#xff0c;有若干个pps吗&#xff1f; 这主要又编码器决定&#xff0c;但J…

云计算(cloud computing)十大问答

本文讲的是云计算&#xff08;cloud computing&#xff09;十大问答&#xff0c;【IT168 资讯】云计算这个新名词最近甚嚣尘上&#xff0c;最近周围不少朋友都在谈&#xff0c;有必要写一个关于云计算的科普了。  一般的业界比较喜欢用一些新名词来体现 自己的战略眼光和与对…

3150cdn打印机清零 hl_兄弟HL-3150/3140彩色打印机粉盒清零方法,我们提前了解一下...

原标题&#xff1a;兄弟HL-3150/3140彩色打印机粉盒清零方法&#xff0c;我们提前了解一下对于兄弟品牌的打印机&#xff0c;相信各位经销商朋友都遇到过&#xff0c;更换新的粉盒或者加粉后还会提示墨粉不足、更换碳粉盒、更换硒鼓。这个情况需要在机器上操作清零&#xff01;…

Python 关于bytes类方法对数字转换的误区, Json的重要性

本文起源于一次犯错, 在发觉bytes()里面可以填数字, 转出来的也是bytes类型, 就心急把里面的东西decode出来. 结果为空.搞来搞去以为是命令不熟练事实上错在逻辑.a1 bytes(11, encodingutf-8) print(a1)b1 a1.decode()print(b1)a2 bytes(11) print(a2)b2 a2.decode() print…