根据尚硅谷韩老师的数据结构课程,自己敲得代码,有一些是自己的思路,解决的问题有一下五个,代码的注释基本都写了思路,如果看不懂可以评论区交流。
package dataStructAndAlgorithm.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, "公孙胜", "入云龙");
HeroNode hero5 = new HeroNode(5, "关胜", "大刀");
HeroNode hero6 = new HeroNode(6, "林冲", "豹子头");
HeroNode hero7 = new HeroNode(7, "秦明", "霹雳火");
HeroNode hero8 = new HeroNode(8, "呼延灼", "双鞭");
SingleLinkedList singleLinkedList = new SingleLinkedList();
// singleLinkedList.add(hero1);
// singleLinkedList.add(hero2);
// singleLinkedList.add(hero3);
// singleLinkedList.add(hero4);
singleLinkedList.addByOrder(hero1);
singleLinkedList.addByOrder(hero2);
singleLinkedList.addByOrder(hero3);
singleLinkedList.addByOrder(hero5);
singleLinkedList.list();
System.out.println("==============================================");
// singleLinkedList.update(new HeroNode(4, "蒋狗","狗中王中王"));
// singleLinkedList.list();
// System.out.println("==============================================");
// singleLinkedList.delete(4);
// singleLinkedList.list();
// System.out.println("==============================================");
// System.out.println(singleLinkedList.count());
// System.out.println("==============================================");
// System.out.println(singleLinkedList.findHero(1));
// System.out.println("==============================================");
// singleLinkedList.reversetList();
// singleLinkedList.list();
// System.out.println("==============================================");
// singleLinkedList.reversePrint();
// System.out.println("==============================================");
SingleLinkedList singleLinkedList2 = new SingleLinkedList();
singleLinkedList2.addByOrder(hero4);
singleLinkedList2.addByOrder(hero6);
singleLinkedList2.addByOrder(hero7);
singleLinkedList2.addByOrder(hero8);
singleLinkedList2.list();
System.out.println("==============================================");
integrate(singleLinkedList.getHead(),singleLinkedList2.getHead());
singleLinkedList.list();
System.out.println("==============================================");
}
//合并两个有序的单链表,合并以后依然有序
public static void integrate(HeroNode head1,HeroNode head2){
if (head1.next == null && head2.next == null){
System.out.println("两个链表都为空,无法合并");
return;
}
HeroNode temp =head1;//需要一个辅助节点来帮助我们遍历原来的单向链表
if (head1.next == null){//如果单向链表1为空,直接打印链表1就好
temp.next = head2.next;
}else {
temp.next = head1.next;//将辅助节点的next指向链表1
HeroNode temp2 = head2.next;//创建辅助节点2帮我们遍历链表2
HeroNode next = null;//指向辅助节点的下一个节点
while (temp2 != null){
if (temp.next == null){//链表1遍历完了以后,直接把链表2中剩余的接在链表1后面
temp.next = temp2;
break;
}
if (temp2.no <= temp.next.no) {
next = temp2.next;// 先暂时保存链表2中当前节点的下一个节点,方便后续使用
temp2.next = temp.next;// 将temp2的下一个节点指向temp的下一个节点
temp.next = temp2;// 将temp2连接到链表1上
temp2 = next; //temp2后移
}
temp = temp.next; //temp后移
}
}
}
}
//定义SingleLinkedList,管理我们的英雄
class SingleLinkedList{
//先初始化一个头节点,头节点不要动,不存放具体的数据
private HeroNode head = new HeroNode(0, "","");
public HeroNode getHead() {
return head;
}
//添加节点到单向链表
//不考虑编号顺序时
//1、找到当前链表的最后节点
//2、将最后这个节点地next指向新的节点
public void add(HeroNode HeroNode){
//因为头节点(head)不能动,因此我们需要一个辅助遍历temp
HeroNode 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标志添加的编号是否存在,默认为false
while (true){
if (temp.next == null){
break;
}
if (temp.next.no > heroNode.no){//temp.next.no > heroNode.no 那么位置就在temp和temp.next之间,就在temp后面插入
break;
}else if (temp.next.no == heroNode.no){//相等说明已经存在不用添加
flag = true;
break;
}
temp = temp.next;
}
//判断是否需要添加
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;//flag表示是否找到该节点
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);
}
}
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){//找到
temp.next = temp.next.next;
}else {
System.out.printf("没有找到编号 %d 的英雄,无法进行删除操作\n",no);
}
}
public void list(){
//先判断链表是否为空
if(head.next == null){
System.out.println("链表为空");
return;
}
//因为头节点(head)不能动,因此我们需要一个辅助遍历temp
HeroNode temp = head.next;
while (true){
//判断是否到链表最后
if (temp == null){
break;
}
//输出节点的信息
System.out.println(temp);
//将temp后移
temp = temp.next;
}
}
//计算单链表有多少个节点
public int count(){
//先判断链表是否为空
if(head.next == null){
return 0;
}
//因为头节点(head)不能动,因此我们需要一个辅助遍历temp
HeroNode temp = head.next;
int count = 0;
while (true){
//判断是否到链表最后
if (temp == null){
break;
}
//将temp后移
count++;
temp = temp.next;
}
return count;
}
//查找单链表中的倒数第k个节点
//1、编写一个方法,接受head节点,同时接受一个index,index表示倒数第几个节点
//2、先获得链表的总长度length,然后找到length-index+1就好
public HeroNode findHero(int index){
//先判断链表是否为空
if(head.next == null){
return null;
}
HeroNode temp = head.next;
int count =0;
int length = count();
boolean flag = false;
if (index < 1 || index > length){
return null;
}
while (true){
//判断是否到链表最后
if (temp == null){
break;
}
count++;
if (count == length-index+1){
flag = true;
break;
}
//将temp后移
temp = temp.next;
}
if (flag){
return temp;
}else {
return null;
}
}
//反转单向链表
public void reversetList(){
//如果当前链表为空,或者只有一个节点,无需反转,直接返回
if (head.next == null || head.next.next == null){
return;
}
//定义一个辅助的指针(变量),帮助我们遍历原来的链表
HeroNode temp = head.next;
HeroNode next = null;//指向当前节点temp的下一个节点
HeroNode reverseHead = new HeroNode(0, "","");
//遍历原来的链表,每遍历一个节点,就将其取出,并放在新的链表reverseHead的最前端
while(temp != null){
next = temp.next;//暂时保存当前节点的下一个节点
temp.next = reverseHead.next;//将temp的下一个节点指向新的链表的最前端
reverseHead.next = temp;
temp = next;//让temp后移
}
//将head.next指向reverseHead.next,实现单链表的反转
head.next = reverseHead.next;
}
//逆序打印
public void reversePrint(){
//如果当前链表为空,无法打印,直接返回
if (head.next == null){
return;
}
Stack<HeroNode> stack = new Stack<>();
HeroNode temp = head.next;
while (temp != null){
stack.add(temp);
temp = temp.next;
}
while (stack.size()>0){
System.out.println(stack.pop());
}
}
}
//定义一个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;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
打印结果如下:
tip: 这只是合并单向链表的打印结果,其他题的答案也在代码里,我在开头注释了,太多我就不一一展示了