数据结构系列第一部分:表

本文深入探讨了链表数据结构,包括单向链表、双向链表和单向环形链表的概念、实现原理及应用实例。通过代码实现增、删、改、查等操作,并对比了单向链表与双向链表的区别,如双向链表的自我删除能力。此外,文章还介绍了约瑟夫环问题的解决方案,展示了如何用单向环形链表解决此问题。最后,讨论了队列的概念,包括普通队列和循环队列,并提供了用数组实现队列的代码示例。
摘要由CSDN通过智能技术生成

/**

  • 1.2 在链表中间,根据节点的序号来插入节点,这样的话,上述在链表尾部增加节点可以看成是这种情况的特例

  • @param heroNode 加入的节点

*/

public void addMiddleNode(HeroNode heroNode) {

//flag来判断该节点的序号在链表中是否存在

//要考虑三种情况:

//1 新加入节点的序号在尾节点

//2 新加入的节点的序号在链表中已经存在,所以,要做一个报错处理

//3 新加入的节点的序号在链表中不存在,允许加入

boolean flag = false;

HeroNode tempNode = headNode;

while (true) {

if(tempNode.next==null){

break;

}

if (tempNode.next.no==heroNode.no){

flag=true;

break;

}

else if (tempNode.next.no>heroNode.no){

break;

}

tempNode=tempNode.next;

}

if (flag) {

System.out.println(“该链表中已经存在该序号的节点\n”);

} else {

heroNode.next=tempNode.next;

tempNode.next=heroNode;

}

}

/**

  • 2 删。因此tempNode初始定义为headNode,所以,它之后就代表了这条链表

  • 很好,没有补位,只是将这个节点删除了。

*/

public void deleteNode(int no){

boolean flag=false;

HeroNode tempNode = headNode;

while(true){

if(tempNode.next==null){

break;

}

if(tempNode.next.no==no){

flag=true;

break;

}

tempNode=tempNode.next;

}

if (flag==true){

//tempNode.next这个节点会被Java的垃圾回收机制自动回收

tempNode.next=tempNode.next.next;

}

else{

System.out.println(“该链表中不存在该节点。\n”);

}

}

/**

  • 3 改。改的原则就是四个域中,只需修改name域与nickname域,no不必修改。

  •   之前想不明白的就是为什么next域不用改,现在知道了。
    

*/

public void replaceNode(HeroNode heroNode){

//考虑两种情况:

//1 链表中不存在该序号

//2 链表中存在该序号

boolean flag=false;

HeroNode tempNode = headNode;

//考虑所有可能出现的情况

if(tempNode.next==null){

System.out.println(“该链表为空,无法修改节点。\n”);

//直接跳出方法

return;

}

while(true){

if(tempNode.next.no==heroNode.no){

flag=true;

break;

}

if(tempNode.next==null){

break;

}

tempNode=tempNode.next;

}

if(flag==true){

tempNode.next.name=heroNode.name;

tempNode.next.nickname=heroNode.nickname;

}

else{

System.out.println(“链表中不存在该序号!\n”);

}

}

/**

  • 4 查,即遍历输出链表中的全部元素。

*/

public void shownode() {

HeroNode tempNode = headNode;

//对于数组中个数未知的情况,就不适合用for,而是应该用while

while (true) {

if (tempNode == null) {

break;

}

//因为我在HeroNode类中重写了toString方法,所以这里的toString的作用就是控制器print输出对象的全部属性

System.out.println(tempNode);

tempNode = tempNode.next;

}

}

}

/**

  • 一个基本类是必不可少的

*/

//为什么这个类前面不能加public →因为文件名必须与 public 的类名保持一致,如果一个文件里面有多个public关键字定义的类,那就会报错

class HeroNode {

public int no;

public String name;

public String nickname;

//我还是想不明白,为什么next可以当成一个,不断指向后一个数。2020/9/3 明天写好这段代码,调试一下。

//调试完我终于知道了,这个类与上述的list类相结合起来时,这个next域起到作用,太妙了。把next当成一个变量。

//我似乎知道了,其实链表的每一个节点存储着两个域,分别是data域和next域,next域用于指向下一个节点 2020/9/4

public HeroNode next;

public HeroNode(int no, String name, String nickname) {

this.no = no;

this.name = name;

this.nickname = nickname;

}

//重写的话尽然还需要专门来一个注释,可怕

//我们可以重写同String()方法来获得(控制器输出)对象的全部属性

@Override

public String toString() {

return “HeroNode[no=” + no + “,name=” + name + “,nickname=” + nickname + “]”;

}

}

[](()3.2 双向链表


[](()3.2.1 概念

为什么要用双向链表呢?因为,单向链表存在以下缺点:

  1. 单向链表的查找方向只能是一个方向,而双向链表可以向前或者向后查找;

  2. 单向链表不能自我删除节点,而需要靠辅助节点,而双向链表可以实现自己删除,但是在代码实现中还是需要定义 tempNode 临时结点。

[](()3.2.2 实现原理和应用实例

和单向链表一样,我用水浒传排行榜的增、删、改、查来代码实现双向链表。

在节点类中,唯一与单向链表不同的是,双向链表除了单向链表的域外,还有一个 pre域,用于指向前一个节点。如下图所示:

在这里插入图片描述

代码的实现原理见代码中注释,具体步骤和单向链表类似。

[](()3.2.3 代码实现

public class DoubleLinkedListView {

public static void main(String[] args) {

//首先可以先建立一些节点

HeroNode hero1 = new HeroNode(1, “宋江”, “及时雨”);

HeroNode hero2 = new HeroNode(2, “卢俊义”, “玉麒麟”);

HeroNode hero3 = new HeroNode(3, “吴用”, “智多星”);

DoubleLinkedList doublelinkedlist = new DoubleLinkedList();

//增

doublelinkedlist.addTailNode(hero1);

doublelinkedlist.addTailNode(hero3);

//删

doublelinkedlist.deleteNode(3);

//改:只修改name和nickname,不修改其它四个变量

HeroNode hero4=new HeroNode(1,“赵志明”,“sharm”);

doublelinkedlist.replaceNode(hero4);

//查

System.out.println(“显示链表的信息……”);

doublelinkedlist.shownode();

}

}

/**

  • 用来存放基本类,这是一种面向对象的编程思想

*/

class DoubleLinkedList {

//首先定义一个头节点:头节点的作用仅仅是表示单链表的头

public HeroNode headNode = new HeroNode(0, “”, “”);

//增、删、改、查

//首先书写增。增有两种情况,一种是在链表末尾增加节点,另一种是在链表中增加节点。

/**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值