数据结构示例代码
准备
public class Const {
public static final String BASE_PATH = "存放文件路径";
public static final String DELIMITER = ">>>>>>o(=•ェ•=)m<<<<<<";
}
// 如需性能测试则直接继承
public class Efficiency {
private long start;
@BeforeEach
public void before() {
start = System.currentTimeMillis();
}
@AfterEach
public void after() {
System.out.println("用时:" + (System.currentTimeMillis() - start) + "ms");
}
}
稀疏数组和队列
队列
public class ArrayQueue {
/**
* 表示数组地最大容量
*/
private final int maxSize;
/**
* 队列头
*/
private int front;
/**
* 队列尾
*/
private int rear;
/**
* 该数组用于存放数据,模拟队列
*/
private final int[] arr;
public ArrayQueue(int maxSize) {
this.maxSize = maxSize + 1;
this.arr = new int[this.maxSize];
front = 0;
rear = 0;
}
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
public boolean isEmpty() {
return front == rear;
}
public void addQueue(int n) {
if (isFull()) {
throw new RuntimeException("队列已满,无法添加数据");
}
arr[rear] = n;
rear = (rear + 1) % maxSize;
}
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列空,无法取出数据");
}
int val = arr[front];
front = (front + 1) % maxSize;
return val;
}
public void showQueue() {
if (isEmpty()) {
throw new RuntimeException("队列为空,无数据~");
}
if (front < rear) {
for (int i = front; i < rear; i++) {
System.out.println("arr[" + i + "]=" + arr[i]);
}
} else {
for (int i = front; i < maxSize; i++) {
System.out.println("arr[" + i + "]=" + arr[i]);
}
for (int i = 0; i < rear; i++) {
System.out.println("arr[" + i + "]=" + arr[i]);
}
}
}
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("队列空,无法取出数据");
}
return arr[front];
}
public int size() {
if (front <= rear) {
return rear - front;
} else {
return maxSize - front + rear;
}
}
}
public class ArrayQueueDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入队列大小:");
int val = scanner.nextInt();
ArrayQueue arrayQueue = new ArrayQueue(val);
System.out.println("s(show):显示队列");
System.out.println("e(exit):退出程序");
System.out.println("a(add):添加数据到队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head):查看队列头的数据");
// 接收用户输入
char key = ' ';
boolean loop = true;
// 输出一个菜单
while (loop) {
System.out.println("请输入操作:");
key = scanner.next().charAt(0);
switch (key) {
case 's':
try {
arrayQueue.showQueue();
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'a':
System.out.println("请输入一个数字:");
try {
val = scanner.nextInt();
arrayQueue.addQueue(val);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'g':
try {
System.out.println(arrayQueue.getQueue());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h':
try {
System.out.println(arrayQueue.headQueue());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e':
loop = false;
break;
default:
System.out.println("请输入正确的命令~");
break;
}
}
System.out.println("程序退出~");
}
}
稀疏数组
public class SparseArray {
public static void main(String[] args) {
// 创建一个原始的二维数组 11 * 11
// 0 表示没有棋子。1表示黑子,2表示蓝子
int[][] chessArr = new int[11][11];
chessArr[1][2] = 1;
chessArr[2][3] = 2;
chessArr[4][5] = 2;
// 输出原始二维数组
print(chessArr);
System.out.println("===");
int[][] sparseArr = chess2sparse(chessArr);
print(sparseArr);
System.out.println("===");
chessArr = sparse2chess(sparseArr);
print(chessArr);
}
private static int[][] sparse2chess(int[][] sparseArr) {
int[][] chessArr = new int[sparseArr[0][0]][sparseArr[0][1]];
for (int i = 1; i <= sparseArr[0][2]; i++) {
chessArr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
return chessArr;
}
private static int[][] chess2sparse(int[][] chessArr) {
int row = chessArr.length;
int col = chessArr[0].length;
int count = 0;
for (int[] ints : chessArr) {
for (int j = 0; j < col; j++) {
if (ints[j] != 0) {
count++;
}
}
}
int[][] sparseArr = new int[count + 1][3];
sparseArr[0][0] = row;
sparseArr[0][1] = col;
sparseArr[0][2] = count;
count = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (chessArr[i][j] != 0) {
count++;
sparseArr[count][0] = i;
sparseArr[count][1] = j;
sparseArr[count][2] = chessArr[i][j];
}
}
}
return sparseArr;
}
private static void print(int[][] array) {
for (int[] row : array) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
}
}
链表
@Data
@NoArgsConstructor
public class HeroNode {
private int no;
private String name;
private String nikeName;
private HeroNode next;
public HeroNode(int no, String name, String nikeName) {
this.no = no;
this.name = name;
this.nikeName = nikeName;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nikeName='" + nikeName + '\'' +
'}';
}
}
@Data
@NoArgsConstructor
public class HeroNode2 {
private int no;
private String name;
private String nikeName;
/**
* 指向下一个节点,默认是null
*/
private HeroNode2 next;
/**
* 指向前一个节点,默认是null
*/
private HeroNode2 pre;
public HeroNode2(int no, String name, String nikeName) {
this.no = no;
this.name = name;
this.nikeName = nikeName;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nikeName='" + nikeName + '\'' +
'}';
}
}
public class HeroNodeDemo {
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, "林冲", "豹子头");
// 创建链表
SingleLinkedList singleLinkedList = new SingleLinkedList();
// 添加
singleLinkedList.add(hero1).add(hero4).add(hero2).add(hero3).list();
System.out.println(Const.DELIMITER);
// 删除
singleLinkedList.del(2).list();
System.out.println(Const.DELIMITER);
hero4 = new HeroNode(4, "林冲冲", "豹子头");
// 修改
singleLinkedList.update(hero4).list();
System.out.println(Const.DELIMITER);
// 循序添加
singleLinkedList.addByOrder(hero2).list();
}
}
单链表
public class SingleLinkedList {
/**
* 初始化一个头节点,头节点不要动,不存放具体的数据
*/
private final HeroNode head = new HeroNode(0, "", "");
/**
* 添加节点到单链表
* 不考虑英雄编号顺序
*/
public SingleLinkedList add(HeroNode node) {
HeroNode temp = head;
while (true) {
// 找到链表最后
if (temp.getNext() == null) {
temp.setNext(node);
break;
}
// 没有找到最后,将temp后移
temp = temp.getNext();
}
return this;
}
/**
* 添加节点到单链表
* 考虑英雄编号顺序
*/
public SingleLinkedList addByOrder(HeroNode node) {
int no = node.getNo();
HeroNode temp = head;
while (true) {
// 找到链表最后
if (temp.getNext() == null) {
temp.setNext(node);
break;
}
if (temp.getNo() == no) {
System.out.println("已存在");
break;
}
if (temp.getNext().getNo() > no) {
node.setNext(temp.getNext());
temp.setNext(node);
break;
}
// 没有找到最后,将temp后移
temp = temp.getNext();
}
return this;
}
/**
* 添加节点到单链表
* 考虑英雄编号顺序
*/
public SingleLinkedList update(HeroNode node) {
int no = node.getNo();
HeroNode temp = head;
while (true) {
// 找到链表最后
if (temp.getNext() == null) {
break;
}
if (temp.getNext().getNo() == no) {
node.setNext(temp.getNext().getNext());
temp.setNext(node);
break;
}
// 没有找到最后,将temp后移
temp = temp.getNext();
}
return this;
}
/**
* 添加节点到单链表
* 考虑英雄编号顺序
*/
public SingleLinkedList del(int no) {
HeroNode temp = head;
while (true) {
// 找到链表最后
if (temp.getNext() == null) {
break;
}
if (temp.getNext().getNo() == no) {
temp.setNext(temp.getNext().getNext());
break;
}
// 没有找到最后,将temp后移
temp = temp.getNext();
}
return this;
}
public void list() {
HeroNode temp = head;
while (temp.getNext() != null) {
System.out.println(temp.getNext());
temp = temp.getNext();
}
}
public HeroNode getHead() {
return head;
}
}
public class SubjectTest extends Efficiency {
private HeroNode heroNode;
@Test
public void test1() {
init();
System.out.println(getLength(heroNode));
System.out.println(findLastIndexNode(heroNode, 2));
System.out.println(Const.DELIMITER);
list(reverseList(this.heroNode));
System.out.println(Const.DELIMITER);
list(reverseList2(this.heroNode));
System.out.println(Const.DELIMITER);
stackPrint(heroNode);
}
public void stackPrint(HeroNode heroNode) {
Stack<HeroNode> heroNodes = new Stack<>();
HeroNode temp = heroNode;
while (temp != null) {
heroNodes.push(new HeroNode(temp.getNo(), temp.getName(), temp.getNikeName()));
temp = temp.getNext();
}
while (!heroNodes.isEmpty()) {
System.out.println(heroNodes.pop());
}
}
public HeroNode reverseList(HeroNode heroNode) {
if (heroNode == null) {
return null;
}
HeroNode temp = heroNode;
HeroNode reverseNode = new HeroNode(0, "", "");
while (temp.getNext() != null) {
temp = temp.getNext();
HeroNode next = new HeroNode(temp.getNo(), temp.getName(), temp.getNikeName());
next.setNext(reverseNode);
reverseNode = next;
}
return reverseNode;
}
public HeroNode reverseList2(HeroNode heroNode) {
if (heroNode == null) {
return null;
}
HeroNode cur = heroNode.getNext();
HeroNode next = null;
HeroNode reverseNode = new HeroNode(0, "", "");
while (cur != null) {
// 先暂时保存当前节点的下一个节点,因为后面需要使用
next = cur.getNext();
// 将 cur 的下一个节点指向新链表的最前端
cur.setNext(reverseNode.getNext());
// 将 cur 连接到新的链表上
reverseNode.setNext(cur);
cur = next;
}
return reverseNode.getNext();
}
public HeroNode findLastIndexNode(HeroNode heroNode, int index) {
if (heroNode == null || index <= 0) {
return null;
}
int len = getLength(heroNode);
if (index > len) {
return null;
}
HeroNode temp = heroNode.getNext();
for (int i = 0; i < len - index; i++) {
temp = temp.getNext();
}
return temp;
}
public int getLength(HeroNode heroNode) {
int len = 0;
if (heroNode != null) {
HeroNode temp = heroNode;
while (temp.getNext() != null) {
len++;
temp = temp.getNext();
}
}
return len;
}
public void list(HeroNode heroNode) {
HeroNode temp = heroNode;
while (temp != null) {
System.out.println(temp);
temp = temp.getNext();
}
}
public void init() {
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode hero3 = new HeroNode(3, "吴用", "智多星");
HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");
// 创建链表
SingleLinkedList singleLinkedList = new SingleLinkedList();
// 添加
singleLinkedList.add(hero1).add(hero2).add(hero3).add(hero4);
heroNode = singleLinkedList.getHead();
}
}
双链表
public class DoubleLinkedList {
/**
* 初始化一个头节点,头节点不要动,不存放具体的数据
*/
private final HeroNode2 head = new HeroNode2(0, "", "");
/**
* 返回头节点
*/
public HeroNode2 getHead() {
return head;
}
public void list() {
HeroNode2 tmp = head.getNext();
while (tmp != null) {
System.out.println(tmp);
tmp = tmp.getNext();
}
}
public DoubleLinkedList add(HeroNode2 heroNode) {
HeroNode2 tmp = head;
while (true) {
if (tmp.getNext() == null) {
tmp.setNext(heroNode);
heroNode.setPre(tmp);
break;
}
tmp = tmp.getNext();
}
return this;
}
public DoubleLinkedList update(HeroNode2 heroNode) {
HeroNode2 tmp = head.getNext();
while (true) {
if (tmp == null) {
break;
}
if (tmp.getNo() == heroNode.getNo()) {
tmp.setName(heroNode.getName());
tmp.setNikeName(heroNode.getNikeName());
break;
}
tmp = tmp.getNext();
}
return this;
}
public DoubleLinkedList del(int no) {
HeroNode2 tmp = head.getNext();
while (true) {
if (tmp == null) {
break;
}
if (tmp.getNo() == no) {
HeroNode2 pre = tmp.getPre();
HeroNode2 next = tmp.getNext();
pre.setNext(next);
if (next != null) {
next.setPre(pre);
}
break;
}
tmp = tmp.getNext();
}
return this;
}
}
public class DoubleLinkedListDemo {
public static void main(String[] args) {
HeroNode2 hero1 = new HeroNode2(1, "宋江", "及时雨");
HeroNode2 hero2 = new HeroNode2(2, "卢俊义", "玉麒麟");
HeroNode2 hero3 = new HeroNode2(3, "吴用", "智多星");
HeroNode2 hero4 = new HeroNode2(4, "林冲", "豹子头");
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
// 增加
doubleLinkedList.add(hero1).add(hero2).add(hero3).add(hero4).list();
System.out.println(Const.DELIMITER);
// 改
hero4 = new HeroNode2(4, "林冲冲", "豹子头");
doubleLinkedList.update(hero4).list();
System.out.println(Const.DELIMITER);
// 删
doubleLinkedList.del(2).list();
System.out.println(Const.DELIMITER);
// 添
hero2 = new HeroNode2(2, "卢俊义", "玉麒麟");
doubleLinkedList.add(hero2).list();
}
}
Josephu 问题
public class JosepFu {
public static void main(String[] args) {
// CircleSingleLinkedListDemo
// TODO: do some thing...
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Body {
private int no;
private Body next;
public Body(int no) {
this.no = no;
}
@Override
public String toString() {
return "Body{" +
"no=" + no +
'}';
}
}
public class CircleSingleLinkedList {
// 创建第一个节点,当前没有编号
private Body first = null;
public CircleSingleLinkedList addBody(int num) {
if (first == null) {
first = new Body(num);
first.setNext(first);
return this;
}
Body next = first;
while (true) {
if (next.getNext() == first) {
next.setNext(new Body(num));
next.getNext().setNext(first);
break;
}
next = next.getNext();
}
return this;
}
public void showBody() {
if (first != null) {
Body tmp = first;
while (true) {
System.out.println(tmp);
if (tmp.getNext() == first) {
break;
}
tmp = tmp.getNext();
}
}
}
public int size() {
int i = 0;
if (first != null) {
Body tmp = first;
while (true) {
++i;
if (tmp.getNext() == first) {
break;
}
tmp = tmp.getNext();
}
}
return i;
}
/**
* 计算出圈顺序
*
* @param startNo 表示从第几个小孩开始数数
* @param countNum 表示数几下
*/
public List<Integer> countBody(int startNo, int countNum) {
int nums = size();
if (first == null || startNo < 1 || startNo > nums || countNum < 1) {
return null;
}
Body tmp = first;
for (int i = 1; i < startNo; i++) {
tmp = tmp.getNext();
}
ArrayList<Integer> order = new ArrayList<>();
if (countNum == 1) {
Body start = tmp;
while (true) {
order.add(tmp.getNo());
if (tmp.getNext() == start) {
return order;
}
tmp = tmp.getNext();
}
}
int i = 1;
while (true) {
if (tmp.getNext() == tmp) {
order.add(tmp.getNo());
break;
}
++i;
if (i == countNum) {
i = 1;
order.add(tmp.getNext().getNo());
tmp.setNext(tmp.getNext().getNext());
}
tmp = tmp.getNext();
}
return order;
}
}
public class CircleSingleLinkedListDemo {
public static void main(String[] args) {
CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
circleSingleLinkedList.addBody(1).addBody(2).addBody(3).addBody(4).addBody(5).showBody();
System.out.println(circleSingleLinkedList.countBody(5, 5));
}
}
栈
public class ArrayStack {
@Getter
private final int maxSize;
private int[] stack;
@Getter
private int top = -1;
public ArrayStack(int maxSize) {
this.maxSize = maxSize;
this.stack = new int[maxSize];
}
public boolean isFull() {
return top == maxSize - 1;
}
public boolean isEmpty() {
return top == -1;
}
public void push(int val) {
if (isFull()) {
throw new RuntimeException("栈满");
}
stack[++top] = val;
}
public int pop() {
if (isEmpty()) {
throw new RuntimeException("栈空");
}
return stack[top--];
}
public void list() {
if (isEmpty()) {
throw new RuntimeException("栈空");
}
for (int i = top; i >= 0; i--) {
System.out.println("stack[" + i + "] = " + stack[i]);
}
}
}
public class ArrayStack2 {
@Getter
private final int maxSize;
private int[] stack;
@Getter
private int top = -1;
public ArrayStack2(int maxSize) {
this.maxSize = maxSize;
this.stack = new int[maxSize];
}
public boolean isFull() {
return top == maxSize - 1;
}
public boolean isEmpty() {
return top == -1;
}
public void push(int val) {
if (isFull()) {
throw new RuntimeException("栈满");
}
stack[++top] = val;
}
public int pop() {
if (isEmpty()) {
throw new RuntimeException("栈空");
}
return stack[top--];
}
public int peek() {
if (isEmpty()) {
throw new RuntimeException("栈空");
}
return stack[top];
}
public void list() {
if (isEmpty()) {
return;
}
for (int i = top; i >= 0; i--) {
System.out.println("stack[" + i + "] = " + stack[i]);
}
}
public int priority(char operator) {
if (operator == '*' || operator == '/') {
return 1;
}
if (operator == '+' || operator == '-') {
return 0;
}
return -1;
}
public boolean isOperator(char val) {
return val == '+' || val == '-' || val == '*' || val == '/';
}
public int cal(int val1, int val2, char operator) {
int res = 0;
switch (operator) {
case '+':
res = val1 + val2;
break;
case '-':
res = val2 - val1;
break;
case '*':
res = val1 * val2;
break;
case '/':
res = val2 / val1;
break;
default:
break;
}
return res;
}
}
public class ArrayStackDemo {
public static void main(String[] args) {
boolean loop = true;
System.out.println("请输入栈大小");
Scanner scanner = new Scanner(System.in);
String key = "";
int val = scanner.nextInt();
ArrayStack stack = new ArrayStack(val);
System.out.println("show:显示栈");
System.out.println("exit:退出程序");
System.out.println("push:入栈");
System.out.println("pop:出栈");
while (loop) {
key = scanner.next();
switch (key) {
case "show":
try {
stack.list();
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case "push":
System.out.println("请输入要入栈的值");
val = scanner.nextInt();
try {
stack.push(val);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case "pop":
try {
System.out.println(stack.pop());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case "exit":
System.out.println("退出~");
loop = false;
break;
default:
System.out.println("请输入正确的命令");
break;
}
}
System.out.println("退出~");
}
}
简易计算器
public class Calculator {
public static void main(String[] args) {
// String expression = "7 * 2 * 2 - 5 + 1 - 5 + 3 - 4";
String expression = "7 * 2 * 12 - 5 + 1 - 5 + 13 - 14";
expression = expression.replace(" ", "");
// 数字栈 符合栈
int length = expression.length();
if (length == 0) {
System.out.println(0);
return;
}
if (length == 1) {
System.out.println(expression);
return;
}
int num1, num2, res;
char operator;
int len = length / 2;
boolean flag = false;
ArrayStack2 numStack = new ArrayStack2(len + 1);
ArrayStack2 operatorStack = new ArrayStack2(len);
for (char val : expression.toCharArray()) {
if (operatorStack.isOperator(val)) {
flag = false;
if (!operatorStack.isEmpty() && operatorStack.priority(val) <= operatorStack.priority((char) operatorStack.peek())) {
num1 = numStack.pop();
num2 = numStack.pop();
operator = (char) operatorStack.pop();
res = numStack.cal(num1, num2, operator);
numStack.push(res);
operatorStack.push(val);
continue;
}
operatorStack.push(val);
} else {
if (flag) {
numStack.push(Integer.parseInt(numStack.pop() + String.valueOf(val)));
continue;
}
flag = true;
numStack.push(val - '0');
}
}
while (!operatorStack.isEmpty()) {
num1 = numStack.pop();
num2 = numStack.pop();
operator = (char) operatorStack.pop();
res = numStack.cal(num1, num2, operator);
numStack.push(res);
}
System.out.println(expression + " = " + numStack.pop());
}
}
逆波兰表达式
public class PolandNotation {
public static void main(String[] args) {
// 先定义一个逆波兰表达式
// (3 + 4) * 5 -6 => 30 4 + 5 * 6 - => 164
// 4 * 5 - 8 + 60 + 8 / 2 => 4 5 * 8 - 60 + 8 2 / +
// 测试
// String suffixExpression = "3 4 + 5 * 6 -";
String suffixExpression = "4 5 * 8 - 60 + 8 2 / +";
// 思路
// 1. 先将 "30 4 + 5 * 6 -" => 放到 ArrayList中
// 2. 将 ArrayList 传递给一个方法,遍历 ArrayList 配合栈 完成计算
List<String> list = getListString(suffixExpression);
System.out.println("list = " + list);
System.out.println("calculate(suffixExpression) = " + calculate(suffixExpression));
}
/**
* 将一个逆波兰表达式,依次将数据和运算符 放入到 ArrayList 中
*
* @param suffixExpression 逆波兰表达式
* @return 集合
*/
public static List<String> getListString(String suffixExpression) {
// 将 suffixExpression 分割
char[] seCs = suffixExpression.replace(" ", "").toCharArray();
ArrayList<String> list = new ArrayList<>();
for (char seC : seCs) {
list.add(String.valueOf(seC));
}
return list;
}
/**
* 完成逆波兰表达式的计算
* 1) 从左至右扫描,将 3 和 4 压入栈堆
* 2) 遇到 + 运算符,因此弹出 4 和 3 (4 为栈顶元素, 3 为次栈顶元素),计算出 3 + 4 的值,得 7,再将 7 入栈
* 3) 将 5 入栈
* 4) 接下来是 * 运算符,因此弹出 5 和 7,计算出 7 * 5 = 35,将 35 入栈
* 5) 将 6 入栈
* 6) 最后是 - 运算符,计算出 35 - 6 的值,即 29,因此得出最终结果
*
* @return 结果
*/
public static int calculate(String suffixExpression) {
// 创建栈,只需要一个栈即可
Stack<String> stack = new Stack<>();
// 遍历
String[] ses = suffixExpression.split(" ");
for (String se : ses) {
// 如果是数字
if (se.matches("\\d+")) {
// 入栈
stack.push(se);
} else {
// 出栈两个数字,并运算,再入栈
Integer num2 = Integer.parseInt(stack.pop());
Integer num1 = Integer.parseInt(stack.pop());
int res;
switch (se) {
case "+":
res = num1 + num2;
break;
case "-":
res = num1 - num2;
break;
case "*":
res = num1 * num2;
break;
case "/":
res = num1 / num2;
break;
default:
throw new RuntimeException("运算符有误");
}
stack.push(String.valueOf(res));
}
}
return Integer.parseInt(stack.pop());
}
}
中缀转成逆波兰表达式
public class PolandNotation02 {
public static void main(String[] args) {
// 完成将一个中缀表达式转成后缀表达式的功能
// 说明
// 1 + ((2 + 3) * 4) - 5 => 转成 1 2 3 + 4 * + 5 -
String expression = "1 + ((2 + 3) * 4) - 5";
System.out.println(toInfixExpressionList(expression));
System.out.println(parseSuffixExpressionList(expression));
}
private static List<String> parseSuffixExpressionList(String expression) {
List<String> els = toInfixExpressionList(expression);
// 定义两个栈
// 符号栈
Stack<String> s1 = new Stack<>();
// 说明: 因为 s2 这个 栈,在整个转换过程中,没有 pop 操作,而且后面我们还需要逆序输出
// 因此比较麻烦,这里我们就不用 Stack<String> 直接使用 List<String> s2
// Stack<String> s2 = new Stack<String> s2 // 存储中间结果的栈 s2
// 存储中间结果的 List s2
List<String> s2 = new ArrayList<>();
// 遍历 els
for (String el : els) {
if (el.matches("\\d+")) {
s2.add(el);
} else if ("(".equals(el)) {
s1.push(el);
} else if (")".equals(el)) {
while (true) {
String symbol = s1.pop();
if ("(".equals(symbol)) {
break;
}
s2.add(symbol);
}
} else {
// 比较优先级
while (!s1.isEmpty() && priority(s1.peek()) >= priority(el)) {
s2.add(s1.pop());
}
s1.push(el);
}
}
while (!s1.isEmpty()) {
s2.add(s1.pop());
}
return s2;
}
public static List<String> toInfixExpressionList(String expression) {
char[] chars = expression.replace(" ", "").toCharArray();
ArrayList<String> els = new ArrayList<>();
for (char a : chars) {
if (a >= '0' && a <= '9') {
int li = els.size() - 1;
if (li >= 0) {
String la = els.get(li);
char lac = la.charAt(0);
if (lac >= '0' && lac <= '9') {
els.set(li, la + a);
continue;
}
}
}
els.add(String.valueOf(a));
}
return els;
}
private static int priority(String operator) {
if ("*".equals(operator) || "/".equals(operator)) {
return 1;
}
if ("+".equals(operator) || "-".equals(operator)) {
return 0;
}
return -1;
}
}
完整计算器
public class ReversePolishMultiCalc {
/**
* 匹配运算符 + - * / ( ) 运算符
*/
private static final String SYMBOL = "\\+|-|\\*|/|\\(|\\)";
private static final String LEFT = "(";
private static final String RIGHT = ")";
private static final String ADD = "+";
private static final String MINUS = "-";
private static final String MULTIPLY = "*";
private static final String DIVIDE = "/";
/**
* 加减 + -
*/
private static final int LEVEL_01 = 1;
/**
* 乘除 * /
*/
private static final int LEVEL_02 = 2;
/**
* 括号
*/
private static final int LEVEL_HIGH = Integer.MAX_VALUE;
private static Stack<String> stack = new Stack<>();
private static List<String> data = Collections.synchronizedList(new ArrayList<>());
/**
* 去除所有空格
*/
public static String replaceAllBlank(String s) {
// \\s+ 匹配任何空格字符,包括空格,制表符,换页符等等,等价于 [\f\n\r\t\v]
return s.replaceAll("\\s+", "");
}
/**
* 判断是不是数字
*/
public static boolean isNumber(String s) {
Pattern pattern = Pattern.compile("^[-|+]?[.\\d]*$");
return pattern.matcher(s).matches();
}
/**
* 判断是不是运算符
*/
public static boolean isSymbol(String s) {
return s.matches(SYMBOL);
}
/**
* 匹配运算等级
*/
public static int caleLevel(String s) {
if ("+".equals(s) || "-".equals(s)) {
return LEVEL_01;
} else if ("*".equals(s) || "/".equals(s)) {
return LEVEL_02;
}
return LEVEL_HIGH;
}
/**
* 匹配
*/
public static synchronized List<String> doMatch(String s) {
if (Objects.isNull(s) || "".equals(s.trim())) {
throw new RuntimeException("data is empty");
}
if (!isNumber(String.valueOf(s.charAt(0)))) {
throw new RuntimeException("data illeagle, start not with a number");
}
s = replaceAllBlank(s);
String each;
int start = 0;
for (int i = 0; i < s.length(); i++) {
String symbol = String.valueOf(s.charAt(i));
if (isSymbol(symbol)) {
each = symbol;
// 栈为空,操作符,或者 操作符优先级大于栈顶优先级 && 操作符优先级不是 () 的优先级 即是 ( 直接入栈
if (RIGHT.equals(each)) {
// ) 操作符, 依次出栈入列直到栈空 或者遇到第一个 ) 操作符,此时 ) 出栈
while (!stack.isEmpty()) {
String pop = stack.pop();
if (LEVEL_HIGH == caleLevel(pop)) break;
data.add(pop);
}
} else {
while (!stack.isEmpty() && caleLevel(each) <= caleLevel(stack.peek())) {
if (caleLevel(stack.peek()) == LEVEL_HIGH) break;
data.add(stack.pop());
}
stack.push(each);
}
// 前一个运算符位置
start = i;
} else if (i == s.length() - 1 || isSymbol(String.valueOf(s.charAt(i + 1)))) {
// 为最后一位 或者 下一位是符号 适配多位数
each = start == 0 ? s.substring(start, i + 1) : s.substring(start + 1, i + 1);
if (isNumber(each)) {
data.add(each);
continue;
}
throw new RuntimeException("data not match number");
}
}
// 如果栈里还有元素,此时元素需要依次出栈入队,可以想象为战里面只剩下栈顶为 / ,栈底为 + ,应该依次出栈入列,可以直接翻转整个 stack 添加到队列
Collections.reverse(stack);
data.addAll(new ArrayList<>(stack));
System.out.println(data);
return data;
}
/**
* 算出结果
*/
public static synchronized Double doCalc(List<String> list) {
double d = 0D;
if (list == null || list.isEmpty()) {
return null;
}
if (list.size() == 1) {
return Double.parseDouble(list.get(0));
}
List<String> tmp = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
tmp.add(list.get(i));
if (isSymbol(list.get(i))) {
d += doTheMatch(list.get(i - 2), list.get(i - 1), list.get(i));
tmp.remove(i);
tmp.remove(i - 1);
tmp.set(i - 2, String.valueOf(d));
tmp.addAll(list.subList(i + 1, list.size()));
break;
}
}
return doCalc(tmp);
}
public static Double doTheMatch(String s1, String s2, String symbol) {
Double result;
switch (symbol) {
case ADD:
result = Double.parseDouble(s1) + Double.parseDouble(s2);
break;
case MINUS:
result = Double.parseDouble(s1) - Double.parseDouble(s2);
break;
case MULTIPLY:
result = Double.parseDouble(s1) * Double.parseDouble(s2);
break;
case DIVIDE:
result = Double.parseDouble(s1) / Double.parseDouble(s2);
break;
default:
result = null;
}
return result;
}
public static void main(String[] args) {
// System.out.println(doCalc(doMatch("1 + 1")));
// [9, 3, 1, -, 3, *, +, 10, 2, /, +]
// System.out.println(doCalc(doMatch("9 + (3 - 1) * 3 + 10 / 2")));
System.out.println(doCalc(doMatch("12.8 + (2 - 3.55) * 4 + 10 / 5.0")));
}
}
递归
public class Recursion {
public static void main(String[] args) {
// 打印问题
test(4);
// 阶乘问题
System.out.println(factorial(3));
}
// 打印问题
public static void test(int n) {
if (n > 2) {
test(n - 1);
} else {
System.out.println("n = " + n);
}
}
// 阶乘问题
public static int factorial(int n) {
if (n == 1) {
return n;
} else {
return n * factorial(n - 1);
}
}
}
迷宫
public class MiGong {
public static void main(String[] args) {
// 先创建一个二维数组,模拟迷宫
// 地图
int[][] map = new int[8][7];
// 使用 1 表示墙
// 上下全部设置为 1
for (int i = 0; i < 7; i++) {
map[0][i] = 1;
map[7][i] = 1;
}
for (int i = 0; i < 8; i++) {
map[i][0] = 1;
map[i][6] = 1;
}
// 设置挡板,1 表示
map[3][1] = 1;
map[3][2] = 1;
// map[6][5] = 1;
// map[1][2] = 1;
// map[2][2] = 1;
// 输出地图
System.out.println("地图的情况");
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + "\t");
}
System.out.println();
}
// 使用递归回溯给小球找路
System.out.println(setWay(map, 1, 1));
// System.out.println(setWay2(map, 1, 1));
// 输出新的地图,小球走过,并标识过的地图情况
System.out.println("小球走过,并标识过的地图情况");
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + "\t");
}
System.out.println();
}
}
/**
* 使用递归回溯给小球找路
* 说明
* 1. map 表示地图
* 2. i, j 表示从地图哪个位置开始出发
* 3. 如果小球能到 map[6][5] 位置, 则说明通路找到
* 4. 约定:当 map[i][j] 为 0 表示该点没有走过;当为 1 表示墙;2 表示通路可以走;3 表示该点已经走过,但走不通
* 5. 在走迷宫时需要约定一个策略(方法) 下 -> 右 -> 上 -> 左, 如果该点走不通, 再回溯
*/
public static boolean setWay(int[][] map, int i, int j) {
// 通路已经找到
if (map[6][5] == 2) {
return true;
} else {
// 如果当前这个点还没有走过
if (map[i][j] == 0) {
// 假定该点可以走通
map[i][j] = 2;
// 按照策略 下 -> 右 -> 上 -> 左 走
if (setWay(map, i + 1, j)
|| setWay(map, i, j + 1)
|| setWay(map, i - 1, j)
|| setWay(map, i, j - 1)) {
return true;
} else {
// 说明该点走不通,是死路
map[i][j] = 3;
return false;
}
} else {
// map[i][j] != 0, 则可能为 1, 2, 3
return false;
}
}
}
/**
* 修改找路策略,改为 上 -> 右 -> 下 -> 左
*/
public static boolean setWay2(int[][] map, int i, int j) {
// 通路已经找到
if (map[6][5] == 2) {
return true;
} else {
// 如果当前这个点还没有走过
if (map[i][j] == 0) {
// 假定该点可以走通
map[i][j] = 2;
// 按照策略 上 -> 右 -> 下 -> 左 走
if (setWay(map, i - 1, j)
|| setWay(map, i, j + 1)
|| setWay(map, i + 1, j)
|| setWay(map, i, j - 1)) {
return true;
} else {
// 说明该点走不通,是死路
map[i][j] = 3;
return false;
}
} else {
// map[i][j] != 0, 则可能为 1, 2, 3
return false;
}
}
}
}
八皇后
@SuppressWarnings("all")
public class Queue8 {
// 定义 一个 max 表示 共有多少个皇后
private final int MAX = 8;
// 定义 数组 array, 保存皇后放置位置的结果,比如 arr = {0, 4, 7, 5, 2, 6, 1, 3}
// array 下标代表第几行,即第几个皇,arr[i] = val, val 表示第 i + 1 个皇后,放在第 i + 1 行的第 val + 1 列
private int[] array = new int[MAX];
private int count = 0;
private int judgeCount = 0;
public static void main(String[] args) {
// 测试
Queue8 queue8 = new Queue8();
queue8.check(0);
System.out.println();
System.out.printf("一共%d种解法%n", queue8.count);
System.out.printf("一共判断冲突的次数%d次", queue8.judgeCount);
}
/**
* 编写一个方法吗,放置第n个皇后
* 特别注意:check 是 每一次递归时,进入到 check 中都有 for (int i = 0; i < max; i++) 因此会有回溯
*/
private void check(int n) {
// n = 8,其实 8 个皇后就刚好放好
if (n == MAX) {
count++;
print();
return;
}
// 依次放入皇后,并判断冲突
for (int i = 0; i < MAX; i++) {
// 先把当前这个皇后n, 放到改行的第一列
array[n] = i;
// 判断当前放置第 n 个皇后到 i 列时,是否冲突
if (judge(n)) {
// 不冲突
// 接着放 n+1 个皇后,即开始递归
check(n + 1);
}
// 如果冲突,就继续执行 array[n] = i, 即将第 n 个皇后,放置在本行的 后移的一个位置
}
}
/**
* 查看当我们放置第 n 个 皇后,就去检测皇后是否和前面已经摆放的皇后冲突
*/
public boolean judge(int n) {
judgeCount++;
for (int i = 0; i < n; i++) {
// 说明
// 1. array[i] == array[n] 表示判断 第 n 个皇后是否和前面的 n-1 个皇后在同一列
// 2. Math.abs(n - i) == Math.abs(array[n] - array[i]) 表示判断第 n 个皇后是否和第 i 皇后是否在同一斜线
// n = 1 放置第 2 列 1 n = 1 array[1] = 1
// Math.abs(1 - 0) == 1 Math.abs(array[n] - array[i]) = Math.abs(1 - 0) = 1
// 3. 判断是否在同一行,没有必要,n 每次都在递减
if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[n] - array[i])) {
return false;
}
}
return true;
}
/**
* 写一个方法,可以将皇后摆放的位置输出
*/
private void print() {
for (int i : array) {
System.out.print(i + "\t");
}
System.out.println();
}
}
排序算法
时间复杂度
public class TimeComplexity {
// O(1) < O(log₂n) < O(n) < O(nlog₂n) < O(n²) < O(n³) < O(n^k) < O(2^n)
/**
* 常熟阶 O(1)
* 无论代码多少行 只要没有循环,代码时间复杂度就是 O(1)
*/
public void one() {
int i = 1;
int j = 1;
++i;
j++;
int m = i + j;
}
/**
* 对数阶 O(log₂n)
*/
public void two(int n) {
int i = 1;
while (i < n) {
i = i * 2;
}
// 解释:i(1) * 2 * 2... > n 后循环结束,假设 循环 x 次后,即 2 ^ x = n => x = log₂n
}
/**
* 线性阶 O(n)
*/
public void three(int n) {
int j = 0;
for (int i = 0; i < n; i++) {
j += i;
j++;
}
// 解释:循环 n 次
}
/**
* 对线性阶 O(nlog₂n)
*/
public void four(int n) {
for (int i = 0; i < n; i++) {
int j = 1;
while (j < n) {
j = j * 2;
}
}
// 解释:将 时间复杂度为 O(log₂n) 的代码循环 n 次
}
/**
* 平方阶 O(n²)
*/
public void five(int n) {
int k = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
k += i + j;
k++;
}
}
// 解释:将 时间复杂度为 O(n) 的 代码再嵌套循环一次
// 如果是将外层循环 n 改为 m, 那么它的时间复杂度就为 O(m * n)
// 立方阶 O(n³) < k次阶 (n^k) 与 平方阶 类似,即 嵌套循环 对应次
}
// 平均时间复杂度 ==> 可能的输入实例均以等概率出现情况下该算法的运行时间
// 最坏时间复杂度
// 一般讨论的时间复杂度均是最坏时间复杂度,因为可以保证任何输入实例 的运行时间都不会比最坏时间最长
// 平均时间复杂度 和 最坏时间复杂度 是否一致与算法有关
// 基本 排序算法 各 时间复杂度 百度图表 了解
// 空间复杂度 自行了解
}
工具
public interface Sort {
int[] sort(int[] arr);
}
public class SortUtil {
public static void sortPrint(int[] arr, Sort sort) {
System.out.println(Arrays.toString(sort.sort(arr)));
}
public static void print(int i, int[] arr) {
System.out.println("第" + i + "轮后");
System.out.println(Arrays.toString(arr));
}
public static void capability(Sort sort) {
int[] arr = new int[80000];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * 8000000);
}
long start = System.currentTimeMillis();
System.out.println(Arrays.toString(sort.sort(arr)));
System.out.println("耗时:" + (System.currentTimeMillis() - start) + " ms");
}
public static void printCapability(int[] arr, Sort sort) {
sortPrint(arr, sort);
System.out.println(Const.DELIMITER);
capability(sort);
}
}
冒泡排序
public class BubbleSort implements Sort {
public static void main(String[] args) {
int[] arr = {3, 9, -1, 10, 20};
SortUtil.printCapability(arr, new BubbleSort());
}
/**
* 冒泡排序 时间复杂度 O(n^2)
*/
public int[] bubbleSort(int[] arr) {
// 临时变量
int temp = 0;
boolean flag = false;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1; j++) {
// 如果前面的数比后面的大,则交换
if (arr[j] > arr[j + 1]) {
flag = true;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
// SortUtil.print(i + 1, arr);
if (!flag) {
// 在一趟交换中,一次交换都没有发生过
break;
} else {
// 重置 flag 进行下次判断
flag = false;
}
}
return arr;
}
@Override
public int[] sort(int[] arr) {
return bubbleSort(arr);
}
}
选择排序
public class SelectSort implements Sort {
public static void main(String[] args) {
int[] arr = {101, 34, 119, 1, -1, 90, 123};
SortUtil.printCapability(arr, new SelectSort());
}
/**
* 选择排序 时间复杂度 O(n^2)
*/
public int[] selectSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
int minIndex = i;
int min = arr[i];
for (int j = i + 1; j < arr.length; j++) {
// 说明假定的最小值,并不是最小值
if (min > arr[j]) {
// 重置 min
min = arr[j];
// 重置 minIndex
minIndex = j;
}
}
// 将最小值,放在 arr[i],即交换
if (minIndex != i) {
arr[minIndex] = arr[i];
arr[i] = min;
}
// SortUtil.print(i + 1, arr);
}
return arr;
}
@Override
public int[] sort(int[] arr) {
return selectSort(arr);
}
}
插入排序
public class InsertSort implements Sort {
public static void main(String[] args) {
int[] arr = {101, 34, 119, 1, -1, 89};
// SortUtil.printSort(arr, new InsertSort());
SortUtil.printCapability(arr, new InsertSort());
}
/**
* 插入排序 时间复杂度 O(n^2)
*/
public int[] insertSort(int[] arr) {
int insertVal;
int insertIndex;
for (int i = 1; i < arr.length; i++) {
// 定义带插入的数
insertVal = arr[i];
// arr[i] 前面数的下标
insertIndex = i - 1;
// 给 insertVal 找到插入的位置
// 说明
// 1. insertIndex >= 0 保证在给 insertVal 找到插入位置,不越界
// 2. insertIndex < arr[insertIndex] 待插入的数,还没有找到插入位置
// 3. 就需要将 arr[insertIndex] 后移
while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;
}
// 当退出 while 循环时,说明插入的位置找到了,insertIndex + 1
if (insertIndex + 1 != i) {
arr[insertIndex + 1] = insertVal;
}
// SortUtil.print(i, arr);
}
return arr;
}
@Override
public int[] sort(int[] arr) {
return insertSort(arr);
}
}
希尔排序
public class ShellSort implements Sort {
public static void main(String[] args) {
int[] arr = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
// SortUtil.printSort(arr, new ShellSort());
SortUtil.printCapability(arr, new ShellSort());
}
/**
* 希尔排序时,对有序序列插入时采用 => 交换法
*/
public int[] shellSort(int[] arr) {
int temp;
// int count = 1;
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
for (int i = gap; i < arr.length; i++) {
// 遍历组中所有的元素,共 gap 组,每组有个元素,步长为 gap
for (int j = i - gap; j >= 0; j -= gap) {
// 如果当前元素大于加上步长后的那个元素,说明交换
if (arr[j] > arr[j + gap]) {
temp = arr[j];
arr[j] = arr[j + gap];
arr[j + gap] = temp;
}
}
}
// SortUtil.print(count++, arr);
}
return arr;
}
/**
* 希尔排序时,对有序序列插入时采用 => 移位法 时间复杂度 O(n^(1.3-2))
*/
public int[] shellSort2(int[] arr) {
// 增量 gap,并逐步缩小增量
// int count = 1;
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
for (int i = gap; i < arr.length; i++) {
// 从第 gap 个元素,逐个对其中所在的组进行直接插入排序
int j = i;
int temp = arr[j];
if (arr[j] < arr[j - gap]) {
while (j - gap >= 0 && temp < arr[j - gap]) {
// 移动
arr[j] = arr[j - gap];
j -= gap;
}
// 当退出 while 后,就给 temp 找到插入的位置
arr[j] = temp;
}
}
// SortUtil.print(count++, arr);
}
return arr;
}
@Override
public int[] sort(int[] arr) {
// 这个快太多了
return shellSort2(arr);
// return shellSort(arr);
}
}
快速排序
public class QuickSort implements Sort {
public static void main(String[] args) {
int[] arr = {-9, 78, 0, 23, -567, 70, -1, 900, 4561};
// SortUtil.printSort(arr, new QuickSort());
SortUtil.printCapability(arr, new QuickSort());
}
/**
* 分析:
* 1.选定一个基准值,array[low]
* 2.右指针从右向左遍历high--,查找比基准值小的数据,左指针从左向右low++,查找比基准值大的数据
* 3.如果指针未相遇,交换左右两值位置,如果指针相遇,则替换基准值的位置
* 4.左递归,右递归
*/
public void quickSort(int[] array, int low, int high) {
// 方法退出条件,指针相遇或错过
if (low >= high) {
return;
}
// 1. 指定基准值和左右指针记录位置
int pivot = array[low];
int l = low;
int r = high;
int temp = 0;
// 2. 遍历条件,左右指针位置
while (l < r) {
// 2.1 右侧遍历
while (l < r && array[r] >= pivot) {
r--;
}
// 2.2 左侧遍历
while (l < r && array[l] <= pivot) {
l++;
}
// 2.3 l指针还在r指针右侧,尚未相遇
if (l < r) {
temp = array[l];
array[l] = array[r];
array[r] = temp;
}
}
// 3. 当左右指针相遇,交换基准值位置
array[low] = array[l];
array[l] = pivot;
// 4. 根据条件左侧递归遍历
if (low < l) {
quickSort(array, low, l - 1);
}
// 5. 根据条件右侧递归遍历
if (r < high) {
quickSort(array, r + 1, high);
}
}
@Override
public int[] sort(int[] arr) {
quickSort(arr, 0, arr.length - 1);
return arr;
}
}
归并排序
public class MergeSort implements Sort {
public static void main(String[] args) {
int[] arr = {8, 4, 5, 7, 1, 3, 6, 2};
// SortUtil.printSort(arr, new MergeSort());
SortUtil.printCapability(arr, new MergeSort());
}
/**
* 分 + 合 方法
*/
public void mergeSort(int[] arr, int left, int right, int[] temp) {
if (left < right) {
// 中间索引
int mid = (left + right) / 2;
// 向左递归进行分解
mergeSort(arr, left, mid, temp);
// 向右递归进行分解
mergeSort(arr, mid + 1, right, temp);
// 合并
merge(arr, left, mid, right, temp);
}
}
/**
* 合并的方法
*
* @param arr 排序的原始数组
* @param left 左边有序序列的初始索引
* @param mid 中间索引
* @param right 右边索引
* @param temp 做中转的数组
*/
private void merge(int[] arr, int left, int mid, int right, int[] temp) {
// 初始化i,左边有序序列的初始值
int i = left;
// 初始化 j, 右边有序序列的初始索引
int j = mid + 1;
// 指向 temp 数组的当前索引
int t = 0;
// (一)
// 先把左右两边(有序)的数据按照规则填充到 temp 数组
// 直到左右两边的有序序列,有一边处理完为止
while (i <= mid && j <= right) {
// 继续
// 如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
// 即将左边的当前元素,填充到 temp 数组
// 然后 t++, i++
if (arr[i] <= arr[j]) {
temp[t] = arr[i];
++t;
++i;
} else {
// 反之,将右边有序序列的但当前元素,填充到 temp 数组
temp[t] = arr[j];
++t;
++j;
}
}
// (二)
// 把有剩余数据的一边的数据依次全部填充到 temp
while (i <= mid) {
// 左边的有序序列还有剩余元素,就全部填充到temp
temp[t] = arr[i];
++t;
++i;
}
while (j <= right) {
// 右边的有序序列还有剩余元素,就全部填充到temp
temp[t] = arr[j];
++t;
++j;
}
// (三)
// 将 temp 数组的元素拷贝到 arr
// 注意,并不是每次都拷贝所有
int tempLeft = left;
t = 0;
while (tempLeft <= right) {
arr[tempLeft] = temp[t];
++t;
++tempLeft;
}
}
@Override
public int[] sort(int[] arr) {
int len = arr.length;
mergeSort(arr, 0, len - 1, new int[len]);
return arr;
}
}
基数排序
public class RadixSort implements Sort {
public static void main(String[] args) {
int[] arr = {53, 3, 542, 748, 14, 214};
// SortUtil.printSort(arr, new RadixSort());
SortUtil.printCapability(arr, new RadixSort());
}
/**
* 基数排序方法
*/
public int[] radixSort(int[] arr) {
// 根据前面的推导过程,得到最终的基数排序算法
// 1. 得到数组中最大位数的数
// 假设第一位就是最大数
int max = arr[0];
for (int a : arr) {
if (a > max) {
max = a;
}
}
// 得到最大的数是几位数
int maxLength = 1;
while (max > 10) {
max /= 10;
++maxLength;
}
// 定义一个二维数组,表示10个桶,每个桶就是一个一维数组
// 说明:
// 1. 二维数组包含 10 个一维数组
// 2. 为了防止放入数的时候,数据溢出,则每个一维数组(桶),大小定义为 arr.length
// 3. 基数排序是使用空间排序换时间排序的经典算法
int[][] bucket = new int[10][arr.length];
// 为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶每个放入的数据个数
int[] bucketElementCounts = new int[10];
// 这里我们使用循环将代码处理
for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
// 针对每个元素的对应位进行排序处理,第一位是个位,第二位是十位,第三位是百位
for (int k : arr) {
// 取出每个元素对应的位数
int digitOfElement = k / n % 10;
// 放入对应的桶中
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = k;
bucketElementCounts[digitOfElement]++;
}
// 按照这个桶的顺序,一维数组的下标依次取出数据,放入原来的数组
int index = 0;
for (int k = 0; k < bucketElementCounts.length; k++) {
// 如果桶中有数据,我们才放入原数组
if (bucketElementCounts[k] != 0) {
// 循环该桶即第 k 个桶,即第 k 个一维数组,放入
for (int j = 0; j < bucketElementCounts[k]; j++) {
// 取出元素放入到 arr
arr[index++] = bucket[k][j];
}
}
// 第 i + 1 轮处理后,需要将每个 bucketElementCounts[i] = 0
bucketElementCounts[k] = 0;
}
}
return arr;
}
@Override
public int[] sort(int[] arr) {
return radixSort(arr);
}
}
查找算法
线性查找算法
二分查找算法
插值查找算法