单链表

public class SingleLinkedListDemo {public static void main(String[] args) {// TODO Auto-generated method stub// 开始测试HeroNode hero1 = new HeroNode(1, "亚索", "疾风剑豪");HeroNode hero2 = new HeroNode(2, "易", "无极剑圣");HeroNode hero3 = new HeroNode(3, "菲奥娜", "无双剑姬");HeroNode hero4 = new HeroNode(4, "阿托", "暗裔剑魔");// 创建单链表SingleLinkedList list = new SingleLinkedList();
//      list.add(hero1);
//      list.add(hero2);
//      list.add(hero3);
//      list.add(hero4);
//      System.out.println("普通 插入……");
//      list.list();// 按顺序添加list.addByNo(hero2);list.addByNo(hero4);list.addByNo(hero3);list.addByNo(hero2);list.addByNo(hero1);// 按排序插入完打印下System.out.println("orderbyno 插入……");list.list();// 测试修改HeroNode hero5 = new HeroNode(4, "亚托克斯", "光明使者");list.update(hero5);System.out.println("修改完的链表");list.list();// 测试删除list.del(2);list.del(4);System.out.println("删除完的链表");list.list();// 测试链表中的有效个数System.out.println(list.getLength(list.getHead()));// 测试是否查找到单链表中倒数第k个节点System.out.println(list.getLastIndexNode(list.getHead(),4));// 测试单链表的反转list.reverse(list.getHead());System.out.println("反转后的链表");list.list();// 测试从尾到头打印单链表System.out.println("从尾到头……");list.reverseList(list.getHead());// 测试合并两个有序链表SingleLinkedList list2 = new SingleLinkedList();list2.addByNo(hero2);list2.addByNo(hero4);list.reverse(list.getHead());System.out.println("打印list1");list.list();System.out.println("打印list2");list2.list();System.out.println("打印合并后的链表");System.out.println(list.mergeTwoList(list.getHead(), list2.getHead()));}}
// 创建单链表但列表 管理英雄节点
class SingleLinkedList{// 先定义一个头结点 头结点不要动 不存放具体的数据HeroNode head = new HeroNode(0, "", "");// 添加节点到单链表// 思路:不考虑英雄排名顺序时 // 1、先找到当前链表的最后节点// 2、将最后节点的next指向新的节点public void add(HeroNode heroNode) {// 定义一个临时节点 指向head;HeroNode temp = head;while (true) {// 找到链表的最后一个节点位置if (temp.next == null) {break;}// 如果没有找到最后 将指针后移temp = temp.next;}// 退出循环时即找到了当前链表的最后一个节点// 将当前节点的next 指向新的节点temp.next = heroNode;}// 添加节点到单链表// 思路:考虑英雄排名顺序时 // 1、先找到要插入节点的前一个位置// 2、heroNode.next = temp.next// 3、temp.next = heroNodepublic void addByNo(HeroNode heroNode) {// 定义一个临时节点 指向head;HeroNode temp = head;boolean flag = false;// 标志要插入的节点是否已经存在 默认不存在while (true) {// 找到链表的最后一个节点位置if (temp.next == null) {break;}if (temp.next.no > heroNode.no) {// 找到要插入节点的前一个位置break;}else if (temp.next.no == heroNode.no) {// 要插入的节点已经存在flag = true;break;}// 如果没有找到 将指针后移temp = temp.next;}if (!flag) {// 即找到了要插入节点的前一个位置heroNode.next = temp.next;temp.next = heroNode;}else {// 说明要插入的节点已经存在System.out.printf("要插入的节点 %d 已存在,不能插入\n",heroNode.no);}}// 修改节点// 思路:先判断找没找到要修改的节点// 找到了让heroNode的name 和 nicename 赋值给当前节点// 没找到就显示没有要修改的节点 无法修改public void update(HeroNode heroNode) {// 头结点不能动所以需要临时节点HeroNode temp = head;boolean flag = false;// 标志找没找到要修改的节点while (true) {// 链表空了if (temp.next == null) {break;}if (temp.next.no == heroNode.no) {// 找到要修改的节点flag = true;break;}// 指针后移 遍历链表temp = temp.next;}if (flag) {// 找到了要修改的节点 开始修改temp.next.name = heroNode.name;temp.next.nickname = heroNode.nickname;}else {System.out.printf("要添加的节点%d不存在,无法修改\n", heroNode.no);}}// 删除链表// 思路:先找到要删除链表的前一个位置 将temp.next = temp.next.next即删除public void del(int no) {// 老规矩 头结点不能动 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) {// 找到了要删除的节点temp.next = temp.next.next;}else {System.out.printf("要删除的节点%d不存在,无法删除", no);}}// 打印链表public void list() {// 先判断当前链表是否为空if (head == null) {System.out.println("当前链表为空,没有数据呐,兄弟");return;}// 定义一个临时变量辅助遍历HeroNode temp = head.next;while (true) {// 判断是否到了最后if(temp == null) {break;}// 打印节点内容System.out.println(temp.toString());// 后移指针temp = temp.next;                  }}/*** 获取单链表中的有效个数* @param head 传进来的头结点* @return 链表中的有效个数*/public int getLength(HeroNode head) {//空链表if (head == null || head.next == null) {return 0;}// 头结点不计算HeroNode cur = head.next;int count = 0;while(cur != null) {count++;// 后移cur = cur.next;}return count;}// 查找单链表中倒数第k个节点public HeroNode getLastIndexNode(HeroNode head,int index) {//空链表if (head == null || head.next == null) {return null;}HeroNode cur = head.next;// 获得当前链表的有效个数int count = getLength(head);// 倒数index不存在if (index < 0 || index > count) {return null;}// 返回count - index 的节点// count = 3 index = 1for (int i = 0; i < count - index; i++) {cur = cur.next;}return cur;}// 单链表的翻转public void reverse(HeroNode head) {// 链表为空或只有一个数据 不需要翻转 直接返回if (head.next == null || head.next.next == null) {return;}// 定义一个新链表 HeroNode newHead = new HeroNode(0, "", "");// 辅助变量 帮助我们遍历HeroNode cur = head.next;// 定义一个next 指向当前cur的下一个节点HeroNode next = null;// 遍历当前链表 将遍历的节点取出 存放在newHead的最前面while(cur != null) {next = cur.next;// 存放当前节点的下一个节点cur.next = newHead.next;// 将cur指向newHead的下一个节点 newHead.next = cur;// 将newHead的下一个节点指向cur 即遍历当前链表取出节点放在newHead的最前面cur = next;// 后移}// 最后将head 指向newHead.next并返回  完成翻转head.next = newHead.next;}// 从尾到头打印单链表public void reverseList(HeroNode head) {if (head == null || head.next == null) {System.out.println("当前链表为空");return;}// 使用栈Stack<HeroNode> stack = new Stack<HeroNode>();// 使用辅助变量 帮助遍历HeroNode cur = head.next;while(cur != null) {stack.push(cur);// 遍历存入栈中cur = cur.next;// 后移}// 开始出栈while (stack.size() > 0) {System.out.println(stack.pop());}}// 合并两个有序链表public HeroNode mergeTwoList(HeroNode node1,HeroNode node2) {// 两个链表为空if (node1.next == null && node2.next == null) {return null;}// 定义一个新链表 HeroNode newHead = new HeroNode(0, "", "");HeroNode prev = newHead;// 遍历当前链表 将遍历的节点取出 存放在newHead的最前面while (node1.next != null && node2.next != null) {if (node1.next.no <= node2.next.no) {prev.next = node1.next;node1.next = node1.next.next;}else {prev.next = node2.next;node2.next = node2.next.next;}prev = prev.next;}prev.next = node1.next == null?node2.next:node1.next;return newHead.next;}public HeroNode getHead() {return head;}public void setHead(HeroNode head) {this.head = head;}}
// 先创建一个英雄节点
class HeroNode{public int no;// 英雄编号public String name;// 英雄名称public String nickname;// 英雄昵称public HeroNode next;// 有参构造方法 alt + shift + s + opublic HeroNode(int no, String nameString, String nicknameString) {this.no = no;this.name = nameString;this.nickname = nicknameString;}// tostring()@Overridepublic String toString() {return "HeroNode [no=" + no + ", nameString=" + name + ", nicknameString=" + nickname + next+"]";}}

双链表

public class DoubleLinkedListDemo {public static void main(String[] args) {// 开始测试HeroNode2 hero1 = new HeroNode2(1, "亚索", "疾风剑豪");HeroNode2 hero2 = new HeroNode2(2, "易", "无极剑圣");HeroNode2 hero3 = new HeroNode2(4, "菲奥娜", "无双剑姬");HeroNode2 hero4 = new HeroNode2(5, "阿托", "暗裔剑魔");// 创建双向链表DoubleLinkedList doubleLinkedList = new DoubleLinkedList();doubleLinkedList.add(hero1);doubleLinkedList.add(hero2);doubleLinkedList.add(hero3);doubleLinkedList.add(hero4);//        // 打印双向链表
//      doubleLinkedList.list();// 测试按排名添加节点
//      doubleLinkedList.addByNo(hero4);
//      doubleLinkedList.addByNo(hero2);
//      doubleLinkedList.addByNo(hero3);
//      doubleLinkedList.addByNo(hero1);// 打印双向链表doubleLinkedList.list();HeroNode2 hero5 = new HeroNode2(4, "亚托克斯", "光明使者");// 测试修改doubleLinkedList.update(hero5);System.out.println("update ");doubleLinkedList.list();// 测试删除doubleLinkedList.del(3);System.out.println("del");doubleLinkedList.list();HeroNode2 hero6 = new HeroNode2(3, "小剑魔", "使者");System.out.println("by order print");doubleLinkedList.addByNo(hero6);doubleLinkedList.list();}
}
// 双向链表
class DoubleLinkedList{HeroNode2 head = new HeroNode2(0,"", "");public HeroNode2 getHead() {return head;}// 添加节点到单链表// 思路:不考虑英雄排名顺序时 // 1、先找到当前链表的最后节点// 2、将最后节点的next指向新的节点public void add(HeroNode2 heroNode) {// 定义一个临时节点 指向head;HeroNode2 temp = head;while (true) {// 找到链表的最后一个节点位置if (temp.next == null) {break;}// 如果没有找到最后 将指针后移temp = temp.next;}// 退出循环时即找到了当前链表的最后一个节点temp.next = heroNode;heroNode.pre = temp;}// 添加节点到单链表// 思路:考虑英雄排名顺序时 // 1、先找到要插入节点的前一个位置// 2、heroNode.next = temp.next// 3、temp.next = heroNodepublic void addByNo(HeroNode2 heroNode) {// 定义一个临时节点 指向head;HeroNode2 temp = head;boolean flag = false;// 标志要插入的节点是否已经存在 默认不存在while (true) {// 找到链表的最后一个节点位置if (temp.next == null) {break;}if (temp.no > heroNode.no) {// 找到要插入节点的前一个位置break;}else if (temp.no == heroNode.no) {// 要插入的节点已经存在flag = true;break;}// 如果没有找到 将指针后移temp = temp.next;}if (!flag) {// 即找到了要插入节点的前一个位置temp.pre.next = heroNode;heroNode.next = temp;heroNode.pre = temp.pre;temp.pre = heroNode;}else {// 说明要插入的节点已经存在System.out.printf("要插入的节点 %d 已存在,不能插入\n",heroNode.no);}}// 修改节点// 思路:先判断找没找到要修改的节点// 找到了让heroNode的name 和 nicename 赋值给当前节点// 没找到就显示没有要修改的节点 无法修改public void update(HeroNode2 heroNode) {// 头结点不能动所以需要临时节点HeroNode2 temp = head;boolean flag = false;// 标志找没找到要修改的节点while (true) {// 链表空了if (temp == null) {break;}if (temp.no == heroNode.no) {// 找到要修改的节点flag = true;break;}// 指针后移 遍历链表temp = temp.next;}if (flag) {// 找到了要修改的节点 开始修改temp.name = heroNode.name;temp.nickname = heroNode.nickname;}else {System.out.printf("要修改的节点%d不存在,无法修改\n", heroNode.no);}}// 删除链表// 思路:先找到要删除链表的前一个位置 将temp.next = temp.next.next即删除public void del(int no) {if (head.next == null) {System.out.println("链表为空无法删除");return;}// 老规矩 头结点不能动 HeroNode2 temp = head;boolean flag = false;// 标志找没找到要删除的节点while (true) {// 链表空了if (temp == null) {break;}if (temp.no == no) {// 找到要删除的节点了flag = true;break;}// 没找到就指针后移 遍历链表temp  = temp.next;}if (flag) {// 找到了要删除的节点temp.pre.next = temp.next;if (temp.next != null) {// 判断temp是否为链表尾部temp.next.pre = temp.pre;}else {// 当前temp在链表尾部temp.pre = null;}}else {System.out.printf("要删除的节点%d不存在,无法删除", no);}}// 打印链表public void list() {// 先判断当前链表是否为空if (head == null) {System.out.println("当前链表为空,没有数据呐,兄弟");return;}// 定义一个临时变量辅助遍历HeroNode2 temp = head.next;while (true) {// 判断是否到了最后if(temp == null) {break;}// 打印节点内容System.out.println(temp.toString());// 后移指针temp = temp.next;                 }}
}
//先创建一个英雄节点
class HeroNode2{public int no;// 英雄编号public String name;// 英雄名称public String nickname;// 英雄昵称public HeroNode2 pre;// 前驱public HeroNode2 next;// 后继// 有参构造方法 alt + shift + s + opublic HeroNode2(int no, String nameString, String nicknameString) {this.no = no;this.name = nameString;this.nickname = nicknameString;}// tostring()@Overridepublic String toString() {return "HeroNode [no=" + no + ", nameString=" + name + ", nicknameString=" + nickname +"]";}}

链表实际应用——约瑟夫环

// 吃小孩的约瑟夫问题
public class Josephu {public static void main(String[] args) {// TODO Auto-generated method stub// 测试一下CircleSingleLinkedList cList = new CircleSingleLinkedList();cList.add(250);// 创建5个超可爱的小孩// 打印他们cList.list();cList.getBoy(250, 1, 2);}}
// 单向环形链表
class CircleSingleLinkedList{// 创建一个first结点 当前没有编号Boy first = null;// 添加小孩结点 创建环形链表public void add(int nums) {// nums做一个数据校验if (nums < 1) {System.out.println("你输入的小孩个数太少了 不够吃的啊");return;}Boy curBoy = null;// 辅助指针,帮助构建环形链表// 使用循环来建立环形链表for (int i = 1; i <= nums; i++) {// 根据编号 创建小孩Boy boy = new Boy(i);// 如果是第一个小孩if (i == 1) {first = boy;first.setNext(boy);// 构成环curBoy = first;// 让 curBoy指向第一个小孩}else {curBoy.setNext(boy);boy.setNext(first);curBoy = boy;}}}// 遍历环形链表public void list() {if (first == null) {System.out.println("当前没有小孩可以吃 ");return;}Boy curBoy = first;while (true) {System.out.printf("当前小孩编号%d\n",curBoy.getNo());if (curBoy.getNext() == first) {// 说明遍历完了 退出break;}curBoy = curBoy.getNext();}}// 从第k哥小孩开始隔n个小孩报数 输出报数的小孩然后吃掉/*** * @param nums 表示最开始圈里有多少小孩* @param k 从第k个小孩开始* @param n 隔几个小孩报数*/public void getBoy(int nums,int k,int n) {Boy helper = first;// 辅助指针 指向环形链表的最后节点while (true) {// 将helper指向当前链表最后一个结点if (helper.getNext() == first) {break;}helper = helper.getNext();}// 小孩报数前 让first 和 helper 移动 k-1for (int i = 0; i < k - 1; i++) {first = first.getNext();helper = helper.getNext();}// 小孩报数时 让first 和 helper 移动 n-1while (true) {if (helper == first) {// 链表里只有一个数据break;}for (int i = 0; i < n - 1; i++) {first = first.getNext();helper = helper.getNext();}// 这时first指向的节点 就是要出圈的小孩节点System.out.printf("出圈的小孩是%d\n",first.getNo());first = first.getNext();helper.setNext(first);}System.out.printf("最后留在圈中的小孩编号%d \n", first.getNo());}}
// 链表节点
class Boy{private int no;private Boy next;public Boy(int no) {this.no = no;}public int getNo() {return no;}public void setNo(int no) {this.no = no;}public Boy getNext() {return next;}public void setNext(Boy next) {this.next = next;}}

链表 java 实现相关推荐

  1. 《LeetCode力扣练习》剑指 Offer 25. 合并两个排序的链表 Java

    <LeetCode力扣练习>剑指 Offer 25. 合并两个排序的链表 Java 一.资源 题目: 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的. 示例1: ...

  2. 《LeetCode力扣练习》剑指 Offer 24. 反转链表 Java

    <LeetCode力扣练习>剑指 Offer 24. 反转链表 Java 一.资源 题目: 定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点. 示例: 输入: 1-& ...

  3. 《LeetCode力扣练习》剑指 Offer 06. 从尾到头打印链表 Java

    <LeetCode力扣练习>剑指 Offer 06. 从尾到头打印链表 Java 一.资源 题目: 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回). 示例 1: 输入: ...

  4. 《LeetCode力扣练习》第206题 反转链表 Java

    <LeetCode力扣练习>第206题 反转链表 Java 一.资源 题目: 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表. 示例 1: 输入:head = [1,2, ...

  5. 《LeetCode力扣练习》第160题 相交链表 Java

    <LeetCode力扣练习>第160题 相交链表 Java 一.资源 题目: 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点.如果两个链表不存 ...

  6. 《LeetCode力扣练习》第141题 环形链表 Java

    <LeetCode力扣练习>第141题 环形链表 Java 一.资源 题目: 给你一个链表的头节点 head ,判断链表中是否有环. 如果链表中有某个节点,可以通过连续跟踪 next 指针 ...

  7. 《LeetCode力扣练习》第21题 合并两个有序链表 Java

    <LeetCode力扣练习>第21题 合并两个有序链表 Java 一.资源 题目: 将两个升序链表合并为一个新的 升序 链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例 ...

  8. 浅谈:数据结构之单链表,java代码演示单链表

    单链表 本文是观看尚硅谷韩老师视频学习总结,部分来源网络. 单链表介绍 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每 ...

  9. java不带头结点单链表,java带头结点的单链表

    JAVA 循环双链表的建立 import java.util.Scanner; //循环双向链表的结点类 class DuLNode { private Object data;// 存放结点值 前驱 ...

  10. 微软算法100题58 从尾到头输出链表(java)

    题目:输入一个链表的头结点,从尾到头反过来输出每个结点的值 以前做过相似的,可以用递归解决,也可以用非递归解决 1 package com.rui.microsoft; 2 3 import java ...

最新文章

  1. go连接Kafka报错kafka: client has run out of available brokers to talk to
  2. pycharm 报黄(黄字、黄色)警告 Local variable 'xxx' might be referenced before assignment
  3. mysql5.6最好的备份方案_Mysql 5.6迁移至PostgreSQL 9.6的实践小结
  4. docsify——一个神奇的文档站点生成器
  5. linux 改用户组密码,Linux用户和组的操作(八) 修改用户密码 passwd
  6. python进程多任务
  7. 数字图像处理——引导滤波
  8. Facebook承认6亿用户密码可被员工随意读取:已修复故障
  9. Base64编码详解及其变种(解决加号在URL变空格问题)
  10. Kerloud UAV室内光流定位教程
  11. MATLAB绘图函数ezplot入门详解
  12. 数据结构---哈希表的C语言实现
  13. java cobar_Cobar源码解析(二)
  14. 10分钟快速搭建多方视频会议系统
  15. signature=c31ee9b23a444aeb59534b250024e5ac,Assembling unit for tube components
  16. Unity 增加2D游戏的打击感笔记
  17. matlab梯形法求二重积分,复化梯形公式公式求二重积分matlab源码
  18. c语言考试考点,C语言考点精选
  19. 上海精神卫生中心怎么样 (徐汇区)
  20. 数据结构-栈(栈的C语言实现)

热门文章

  1. git_ Git 工具 - 储藏(Stashing)
  2. 卸载python2_彻底卸载python
  3. 使用Guacamole实现远程桌面控制
  4. ChatGpt:OpenAI 最近推出了一款聊天AI ——ChatGPT
  5. 打造我们自己的数字图书馆
  6. 天行数据-API调用
  7. 图解阿里达摩院内部结构
  8. rap格式鸿蒙,你,想要成为rap star吗?
  9. 黎明回港避谈婚事 被曝宴请好友庆祝新婚(附图)
  10. V831烧录 【app文件的烧写】