目录
1稀疏数组
1.1使用场景
当一个数组中大部分的元素为0,或为同一个值的数组时,可以使用稀疏数组来保存该数组。
1.2 代码实现
import java.util.Arrays;
/**
* @ClassName: SparseArray
* @Author: haojie.sun
* @Description: 稀疏数组与普通二维数组的转化(五子棋)
* @Date: 2021/2/18 9:58
* @Version: 1.0
*/
public class SparseArray {
public static void main(String[] args) {
// 新建一个二维数组,模拟一个五子棋的棋盘
int[][] arr = new int[15][15];
System.out.println("初始数组");
showArr(arr);
// 假设棋盘上共有2个棋子
arr[2][2] =1;
arr[3][3]=2;
System.out.println("棋子数组");
showArr(arr);
// 保存为稀疏数组
// 判断稀疏数组的行
int sum = 0;
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
if (arr[i][j] !=0) {
sum++;
}
}
}
System.out.println("非0数据" + sum);
int[][] sparseArray = new int [sum+1][3];
sparseArray[0][0] = 15;
sparseArray[0][1]= 15;
sparseArray[0][2]= sum;
int k =0;
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
if (arr[i][j] !=0) {
k++;
sparseArray[k][0]=i;
sparseArray[k][1]=j;
sparseArray[k][2]=arr[i][j];
}
}
}
System.out.println("稀疏数组");
showArr(sparseArray);
}
private static void showArr(int[][] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(Arrays.toString(arr[i]));
}
}
}
2环形队列数组实现
- 当队列不为空时,front指向队列的第一个元素,rear指向队列最后一个元素的下一个位置。
- 当队列为空时,front=rear
- 队列满时:(rear+1)%maxsiz=front,少用一个存储空间,也就是数组的最后一个存数空间不用
循环队列的相关条件和公式:
1.队空条件:rear==front
2.队满条件:(rear+1) %QueueSIze==front,其中QueueSize为循环队列的最大长度
3.计算队列长度:(rear-front+QueueSize)%QueueSize
4.入队:(rear+1)%QueueSize
5.出队:(front+1)%QueueSize
import java.util.Arrays;
import java.util.Scanner;
/**
* @ClassName: CircleArrayQueue
* @Author: haojie.sun
* @Description: 环形数组模拟队列
*
* @Date: 2021/2/18 9:59
* @Version: 1.0
*/
public class CircleArrayQueueDemo {
public static void main(String[] args) {
CircleArrayQueue queue = new CircleArrayQueue(4);
boolean flag = true;
while (flag) {
System.out.println("请输入 e: 退出, a 新增,g:获取, h:第一个元素, s: 查看队列, q: 查看数组");
Scanner scanner = new Scanner(System.in);
char c = ' ';
c = scanner.next().charAt(0);
switch (c){
case 'e':
flag = false;
break;
case 'a':
System.out.println("请输入数字");
int val = scanner.nextInt();
try{
queue.add(val);
}catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'g':
System.out.println(queue.get());
break;
case 'h':
try{
System.out.println(queue.head());
}catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 's':
queue.showQueue();
break;
case 'q':
System.out.println(queue);
break;
default:
break;
}
}
System.out.println("退出");
}
}
class CircleArrayQueue{
int front;
int end;
int[] arr;
int maxSize;
public CircleArrayQueue(int size){
maxSize =size;
arr = new int[maxSize];
}
public boolean isEmpty(){
return front == end;
}
public boolean isFull() {
return (end + 1) % maxSize == front;
}
//新增
public void add (int n) {
if (isFull()) {
throw new RuntimeException("队列已满,不能增加");
}
arr[end] = n;
end = (end+1)%maxSize;
}
//取出
public int get () {
if (isEmpty()) {
throw new RuntimeException("队列为空,不能取出");
}
int value = arr[front];
front = (front+1)%maxSize;
return value;
}
// 查看队列
public void showQueue() {
for (int i = front; i < front + size(); i++) {
System.out.printf("queue[%d]=%d\n", (i % maxSize), arr[i % maxSize]);
}
}
// 队列中的有效元素
public int size() {
return (end - front +maxSize) % maxSize;
}
public int head() {
if (isEmpty()) {
throw new RuntimeException("队列为空");
}
return arr[front];
}
@Override
public String toString() {
return "CircleArrayQueue{" +
"front=" + front +
", end=" + end +
", arr=" + Arrays.toString(arr) +
", maxSize=" + maxSize +
'}';
}
}
3 链表
3.1 带头节点的单链表实现
存储的节点内容
import java.util.Objects;
/**
* @ClassName: Node
* @Author: haojie.sun
* @Description:
* @Date: 2021/2/18 14:51
* @Version: 1.0
*/
public class Node {
private int no;
private String name;
private String nickName;
private Node next;
public Node(int no, String name, String nickName) {
this.name = name;
this.no = no;
this.nickName = nickName;
}
public boolean hashNext() {
return Objects.nonNull(this.getNext());
}
public void setNext(Node next) {
this.next = next;
}
public Node getNext() {
return next;
}
public int getNo() {
return no;
}
@Override
public String toString() {
return "Node{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node node = (Node) o;
return no == node.no &&
Objects.equals(name, node.name) &&
Objects.equals(nickName, node.nickName) ;
}
@Override
public int hashCode() {
return Objects.hash(no, name, nickName, next);
}
}
实现并测试单向链表
package com.shj.home.datastruct;
import java.util.Objects;
/**
* @ClassName: SingleLinkedList
* @Author: haojie.sun
* @Description:
* @Date: 2021/2/18 14:50
* @Version: 1.0
*/
public class SingleLinkedListDemo {
public static void main(String[] args) {
SingleLinkedList singleLinkedList = new SingleLinkedList();
Node n1 = new Node(1,"n1", "nc1");
Node n2 = new Node(2,"n2", "nc2");
Node n3 = new Node(3,"n3", "nc3");
Node n4 = new Node(4,"n4", "nc4");
Node n5 = new Node(5,"n5", "nc5");
addList(singleLinkedList,n1,n2,n3,n4,n5);
singleLinkedList.list();
singleLinkedList.remove(n1);
singleLinkedList.remove(n1);
System.out.println(singleLinkedList.getSize());
singleLinkedList.list();
Node n11 = new Node(11,"n11", "nc1");
Node n12 = new Node(12,"n12", "nc2");
Node n13 = new Node(13,"n13", "nc3");
Node n14 = new Node(14,"n14", "nc4");
Node n15 = new Node(15,"n15", "nc5");
// singleLinkedList = null;
SingleLinkedList singleLinkedList1 = new SingleLinkedList();
addSortedList(singleLinkedList1,n11,n12,n13,n14,n15);
System.out.println(singleLinkedList1.getSize());
singleLinkedList1.list();
singleLinkedList1.remove(n11);
singleLinkedList1.remove(n12);
singleLinkedList1.list();
}
private static void addList(SingleLinkedList singleLinkedList,Node n1, Node n2, Node n3, Node n4, Node n5) {
singleLinkedList.addList(n1);
// 如果加入重复的节点,则会无限加
// singleLinkedList.addList(n1);
singleLinkedList.addList(n2);
singleLinkedList.addList(n4);
singleLinkedList.addList(n5);
singleLinkedList.addList(n3);
}
private static void addSortedList(SingleLinkedList singleLinkedList,Node n1, Node n2, Node n3, Node n4, Node n5) {
singleLinkedList.addSorted(n5);
singleLinkedList.addSorted(n4);
singleLinkedList.addSorted(n3);
singleLinkedList.addSorted(n5);
singleLinkedList.addSorted(n3);
singleLinkedList.addSorted(n1);
}
}
class SingleLinkedList {
private Node head;
private int size;
public SingleLinkedList() {
// 初始化头节点
head = new Node(-1,"","");
}
// add
public void addList(Node node){
Node temp = head;
while(true) {
if(temp.getNext() == null) {
temp.setNext(node);
size ++;
break;
}
else {
temp = temp.getNext();
}
}
}
public int getSize(){
return size;
}
public void remove(Node node){
Node temp = head;
while(true) {
if (Objects.isNull(temp)) {
System.out.println("已到末尾,没有对应的元素");
break;
}
System.out.println("temp-<"+temp);
if(Objects.nonNull(temp.getNext()) &&temp.getNext().equals(node)) {
temp.setNext(node.getNext());
System.out.println("已删除元素");
size--;
break;
}
else {
temp = temp.getNext();
}
}
}
public void addSorted(Node node) {
Node temp = head;
while(true) {
if (temp.hashNext()) {
// 判断下一个元素
if(temp.getNext().getNo() == node.getNo()) {
System.out.printf("已存在编号为%d的元素\n", node.getNo());
break;
}
if(temp.getNext().getNo() > node.getNo()) {
//下一个元素比要插入的大
Node next = temp.getNext();
temp.setNext(node);
temp.getNext().setNext(next);
System.out.println("插入成功");
size++;
break;
}
if(temp.getNext().getNo() < node.getNo()) {
//下一个元素比要插入的小
temp = temp.getNext();
}
}
else {
temp.setNext(node);
break;
}
}
}
// 遍历
public void list() {
Node temp = head;
while(true) {
if (temp.hashNext()) {
System.out.println(temp);
temp = temp.getNext();
}
else{
System.out.println(temp);
break;
}
}
}
}
环形链表(约瑟夫问题)
有m个人围成一圈,从n开始,每数到k,出圈,
public class JosepfuLinkedListDemo {
public static void main(String[] args) {
JosepfuLinkedList list = new JosepfuLinkedList();
list.add(5);
// list.list();
list.show(1, 2, 5);
}
}
// 环形链表
class JosepfuLinkedList{
public Boy head;
public Boy getHead() {
return head;
}
private boolean isEmpty() {
return head.next ==null;
}
public void add(int nums) {
if (nums <1) {
System.out.println("长度输入不合法");
return;
}
Boy temp = null;
for (int i = 1; i <= nums ; i++) {
Boy curr = new Boy(i);
if (i == 1) {
// 第一个也要成环
head = curr;
head.next = head;
temp = head;
}
else {
temp.next = curr;
curr.next = head;
temp = curr;
}
}
}
public void list() {
if (isEmpty()) {
System.out.println("没有数据");
return;
}
Boy temp = head;
while (true) {
if (temp.next == head) {
System.out.println(temp.no);
break;
}
System.out.println(temp.no);
temp = temp.next;
}
}
public void show(int n, int k , int num){
if (n <1 || k<1 || num<k) {
System.out.println("输入不合法");
return;
}
if (head == null) {
System.out.println("空的");
return;
}
// 找到尾部的节点
Boy end = head;
while(true) {
if(end.next == head) {
break;
}
end = end.next;
}
// 从第n个人开始
for (int i = 0; i < n -1 ; i++) {
head = head.next;
end = end.next;
}
while(true) {
if(end == head) {
System.out.println("last " + head.no);
break;
}
// 每次数k出圈
for (int i = 0; i < k-1 ; i++) {
head =head.next;
end = end.next;
}
System.out.println("out " + head.no);
head = head.next;
end.next = head;
}
}
}
class Boy{
public int no;
public Boy next;
public Boy(int no){
this.no =no;
}
@Override
public String toString() {
return "Boy{" +
"no=" + no +
'}';
}
}