【自学笔记】尚硅谷数据结构与算法Chapter 3 链表
Chapter 3 链表
文章目录
- Chapter 3 链表
- 3.1 链表
- 3.1.1 链表介绍
- 3.1.2 链表CRUD
- 3.1.3 单链表题目
- 3.2 双向链表
- 3.2.1 双向链表介绍
- 3.2.2 双向链表CRUD
- 3.3 循环链表和约瑟夫问题
- 3.3.1 单向环形链表的应用场景
- 3.3.2 单向环形链表的构建与遍历
- 3.3.3 约瑟夫问题实现
3.1 链表
3.1.1 链表介绍
- 链表以结点方式存储,存储空间不一定连续
- 每个结点包含数据域和指针域
- 每个结点不一定是连续存储
- 链表有带头结点和不带头结点的,根据需求确定使用哪一种
3.1.2 链表CRUD
1、按输入顺序建立一个学生链表
/*** The type Single linked list.* @author ybs*/
public class SingleLinkedListTest {public static void main(String[] args) {StudentNode s1 = new StudentNode(1, "jack", "c1");StudentNode s2 = new StudentNode(2, "york", "c1");StudentNode s3 = new StudentNode(3, "peter", "c1");StudentNode s4 = new StudentNode(4, "marry", "c1");SingleLinkedList singleLinkedList = new SingleLinkedList();singleLinkedList.addNode(s1);singleLinkedList.addNode(s2);singleLinkedList.addNode(s3);singleLinkedList.addNode(s4);singleLinkedList.listLinkedList();}
}class SingleLinkedList{/*** head 头结点*/public StudentNode head = new StudentNode(0, "", "");public void addNode(StudentNode student){StudentNode temp = head;//找到最后一个结点while(true){if(temp.next==null) {break;}temp = temp.next;}temp.next=student;}public void listLinkedList(){if(head.next==null){System.out.println("空链表");return;}StudentNode temp = head.next;while(true){if(temp==null){break;}System.out.println(temp);temp = temp.next;}}}class StudentNode{public int stuNo;public String stuName;public String stuClass;public StudentNode next;public StudentNode(int stuNo, String stuName, String stuClass) {this.stuNo = stuNo;this.stuName = stuName;this.stuClass = stuClass;}@Overridepublic String toString() {return "Student{" +"stuNo=" + stuNo +", stuName='" + stuName + '\'' +", stuClass='" + stuClass + '\'' +'}';}
}
2、按照编号顺序建立一个学生表
/*** The type Single linked list.* @author ybs*/
public class SingleLinkedListTest {public static void main(String[] args) {StudentNode s1 = new StudentNode(1, "jack", "c1");StudentNode s2 = new StudentNode(2, "york", "c1");StudentNode s3 = new StudentNode(3, "peter", "c1");StudentNode s4 = new StudentNode(4, "marry", "c1");SingleLinkedList singleLinkedList = new SingleLinkedList();
/* singleLinkedList.addNode(s1);singleLinkedList.addNode(s2);singleLinkedList.addNode(s3);singleLinkedList.addNode(s4);*/singleLinkedList.addNodeByOrder(s3);singleLinkedList.addNodeByOrder(s1);singleLinkedList.addNodeByOrder(s2);singleLinkedList.addNodeByOrder(s4);singleLinkedList.addNodeByOrder(s4);singleLinkedList.listLinkedList();}
}class SingleLinkedList{/*其他同1*///按照序号加入链表public void addNodeByOrder(StudentNode student){StudentNode temp = head;boolean flag = false;//判断是否有重复的序号//找到插入位置while(true){if(temp.next==null){break;}if(temp.next.stuNo > student.stuNo){break;}else if(temp.next.stuNo == student.stuNo){flag=true;break;}temp = temp.next;}if(flag){System.out.printf("重复序号%d,无法加入\n",student.stuNo);}else{student.next = temp.next;temp.next = student;}}}class StudentNode{/*同1*/
}
3、修改链表
/*** The type Single linked list.* @author ybs*/
public class SingleLinkedListTest {public static void main(String[] args) {StudentNode s1 = new StudentNode(1, "jack", "c1");StudentNode s2 = new StudentNode(2, "york", "c1");StudentNode s3 = new StudentNode(3, "peter", "c1");StudentNode s4 = new StudentNode(4, "marry", "c1");SingleLinkedList singleLinkedList = new SingleLinkedList();
/* singleLinkedList.addNode(s1);singleLinkedList.addNode(s2);singleLinkedList.addNode(s3);singleLinkedList.addNode(s4);*/singleLinkedList.addNodeByOrder(s3);singleLinkedList.addNodeByOrder(s1);singleLinkedList.addNodeByOrder(s2);singleLinkedList.addNodeByOrder(s4);singleLinkedList.addNodeByOrder(s4);singleLinkedList.listLinkedList();singleLinkedList.updateNode(new StudentNode(3, "sam", "c2"));singleLinkedList.listLinkedList();}
}class SingleLinkedList{/*其他同1*///修改结点//根据要修改的结点newStudent的stuNo编号查找修改public void updateNode(StudentNode newStudent){if(head.next==null){System.out.println("空链表");return;}StudentNode temp = head.next;boolean flag = false;//判断是否找到序号while(true){if(temp==null){break;}if(temp.stuNo== newStudent.stuNo){flag=true;break;}temp = temp.next;}if(flag){temp.stuName = newStudent.stuName;temp.stuClass = newStudent.stuClass;}else{System.out.printf("未找到序号%d的学生",newStudent.stuNo);}}}class StudentNode{/*同1*/
}
3.1.3 单链表题目
1、求单链表的有效结点个数
//获取单链表的长度
public static int getLength(StudentNode head){if(head.next == null){return 0;}int length = 0;StudentNode temp = head.next;while(temp!=null){length++;temp=temp.next;}return length;
}
2、查找单链表倒数第k个结点
//获取单链表倒数第index个元素
//1.先得到单链表目前的长度size 2.从头遍历(size-index)个
public static StudentNode getLastIndexNode(StudentNode head, int index){if(head.next==null || index <= 0 || index > getLength(head)){return null;}int size = getLength(head);StudentNode temp = head.next;for(int i=0;i<(size-index);++i){temp = temp.next;}return temp;
}
3、单链表反转
//反转单链表
//1.设置一个新的头结点reverseHead 2.遍历链表,每次将结点放到reverseHead的最前端 3.将原来的头结点指向新的头结点的下一个结点
public static void reverseLinkedList(StudentNode head){//如果为空或者只有一个结点就直接返回if(head.next==null||head.next.next==null){return;}StudentNode temp = head.next;//循环指针StudentNode next = null;//指向当前循环下一个的指针StudentNode reverseHead = new StudentNode(0, "", "");//新的头结点while(temp!=null){next = temp.next;temp.next = reverseHead.next;reverseHead.next = temp;temp = next;}head.next = reverseHead.next;
}
4、从尾到头打印单链表
//从尾到头打印单链表
public void reverseListLinkedList(){if(head.next==null){return;}Stack<StudentNode> stack = new Stack<>();StudentNode temp = head.next;while(temp!=null){stack.push(temp);temp = temp.next;}while(stack.size()>0){System.out.println(stack.pop());}
}
5、合并两个有序单链表,合并之后依然有序
//合并两个有序单链表,合并依然有序
public static SingleLinkedList mergeLinkedList(SingleLinkedList sglList1, SingleLinkedList sglList2){SingleLinkedList singleLinkedList = new SingleLinkedList();StudentNode list1 = sglList1.head;StudentNode list2 = sglList2.head;StudentNode newList = new StudentNode(0, "", "");if(list1.next==null){newList.next = list2.next;singleLinkedList.head = newList;return singleLinkedList;}else if(list2.next==null){newList.next = list1.next;singleLinkedList.head = newList;return singleLinkedList;}StudentNode temp1 = list1.next;StudentNode temp2 = list2.next;StudentNode tempNewList = newList;while (temp1!=null && temp2!=null){if(temp1.stuNo< temp2.stuNo){tempNewList.next=temp1;tempNewList = tempNewList.next;temp1 = temp1.next;}else{tempNewList.next=temp2;tempNewList = tempNewList.next;temp2 = temp2.next;}}if (temp1==null){tempNewList.next = temp2;}else{tempNewList.next = temp1;}singleLinkedList.head = newList;return singleLinkedList;
}
3.2 双向链表
3.2.1 双向链表介绍
- 单链表只能往一个方向查找,双向链表可以向前向后查找
- 单链表的结点不能自我删除,双链表的结点可以
3.2.2 双向链表CRUD
public class DoubleLinkedListTest {public static void main(String[] args) {StudentNode2 s1 = new StudentNode2(1, "jack", "c1");StudentNode2 s2 = new StudentNode2(2, "york", "c1");StudentNode2 s3 = new StudentNode2(3, "peter", "c1");StudentNode2 s4 = new StudentNode2(4, "marry", "c1");StudentNode2 s5 = new StudentNode2(5, "sam", "c2");DoubleLinkedList doubleLinkedList = new DoubleLinkedList();doubleLinkedList.addNode(s1);doubleLinkedList.addNode(s2);doubleLinkedList.addNode(s3);doubleLinkedList.addNode(s4);doubleLinkedList.addNode(s5);//doubleLinkedList.updateNode(new StudentNode2(3, "peter", "c2"));//doubleLinkedList.deleteNode(3);doubleLinkedList.listLinkedList();}
}class DoubleLinkedList{/*** head 头结点*/public StudentNode2 head = new StudentNode2(0, "", "");public void addNode(StudentNode2 student){StudentNode2 temp = head;//找到最后一个结点while(true){if(temp.next==null) {break;}temp = temp.next;}temp.next=student;student.previou = temp;}public void listLinkedList(){if(head.next==null){System.out.println("空链表\n");return;}StudentNode2 temp = head.next;while(true){if(temp==null){break;}System.out.println(temp);temp = temp.next;}}//删除结点//根据编号删除结点public void deleteNode(int stuNo){StudentNode2 temp = head.next;boolean flag = false;//判断是否找到该结点while(true){if(temp==null){break;}if(temp.stuNo==stuNo){flag=true;break;}temp = temp.next;}if(flag){temp.next.previou = temp.previou;temp.previou.next = temp.next;}else{System.out.printf("未找到编号为%d的结点",stuNo);}}//修改结点//根据要修改的结点newStudent的stuNo编号查找修改public void updateNode(StudentNode2 newStudent){if(head.next==null){System.out.println("空链表");return;}StudentNode2 temp = head.next;boolean flag = false;//判断是否找到序号while(true){if(temp==null){break;}if(temp.stuNo== newStudent.stuNo){flag=true;break;}temp = temp.next;}if(flag){temp.stuName = newStudent.stuName;temp.stuClass = newStudent.stuClass;}else{System.out.printf("未找到序号%d的学生",newStudent.stuNo);}}
}class StudentNode2 {public int stuNo;public String stuName;public String stuClass;public StudentNode2 next;public StudentNode2 previou;public StudentNode2(int stuNo, String stuName, String stuClass) {this.stuNo = stuNo;this.stuName = stuName;this.stuClass = stuClass;}@Overridepublic String toString() {return "Student{" +"stuNo=" + stuNo +", stuName='" + stuName + '\'' +", stuClass='" + stuClass + '\'' +'}';}
}
3.3 循环链表和约瑟夫问题
3.3.1 单向环形链表的应用场景
Josephu(约瑟夫、约瑟夫环)问题
3.3.2 单向环形链表的构建与遍历
1、构建思路
先创建一个first结点,并形成环形,每增加一个新的结点,就把该结点加入已有的环形链表中
2、遍历思路
先让一个辅助指针cur指向first,然后通过while遍历环形链表,当cur.next=first时结束
3、实现
public class JosephuProblemTest {public static void main(String[] args) {CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();circleSingleLinkedList.addGirl(5);circleSingleLinkedList.listGirls();}
}class CircleSingleLinkedList{public Girl first = null;public CircleSingleLinkedList(){}public void addGirl(int num){if (num<1){System.out.println("num不符合");return;}Girl curGirl = null;for(int i=1;i<=num;++i){Girl girl = new Girl(i);if (i==1){first = girl;curGirl = first;girl.setNext(first);}else{curGirl.setNext(girl);girl.setNext(first);curGirl = girl;}}}public void listGirls(){if (first==null){System.out.println("空表");return;}Girl curGirl = first;while(true){System.out.println("Girl "+curGirl.getId());if(curGirl.getNext()==first){break;}curGirl = curGirl.getNext();}}
}class Girl{private int id;private Girl next;public Girl(int id) {this.id = id;}public int getId() {return id;}public void setId(int id) {this.id = id;}public Girl getNext() {return next;}public void setNext(Girl next) {this.next = next;}
}
3.3.3 约瑟夫问题实现
思路:n 一共有几个人; k 表示从第k个人开始报数; m 表示每次数几个数
- 需要创建一个辅助指针helper,事先应该指向环形链表的最后一个结点
- 报数前,让 first 和 helper 同时移动 k-1 次
- 报数时,让 first 和 helper 同时移动 m-1 次
- 此时 first 指向的结点出圈
/*** 约瑟夫问题实现** @param startId 表示从第几个开始数数* @param countNum 表示每次数到几出圈* @param sumNum 表示最初有多少小孩*/
public void josephuCountGirl(int startId,int countNum,int sumNum){if (first==null || startId < 1 || startId > sumNum){System.out.println("链表或输入异常");return;}Girl helper = first;//将helper移动到最后一个结点while(true){if(helper.getNext()==first){break;}helper = helper.getNext();}//将first移动到起始结点,helper移动到first的前一个结点for(int i=0;i<startId-1;++i){first = first.getNext();helper = helper.getNext();}//数数,出圈while(true){//first==helper时,说明圈内只剩下一个结点,跳出if (first==helper){break;}//数数for (int i=0;i<countNum-1;++i){first = first.getNext();helper = helper.getNext();}System.out.printf("%d出圈\n",first.getId());first = first.getNext();//first移动到出圈结点的下一个结点helper.setNext(first);//helper.next指向first,出圈结点被移出链表}System.out.printf("最后剩下%d\n",first.getId());
}
【自学笔记】尚硅谷数据结构与算法Chapter 3 链表相关推荐
- 【自学笔记】尚硅谷数据结构与算法Chapter 1 数据结构与算法概述
Chapter 1 数据结构与算法概述 文章目录 Chapter 1 数据结构与算法概述 1.1.1 数据结构和算法的关系 1.2.1 线性结构 1.2.2 非线性结构 尚硅谷数据结构B站学习视频地址 ...
- 【自学笔记】尚硅谷数据结构与算法Chapter 5 递归
Chapter 5 递归 文章目录 Chapter 5 递归 5.1 递归概念 5.2 递归的调用机制 5.3 迷宫问题(回溯) 5.4 八皇后问题(回溯) 5.1 递归概念 递归好就是方法自己调用自 ...
- 【自学笔记】尚硅谷数据结构与算法Chapter 4 栈
Chapter 4 栈 文章目录 Chapter 4 栈 4.1 栈 4.1.1 栈的介绍 4.1.2 数组模拟栈 4.1.3 练习:用链表模拟栈 4.1.4 例题:用栈完成表达式计算(中缀表达式) ...
- 【自学笔记】尚硅谷数据结构与算法Chapter 2 稀疏数组和队列
Chapter 2 稀疏数组和队列 文章目录 Chapter 2 稀疏数组和队列 2.1 稀疏数组 2.1.1 基本介绍 2.1.2 应用案例 2.2 队列 2.2.1 队列介绍 2.2.2 用数组模 ...
- 尚硅谷数据结构与算法(Java)--17--归并排序
:归并排序 归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 将已有序的子序列合并,得到完全有序的序列:即先使每个 ...
- 尚硅谷数据结构和算法01-数据结构介绍和稀疏数组
文章目录 一.数据结构组成 1.线性结构 2.非线性结构 二.稀疏数组 1.应用场景: 2.稀疏数组转换的思路分析 3.代码实现 补充: %d\t 一.数据结构组成 包括:线性结构和非线性结构 1.线 ...
- 电商数仓描述_笔记-尚硅谷大数据项目数据仓库-电商数仓V1.2新版
架构 项目框架 数仓架构 存储压缩 Snappy与LZO LZO安装: 读取LZO文件时,需要先创建索引,才可以进行切片. 框架版本选型Apache:运维麻烦,需要自己调研兼容性. CDH:国内使用最 ...
- 【笔记】Java数据结构与算法
[笔记]Java数据结构与算法 文章目录 [笔记]Java数据结构与算法 1.八大排序应用场景 2.未完待续-- 1.八大排序应用场景 冒泡排序:优化后的冒泡排序可用于当数据已经基本有序,且数据量较小 ...
- MySQL学习笔记——尚硅谷李玉婷经典版MySQL基础笔记(一)
MySQL学习笔记--尚硅谷李玉婷经典版MySQL基础笔记(一) MySQL学习笔记目录 MySQL学习笔记--尚硅谷李玉婷经典版MySQL基础笔记(一) 一.基础知识 1.MySQL的语法规范 2. ...
最新文章
- Docker compose多容器管理
- db2 日期英式写法_《学霸英语》16:美国人和英国人“表达日期”,差距竟然这么大!...
- 如果在安装32位oracle 客户端组件时的情况下以64位模式运行,将出现问题
- 两个排序数组中求第k大的sum(a+b)
- mysqldump主要参数探究
- react中使用构建缓存_完整的React课程:如何使用React构建聊天室应用
- wamp替换mysql_将wamp集成的mysql替换成安装版的
- js如何监听元素事件是否被移除_JS移除事件监听的方法 .removeEventListener( )
- python 发红包import random用redenv_python 常用模块之random,os,sys 模块
- 经典案例之MouseJack
- c语言贪吃蛇毕业论文,毕业论文c语言贪吃蛇
- 100个优秀安全测试工具
- 什么是线程安全性,如何保证线程安全*
- 电脑计算机网络都打不开怎么办,电脑网页打不开怎么回事的常规处理方法
- Qt for Mac苹果开发中,使用Apple Developer文档
- 科技巨头们在SaaS市场“雷声大雨点小”背后的症结
- 浅识Flutter 基本组件之showDatePicker方法
- Pr 入门教程之如何创建新序列?
- 全国职业院校技能大赛网络搭建与应用赛项——云平台底层的一些命令
- 美国买车维权,是怎样告别“按‘闹’分配”的?