数据结构与算法之链表(Java版)
文章目录
- 链表
- 单链表完成添加的遍历
- 按照顺序添加英雄
- 解题思路:
- 代码实现:
- 单链表的修改
- 解题思路:
- 代码实现:
- 单链表的删除:
- 解题思路:
- 代码实现:
- 实战演练
- 找出单链表中有效节点的个数
- 查找单链表倒数第K个节点[新浪面试]
- 解题思路:
- 单链表的反转:
- 解题思路:
- 代码实现:
- 从尾到头打印单链表[百度]
- 解题思路:
- 双向链表
- 解题思路:
- 双向链表的创建(多了pre)
- 双线链表的添加
- 双向链表的修改
- 双链表的删除
- 单向环形链表
- 创建节点起始结构
- 构建
- 遍历环形链表
- 解决约瑟夫环
- 思路分析:
- 代码实现:
- 1.应用场景
- 2.数据结构的算法
- 3.原理剖析
- 4.分析实验步骤
- 5.代码实现
链表
单链表完成添加的遍历
package LinkedList;
class HeroNode{//编号public int no;//名字public String name;//昵称public String niceName;//指针指向后面public HeroNode next;public HeroNode(int no, String name, String niceName) {this.no = no;this.name = name;this.niceName = niceName;}@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +", niceName='" + niceName + '\'' +'}';}
}//再次定义一个单链表
class MyLinkedList{//定义一个头结点private HeroNode head = new HeroNode(0,"","");//添加节点到单链表/**当不考虑编号顺序* 1.找到当前链表的最后节点* 2.将该节点的next域指向其他节点*/public void add(HeroNode heroNode){//需要创建一个临时的temp来替代headHeroNode temp = head;while (true){//这个next算是节点里面的属性,节点里面还有一个属性节点if (temp.next==null){break;}//如果不是,就把temp后移temp = temp.next;}//从上面出来的时候也代表节点指向最后temp.next = heroNode;}//遍历这个链表public void list(){//需要先判断头结点是否为空if (head.next ==null){System.out.println("链表为空");return;}//需要判断是否到达尾节点,如果没有到达就输出并指针后移并输出节点位置HeroNode temp = head.next;while (true){if (temp == null){break;}else {System.out.println("节点位置为"+temp);temp = temp.next;}}}
}public class SingleLinkedList {//在链表尾部加入英雄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,"林冲","豹子头");MyLinkedList linkedList = new MyLinkedList();linkedList.add(hero4);linkedList.add(hero1);linkedList.add(hero2);linkedList.add(hero3);linkedList.list();}}
按照顺序添加英雄
解题思路:
- 1.通过遍历找到节点,并从该节点处做一个辅助节点temp
- 2.该节点的next指向temp的next
- 3.temp.next指向该节点
代码实现:
//按照顺序添加public void addOrderBy(HeroNode heroNode){HeroNode temp = head;//设置标志位,刚开始为false,用来判断是否重复的boolean flag = false;//然后通过变量来找到需要插入的位置while (true){if (temp.next==null){//如果只有头结点,那么就返回,因为不存在重复的break;}//如果temp当前的编号,大于节点的编号,那就说明已经过了,就说明需要在temp的后面添加//因为temp是从前往后推的,所以只能出现temp<heroNode<temp.next的情况if (temp.next.no > heroNode.no){break;}else if (temp.next.no == heroNode.no){//如果相等就说明重复了flag = true;//说明编号存在break;}//temp是从前往后推的temp = temp.next;}if (flag == true){System.out.println("需要插入的节点和列表节点重复"+heroNode.no);}else {//正式因为这两步才将链表插入在中间heroNode.next = temp.next;temp.next = heroNode;}}
单链表的修改
解题思路:
- 1.判断链表是否为空
- 2.创建辅助节点,设置标志位
- 2.进入循环,判断链表是否遍历到最后,如果不是指针后移
- 4.判断标志位是否为1,是则修改
temp.name = newHeroNode.name;temp.niceName = newHeroNode.niceName;
代码实现:
//修改节点的信息//1.根据newHeroNode的no来修改public void update(HeroNode newHeroNode){//判断判断除了头结点外是否为空if (head.next == null){System.out.println("链表为空");return;}//找到需要修改的节点//遍历所有节点,找到需要修改的节点//需要做辅助节点HeroNode temp = head;boolean flag = false;while (true){if (temp == null){System.out.println("说明已经遍历完了链表");}//如果没有遍历完成,就开始找和修改匹配的情况if (temp.no == newHeroNode.no){flag = true;break;}//如果没找到就往后遍历temp = temp.next;//如果真到了最后一个位final//这里是如果temp不为空,就把temp的}if (flag == true){//如果找到这个位置,就对这个位置的昵称的名字进行修改temp.name = newHeroNode.name;temp.niceName = newHeroNode.niceName;}else {//没有找到System.out.println("没有找到编号是这个的节点"+newHeroNode.no);}}//创建节点
// HeroNode newHeroNode = new HeroNode(4,"零充","豹子头");
// linkedList.update(newHeroNode);
// linkedList.list();
单链表的删除:
解题思路:
- 1.判断链表是否为空
- 2.设置标志位,设置辅助节点
- 3.进入循环,判断temp.next.no 是否等于参数no,如果是标志位置1,如果不是指针后移
- 4.判断标志位状态,为1就将当前指针指向下个指针
代码实现:
//删除方法
public void delete(int no){if (head.next==null){System.out.println("链表为空链表");return;}HeroNode temp = head;boolean flag = false;while (true){if (temp.next == null){break;}if (temp.next.no == no){flag = true;break;}temp = temp.next;}if (flag == true){//将temp的next指针指向temp指针的下一个指针temp.next = temp.next.next;}}//调用String a = "----------------------------------";//删除节点linkedList.delete(5);System.out.println(a);System.out.println("删除后的链表情况");linkedList.list();linkedList.delete(2);System.out.println(a);System.out.println("删除后的链表情况");linkedList.list();linkedList.delete(3);linkedList.delete(1);linkedList.delete(4);System.out.println(a);System.out.println("删除后的链表情况");linkedList.list();
实战演练
找出单链表中有效节点的个数
public int Valid(HeroNode heroNode){if (head.next == null){//如果是这样就返回一个空链表return 0;}//这里没有统计头结点HeroNode temp = head.next;int length = 0;/*这里应该是while temp != null* 而不是 while(true)包裹的if(temp != null)*/while (temp !=null){length++;temp = temp.next;}return length;}}
//这里需要获取头结点,需要获取一个getHead方法//统计除头结点外其他节点的个数System.out.println(a);System.out.println("有效节点为");System.out.println(linkedList.Valid(linkedList.getHead()));
查找单链表倒数第K个节点[新浪面试]
解题思路:
- 1.设置一个方法接收head以及一个参数index
- 2.index表示是倒数第index节点
- 3.先把链表从头到尾遍历,得到链表长度getLength
- 4.得到size后,我们从链表遍历size-length个
- 5如果找到了返回节点,找不到返回为null
public static HeroNode findLastIndexNode(HeroNode head, int index) {if (head.next == null) {return null; //没有找到}//找到size的长度int size = Valid(head);//如果下标越界的话,也是没有找到if (index <= 0 || index > size) {//这个也是没有找到return null;}//然后做一个辅助节点,定位到倒数第几个节点HeroNode temp = head.next;for (int i = 0; i <size-index; i++) {temp = temp.next;}//将temp值返回出去return temp;}
单链表的反转:
解题思路:
- 1.先定义一个节点reverseNode = new HeroNode();
- 2.遍历原来链表,编列节点,放在链表最前端
- 3.原来的链表head.next = reverseNode.next
代码实现:
前面的是指针,后面是指针指向的数据
public static void reserseList(HeroNode head){//如果当前链表为空,或只有一个节点,无需反转直接返回if (head.next == null|| head.next.next == null){return;}//定义一个辅助指针,帮我们遍历链表HeroNode cur = head.next;HeroNode next = null;HeroNode reverseHead = new HeroNode(0,"","");//遍历原来的链表,每遍历一个结点,就取出,让后放在reverseHead最前面while (cur != null){next = cur.next; //首先把cur.next储存起来之后要用cur.next = reverseHead.next; //将reverseHead.next以后的拼接到cur上面reverseHead.next = cur; //给reverseHead.next赋值,顺便放在第一位cur = next; //将现在的cur.next也就是next赋给cur也就是指针后移}//将head.next指向reverseHead.next实现单链表反转(等于说将head.next拼接上已经反转好的reverseHead.next)head.next = reverseHead.next;System.out.println();}
从尾到头打印单链表[百度]
解题思路:
- 1.上面题就是要逆序打印大连表
- 2.方式一:反转再打印,这会破坏单链表结构
- 3.方式二:将数据压入栈中然后利用栈的先进后出,就实现逆序
/*** 利用栈来实现对单链表逆序打印* @param head*/public static void reversePrint(HeroNode head){if (head.next == null){return;}//需要设置辅助节点HeroNode temp = head.next;Stack<HeroNode> heroNodes = new Stack<>();while (temp != null){// temp不为空则压入栈中heroNodes.push(temp);temp = temp.next;}while(!heroNodes.empty()){System.out.println(heroNodes.pop());}}
双向链表
解题思路:
- 1.遍历方式和单链表一样,可以向前查找也可以向后查找
- 2.添加(默认加在双向链表的最后)
- 先找到双向链表最后的这个结点
- temp.next = new HeroNode;
- new Heronode.pre = temp ;
- 3.修改思路和单链表一样
- 4.删除
- 因为是双向链表,因此我们可以实现自我删除
- temp.pre.next = temp .next;
- temp.next.pre = temp. pre;
双向链表的创建(多了pre)
class HeroNode2 {//编号public int no;//名字public String name;//昵称public String niceName;//指针指向后面public HeroNode2 next; //指向下一个节点public HeroNode2 pre; //指向前一个节点public HeroNode2(int no, String name, String niceName) {this.no = no;this.name = name;this.niceName = niceName;}@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +", niceName='" + niceName + '\'' +'}';}
}
双线链表的添加
temp.next = heroNode;heroNode.pre = temp;
双向链表的修改
//较之前的没啥区别
双链表的删除
双链表的删除不用使用删除节点前面的节点了,所以修改还是比较大的
public void delete(int no) {if (head.next == null) {System.out.println("链表为空链表");return;}//原来为headHeroNode2 temp = head.next;boolean flag = false;while (true) {//这里就直接用temp而不是temp.nextif (temp == null) {break;}if (temp.no == no) {flag = true;break;}temp = temp.next;}if (flag == true) {//这里也是修改了temp.pre.next= temp.next;//如果是最后一个特节点就不需要执行下面这句话temp.next.pre = temp.pre;}}
单向环形链表
创建节点起始结构
//创建一个Boy,表示一个节点
class Boy {private int no; //编号private Boy next; // 指向下一个节点,默认为nullpublic void setNo(int no) {this.no = no;}public int getNo() {return no;}public Boy(int no) {this.no = no;}public Boy getNext() {return next;}public void setNext(Boy next) {this.next = next;}
}
构建
- 创建第一个节点,让first指向该节点,形成环形
- 创建一个新节点,把节点加入这个新的环形链表
public void addBoy(int nums) {//nums做一个数据校验if (nums < 2) {System.out.println("num值不正确 ");}Boy curBoy = null;//for循环创建链表for (int i = 1; i <= nums; i++) {Boy boy = new Boy(i);if (i == 1) {//1.设置自己为第一个节点first = boy;//2.将自己组成环first.setNext(first);//3.讲辅助节点设置为当前curBoy = first;} else {//否则就是之后的节点了,就开始解环,组环/*1.从辅助节点入手,将curBoy和boy连起来2.将boy和first连起来3.将辅助指针curboy后推*/curBoy.setNext(boy);boy.setNext(first);curBoy = boy;}}}
遍历环形链表
1.先让一个辅助指针curBoy,指向first节点
2.然后通过while遍历环形链表即可curBoy.next== first结束
/*** 遍历所有结点*/public void showBoy() {if (first == null) {System.out.println("节点为空");}//设置辅助指针Boy curBoy = first;while (true) {System.out.println("这是第" + curBoy.getNo() + "个节点");//判断遍历完毕条件if (curBoy.getNext() == first) {break;}//否则就继续遍历curBoy = curBoy.getNext();}}
解决约瑟夫环
思路分析:
代码实现:
/*** @param startNo 从几开始数* @param countNum 一次数几个* @param nums 一共有多少*/public void CountBoy(int startNo, int countNum, int nums) {//首先对传入的数字进行校验if (first == null || startNo < 1 || startNo > nums) {System.out.println("参数有误,请校验后再继续执行");}//然后设置辅助节点helper,我们需要把helper放在对位,以便于删链Boy helper = first;while (true) {//这个操作是将helper放在最后一位if (helper.getNext() == first) {break;}helper = helper.getNext();}//然后我们需要在报数之前移动startNo - 1 次for (int i = 0; i < startNo - 1; i++) {helper = helper.getNext();first = first.getNext();}int count = 0;while (true){if (helper == first){break;}for (int j = 0; j < countNum - 1; j++) {helper = helper.getNext();first = first.getNext();}count++;//然后将节点取消System.out.println("第"+count+"轮出圈的小孩为"+first.getNo());//将first往后推,然后将helper指向firstfirst = first.getNext();helper.setNext(first) ;}System.out.println("最后一个留在圈中的小孩为"+first.getNo());}
数据结构与算法之链表(Java版)相关推荐
- 数据结构与算法基础(java版)
目录 数据结构与算法基础(java版) 1.1数据结构概述 1.2算法概述 2.1数组的基本使用 2.2 数组元素的添加 2.3数组元素的删除 2.4面向对象的数组 2.5查找算法之线性查找 2.6查 ...
- 一文通数据结构与算法之——链表+常见题型与解题策略+Leetcode经典题
文章目录 1 链表 1.1 常见题型及解题策略 1.1.1 LeetCode中关于链表的题目有以下五种类型题: 1.1.2 解题策略 1.2 链表的基本内容 1.2.1 链表的基本结构: 1.2.2 ...
- python定义链表节点_Python数据结构与算法之链表定义与用法实例详解【单链表、循环链表】...
本文实例讲述了Python数据结构与算法之链表定义与用法.分享给大家供大家参考,具体如下: 本文将为大家讲解: (1)从链表节点的定义开始,以类的方式,面向对象的思想进行链表的设计 (2)链表类插入和 ...
- 数据结构与算法之链表结构寻找p、q最近的公共祖先
链表结构,寻找p.q最近的公共祖先 数据结构与算法之链表结构寻找p.q最近的公共祖先 链表结构,寻找p.q最近的公共祖先 问题 想法 代码 问题 设一棵二叉树的结点结构为(LLINK, INFO, R ...
- 数据结构与算法--单链表相关面试题
此文章仅作为自己学习过程中的记录和总结,同时会有意地去用英文来做笔记,一些术语的英译不太准确,内容如有错漏也请多指教,谢谢! 一.概述 获取单链表的有效元素个数[新浪面试题1] 获取单链表倒数第k个结 ...
- 数据结构与算法(陈越版)第五讲 (树下)树的应用——集合及其运算
数据结构与算法(陈越版)第五讲 (树下)树的应用--集合及其运算 一.集合的表示 1.1.集合的表示 1.2.集合的储存 二.集合的运算 2.1查找以及普通并 2.2按照秩的合并算法 2.3路径压缩优 ...
- 数据结构与算法 内核链表实现商品购物系统项目+Makefile
数据结构与算法 内核链表实现商品购物系统项目 第一章 项目实现思维 [1]编译介绍 [2]框架思维 第二章 Makefile编写 第三章 代码编写实现 [1]favorite.txt文件 [2]his ...
- java动态分区分配_操作系统 动态分区分配算法课程设计 java版.pdf
操作系统 动态分区分配算法课程设计 java版 湖 南 文 理 学 院 实 验 报 告 课程名称 操作系统课程设计 实验名称 存储管理--动态分区分配算法的模拟 成绩 学生姓名 曹乐 专业 计算机 班 ...
- java数据接口之链表_Java数据结构和算法之链表
三.链表 链结点 在链表中,每个数据项都被包含在'点"中,一个点是某个类的对象,这个类可认叫做LINK.因为一个链表中有许多类似的链结点,所以有必要用一个不同于链表的类来表达链结点.每个LI ...
最新文章
- Silverlight实例教程 - Out of Browser开篇
- SpringCloud--Eureka服务注册与发现 Eureka 集群搭建 详细案例!!!
- 兴义高考八中2021成绩查询,兴义第八中学2021年录取分数线
- .NET开发作业调度(job scheduling) - Quartz.NET
- 将Spring集成到旧版应用程序中
- Thinkphp 数据库配置参数
- 用Python玩转统计数据:取样、计算相关性、拆分训练模型和测试
- iPhone应用中APNS推送通知流程代码实现案例
- iframe嵌套微信网页,图片无法显示问题
- 数据分析:使用Imblearn处理不平衡数据(过采样、欠采样)
- Servlet规范简介
- 算法设计与分析(1)——基础知识
- 美化版缤纷彩色文字广告代码文字+网站添加AD教程
- DataSource 详解
- tableau public使用形状文件进行数据可视化
- java poi 导出excel不能超过65536行
- K8S调试工具之--nsenter
- Power BI中的透视列和逆透视
- 二叉树的遍历(递归、非递归)
- mysql 数据库的编辑工具有哪些_常用的MySQL数据库管理工具有哪些
热门文章
- JS----addEventListener()
- .Net验证18位身份证格式
- C++程序设计:日历记事本
- git 不常用命令小札
- qsort的自主实现
- 苹果终端date命令_终端下如何修改系统时间?
- JVM-XX:NewRatio 、-XX:SurvivorRatio 参数的含义
- 在 SharePoint Server 中使用 iFrame 嵌入“Power BI 报表服务器”报表
- java读写器代码,JAVA:配置文件读取器-JSP教程,Java技巧及代码
- 从零开始用人工智能预测股票(一、特征选取)