数据结构和算法
算法
稀疏(spare)数组
场景
用于重复值多,不同值多的压缩处理
实现
/**
* 压缩
*
* @param arr 源数组
* @return 稀疏数组
*/
public int[][] compress(int[][] arr) {
int line = arr.length;
int column = arr[0].length;
int num = 0;
for (int[] i : arr) {
for (int j : i) {
if (j != 0) {
num++;
}
}
}
int compress[][] = new int[num + 1][3];
compress[0][0] = line;
compress[0][1] = column;
compress[0][2] = num;
int compressLine = 1;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j] != 0) {
compress[compressLine][0] = i;
compress[compressLine][1] = j;
compress[compressLine][2] = arr[i][j];
compressLine++;
}
}
}
return compress;
}
/**
* 恢复
*
* @param compress 压缩数组
* @return 源数组
*/
public int[][] recover(int[][] compress) {
int source[][] = new int[compress[0][0]][compress[0][1]];
for (int i = 1; i < compress.length; i++) {
source[compress[i][0]][compress[i][1]] = compress[i][2];
}
return source;
}
递归
迷宫问题
排序
冒泡排序
找最大的值,移至最后
/**
* 冒泡排序
*
* @param arr
* @return
*/
public static int[] bubbling(int[] arr) {
/*优化排序*/
boolean flag = false;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
flag = true;
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (!flag) {
break;
} else {
flag = false;
}
}
return arr;
}
选择排序
找最小值,移至最前
/**
* 选择排序
*
* @param arr
* @return
*/
public static int[] select(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
int min = arr[i];
for (int j = i + 1; j < arr.length; j++) {
if (min > arr[j]) {
minIndex = j;
min = arr[j];
}
}
if (minIndex != i) {
arr[minIndex] = arr[i];
arr[i] = min;
}
}
return arr;
}
数据结构
队列
先进先出,后进后出
数组实现
package cn.axunl.structure;
/**
* 队列
*/
public class ArrayQueue {
private int maxSize;
private Object arr[];
private int front;
private int rear;
/**
* 构造函数
*/
public ArrayQueue() {
this(10);
}
/**
* 构造函数
*
* @param maxSize 数组最大值
*/
public ArrayQueue(int maxSize) {
this.maxSize = maxSize;
arr = new Object[maxSize];
}
/**
* 队列是否满
*
* @return
*/
private boolean isFull() {
return (rear + 1) % maxSize == front;
}
/**
* 队列是否空
*
* @return
*/
private boolean isEmpty() {
return rear == front;
}
/**
* 入列
*
* @param i 数据
* @return
*/
public int push(Object i) {
if (isFull()) {
return -1;
} else {
arr[rear] = i;
rear = (rear + 1) % maxSize;
return 1;
}
}
/**
* 出列
*
* @return Object
*/
public Object pop() {
if (isEmpty()) {
return null;
} else {
Object value = arr[front];
front = (front + 1) % maxSize;
return value;
}
}
/**
* 队列数据
*/
public void show() {
if (isEmpty()) {
System.out.println("队列空");
} else {
for (int i = front; i <front+size(); i++) {
System.out.printf("arr[%d]=%d\n", i%maxSize, arr[i%maxSize]);
}
}
}
/**
* 队列头数据
*
* @return Object
*/
public Object peek() {
if (isEmpty()) {
return null;
} else {
return arr[front];
}
}
/**
* 队列有效个数
*
* @return
*/
private int size() {
return (rear + maxSize - front) % maxSize;
}
}
链表
单向链表
package cn.axunl.structure;
/**
* 节点
*/
public class Node {
/*顺序*/
public int no;
/*下一节点*/
public Node nextNode;
/*节点名字*/
public String name;
public Node(int no, String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "Node{" +
"no=" + no +
", name='" + name + '\'' +
'}' + "\n";
}
}
package cn.axunl.structure;
/**
* 单链表
*/
public class SingleLinkedList {
/*头节点*/
private Node headNode = new Node(0, null);
/**
* 添加
*
* @param node node节点
*/
public void add(Node node) {
Node temp = headNode;
while (true) {
if (temp.nextNode == null) {//最后一个node节点
temp.nextNode = node;
break;
} else if (temp.nextNode.no > node.no) {
node.nextNode = temp.nextNode;
temp.nextNode = node;
break;
} else if (temp.nextNode.no == node.no) {//同节点
break;
}
temp = temp.nextNode;
}
}
/**
* 更新
*
* @param node node节点
*/
public void update(Node node) {
Node temp = headNode.nextNode;
while (true) {
if (temp.nextNode == null) {
break;
}
if (temp.no == node.no) {
temp.name = node.name;
break;
}
temp = temp.nextNode;
}
}
/**
* 删除
*
* @param i 节点no
*/
public void delete(int i) {
Node temp = headNode;
while (true) {
if (temp.nextNode == null) {
break;
}
if (temp.nextNode.no == i) {
temp.nextNode = temp.nextNode.nextNode == null ? null : temp.nextNode.nextNode;
break;
}
temp = temp.nextNode;
}
}
/**
* 单链表反转
*
* @return SingleLinkedList
*/
public SingleLinkedList reverse() {
SingleLinkedList list = new SingleLinkedList();
Node cur = headNode.nextNode;
while (true) {
if (cur == null) {
break;
}
/*下个节点链*/
Node next = cur.nextNode;
/*当前节点的下个节点链,相当于插入*/
cur.nextNode = list.headNode.nextNode;
/*赋值回去*/
list.headNode.nextNode = cur;
/*移至下个节点链的节点*/
cur = next;
}
return list;
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer("");
Node temp = headNode;
while (true) {
if (temp != headNode) {
buffer.append(temp.toString());
}
if (temp.nextNode == null) {
break;
}
temp = temp.nextNode;
}
return new String(buffer);
}
}
双向链表
package cn.axunl.structure;
/**
* 双向链表
*/
public class DoubleLinkList {
private Node headNode = new Node(0, null);
/**
* 添加
*
* @param node node节点
*/
public void add(Node node) {
Node temp = headNode;
while (true) {
if (temp.nextNode == null) {//最后一个node节点
temp.nextNode = node;
node.preNode = temp;
break;
} else if (temp.no > node.no) {
temp.preNode.nextNode = node;
node.preNode = temp.preNode;
node.nextNode = temp;
temp.preNode = node;
break;
} else if (temp.no == node.no) {//同节点
break;
}
temp = temp.nextNode;
}
}
/**
* 更新
*
* @param node node节点
*/
public void update(Node node) {
Node temp = headNode.nextNode;
while (true) {
if (temp.nextNode == null) {
break;
}
if (temp.no == node.no) {
temp.name = node.name;
break;
}
temp = temp.nextNode;
}
}
/**
* 删除
*
* @param i 节点no
*/
public void delete(int i) {
Node temp = headNode;
while (true) {
if (temp.nextNode == null) {
break;
}
if (temp.no == i) {
if (temp.nextNode != null) {
temp.preNode.nextNode = temp.nextNode;
temp.nextNode.preNode = temp.preNode;
} else {
temp.preNode.nextNode = null;
}
break;
}
temp = temp.nextNode;
}
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer("");
Node temp = headNode;
while (true) {
if (temp != headNode) {
buffer.append(temp.toString());
}
if (temp.nextNode == null) {
break;
}
temp = temp.nextNode;
}
return new String(buffer);
}
}
栈
先进后出,后进先出
package cn.axunl.structure;
/**
* 栈
*/
public class ArrayStack {
/*栈顶小标*/
private int top = -1;
/*栈数组*/
private int[] arr;
/*栈数组大小*/
private int maxSize;
public ArrayStack(int maxSize) {
this.maxSize = maxSize;
arr = new int[maxSize];
}
private boolean isEmpty() {
return top == -1;
}
private boolean isFull() {
return top == maxSize - 1;
}
/**
* 入栈
*
* @param i
*/
public void push(int i) {
if (!isFull()) {
top++;
arr[top] = i;
}
}
/**
* 出栈
*
* @return
*/
public int pop() {
if (!isEmpty()) {
int i = arr[top];
top--;
return i;
}
throw new RuntimeException();
}
}
哈希表
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。
package cn.axunl.structure;
/**
* 节点
*/
public class Node {
/*顺序*/
public int no;
public Node nextNode;
public Node preNode;
public String name;
public Node(int no, String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "Node{" +
"no=" + no +
", name='" + name + '\'' +
'}' + "\n";
}
}
package cn.axunl.structure;
/**
* 单链表
*/
public class SingleLinkedList {
/*头节点*/
private Node headNode = new Node(0, null);
/**
* 添加
*
* @param node node节点
*/
public void add(Node node) {
Node temp = headNode;
while (true) {
if (temp.nextNode == null) {//最后一个node节点
temp.nextNode = node;
break;
} else if (temp.nextNode.no > node.no) {
node.nextNode = temp.nextNode;
temp.nextNode = node;
break;
} else if (temp.nextNode.no == node.no) {//同节点
break;
}
temp = temp.nextNode;
}
}
/**
* 更新
*
* @param node node节点
*/
public void update(Node node) {
Node temp = headNode.nextNode;
while (true) {
if (temp.nextNode == null) {
break;
}
if (temp.no == node.no) {
temp.name = node.name;
break;
}
temp = temp.nextNode;
}
}
/**
* 删除
*
* @param i 节点no
*/
public void delete(int i) {
Node temp = headNode;
while (true) {
if (temp.nextNode == null) {
break;
}
if (temp.nextNode.no == i) {
temp.nextNode = temp.nextNode.nextNode;
break;
}
temp = temp.nextNode;
}
}
/**
* 单链表反转
*
* @return SingleLinkedList
*/
public SingleLinkedList reverse() {
SingleLinkedList list = new SingleLinkedList();
Node cur = headNode.nextNode;
while (true) {
if (cur == null) {
break;
}
/*下个节点链*/
Node next = cur.nextNode;
/*当前节点的下个节点链,相当于插入*/
cur.nextNode = list.headNode.nextNode;
/*赋值回去*/
list.headNode.nextNode = cur;
/*移至下个节点链的节点*/
cur = next;
}
return list;
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer("");
Node temp = headNode;
while (true) {
if (temp != headNode) {
buffer.append(temp.toString());
}
if (temp.nextNode == null) {
break;
}
temp = temp.nextNode;
}
return new String(buffer);
}
}
package cn.axunl.structure;
/**
* 哈希表(链表+数组)
*/
public class ArrayHashList {
private SingleLinkedList[] lists;
private int initSize = 10;
public ArrayHashList() {
lists = new SingleLinkedList[initSize];
for (int i = 0; i < lists.length; i++) {
lists[i] = new SingleLinkedList();
}
}
/**
* 添加
*/
public void add(Node node) {
int id = hash(node.no);
System.out.println(id);
lists[id].add(node);
}
/**
* 遍历
*/
public void list() {
for (SingleLinkedList list : lists) {
list.toString();
}
}
public SingleLinkedList get(int index) {
int id = hash(index);
return lists[index];
}
/**
* update
*/
public void update() {
}
/**
* delete
*/
public void delete() {
}
/**
* 哈希
*
* @param id
* @return
*/
private int hash(int id) {
return id % initSize;
}
}
树
二叉树
堆
完全二叉树
二叉排序树
插入节点值比父节点小到左边,否则右边
二叉平衡树
左节点层-右节点层的绝对值不大于1
package cn.axunl.structure;
/**
* 二叉树节点
*/
public class TreeNode {
public String name;
/*左节点*/
public TreeNode leftNode;
/*右节点*/
public TreeNode rightNode;
public TreeNode() {
}
public TreeNode(String name, TreeNode leftNode, TreeNode rightNode) {
this.name = name;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
@Override
public String toString() {
return "TreeNode{" +
"name='" + name + '\'' +
", leftNode=" + leftNode +
", rightNode=" + rightNode +
'}';
}
}
package cn.axunl.structure;
/**
* 二叉树
*/
public class BinaryTree {
/*根节点*/
TreeNode root;
/**
* 构造方法,这里不允许空树
*
* @param root
*/
public BinaryTree(TreeNode root) {
if (root == null) throw new RuntimeException("根节点不允许为空");
this.root = root;
}
public void preOrder() {
preOrder(root);
}
public void infixOrder() {
infixOrder(root);
}
public void postOrder() {
postOrder(root);
}
/**
* 前序遍历(父节点->左节点->右节点)
*
* @param node
*/
public void preOrder(TreeNode node) {
//输出根节点
System.out.println(node);
//输出左节点
if (node.leftNode != null) {
preOrder(node.leftNode);
}
//输出右节点
if (node.rightNode != null) {
preOrder(node.rightNode);
}
}
/**
* 中序遍历(左节点->父节点->->右节点)
*
* @param node
*/
public void infixOrder(TreeNode node) {
//输出左节点
if (node.leftNode != null) {
preOrder(node.leftNode);
}
//输出根节点
System.out.println(node);
//输出右节点
if (node.rightNode != null) {
preOrder(node.rightNode);
}
}
/**
* 后序遍历(左节点->右节点->父节点)
*
* @param node
*/
public void postOrder(TreeNode node) {
//输出左节点
if (node.leftNode != null) {
preOrder(node.leftNode);
}
//输出右节点
if (node.rightNode != null) {
preOrder(node.rightNode);
}
//输出根节点
System.out.println(node);
}
}