一、稀疏数组
1.1 实际需求
1.2 基本介绍
1.3 应用实例
package com.gyh.sparsearray;
import java.util.Arrays;
public class SparseArray {
public static void main(String[] args) {
int[][] chessArr = new int[11][11];
chessArr[1][2] = 1;
chessArr[2][3] = 2;
chessArr[5][6] = 2;
for (int[] cRaw : chessArr) {
for (int c : cRaw) {
System.out.print(c + "\t");
}
System.out.println();
}
int[][] ints = ToSparseArray(chessArr, 0);
for (int[] cRaw : ints) {
for (int c : cRaw) {
System.out.print(c + "\t");
}
System.out.println();
}
int[][] ints1 = restoreArray(ints, 0);
for (int[] cRaw : ints1) {
for (int c : cRaw) {
System.out.print(c + "\t");
}
System.out.println();
}
}
public static int[][] restoreArray(int[][] sparseArray, int defaultValue) {
int[][] ints = new int[sparseArray[0][0]][sparseArray[0][1]];
for (int[] anInt : ints) {
Arrays.fill(anInt, defaultValue);
}
for (int i = 1; i < sparseArray.length; i++) {
ints[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
}
return ints;
}
public static int[][] ToSparseArray(int[][] arr, int defaultValue) {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j] == defaultValue) continue;
sum++;
}
}
int raw = 1;
int[][] SparseArray = new int[sum + 1][3];
SparseArray[0][0] = arr.length;
SparseArray[0][1] = arr[0].length;
SparseArray[0][2] = sum;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j] == defaultValue) continue;
SparseArray[raw][0] = i;
SparseArray[raw][1] = j;
SparseArray[raw][2] = arr[i][j];
raw++;
}
}
return SparseArray;
}
}
二、队列
2.1 引入
2.2 基本介绍
2.3 数组模拟队列
- 注:队列中
front
指向队首元素的前面一个位置,rear
指向队尾元素, maxSize
表示队列的最大容量
package com.gyh.queue;
public class Queue {
public static void main(String[] args) {
ArrayQueue arrayQueue = new ArrayQueue(5);
arrayQueue.addQueue(1);
arrayQueue.addQueue(2);
arrayQueue.addQueue(3);
arrayQueue.addQueue(4);
arrayQueue.addQueue(5);
arrayQueue.getQueue();
arrayQueue.getQueue();
arrayQueue.getQueue();
arrayQueue.getQueue();
arrayQueue.getQueue();
arrayQueue.addQueue(6);
}
}
class ArrayQueue {
private int maxSize;
private int front = -1;
private int rear = -1;
private int[] arr;
public ArrayQueue(int maxSize) {
this.maxSize = maxSize;
arr = new int[maxSize];
}
public boolean isFull() {
return rear == maxSize - 1;
}
public boolean isEmpty() {
return front == rear;
}
public void addQueue(int data) {
if (isFull()) {
System.out.println("队列满不能加入数据");
return;
}
arr[++rear] = data;
}
public int getQueue(){
if(isEmpty()){
System.out.println("队列已空");
throw new ArrayIndexOutOfBoundsException("队列为空");
}
return arr[++front];
}
public void showQueue(){
if(isEmpty()){
System.out.println("队列为空");
return;
}
for (int i : arr) {
System.out.println(i);
}
}
}
package com.gyh.queue;
public class ArrayQueue2 {
public static void main(String[] args) {
AnnularArrayQueue annularArrayQueue = new AnnularArrayQueue(5);
annularArrayQueue.addQueue(1);
annularArrayQueue.addQueue(2);
annularArrayQueue.addQueue(3);
annularArrayQueue.addQueue(4);
annularArrayQueue.getQueue();
annularArrayQueue.getQueue();
annularArrayQueue.getQueue();
annularArrayQueue.addQueue(5);
annularArrayQueue.addQueue(6);
annularArrayQueue.addQueue(7);
annularArrayQueue.showQueue();
}
}
class AnnularArrayQueue {
private final int MAX_SIZE;
private int front = 0;
private int rear = 0;
private int[] arr;
public AnnularArrayQueue(int maxSize) {
this.MAX_SIZE = maxSize;
arr = new int[maxSize];
}
public int getQueueLength() {
return (rear - front + MAX_SIZE) % MAX_SIZE;
}
public boolean isFull() {
return (rear + 1) % MAX_SIZE == front;
}
public boolean isEmpty() {
return front == rear;
}
public void addQueue(int data) {
if (isFull()) {
System.out.println("队列已满");
return;
}
arr[rear] = data;
rear = (rear + 1) % MAX_SIZE;
}
public int getQueue() {
if (isEmpty()) {
throw new ArrayIndexOutOfBoundsException("队列已空");
}
int data = arr[front];
front = (front + 1) % MAX_SIZE;
return data;
}
public void showQueue() {
if (isEmpty()) {
System.out.println("队列为空");
return;
}
if (rear > front) {
for (int i = front; i < rear; i++) {
System.out.println(arr[i]);
}
} else {
for (int i = 0; i < getQueueLength(); i++) {
System.out.println(arr[(front + i) % MAX_SIZE]);
}
}
}
}
三、链表
3.1 链表介绍
3.2 单链表的应用实例
package com.gyh.Link;
import java.util.Comparator;
import java.util.Objects;
public class SingleLink {
public static void main(String[] args) {
Hero hero = new Hero(1, "宋江", "及时雨");
Hero hero1 = new Hero(2, "卢俊义", "玉麒麟");
Hero hero2 = new Hero(3, "吴用", "智多星");
Hero hero3 = new Hero(4, "林冲", "豹子头");
SLink<Hero> heroSLink = new SLink<>(Comparator.comparingInt(Hero::getNo));
heroSLink.add(hero);
heroSLink.add(hero3);
heroSLink.add(hero1);
heroSLink.add(hero2);
heroSLink.remove(new Hero(1, null, null));
heroSLink.list();
}
}
class SLink<T> {
private int length = 0;
private final Node<T> head = new Node<>(null, null);
private Comparator<T> compara;
public SLink(Comparator<T> compara) {
this.compara = compara;
}
public void update(T d) {
Node<T> c = head;
while (c.next != null) {
int compare = compara.compare(c.next.getData(), d);
if (compare == 0) {
c.next.setData(d);
break;
}
c = c.next;
}
}
public int getLength() {
return length;
}
public void addByOrder(T d) {
Node<T> c = head;
boolean flag = true;
while (c.next != null) {
int compare = compara.compare(c.next.getData(), d);
if (compare > 0) {
break;
} else if (compare == 0) {
flag = false;
break;
}
c = c.next;
}
if (flag) {
c.next = new Node<>(d, c.next);
length++;
} else
System.out.println("已经存在不能添加");
}
public void add(T d) {
Node<T> c = head;
while (c.next != null) {
c = c.next;
}
c.setNext(new Node<>(d, null));
length++;
}
public void remove(T d) {
Node<T> c = head;
int com;
while (c.next != null) {
com = compara.compare(c.next.getData(), d);
if (com == 0) {
c.next = c.next.next;
break;
}
c = c.next;
}
}
public void list() {
if (head.next == null) {
System.out.println("链表为空");
return;
}
Node<T> c = head.next;
while (c != null) {
System.out.println(c.data);
c = c.next;
}
}
}
class Node<T> {
T data;
Node<T> next;
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Node<T> getNext() {
return next;
}
public void setNext(Node<T> next) {
this.next = next;
}
}
class Hero {
private int no;
private String name;
private String nickName;
public Hero(int no, String name, String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Hero hero = (Hero) o;
return no == hero.no &&
Objects.equals(name, hero.name) &&
Objects.equals(nickName, hero.nickName);
}
@Override
public int hashCode() {
return Objects.hash(no, name, nickName);
}
@Override
public String toString() {
return "Hero{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
}
3.3 单链表面试题
package com.gyh.Link;
import java.util.Stack;
public class Test {
public static void main(String[] args) {
SLinkList<Hero> heroSLinkList = new SLinkList<>();
Hero hero = new Hero(1, "宋江", "及时雨");
Hero hero1 = new Hero(2, "卢俊义", "玉麒麟");
Hero hero2 = new Hero(3, "吴用", "智多星");
Hero hero3 = new Hero(4, "林冲", "豹子头");
heroSLinkList.add(hero);
heroSLinkList.add(hero1);
heroSLinkList.add(hero2);
heroSLinkList.add(hero3);
heroSLinkList.printReverseLinkList();
}
}
class SLinkList<T> {
private int length = 0;
private final Node<T> head = new Node<>(null, null);
public void add(T d) {
Node<T> c = head;
while (c.next != null) {
c = c.next;
}
c.setNext(new Node<>(d, null));
length++;
}
public int getLength() {
Node<T> c = head;
if (c.next == null) return 0;
int n = 0;
while (c.next != null) {
n++;
c = c.next;
}
return n;
}
public T getNode(int index) {
Node<T> c = head;
int length = 0;
while (c.next != null) {
length++;
c = c.next;
}
if (length == 0) return null;
c = head.next;
for (int i = 0; i < length - index; i++) {
c = c.next;
}
return c.getData();
}
public void reverseLink() {
if (head.next == null || head.next.next == null) return;
Node<T> reverseHead = new Node<>(null, null);
Node<T> cur = head.next;
Node<T> next;
while (cur != null) {
next = cur.next;
cur.next = reverseHead.next;
reverseHead.next = cur;
cur = next;
}
head.next = reverseHead.next;
}
public void printReverseLinkList() {
if (head.next == null) return;
Stack<T> stack = new Stack<>();
Node<T> cur = head.next;
while (cur != null) {
stack.push(cur.getData());
cur = cur.next;
}
while (stack.size() > 0) {
System.out.println(stack.pop());
}
}
public void list() {
if (head.next == null) {
System.out.println("链表为空");
return;
}
Node<T> c = head.next;
while (c != null) {
System.out.println(c.data);
c = c.next;
}
}
}
3.4 双向链表应用实例
package com.gyh.Link;
import java.util.LinkedList;
public class DoubleLinkedListDemo {
public static void main(String[] args) {
}
}
class DoubleLinkedList<T> {
private final DuNode<T> head = new DuNode<>();
public void remove(T d) {
DuNode<T> cur = head;
while (cur.next != null) {
if (d.equals(cur.next.data)) {
cur.next = cur.next.next;
if (cur.next != null) cur.next.pre = cur;
}
cur = cur.next;
}
}
public void add(T d) {
DuNode<T> cur = head;
while (cur.next != null) {
cur = cur.next;
}
cur.next = new DuNode<>(d, cur, null);
}
}
class DuNode<T> {
T data;
DuNode<T> pre;
DuNode<T> next;
public DuNode() {
}
public DuNode(T data, DuNode<T> pre, DuNode<T> next) {
this.data = data;
this.pre = pre;
this.next = next;
}
}
3.5 单向环形链表
package com.gyh.Link;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SingleCircularLinkedListDemo {
public static void main(String[] args) {
SingleCircularLinkedList<Integer> integerSingleCircularLinkedList = new SingleCircularLinkedList<>();
for (int i = 0; i < 10; i++) {
integerSingleCircularLinkedList.add(i);
}
List<Integer> josephu = integerSingleCircularLinkedList.josephu(4, 6);
josephu.forEach(System.out::println);
}
}
class SingleCircularLinkedList<T> {
private Node<T> last;
public boolean isEmpty() {
return last == null;
}
public void add(T d) {
if (isEmpty()) {
last = new Node<>(d, null);
last.setNext(last);
return;
}
last.next = new Node<T>(d, last.next);
last = last.next;
}
public int getLength() {
if (isEmpty()) return 0;
int n = 1;
Node<T> cur = last.next;
while (cur != last) {
n++;
cur = cur.next;
}
return n;
}
public List<T> josephu(int k, final int m) {
int n = getLength();
assert k >= 1 && k <= n;
if (n == 1) return Collections.singletonList(last.getData());
List<T> out = new ArrayList<>();
Node<T> pre = last;
for (int i = 1; i < k; i++) {
pre = pre.next;
}
while (true) {
if (last.next == last) {
out.add(last.getData());
last = null;
break;
}
for (int i = 1; i < m; i++) {
pre = pre.next;
}
if (pre.next == last) last = pre;
out.add(pre.next.getData());
pre.next = pre.next.next;
}
return out;
}
}
四、栈
4.1 基本介绍
4.2 数组模拟栈
package com.gyh.stack;
public class StackDemo {
public static void main(String[] args) {
ArrayStack arrayStack = new ArrayStack(5);
for (int i = 0; i < 5; i++) {
arrayStack.push(i);
}
arrayStack.list();
System.out.println(arrayStack.pop());
System.out.println(arrayStack.pop());
System.out.println(arrayStack.pop());
System.out.println(arrayStack.pop());
System.out.println(arrayStack.pop());
}
}
class ArrayStack {
private final int maxSize;
private int[] arr;
private int stackTop;
public ArrayStack(int size) {
this.maxSize = size;
this.arr = new int[size];
this.stackTop = 0;
}
public boolean isFull() {
return stackTop == maxSize;
}
public boolean isEmpty() {
return stackTop == 0;
}
public void push(int n) {
if (isFull()) {
System.out.println("已满");
return;
}
arr[stackTop++] = n;
}
public int pop() {
if (isEmpty()) throw new RuntimeException("栈已空");
return arr[--stackTop];
}
public void list(){
if(isEmpty()) {
System.out.println("栈空");
return;
}
for (int i : arr) {
System.out.println(i);
}
}
}
4.3 链表模拟栈
package com.gyh.stack;
public class StackDemo2 {
public static void main(String[] args) {
LinkedStack<Integer> integerLinkedStack = new LinkedStack<Integer>();
for (int i = 0; i < 5; i++) {
integerLinkedStack.push(i);
}
integerLinkedStack.list();
System.out.println(integerLinkedStack.pop());
System.out.println(integerLinkedStack.pop());
System.out.println(integerLinkedStack.pop());
System.out.println(integerLinkedStack.pop());
System.out.println(integerLinkedStack.pop());
}
}
class LinkedStack<T> {
private Node<T> stackTop;
public boolean isEmpty() {
return stackTop == null;
}
public void push(T d) {
if (stackTop == null) {
stackTop = new Node<>(d, null);
return;
}
stackTop = new Node<>(d, stackTop);
}
public T pop() {
if (isEmpty()) throw new RuntimeException("栈空");
T d = stackTop.data;
stackTop = stackTop.next;
return d;
}
public void list() {
if (isEmpty()) System.out.println("栈空");
Node<T> cur = stackTop;
while (cur != null) {
System.out.println(cur.data);
cur = cur.next;
}
}
}
class Node<T> {
T data;
Node<T> next;
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
}
4.4 栈实现综合计算器
package com.gyh.stack;
import java.util.Arrays;
import java.util.List;
public class CalculatorDemo {
public static void main(String[] args) {
String expression = "70*2*2-5+1-5+3-4";
LinkedStack<Double> numStack = new LinkedStack<>();
LinkedStack<Character> operStack = new LinkedStack<>();
double n1, n2, res = 0;
char oper = ' ', c;
char[] chars = expression.toCharArray();
int length = chars.length;
StringBuffer numBuf = new StringBuffer();
for (int i = 0; i < length; i++) {
c = chars[i];
if (Calculator.isOper(c) && !operStack.isEmpty()) {
oper = operStack.pop();
if (Calculator.priority(oper) >= Calculator.priority(c)) {
n1 = numStack.pop();
n2 = numStack.pop();
res = Calculator.cal(n1, n2, oper);
numStack.push(res);
} else {
operStack.push(oper);
}
}
if (Calculator.isOper(c)) {
operStack.push(c);
} else {
numBuf.append(c);
if (i == length - 1 || Calculator.isOper(chars[i + 1])) {
numStack.push(Double.parseDouble(numBuf.toString()));
numBuf = new StringBuffer();
}
}
}
while (operStack.size() > 0) {
n1 = numStack.pop();
n2 = numStack.pop();
res = Calculator.cal(n1, n2, operStack.pop());
numStack.push(res);
}
System.out.println(expression + "=" + res);
}
}
class Calculator {
private static final List<Character> opters = Arrays.asList('+', '-', '*', '/');
public static double cal(double num1, double num2, int oper) {
double res = 0;
switch (oper) {
case '+':
res = num1 + num2;
break;
case '-':
res = num2 - num1;
break;
case '*':
res = num1 * num2;
break;
case '/':
res = num2 / num1;
break;
default:
throw new RuntimeException("操作符异常");
}
return res;
}
public static boolean isOper(int oper) {
return isOper((char) oper);
}
public static boolean isOper(char oper) {
return opters.contains(oper);
}
public static int priority(int oper) {
if (!isOper(oper)) {
return -1;
}
switch (oper) {
case '*':
case '/':
return 1;
case '+':
case '-':
return 0;
default:
return -1;
}
}
}
4.5 前缀、中缀、后缀表达式(逆波兰表达式)
4.6 逆波兰计算器实现
package com.gyh.stack;
public class InversePolishExpressionDemo {
public static void main(String[] args) {
String expression = "4 5 * 8 - 60 + 8 2 / +";
LinkedStack<Integer> numStack = new LinkedStack<>();
String[] chars = expression.split(" ");
int n1, n2, res = 0;
for (String c : chars) {
if (Calculator.isOper(c.charAt(0))) {
n1 = numStack.pop();
n2 = numStack.pop();
res = Calculator.cal(n1, n2, c.charAt(0));
numStack.push(res);
} else {
numStack.push(Integer.parseInt(c));
}
}
System.out.println(expression + "=" + res);
}
}
4.7 中缀表达式转后缀表达式(*)
package com.gyh.stack;
import java.util.Arrays;
public class MidToReverseDemo {
public static void main(String[] args) {
String expression = "1 + ( ( 2 + 3 ) * 4 ) - 5";
String[] strs = expression.split(" ");
LinkedStack<String> linkedStack = new LinkedStack<>();
LinkedStack<String> tempStack = new LinkedStack<>();
for (String str : strs) {
if (!isNumeric(str)) {
while (true) {
if (str.equals("(") || linkedStack.isEmpty() || linkedStack.peek().equals("("))
linkedStack.push(str);
else if (str.equals(")")) {
while (!linkedStack.peek().equals("(")) {
tempStack.push(linkedStack.pop());
}
linkedStack.pop();
} else if (Calculator.priority(str.charAt(0)) > Calculator.priority(linkedStack.peek().charAt(0))) {
linkedStack.push(str);
} else {
tempStack.push(linkedStack.pop());
continue;
}
break;
}
} else {
tempStack.push(str);
}
}
while (!tempStack.isEmpty()) {
linkedStack.push(tempStack.pop());
}
while (!linkedStack.isEmpty()) {
System.out.print(linkedStack.pop() + " ");
}
}
public static boolean isNumeric(String str) {
for (int i = str.length(); --i >= 0; ) {
int chr = str.charAt(i);
if (chr < 48 || chr > 57)
return false;
}
return true;
}
}
五、递归
5.1 递归的应用场景
5.2 递归的调用机制
5.3 递归可以解决的问题
5.4 递归需要遵守的重要规则
5.5 迷宫问题
package com.gyh.recursion;
public class MiGong {
public static void main(String[] args) {
int[][] matrix = new int[8][7];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
if (i == 0 || i == matrix.length - 1 || j == 0 || j == matrix[i].length - 1) {
matrix[i][j] = 1;
}
}
}
matrix[2][2] = 1;
matrix[3][1] = 1;
matrix[3][2] = 1;
for (int[] ints : matrix) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
System.out.println("*******************");
find(matrix, 1, 1);
for (int[] ints : matrix) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
}
public static boolean find(int[][] map, int i, int j) {
if (map[6][5] == 2) {
return true;
}
if (map[i][j] == 1 || map[i][j] == 2 || map[i][j] == 3) {
return false;
}
map[i][j] = 2;
if (find(map, i + 1, j)) {
return true;
} else if (find(map, i, j + 1)) {
return true;
} else if (find(map, i - 1, j)) {
return true;
} else if (find(map, i, j - 1)) {
return true;
} else {
map[i][j] = 3;
return false;
}
}
}
5.6 八皇后问题
package com.gyh.recursion;
public class EightQueenProblem {
static int max = 8;
static int[] array = new int[max];
static int count = 0;
private static void check(int n) {
if (n == max) {
printArray();
count++;
return;
}
for (int i = 0; i < max; i++) {
array[n] = i;
if (!isComplicit(n)) {
check(n + 1);
}
}
}
private static boolean isComplicit(int n) {
for (int i = 0; i < n; i++) {
if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[n] - array[i])) {
return true;
}
}
return false;
}
private static void printArray() {
for (int a : array) {
System.out.print(a + "\t");
}
System.out.println();
}
public static void main(String[] args) {
check(0);
System.out.println("一共有" + count + "种算法");
}
}