【入门必备】Java数据结构详解
文章目录
- 队列
- 代码实现
- 环形队列
- 链表
- 单链表
- add/addByOrder
- delete/update
- 代码实现
- 双向链表
- 代码实现
- 环形链表(Joseph Ring)
- 环形链表代码实现
- 解决Joseph问题代码实现
- 栈
- 代码实现
- 栈的实际应用
数据结构所必备的知识,适合入门学习,作者也是一边学习一边分享,如果觉得写的还不错的话,欢迎点一个收藏再走哦~~~,后续会出更多有关于数据结构与算法的文章,也请大家多多关注!
队列
队列最显著的特点就是先进先出。
- 思路:
使用front
和rear
两个指针,front永远指向队列头的前一个元素,rear指向队列尾。
入队:rear后移,给数组赋值。
出队:front后移,取出该数组。
arr[front+1]
为队列头部。
代码实现
/*** arr[] 用数组来模拟队列。* maxSize 表示数组最大容量。* front 用于指向队列头。* rear 用于指向队列尾。*/
public class ArrayQueue {private int []arr;private int maxSize;private int front;private int rear;public ArrayQueue(int maxSize){this.maxSize=maxSize;arr = new int[maxSize];front=-1;rear=-1;}// 判断队列是否满public boolean isFull(){return rear==maxSize-1;}//判断队列是否空public boolean isEmpty(){return rear==front;}//添加数据到队列。public void addQueue(int date){if(isFull()){System.out.println("False");return ;}rear++;arr[rear]=date;}//出队列public int getQueue(){if(isEmpty()){//由于返回int所以这里利用抛出异常。throw new RuntimeException("Error");}front++;return arr[front];}// 显示队列的所有数据public void showQueue() {if (isEmpty()) {System.out.println("队列空的,没有数据~~");return;}for (int i = 0; i < arr.length; i++) {System.out.printf("arr[%d]=%d\n", i, arr[i]);}}}
环形队列
这里可以直接参考之前写的一篇文章,里面讲的非常详细!
链接:环形队列详解
链表
单链表不需要连续的存储空间,所以在删除和增加结点时不需要像顺序表一样需要移动全部的元素,提高运行效率。
单链表
add/addByOrder
- (add)设置辅助变量
- 循环遍历链表,找到链表的最后一个结点。
temp.next=node
- (addByOrder)设置辅助变量
- 循环遍历链表,找到插入点的前一个位置。(考虑:如果序号相同,无法插入。)
node.next=temp.next
和temp.next=node
(注意顺序,要让新增节点先指向。)
delete/update
- (delete)设置辅助变量。
- 遍历链表,找到需要删除的结点的前一个结点。
temp.next=temp.next.next
- (update)设置辅助变量。
- 遍历链表,找到需要更改的结点。
temp.date=node.date
代码实现
class SingleList{Node1 head=new Node1(0,0);//增加链表到最后public void add(Node1 node){Node1 temp=head;while(true){if(temp.next==null){break;}temp=temp.next;}temp.next=node;}//按序号增加链表public void addByOrder(Node1 node){Node1 temp=head;while(true){if(temp.next==null){break;}if(temp.next.no>=node.no){break;}temp=temp.next;}node.next=temp.next;temp.next=node;}//删除指定结点public void delNode(Node1 node){Node1 temp=head;while(true){if(temp.next==node){break;}temp=temp.next;}temp.next=temp.next.next;}//修改单链表的结点public void update(Node1 node,int update){Node1 temp=head;while(true){if(temp.no==node.no){break;}temp=temp.next;}temp.date=update;}//打印单链表public void list(){Node1 temp=head.next;if(head.next==null){System.out.println("Empty!");}while(temp!=null){System.out.println(temp.toString());temp=temp.next;}}
}
//创建一个类,每个类的对象就是一个结点。
class Node1{public int date;public int no;public Node1 next;public Node1(int date, int no) {this.date = date;this.no = no;}@Overridepublic String toString() {return "Node1{" +"date=" + date +", no=" + no +'}';}
}
双向链表
对于单向链表而言,只有一个查找方向,并且不能自我删除。
所以引入双向链表,与单向链表的主要不同点只是在于pre指针的引入和删除操作
next:指向下一个结点。
pre:指向前一个结点。
- 操作思路:
- 遍历和修改:和单链表一样,遍历可以向前也可以向后查找。
- 添加(添加到最后):先找到最后的节点。
temp.next=newNode;
newNode.pre=temp;
2.1 添加(按序号添加):除了单链表的两个基础指向代码,还需要新增以下代码:
node.pre=temp;
node.next.pre=node;
- 删除:直接找到待删除节点(temp)。
(1)temp.pre.next=temp.next;
//删除节点的前一个节点【指向】 删除节点的下一个节点。
(2)注意!! 如果要删除的结点不是最后一个结点,那么执行(3)
(3)temp.next.pre=temp.pre;
//删除节点的后一个节点向前【指向】删除节点的前一个节点。
代码实现
class DoubleLinkedlistDemo{private Nodes head=new Nodes(0,0);//默认加到链表最后。public void add(Nodes node){Nodes temp=head;while(true){if(temp.next==null){break;}temp=temp.next;}temp.next=node;node.pre=temp;}//按照no的顺序增加链表。public void addByOrder(Nodes node){Nodes temp=head;boolean flag=false;while(true){if(temp.next==null){flag=true;break;}if(temp.next.no>=node.no){break;}temp=temp.next;}if(flag){add(node);return;}//让添加进来的节点先指向。//单链表指向。node.next=temp.next;temp.next=node;//双向链表新增指向。node.pre=temp;node.next.pre=node;}//删除节点。(找到当前要删除的节点即可)public void del(Nodes node){Nodes temp=head;if(head.next==null){System.out.println("Empty!");return ;}while(true){if(temp== node){break;}temp=temp.next;}//绕过当前结点,指向下一个结点。temp.pre.next=temp.next;if(temp.next!=null){temp.next.pre=temp.pre;}}//打印链表,同单链表一样public void list(){Nodes temp=head;while(true) {temp=temp.next;System.out.println(temp);if(temp.next==null){break;}}}
}class Nodes{public int no;public int date;public Nodes next;public Nodes pre;public Nodes(int no,int date){this.no=no;this.date=date;}@Overridepublic String toString() {return "Nodes{" +"no=" + no +", date=" + date +'}';}
}
环形链表(Joseph Ring)
- 思路分析:
- 创建
first
指针,永远指向第一个元素,并且自成环状。 - 建立辅助指针
cur
,通过移动辅助指针来添加节点。
2.1 具体步骤为:辅助指针指向下一个节点、后移、再指向first。
环形链表代码实现
class CircleLinkedListDemo {//创建first节点,永远指向第一个元素,保持不动。private Node first = null;//创建环形链表。public void buildCLL(int nums) {if (nums < 1) {System.out.println("无法加入小于一个的链表");return;}//先创建第一个结点。Node node1 = new Node(1);//让first指向第一个节点first = node1;//first指向自己,形成环状。first.next = first;//建立辅助指针,通过移动辅助指针来添加节点。Node cur = null;cur = first;for (int i = 2; i <= nums; i++) {Node node = new Node(i);//辅助指针指向下一个节点。cur.next = node;//辅助指针后移。cur = cur.next;//辅助指针指向第一个节点。cur.next = first;}}//用来打印环形链表public void list1(){Node temp=first;while(true){//如果到了环形链表的最后,退出循环。if(temp.next==first){break;}System.out.println(temp.toString());temp=temp.next;}System.out.println(temp.toString());}
}
class Node{// 这里也可以设置为私有属性,重写方法getNext和setNext即可。public int no;public Node next;public Node(int no){this.no=no;}@Overridepublic String toString() {return "Node{" +"no=" + no +'}';}
}
解决Joseph问题代码实现
- 思路分析:
- 创建两个结点,
first
(遍历环形链表)和helper
(帮助出圈)。 - first指向startNo的结点,helper则指向first的前一个结点。
- 找到需要出圈的结点后打印,并将结点出圈:
first=first.next;
helper.next=first;
/**** @param nums 表示环形链表节点个数。* @param startNo 表示从第几个节点开始数。* @param countNo 表示数了几下。 每数countNo下,就删除当前结点。*/public void Joseph(int nums,int startNo,int countNo){if(startNo<1|| startNo>nums || nums<1){System.out.println("数据输入有误");return ;}// 创建一个辅助节点,初始化为指向first的前一个结点。Node helper=first;while(true){if(helper.next==first){break;}helper=helper.next;}// 在开始之前,先将first指向开始的节点。for(int i=0;i<startNo-1;i++){first=first.next;helper=helper.next;}// 出圈,是一个循环过程,使用while循环。while(true){// 开始寻找出圈节点,将first指向要删除的节点,helper指向删除节点的前一个节点。for(int j=0;j<countNo-1;j++){first=first.next;helper=helper.next;}// 当圈中只剩一个元素时,退出循环。if(helper==first){break;}System.out.println(first.toString());// 让first后移first=first.next;// helper指向first,就跳过了一个结点(出圈)。//注意:helper并没有后移。helper.next=first;}System.out.printf("最后一个是:%s",first.toString());}
栈
特点:先入后出,变化的一端在栈顶,栈底固定。
入栈(push):栈顶上移;
出栈(pop):栈顶下移。
Java中也提供了关于栈的类,便于直接调用。
- 数组模拟栈的思路分析
- 定义top表示栈顶指针,初始为-1;
- 入栈:
top++;
stack[top]=data;
- 出栈:拿到数据;
top--;
代码实现
/*** max 表示栈的最大容量* top 栈顶指针* stack[] 用数组模拟栈*/class stack{private int max;private int top=-1;private int stack[];public stack(int max){this.max=max;stack=new int[max];}public boolean isFull(){return top==max-1;}public boolean isEmpty(){return top==-1;}//入栈public void push(int date){if(isFull()){System.out.println("False");return;}top++;stack[top]=date;}//出栈public int pop(){if(isEmpty()){throw new RuntimeException("Empty");}int value= stack[top];top--;return value;}//遍历public void list(){for(int i=top;i>=0;i--){System.out.printf("stack[%d]=%d",i, stack[i]);}}
}
栈的实际应用
栈的应用:子程序调用;递归调用;表达式转换(中缀转后缀表达式);二叉树;深度优先。
关于更多的栈的实际应用,就先不在这里展开了,会写另外一篇文章展开来讲。
最重要的来啦~~~
⭐码字不易,求个关注⭐
⭐点个收藏不迷路哦~⭐
【入门必备】Java数据结构详解相关推荐
- java 数据结构详解,数组,集合,HashMap
数组的特性: 数组在内存中是一块连续的存储单元存储起来的,声明数组的时候我们必须声明其长度,这样才会为我们声明一个连续的存储区域. 这种存储方式造成我们想要往数组中存储一个数据时那么其后面各个元素都要 ...
- 菜鸟入门之JAVA重载详解
重载介绍 重载(overloading) 是在一个类里面,方法名字相同,而参数不同.返回类型可以相同也可以不同.(顾名思义只识别 方法名与形参) 每个重载的方法(或者构造函数)都必须有一个独一无二的参 ...
- Java集合详解6:TreeMap和红黑树
<Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查 ...
- Java集合详解5:深入理解LinkedHashMap和LRU缓存
<Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查 ...
- Java虚拟机详解----JVM常见问题总结
[正文] 声明:本文只是做一个总结,有关jvm的详细知识可以参考本人之前的系列文章,尤其是那篇:Java虚拟机详解04----GC算法和种类.那篇文章和本文是面试时的重点. 面试必问关键词:JVM垃圾 ...
- IDEA 入门:安装使用详解(创建项目/包/类、运行/关闭/导入项目、字体/字号设置、常用快捷键等)
文章目录 前言 一.创建新项目 Project 1.1.选择"Create New Project" 1.2.选择左下角的"Empty Project" 1.3 ...
- 爬虫入门之urllib库详解(二)
爬虫入门之urllib库详解(二) 1 urllib模块 urllib模块是一个运用于URL的包 urllib.request用于访问和读取URLS urllib.error包括了所有urllib.r ...
- [redis] 10 种数据结构详解
[redis] 10 种数据结构详解 简介 5种常见数据结构 string: 最常见的 string key value list: 双向链表 set: 集合- zset: 有序集合 hash: 类似 ...
- 【Java-Java集合】Java集合详解与区别
[Java-Java集合]Java集合详解与区别 1)概述 2)集合框架图 2.1.总框架图 2.2.Iterable 框架图 2.3.Map 框架图 3)List 3.1.ArrayList 类继承 ...
- Java集合排序及java集合类详解
Java集合排序及java集合类详解 (Collection, List, Set, Map) 摘要内容 集合是Java里面最常用的,也是最重要的一部分.能够用好集合和理解好集合对于做Java程序的开 ...
最新文章
- 在CentOS 6.9 x86_64的OpenResty 1.13.6.1上使用基于Redis实现动态路由示例
- 【Zookeeper】编程实战之Zookeeper分布式锁实现秒杀
- Non-zero CodeForces - 1300A
- BGP华为、思科选路规则
- 微信扫一扫不能打开APK下载链接的问题
- 计算机桌面视频录制,电脑上怎么录制屏幕上的视频?
- Android快速开发之appBase——(1).appBase介绍
- 工程经济作业1答案_2018年电大《工程经济与管理》阶段作业1及答案(网上作业).doc...
- dnfdpl服务器维护了,魔兽世界TBC:地狱火半岛隐藏的“大恐怖”,魔能机甲成双出没!...
- 华为中兴为何对未来信心十足?
- java io流过滤流_JAVA io流 文件流 字节流 字符流 过滤流 缓冲流
- 纯虚函数 和 抽象类
- html背景音乐音量控制,视频加背景音乐 调小背景音乐音量 这样不影响原视频声音...
- 步进电机和伺服电机优缺点
- dvd光盘安装linux系统,从单DVD光盘上安装openSUSE
- No BUILD ID 问题解决
- c语言——输入方式gets,scanf,fgets分析
- 虚拟展厅建筑系统解决方案
- 小米集团2022未来星专项招聘开始啦!
- pytorch Dataset类及图像增强