文章目录

  • 链表
    • 单链表完成添加的遍历
    • 按照顺序添加英雄
      • 解题思路:
      • 代码实现:
    • 单链表的修改
      • 解题思路:
      • 代码实现:
    • 单链表的删除:
      • 解题思路:
      • 代码实现:
  • 实战演练
    • 找出单链表中有效节点的个数
    • 查找单链表倒数第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.添加(默认加在双向链表的最后)
    1. 先找到双向链表最后的这个结点
    2. temp.next = new HeroNode;
    3. new Heronode.pre = temp ;
  • 3.修改思路和单链表一样
  • 4.删除
    1. 因为是双向链表,因此我们可以实现自我删除
    2. temp.pre.next = temp .next;
    3. 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;}
}

构建

  1. 创建第一个节点,让first指向该节点,形成环形
  2. 创建一个新节点,把节点加入这个新的环形链表
  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版)相关推荐

  1. 数据结构与算法基础(java版)

    目录 数据结构与算法基础(java版) 1.1数据结构概述 1.2算法概述 2.1数组的基本使用 2.2 数组元素的添加 2.3数组元素的删除 2.4面向对象的数组 2.5查找算法之线性查找 2.6查 ...

  2. 一文通数据结构与算法之——链表+常见题型与解题策略+Leetcode经典题

    文章目录 1 链表 1.1 常见题型及解题策略 1.1.1 LeetCode中关于链表的题目有以下五种类型题: 1.1.2 解题策略 1.2 链表的基本内容 1.2.1 链表的基本结构: 1.2.2 ...

  3. python定义链表节点_Python数据结构与算法之链表定义与用法实例详解【单链表、循环链表】...

    本文实例讲述了Python数据结构与算法之链表定义与用法.分享给大家供大家参考,具体如下: 本文将为大家讲解: (1)从链表节点的定义开始,以类的方式,面向对象的思想进行链表的设计 (2)链表类插入和 ...

  4. 数据结构与算法之链表结构寻找p、q最近的公共祖先

    链表结构,寻找p.q最近的公共祖先 数据结构与算法之链表结构寻找p.q最近的公共祖先 链表结构,寻找p.q最近的公共祖先 问题 想法 代码 问题 设一棵二叉树的结点结构为(LLINK, INFO, R ...

  5. 数据结构与算法--单链表相关面试题

    此文章仅作为自己学习过程中的记录和总结,同时会有意地去用英文来做笔记,一些术语的英译不太准确,内容如有错漏也请多指教,谢谢! 一.概述 获取单链表的有效元素个数[新浪面试题1] 获取单链表倒数第k个结 ...

  6. 数据结构与算法(陈越版)第五讲 (树下)树的应用——集合及其运算

    数据结构与算法(陈越版)第五讲 (树下)树的应用--集合及其运算 一.集合的表示 1.1.集合的表示 1.2.集合的储存 二.集合的运算 2.1查找以及普通并 2.2按照秩的合并算法 2.3路径压缩优 ...

  7. 数据结构与算法 内核链表实现商品购物系统项目+Makefile

    数据结构与算法 内核链表实现商品购物系统项目 第一章 项目实现思维 [1]编译介绍 [2]框架思维 第二章 Makefile编写 第三章 代码编写实现 [1]favorite.txt文件 [2]his ...

  8. java动态分区分配_操作系统 动态分区分配算法课程设计 java版.pdf

    操作系统 动态分区分配算法课程设计 java版 湖 南 文 理 学 院 实 验 报 告 课程名称 操作系统课程设计 实验名称 存储管理--动态分区分配算法的模拟 成绩 学生姓名 曹乐 专业 计算机 班 ...

  9. java数据接口之链表_Java数据结构和算法之链表

    三.链表 链结点 在链表中,每个数据项都被包含在'点"中,一个点是某个类的对象,这个类可认叫做LINK.因为一个链表中有许多类似的链结点,所以有必要用一个不同于链表的类来表达链结点.每个LI ...

最新文章

  1. Silverlight实例教程 - Out of Browser开篇
  2. SpringCloud--Eureka服务注册与发现 Eureka 集群搭建 详细案例!!!
  3. 兴义高考八中2021成绩查询,兴义第八中学2021年录取分数线
  4. .NET开发作业调度(job scheduling) - Quartz.NET
  5. 将Spring集成到旧版应用程序中
  6. Thinkphp 数据库配置参数
  7. 用Python玩转统计数据:取样、计算相关性、拆分训练模型和测试
  8. iPhone应用中APNS推送通知流程代码实现案例
  9. iframe嵌套微信网页,图片无法显示问题
  10. 数据分析:使用Imblearn处理不平衡数据(过采样、欠采样)
  11. Servlet规范简介
  12. 算法设计与分析(1)——基础知识
  13. 美化版缤纷彩色文字广告代码文字+网站添加AD教程
  14. DataSource 详解
  15. tableau public使用形状文件进行数据可视化
  16. java poi 导出excel不能超过65536行
  17. K8S调试工具之--nsenter
  18. Power BI中的透视列和逆透视
  19. 二叉树的遍历(递归、非递归)
  20. mysql 数据库的编辑工具有哪些_常用的MySQL数据库管理工具有哪些

热门文章

  1. JS----addEventListener()
  2. .Net验证18位身份证格式
  3. C++程序设计:日历记事本
  4. git 不常用命令小札
  5. qsort的自主实现
  6. 苹果终端date命令_终端下如何修改系统时间?
  7. JVM-XX:NewRatio 、-XX:SurvivorRatio 参数的含义
  8. 在 SharePoint Server 中使用 iFrame 嵌入“Power BI 报表服务器”报表
  9. java读写器代码,JAVA:配置文件读取器-JSP教程,Java技巧及代码
  10. 从零开始用人工智能预测股票(一、特征选取)