diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5808138
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+# Intellij
+.idea/*
+*.iml
+*.iws
+out/*
+
+# Mac
+.DS_Store
+
+# Maven
+log/*
+target/*
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
deleted file mode 100644
index 97626ba..0000000
--- a/.idea/encodings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index b08e5aa..0000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Arquillian_JUnit_Release.xml b/.idea/libraries/Arquillian_JUnit_Release.xml
deleted file mode 100644
index c21f710..0000000
--- a/.idea/libraries/Arquillian_JUnit_Release.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 0548357..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 790d7ab..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Algorithm.iml b/Algorithm.iml
deleted file mode 100644
index c90834f..0000000
--- a/Algorithm.iml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Caching/src/LRU.java b/Caching/src/LRU.java
new file mode 100644
index 0000000..e10af02
--- /dev/null
+++ b/Caching/src/LRU.java
@@ -0,0 +1,109 @@
+import java.util.HashMap;
+import java.util.Iterator;
+
+public class LRU implements Iterable {
+
+ private Node head;
+ private Node tail;
+ private HashMap map;
+ private int maxSize;
+
+ private class Node {
+
+ Node pre;
+ Node next;
+ K k;
+ V v;
+
+ public Node(K k, V v) {
+ this.k = k;
+ this.v = v;
+ }
+ }
+
+
+ public LRU(int maxSize) {
+
+ this.maxSize = maxSize;
+ this.map = new HashMap<>(maxSize * 4 / 3);
+
+ head = new Node(null, null);
+ tail = new Node(null, null);
+
+ head.next = tail;
+ tail.pre = head;
+ }
+
+
+ public V get(K key) {
+
+ if (!map.containsKey(key)) {
+ return null;
+ }
+
+ Node node = map.get(key);
+ unlink(node);
+ appendHead(node);
+
+ return node.v;
+ }
+
+
+ public void put(K key, V value) {
+
+ if (map.containsKey(key)) {
+ Node node = map.get(key);
+ unlink(node);
+ }
+
+ Node node = new Node(key, value);
+ map.put(key, node);
+ appendHead(node);
+
+ if (map.size() > maxSize) {
+ Node toRemove = removeTail();
+ map.remove(toRemove);
+ }
+ }
+
+
+ private void unlink(Node node) {
+ Node pre = node.pre;
+ node.pre = node.next;
+ node.next = pre;
+ }
+
+
+ private void appendHead(Node node) {
+ node.next = head.next;
+ head.next = node;
+ }
+
+
+ private Node removeTail() {
+ Node node = tail.pre;
+ node.pre = tail;
+ return node;
+ }
+
+
+ @Override
+ public Iterator iterator() {
+
+ return new Iterator() {
+ private Node cur = head.next;
+ @Override
+ public boolean hasNext() {
+ return cur != tail;
+ }
+
+ @Override
+ public K next() {
+ Node node = cur;
+ cur = cur.next;
+ return node.k;
+ }
+ };
+ }
+
+}
diff --git a/Caching/src/LRUTest.java b/Caching/src/LRUTest.java
new file mode 100644
index 0000000..a1bb03b
--- /dev/null
+++ b/Caching/src/LRUTest.java
@@ -0,0 +1,28 @@
+import org.junit.Test;
+
+import java.util.Iterator;
+
+import static org.junit.Assert.assertEquals;
+
+public class LRUTest {
+ @Test
+ public void test() {
+
+ LRU lru = new LRU<>(3);
+
+ lru.put("K1", "V1");
+ lru.put("K2", "V2");
+ lru.put("K3", "V3");
+
+ lru.get("K1");
+ lru.get("K2");
+
+ lru.put("K4", "V4");
+
+ Iterator iterator = lru.iterator();
+
+ assertEquals(iterator.next(), "K4");
+ assertEquals(iterator.next(), "K2");
+ assertEquals(iterator.next(), "K1");
+ }
+}
\ No newline at end of file
diff --git a/Graph/src/Edge.java b/Graph/src/Edge.java
new file mode 100644
index 0000000..4c63c34
--- /dev/null
+++ b/Graph/src/Edge.java
@@ -0,0 +1,33 @@
+public class Edge {
+
+ private int v; // 顶点
+ private int w; // 另一个顶点
+ private double weight; // 权值
+
+
+ public Edge(int v, int w, double weight) {
+ this.v = v;
+ this.w = w;
+ this.weight = weight;
+ }
+
+
+ public int getV() {
+ return v;
+ }
+
+
+ public int getW() {
+ return w;
+ }
+
+
+ public double getWeight() {
+ return weight;
+ }
+
+
+ public int getOther(int vertex) {
+ return vertex ^ (v ^ w);
+ }
+}
diff --git a/Graph/src/EdgeWeighGraph.java b/Graph/src/EdgeWeighGraph.java
new file mode 100644
index 0000000..e9adad1
--- /dev/null
+++ b/Graph/src/EdgeWeighGraph.java
@@ -0,0 +1,42 @@
+import java.util.HashSet;
+import java.util.Set;
+
+public class EdgeWeighGraph {
+
+ private int V; // 顶点总数
+ private Set[] adj; // 邻接表
+
+
+ public EdgeWeighGraph(int v) {
+ this.V = v;
+ adj = new Set[V];
+ for (int i = 0; i < V; i++) {
+ adj[i] = new HashSet<>();
+ }
+ }
+
+
+ public void addEdge(Edge edge) {
+ adj[edge.getV()].add(edge);
+ adj[edge.getW()].add(edge);
+ }
+
+
+ public int getV() {
+ return V;
+ }
+
+
+ public Set adj(int v) {
+ return adj[v];
+ }
+
+
+ public Set edges() {
+ Set edges = new HashSet<>();
+ for (int i = 0; i < V; i++) {
+ edges.addAll(adj[i]);
+ }
+ return edges;
+ }
+}
diff --git a/Graph/src/KruskalMST.java b/Graph/src/KruskalMST.java
new file mode 100644
index 0000000..4927503
--- /dev/null
+++ b/Graph/src/KruskalMST.java
@@ -0,0 +1,43 @@
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.PriorityQueue;
+import java.util.Set;
+
+public class KruskalMST extends MST {
+
+ private Set mst;
+
+
+ public KruskalMST(EdgeWeighGraph graph) {
+
+ super(graph);
+
+ mst = new HashSet<>();
+
+ PriorityQueue pq = new PriorityQueue<>(Comparator.comparing(Edge::getWeight));
+ pq.addAll(graph.edges());
+
+ UF uf = new QuickUnionUF(graph.getV());
+
+ while (!pq.isEmpty() && mst.size() < graph.getV() - 1) {
+
+ Edge edge = pq.poll();
+
+ int v = edge.getV(), w = edge.getW();
+
+ if (uf.connected(v, w)) {
+ continue;
+ }
+
+ uf.connected(v, w);
+ mst.add(edge);
+ }
+ }
+
+
+ @Override
+ public Set getResult() {
+ return mst;
+ }
+
+}
diff --git a/Graph/src/MST.java b/Graph/src/MST.java
new file mode 100644
index 0000000..42fb517
--- /dev/null
+++ b/Graph/src/MST.java
@@ -0,0 +1,14 @@
+import java.util.Set;
+
+public abstract class MST {
+
+ protected EdgeWeighGraph graph;
+
+
+ public MST(EdgeWeighGraph graph) {
+ this.graph = graph;
+ }
+
+
+ public abstract Set getResult();
+}
diff --git a/Graph/src/MSTTest.java b/Graph/src/MSTTest.java
new file mode 100644
index 0000000..13b85de
--- /dev/null
+++ b/Graph/src/MSTTest.java
@@ -0,0 +1,55 @@
+import org.junit.Assert;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class MSTTest {
+
+ private EdgeWeighGraph graph;
+ private Set expect;
+
+
+ @org.junit.Before
+ public void data() {
+
+ Edge edge1 = new Edge(0, 1, 1.0);
+ Edge edge2 = new Edge(1, 2, 2.0);
+ Edge edge3 = new Edge(2, 3, 3.0);
+ Edge edge4 = new Edge(3, 0, 4.0);
+ Edge edge5 = new Edge(0, 2, 5.0);
+
+ graph = new EdgeWeighGraph(4);
+ graph.addEdge(edge1);
+ graph.addEdge(edge2);
+ graph.addEdge(edge3);
+ graph.addEdge(edge4);
+ graph.addEdge(edge5);
+
+ expect = new HashSet<>();
+ expect.add(edge1);
+ expect.add(edge2);
+ expect.add(edge3);
+ }
+
+ @org.junit.Test
+ public void testPrimMST() {
+ test(new PrimMST(graph));
+ }
+
+ @org.junit.Test
+ public void testKruskalMST() {
+ test(new KruskalMST(graph));
+ }
+
+ private void test(MST mst) {
+
+ Set result = mst.getResult();
+ Assert.assertEquals(result.size(), expect.size());
+
+ for (Edge edge : result) {
+ Assert.assertTrue(expect.contains(edge));
+ expect.remove(edge);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Graph/src/PrimMST.java b/Graph/src/PrimMST.java
new file mode 100644
index 0000000..ca8f9b2
--- /dev/null
+++ b/Graph/src/PrimMST.java
@@ -0,0 +1,59 @@
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.PriorityQueue;
+import java.util.Set;
+
+public class PrimMST extends MST {
+
+ private boolean[] marked;
+ private PriorityQueue pq; // 横切边
+ private Set mst; // 最小生成树的边
+
+
+ public PrimMST(EdgeWeighGraph graph) {
+
+ super(graph);
+
+ marked = new boolean[graph.getV()];
+ pq = new PriorityQueue<>(Comparator.comparingDouble((Edge o) -> (o.getWeight())));
+ mst = new HashSet<>();
+
+ visit(0);
+
+ while (!pq.isEmpty()) {
+
+ Edge edge = pq.poll();
+
+ int v = edge.getV(), w = edge.getW();
+
+ if (marked[v] && marked[w]) {
+ continue;
+ }
+ mst.add(edge);
+ if (!marked[v]) {
+ visit(v);
+ }
+ if (!marked[w]) {
+ visit(w);
+ }
+ }
+ }
+
+
+ @Override
+ public Set getResult() {
+ return mst;
+ }
+
+
+ private void visit(int v) {
+
+ marked[v] = true;
+
+ for (Edge edge : graph.adj(v)) {
+ if (!marked[edge.getOther(v)]) {
+ pq.add(edge);
+ }
+ }
+ }
+}
diff --git a/MultiThreading/src/AlternatePrint.java b/MultiThreading/src/AlternatePrint.java
new file mode 100644
index 0000000..dfb424c
--- /dev/null
+++ b/MultiThreading/src/AlternatePrint.java
@@ -0,0 +1,42 @@
+import java.util.concurrent.Semaphore;
+
+public class AlternatePrint {
+
+ private static Semaphore[] semaphores;
+ private static final int ThreadNum = 3;
+ private static final int PrintNum = 10;
+
+
+ public static void main(String[] args) {
+
+ semaphores = new Semaphore[ThreadNum];
+
+ for (int i = 0; i < ThreadNum; i++) {
+ semaphores[i] = new Semaphore(0);
+ }
+
+ semaphores[0].release();
+
+ for (int i = 0; i < ThreadNum; i++) {
+
+ final int cur = i;
+ final int next = (i + 1) % ThreadNum;
+
+ new Thread(() -> {
+
+ for (int j = 0; j < PrintNum; j++) {
+
+ try {
+ semaphores[cur].acquire();
+ char c = (char) ('A' + cur);
+ System.out.println(c);
+ semaphores[next].release();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }).start();
+ }
+ }
+}
diff --git a/Other/src/Hanoi.java b/Other/src/Hanoi.java
new file mode 100644
index 0000000..5c38450
--- /dev/null
+++ b/Other/src/Hanoi.java
@@ -0,0 +1,19 @@
+public class Hanoi {
+
+ public static void move(int n, String from, String buffer, String to) {
+
+ if (n == 1) {
+ System.out.println("from " + from + " to " + to);
+ return;
+ }
+
+ move(n - 1, from, to, buffer);
+ move(1, from, buffer, to);
+ move(n - 1, buffer, from, to);
+ }
+
+
+ public static void main(String[] args) {
+ Hanoi.move(3, "H1", "H2", "H3");
+ }
+}
diff --git a/Other/src/Huffman.java b/Other/src/Huffman.java
new file mode 100644
index 0000000..63e3e43
--- /dev/null
+++ b/Other/src/Huffman.java
@@ -0,0 +1,72 @@
+import java.util.HashMap;
+import java.util.Map;
+import java.util.PriorityQueue;
+
+public class Huffman {
+
+ private class Node implements Comparable {
+
+ char ch;
+ int freq;
+ boolean isLeaf;
+ Node left, right;
+
+
+ public Node(char ch, int freq) {
+ this.ch = ch;
+ this.freq = freq;
+ isLeaf = true;
+ }
+
+
+ public Node(Node left, Node right, int freq) {
+ this.left = left;
+ this.right = right;
+ this.freq = freq;
+ isLeaf = false;
+ }
+
+
+ @Override
+ public int compareTo(Node o) {
+ return this.freq - o.freq;
+ }
+ }
+
+
+ public Map encode(Map frequencyForChar) {
+
+ PriorityQueue priorityQueue = new PriorityQueue<>();
+
+ for (Character c : frequencyForChar.keySet()) {
+ priorityQueue.add(new Node(c, frequencyForChar.get(c)));
+ }
+
+ while (priorityQueue.size() != 1) {
+ Node node1 = priorityQueue.poll();
+ Node node2 = priorityQueue.poll();
+ priorityQueue.add(new Node(node1, node2, node1.freq + node2.freq));
+ }
+
+ return encode(priorityQueue.poll());
+ }
+
+
+ private Map encode(Node root) {
+
+ Map encodingForChar = new HashMap<>();
+ encode(root, "", encodingForChar);
+ return encodingForChar;
+ }
+
+
+ private void encode(Node node, String encoding, Map encodingForChar) {
+
+ if (node.isLeaf) {
+ encodingForChar.put(node.ch, encoding);
+ return;
+ }
+ encode(node.left, encoding + '0', encodingForChar);
+ encode(node.right, encoding + '1', encodingForChar);
+ }
+}
\ No newline at end of file
diff --git a/Other/src/HuffmanTest.java b/Other/src/HuffmanTest.java
new file mode 100644
index 0000000..2a77f71
--- /dev/null
+++ b/Other/src/HuffmanTest.java
@@ -0,0 +1,31 @@
+import org.junit.Assert;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class HuffmanTest {
+
+ @org.junit.Test
+ public void encode() {
+
+ Huffman huffman = new Huffman();
+ Map frequencyForChar = new HashMap<>();
+
+ frequencyForChar.put('a', 10);
+ frequencyForChar.put('b', 20);
+ frequencyForChar.put('c', 40);
+ frequencyForChar.put('d', 80);
+
+ Map result = huffman.encode(frequencyForChar);
+ Map encoding = new HashMap<>();
+
+ encoding.put('a', "000");
+ encoding.put('b', "001");
+ encoding.put('c', "01");
+ encoding.put('d', "1");
+
+ for (Character character : result.keySet()) {
+ Assert.assertEquals(result.get(character), encoding.get(character));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Queue/Queue.iml b/Queue/Queue.iml
deleted file mode 100644
index 3a8ffcf..0000000
--- a/Queue/Queue.iml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Queue/src/ListQueue.java b/Queue/src/ListQueue.java
index 4eb2715..d6d40ee 100644
--- a/Queue/src/ListQueue.java
+++ b/Queue/src/ListQueue.java
@@ -1,30 +1,37 @@
import java.util.Iterator;
public class ListQueue- implements MyQueue
- {
+
private Node first;
private Node last;
int N = 0;
+
private class Node {
Item item;
Node next;
}
+
@Override
public boolean isEmpty() {
return N == 0;
}
+
@Override
public int size() {
return N;
}
+
@Override
public MyQueue
- add(Item item) {
+
Node newNode = new Node();
newNode.item = item;
newNode.next = null;
+
if (isEmpty()) {
last = newNode;
first = newNode;
@@ -32,32 +39,45 @@ public MyQueue
- add(Item item) {
last.next = newNode;
last = newNode;
}
+
N++;
return this;
}
+
@Override
public Item remove() throws Exception {
- if (isEmpty())
+
+ if (isEmpty()) {
throw new Exception("queue is empty");
+ }
+
Node node = first;
first = first.next;
N--;
- if (isEmpty())
+
+ if (isEmpty()) {
last = null;
+ }
+
return node.item;
}
+
@Override
public Iterator
- iterator() {
+
return new Iterator
- () {
+
Node cur = first;
+
@Override
public boolean hasNext() {
return cur != null;
}
+
@Override
public Item next() {
Item item = cur.item;
diff --git a/Queue/src/MyQueue.java b/Queue/src/MyQueue.java
index 1c97d58..8f2340e 100644
--- a/Queue/src/MyQueue.java
+++ b/Queue/src/MyQueue.java
@@ -1,4 +1,5 @@
public interface MyQueue
- extends Iterable
- {
+
int size();
boolean isEmpty();
diff --git a/Queue/src/Test.java b/Queue/src/Test.java
index 756d0f7..1c38089 100644
--- a/Queue/src/Test.java
+++ b/Queue/src/Test.java
@@ -1,18 +1,25 @@
import org.junit.Assert;
public class Test {
+
@org.junit.Test
public void ListStackTest() throws Exception {
+
MyQueue queue = new ListQueue<>();
queue.add(1).add(2).add(3).add(4);
- for (Integer item : queue)
+
+ for (Integer item : queue) {
System.out.println(item);
+ }
+
Assert.assertEquals(queue.size(), 4);
Assert.assertFalse(queue.isEmpty());
- Assert.assertTrue(queue.remove() == 1);
- Assert.assertTrue(queue.remove() == 2);
- Assert.assertTrue(queue.remove() == 3);
- Assert.assertTrue(queue.remove() == 4);
+
+ Assert.assertEquals(1, (int) queue.remove());
+ Assert.assertEquals(2, (int) queue.remove());
+ Assert.assertEquals(3, (int) queue.remove());
+ Assert.assertEquals(4, (int) queue.remove());
+
Assert.assertTrue(queue.isEmpty());
}
}
diff --git a/README.md b/README.md
index 9c58604..d3cb504 100644
--- a/README.md
+++ b/README.md
@@ -4,13 +4,54 @@
对代码的详细说明请参考:[算法](https://github.com/CyC2018/Interview-Notebook/blob/master/notes/%E7%AE%97%E6%B3%95.md)
-以下是实现计划列表,欢迎补充
-
-- [x] ThreeSum
-- [x] 栈
-- [x] 队列
-- [x] 并查集
-- [x] 红黑树
-- [x] 散列表
-- [x] 排序
+```
+| Caching
+| ---- LRU // LRU 缓存淘汰算法
+| Graph
+| ---- KruskalMST // Kruskal 最小生成树
+| ---- PrimMST // Prim 最小生成树
+| MultiThreading
+| ---- AlternatePrint // 多线程交替打印
+| Other
+| ---- Hanoi // 汉诺塔
+| ---- Huffman // 哈夫曼编码
+| Queue // 队列
+| Scheduling
+| ---- FCFS // 先来先服务调度算法
+| ---- SJF // 最短进程优先调度算法
+| Searching
+| ---- OrderedST
+| -------- BinarySearchOrderedST // 二分查找实现的有序符号表
+| -------- BST // 二叉查找树
+| -------- RedBlackBST // 红黑二叉查找树
+| ---- Other
+| -------- SparseVector // 稀疏矩阵
+| -------- Transaction // 交易类,用于演示散列函数的实现
+| ---- UnorderedST
+| -------- LinearProbingHashST // 线性探测法实现的哈希表
+| -------- ListUnorderedST // 链表实现的无序符号表
+| Sorting
+| ---- Bubble // 冒泡排序
+| ---- DownUpMergeSort // 自底向上归并排序
+| ---- Heap // 堆
+| ---- HeapSort // 堆排序
+| ---- Insertion // 插入排序
+| ---- QuickSort // 快速排序
+| ---- Selection // 选择排序
+| ---- Shell // 希尔排序
+| ---- ThreeWayQuickSort // 三路归并快速排序
+| ---- Up2DownMergeSort // 自顶向上归并排序
+| Stack
+| ---- ArrayStack // 数组实现可动态扩容的栈
+| ---- ListStack // 链表实现的栈
+| ThreeSum
+| ---- BinarySearch // 二分查找
+| ---- RatioTest // 倍率实验
+| ---- StopWatch // 计时器
+| ---- ThreeSumFast // 改进的 ThreeSum
+| ---- ThreeSumSlow // 未改进的 ThreeSum
+| Union-Find
+| ---- QuickFindUF // 快速查找并查集
+| ---- QuickUnionUF // 快速合并并查集
+| ---- WeightedQuickUnionUF // 加权快速合并并查集
diff --git a/Scheduling/src/BatchScheduler.java b/Scheduling/src/BatchScheduler.java
new file mode 100644
index 0000000..11d558a
--- /dev/null
+++ b/Scheduling/src/BatchScheduler.java
@@ -0,0 +1,24 @@
+public class BatchScheduler extends Scheduler {
+
+ public BatchScheduler(ProcessQueue processQueue) {
+ super(processQueue);
+ }
+
+
+ @Override
+ public void run() {
+
+ while (true) {
+ if (!processQueue.isEmpty()) {
+ Process process = processQueue.get();
+ process.run(process.getTotalTime());
+ }
+
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/Scheduling/src/FCFSClient.java b/Scheduling/src/FCFSClient.java
new file mode 100644
index 0000000..dc91639
--- /dev/null
+++ b/Scheduling/src/FCFSClient.java
@@ -0,0 +1,13 @@
+public class FCFSClient {
+
+ public static void main(String[] args) {
+
+ ProcessQueue processQueue = new FCFSProcessQueue();
+
+ ProcessComeEmulator processComeEmulator = new ProcessComeEmulator(processQueue);
+ processComeEmulator.start();
+
+ Scheduler scheduler = new BatchScheduler(processQueue);
+ scheduler.start();
+ }
+}
diff --git a/Scheduling/src/FCFSProcessQueue.java b/Scheduling/src/FCFSProcessQueue.java
new file mode 100644
index 0000000..ee948ec
--- /dev/null
+++ b/Scheduling/src/FCFSProcessQueue.java
@@ -0,0 +1,25 @@
+import java.util.LinkedList;
+import java.util.Queue;
+
+public class FCFSProcessQueue implements ProcessQueue {
+
+ private Queue queue = new LinkedList<>();
+
+
+ @Override
+ public void add(Process process) {
+ queue.add(process);
+ }
+
+
+ @Override
+ public Process get() {
+ return queue.poll();
+ }
+
+
+ @Override
+ public boolean isEmpty() {
+ return queue.isEmpty();
+ }
+}
diff --git a/Scheduling/src/Process.java b/Scheduling/src/Process.java
new file mode 100644
index 0000000..59add9a
--- /dev/null
+++ b/Scheduling/src/Process.java
@@ -0,0 +1,50 @@
+/**
+ * 进程数据结构
+ */
+public class Process {
+
+ private String name;
+ private long totalTime;
+ private long remainTime;
+ private long comeInTime;
+
+
+ public Process(String name, long totalTime, long comeInTime) {
+ this.name = name;
+ this.totalTime = totalTime;
+ this.remainTime = totalTime;
+ this.comeInTime = comeInTime;
+ }
+
+
+ public void run(long runTime) {
+
+ System.out.println("process " + name + " is running...");
+ System.out.println("come in time : " + comeInTime);
+ System.out.println("total time : " + totalTime);
+ System.out.println("remain time : " + remainTime);
+ System.out.println();
+
+ remainTime -= runTime;
+ try {
+ Thread.sleep(runTime);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public long getTotalTime() {
+ return totalTime;
+ }
+
+
+ public long getRemainTime() {
+ return remainTime;
+ }
+
+
+ public long getComeInTime() {
+ return comeInTime;
+ }
+}
diff --git a/Scheduling/src/ProcessComeEmulator.java b/Scheduling/src/ProcessComeEmulator.java
new file mode 100644
index 0000000..417713b
--- /dev/null
+++ b/Scheduling/src/ProcessComeEmulator.java
@@ -0,0 +1,36 @@
+public class ProcessComeEmulator extends Thread {
+
+ private ProcessQueue processQueue;
+
+
+ public ProcessComeEmulator(ProcessQueue processQueue) {
+ this.processQueue = processQueue;
+ }
+
+
+ @Override
+ public void run() {
+
+ int processId = 0;
+
+ while (true) {
+
+ System.out.println("process " + processId + " is coming...");
+ System.out.println();
+
+ Process process = new Process((processId++) + "", getRandomTime(), System.currentTimeMillis());
+ processQueue.add(process);
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+
+ private long getRandomTime() {
+ return (long) (Math.random() * 3000);
+ }
+}
diff --git a/Scheduling/src/ProcessQueue.java b/Scheduling/src/ProcessQueue.java
new file mode 100644
index 0000000..adb16bc
--- /dev/null
+++ b/Scheduling/src/ProcessQueue.java
@@ -0,0 +1,8 @@
+public interface ProcessQueue {
+
+ void add(Process process);
+
+ Process get();
+
+ boolean isEmpty();
+}
diff --git a/Scheduling/src/SJFClient.java b/Scheduling/src/SJFClient.java
new file mode 100644
index 0000000..e945782
--- /dev/null
+++ b/Scheduling/src/SJFClient.java
@@ -0,0 +1,13 @@
+public class SJFClient {
+
+ public static void main(String[] args) {
+
+ ProcessQueue processQueue = new SJFProcessQueue();
+
+ ProcessComeEmulator processComeEmulator = new ProcessComeEmulator(processQueue);
+ processComeEmulator.start();
+
+ Scheduler scheduler = new BatchScheduler(processQueue);
+ scheduler.start();
+ }
+}
diff --git a/Scheduling/src/SJFProcessQueue.java b/Scheduling/src/SJFProcessQueue.java
new file mode 100644
index 0000000..82452bc
--- /dev/null
+++ b/Scheduling/src/SJFProcessQueue.java
@@ -0,0 +1,25 @@
+import java.util.PriorityQueue;
+
+public class SJFProcessQueue implements ProcessQueue {
+
+ private PriorityQueue processesQueue = new PriorityQueue<>(
+ (o1, o2) -> (int) (o1.getTotalTime() - o2.getTotalTime()));
+
+
+ @Override
+ public void add(Process process) {
+ processesQueue.add(process);
+ }
+
+
+ @Override
+ public Process get() {
+ return processesQueue.poll();
+ }
+
+
+ @Override
+ public boolean isEmpty() {
+ return processesQueue.isEmpty();
+ }
+}
diff --git a/Scheduling/src/Scheduler.java b/Scheduling/src/Scheduler.java
new file mode 100644
index 0000000..e408605
--- /dev/null
+++ b/Scheduling/src/Scheduler.java
@@ -0,0 +1,9 @@
+public class Scheduler extends Thread {
+
+ protected ProcessQueue processQueue;
+
+
+ public Scheduler(ProcessQueue processQueue) {
+ this.processQueue = processQueue;
+ }
+}
diff --git a/Searching/Searching.iml b/Searching/Searching.iml
deleted file mode 100644
index 3a8ffcf..0000000
--- a/Searching/Searching.iml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Searching/src/OrderedST/BST.java b/Searching/src/OrderedST/BST.java
index cfa1eee..5dbc141 100644
--- a/Searching/src/OrderedST/BST.java
+++ b/Searching/src/OrderedST/BST.java
@@ -8,15 +8,19 @@ public class BST, Value> implements OrderedST 0)
+
+ } else if (cmp > 0) {
x.right = delete(x.right, key);
- else {
- if (x.right == null)
+
+ } else {
+
+ if (x.right == null) {
return x.left;
- if (x.left == null)
+ }
+ if (x.left == null) {
return x.right;
+ }
+
Node t = x;
+
x = min(t.right);
x.right = deleteMin(t.right);
x.left = t.left;
}
+
recalculateSize(x);
+
return x;
}
+
@Override
public Key max() {
return max(root);
}
+
private Key max(Node x) {
- if (x == null)
+
+ if (x == null) {
return null;
- if (x.right == null)
+ }
+
+ if (x.right == null) {
return x.key;
+ }
+
return max(x.right);
}
+
@Override
public int rank(Key key) {
return rank(key, root);
}
+
private int rank(Key key, Node x) {
- if (x == null)
+
+ if (x == null) {
return 0;
+ }
+
int cmp = key.compareTo(x.key);
- if (cmp == 0)
+
+ if (cmp == 0) {
return size(x.left);
- else if (cmp < 0)
+
+ } else if (cmp < 0) {
return rank(key, x.left);
- else
+
+ } else {
return 1 + size(x.left) + rank(key, x.right);
+ }
}
+
@Override
public List keys(Key l, Key h) {
return keys(root, l, h);
}
+
private List keys(Node x, Key l, Key h) {
+
List list = new ArrayList<>();
- if (x == null)
+
+ if (x == null) {
return list;
+ }
+
int cmpL = l.compareTo(x.key);
int cmpH = h.compareTo(x.key);
- if (cmpL < 0)
+
+ if (cmpL < 0) {
list.addAll(keys(x.left, l, h));
- if (cmpL <= 0 && cmpH >= 0)
+ }
+ if (cmpL <= 0 && cmpH >= 0) {
list.add(x.key);
- if (cmpH > 0)
+ }
+ if (cmpH > 0) {
list.addAll(keys(x.right, l, h));
+ }
return list;
}
+
protected void recalculateSize(Node x) {
x.N = size(x.left) + size(x.right) + 1;
}
diff --git a/Searching/src/OrderedST/BinarySearchOrderedST.java b/Searching/src/OrderedST/BinarySearchOrderedST.java
index 0e790cb..db04468 100644
--- a/Searching/src/OrderedST/BinarySearchOrderedST.java
+++ b/Searching/src/OrderedST/BinarySearchOrderedST.java
@@ -9,36 +9,49 @@ public class BinarySearchOrderedST, Value> implement
private Value[] values;
private int N = 0;
+
public BinarySearchOrderedST(int capacity) {
keys = (Key[]) new Comparable[capacity];
values = (Value[]) new Object[capacity];
}
+
@Override
public int size() {
return N;
}
+
@Override
public int rank(Key key) {
+
int l = 0, h = N - 1;
+
while (l <= h) {
+
int m = l + (h - l) / 2;
+
int cmp = key.compareTo(keys[m]);
- if (cmp == 0)
+
+ if (cmp == 0) {
return m;
- else if (cmp < 0)
+ } else if (cmp < 0) {
h = m - 1;
- else
+ } else {
l = m + 1;
+ }
}
return l;
}
+
@Override
public List keys(Key l, Key h) {
+
int index = rank(l);
+
List list = new ArrayList<>();
+
while (keys[index].compareTo(h) <= 0) {
list.add(keys[index]);
index++;
@@ -46,37 +59,49 @@ public List keys(Key l, Key h) {
return list;
}
+
@Override
public void put(Key key, Value value) {
+
int index = rank(key);
+
// 如果找到已经存在的节点键位 key,就更新这个节点的值为 value
if (index < N && keys[index].compareTo(key) == 0) {
values[index] = value;
return;
}
+
// 否则在数组中插入新的节点,需要先将插入位置之后的元素都向后移动一个位置
for (int j = N; j > index; j--) {
keys[j] = keys[j - 1];
values[j] = values[j - 1];
}
+
keys[index] = key;
values[index] = value;
N++;
}
+
@Override
public Value get(Key key) {
+
int index = rank(key);
- if (index < N && keys[index].compareTo(key) == 0)
+
+ if (index < N && keys[index].compareTo(key) == 0) {
return values[index];
+ }
+
return null;
}
+
@Override
public Key min() {
return keys[0];
}
+
@Override
public Key max() {
return keys[N - 1];
diff --git a/Searching/src/OrderedST/OrderedSTTest.java b/Searching/src/OrderedST/OrderedSTTest.java
index 1cb6295..d6d093a 100644
--- a/Searching/src/OrderedST/OrderedSTTest.java
+++ b/Searching/src/OrderedST/OrderedSTTest.java
@@ -9,31 +9,44 @@ public void BinarySearchOrderedSTTest() {
test(new BinarySearchOrderedST(10));
}
+
@org.junit.Test
public void BSTTest() {
test(new BST());
}
+
@org.junit.Test
- public void RedBlackBSTTest(){
+ public void RedBlackBSTTest() {
test(new RedBlackBST());
}
+
private void test(OrderedST st) {
+
Integer key1 = 2, key2 = 1, key3 = 3;
String value1 = "b", value2 = "a", value3 = "c";
+
st.put(key1, value1);
- Assert.assertTrue(st.get(key1) == value1);
+
+ Assert.assertSame(st.get(key1), value1);
Assert.assertNull(st.get(key2));
+
st.put(key2, value2);
st.put(key3, value3);
- Assert.assertTrue(st.get(key2) == value2);
- Assert.assertTrue(st.min() == 1);
- Assert.assertTrue(st.max() == 3);
- Assert.assertTrue(st.size() == 3);
- Assert.assertTrue(st.rank(2) == 1);
+
+ Assert.assertSame(st.get(key2), value2);
+
+ Assert.assertEquals(1, (int) st.min());
+ Assert.assertEquals(3, (int) st.max());
+
+ Assert.assertEquals(3, st.size());
+ Assert.assertEquals(1, st.rank(2));
+
Assert.assertArrayEquals(st.keys(1, 2).toArray(new Integer[2]), new Integer[]{1, 2});
+
st.put(key2, value1);
- Assert.assertTrue(st.get(key2) == value1);
+
+ Assert.assertSame(st.get(key2), value1);
}
}
diff --git a/Searching/src/OrderedST/RedBlackBST.java b/Searching/src/OrderedST/RedBlackBST.java
index 9e6935b..d807b17 100644
--- a/Searching/src/OrderedST/RedBlackBST.java
+++ b/Searching/src/OrderedST/RedBlackBST.java
@@ -1,36 +1,47 @@
package OrderedST;
public class RedBlackBST, Value> extends BST {
+
private static final boolean RED = true;
private static final boolean BLACK = false;
+
private boolean isRed(Node x) {
if (x == null)
return false;
return x.color == RED;
}
+
public Node rotateLeft(Node h) {
+
Node x = h.right;
h.right = x.left;
x.left = h;
x.color = h.color;
h.color = RED;
x.N = h.N;
+
recalculateSize(h);
+
return x;
}
+
public Node rotateRight(Node h) {
+
Node x = h.left;
h.left = x.right;
x.color = h.color;
h.color = RED;
x.N = h.N;
+
recalculateSize(h);
+
return x;
}
+
void flipColors(Node h) {
h.color = RED;
h.left.color = BLACK;
@@ -44,28 +55,39 @@ public void put(Key key, Value value) {
root.color = BLACK;
}
+
private Node put(Node x, Key key, Value value) {
+
if (x == null) {
Node node = new Node(key, value, 1);
node.color = RED;
return node;
}
+
int cmp = key.compareTo(x.key);
- if (cmp == 0)
+
+ if (cmp == 0) {
x.val = value;
- else if (cmp < 0)
+
+ } else if (cmp < 0) {
x.left = put(x.left, key, value);
- else
+
+ } else {
x.right = put(x.right, key, value);
+ }
- if (isRed(x.right) && !isRed(x.left))
+ if (isRed(x.right) && !isRed(x.left)) {
x = rotateLeft(x);
- if (isRed(x.left) && isRed(x.left.left))
+ }
+ if (isRed(x.left) && isRed(x.left.left)) {
x = rotateRight(x);
- if (isRed(x.left) && isRed(x.right))
+ }
+ if (isRed(x.left) && isRed(x.right)) {
flipColors(x);
+ }
recalculateSize(x);
+
return x;
}
}
\ No newline at end of file
diff --git a/Searching/src/Other/SparseVector.java b/Searching/src/Other/SparseVector.java
index 69ee490..cc84906 100644
--- a/Searching/src/Other/SparseVector.java
+++ b/Searching/src/Other/SparseVector.java
@@ -6,23 +6,32 @@
* 稀疏矩阵
*/
public class SparseVector {
+
private HashMap hashMap;
public SparseVector(double[] vector) {
+
hashMap = new HashMap<>();
- for (int i = 0; i < vector.length; i++)
- if (vector[i] != 0)
+
+ for (int i = 0; i < vector.length; i++) {
+ if (vector[i] != 0) {
hashMap.put(i, vector[i]);
+ }
+ }
}
+
public double get(int i) {
return hashMap.getOrDefault(i, 0.0);
}
+
public double dot(SparseVector other) {
+
double sum = 0;
- for (int i : hashMap.keySet())
- sum += this.get(i) * other.get(i);
+ for (int i : hashMap.keySet()) {
+ sum = sum + this.get(i) * other.get(i);
+ }
return sum;
}
}
\ No newline at end of file
diff --git a/Searching/src/Other/SparseVectorTest.java b/Searching/src/Other/SparseVectorTest.java
index 234610e..b136a54 100644
--- a/Searching/src/Other/SparseVectorTest.java
+++ b/Searching/src/Other/SparseVectorTest.java
@@ -6,11 +6,14 @@
public class SparseVectorTest {
@Test
- public void dot() throws Exception {
+ public void dot() {
+
double[] vector1 = {1, 0, 0, 0, 1, 0};
double[] vector2 = {0, 0, 1, 1, 1, 0};
+
SparseVector sparseVector1 = new SparseVector(vector1);
SparseVector sparseVector2 = new SparseVector(vector2);
+
Assert.assertEquals(sparseVector1.dot(sparseVector2), 1, 0.0000001);
}
}
\ No newline at end of file
diff --git a/Searching/src/Other/Transaction.java b/Searching/src/Other/Transaction.java
index d774a23..c0a3f28 100644
--- a/Searching/src/Other/Transaction.java
+++ b/Searching/src/Other/Transaction.java
@@ -6,16 +6,19 @@
* 交易类,用于演示 hashCode() 实现
*/
public class Transaction {
+
private final String who;
private final Date when;
private final double amount;
+
public Transaction(String who, Date when, double amount) {
this.who = who;
this.when = when;
this.amount = amount;
}
+
public int hashCode() {
int hash = 17;
int R = 31;
diff --git a/Searching/src/UnorderedST/LinearProbingHashST.java b/Searching/src/UnorderedST/LinearProbingHashST.java
index a4c0c30..8bd2001 100644
--- a/Searching/src/UnorderedST/LinearProbingHashST.java
+++ b/Searching/src/UnorderedST/LinearProbingHashST.java
@@ -1,75 +1,94 @@
package UnorderedST;
public class LinearProbingHashST implements UnorderedST {
+
private int N = 0;
private int M = 16;
private Key[] keys;
private Value[] values;
+
public LinearProbingHashST() {
init();
}
+
public LinearProbingHashST(int M) {
this.M = M;
init();
}
+
private void init() {
keys = (Key[]) new Object[M];
values = (Value[]) new Object[M];
}
+
private int hash(Key key) {
return (key.hashCode() & 0x7fffffff) % M;
}
+
@Override
public int size() {
return N;
}
+
@Override
public void put(Key key, Value value) {
resize();
putInternal(key, value);
}
+
/**
* 因为 put() 会调用 resize(),而 resize() 操作又需要将键值对重新插入
* 如果 resize() 又调用 put(),那么就会循环调用,不仅容易出错,而且会造成一些多于的检查步骤
*/
private void putInternal(Key key, Value value) {
+
int i;
- for (i = hash(key); keys[i] != null; i = (i + 1) % M)
+
+ for (i = hash(key); keys[i] != null; i = (i + 1) % M) {
if (keys[i].equals(key)) {
values[i] = value;
return;
}
+ }
keys[i] = key;
values[i] = value;
N++;
}
+
@Override
public Value get(Key key) {
- for (int i = hash(key); keys[i] != null; i = (i + 1) % M)
- if (keys[i].equals(key))
- return values[i];
+ for (int i = hash(key); keys[i] != null; i = (i + 1) % M) {
+ if (keys[i].equals(key)) {
+ return values[i];
+ }
+ }
return null;
}
+
@Override
public void delete(Key key) {
+
int i = hash(key);
- while (keys[i] != null && !key.equals(keys[i]))
+
+ while (keys[i] != null && !key.equals(keys[i])) {
i = (i + 1) % M;
+ }
// 不存在,直接返回
- if (keys[i] == null)
+ if (keys[i] == null) {
return;
+ }
keys[i] = null;
values[i] = null;
@@ -77,30 +96,46 @@ public void delete(Key key) {
// 将之后相连的键值对重新插入
i = (i + 1) % M;
while (keys[i] != null) {
+
Key keyToRedo = keys[i];
Value valToRedo = values[i];
+
keys[i] = null;
values[i] = null;
+
N--;
+
putInternal(keyToRedo, valToRedo);
+
i = (i + 1) % M;
}
+
N--;
+
resize();
}
+
private void resize() {
- if (N >= M / 2)
+
+ if (N >= M / 2) {
resize(2 * M);
- else if (N <= M / 8)
+
+ } else if (N <= M / 8) {
resize(M / 2);
+ }
}
+
private void resize(int cap) {
+
LinearProbingHashST t = new LinearProbingHashST(cap);
- for (int i = 0; i < M; i++)
- if (keys[i] != null)
+
+ for (int i = 0; i < M; i++) {
+ if (keys[i] != null) {
t.putInternal(keys[i], values[i]);
+ }
+ }
keys = t.keys;
values = t.values;
diff --git a/Searching/src/UnorderedST/ListUnorderedST.java b/Searching/src/UnorderedST/ListUnorderedST.java
index 555dd85..782cc76 100644
--- a/Searching/src/UnorderedST/ListUnorderedST.java
+++ b/Searching/src/UnorderedST/ListUnorderedST.java
@@ -4,11 +4,14 @@ public class ListUnorderedST implements UnorderedST {
private Node first;
+
private class Node {
+
Key key;
Value value;
Node next;
+
Node(Key key, Value value, Node next) {
this.key = key;
this.value = value;
@@ -16,8 +19,10 @@ private class Node {
}
}
+
@Override
public int size() {
+
int cnt = 0;
Node cur = first;
while (cur != null) {
@@ -27,9 +32,12 @@ public int size() {
return cnt;
}
+
@Override
public void put(Key key, Value value) {
+
Node cur = first;
+
// 如果在链表中找到节点的键等于 key 就更新这个节点的值为 value
while (cur != null) {
if (cur.key.equals(key)) {
@@ -38,17 +46,24 @@ public void put(Key key, Value value) {
}
cur = cur.next;
}
+
// 否则使用头插法插入一个新节点
first = new Node(key, value, first);
}
+
@Override
public void delete(Key key) {
- if (first == null)
+
+ if (first == null) {
return;
- if (first.key.equals(key))
+ }
+ if (first.key.equals(key)) {
first = first.next;
+ }
+
Node pre = first, cur = first.next;
+
while (cur != null) {
if (cur.key.equals(key)) {
pre.next = cur.next;
@@ -59,14 +74,19 @@ public void delete(Key key) {
}
}
+
@Override
public Value get(Key key) {
+
Node cur = first;
+
while (cur != null) {
- if (cur.key.equals(key))
+ if (cur.key.equals(key)) {
return cur.value;
+ }
cur = cur.next;
}
+
return null;
}
}
diff --git a/Searching/src/UnorderedST/UnorderedSTTest.java b/Searching/src/UnorderedST/UnorderedSTTest.java
index 763ecea..29e0fff 100644
--- a/Searching/src/UnorderedST/UnorderedSTTest.java
+++ b/Searching/src/UnorderedST/UnorderedSTTest.java
@@ -9,23 +9,34 @@ public void ListUnorderedSTTest() {
test(new ListUnorderedST());
}
+
@org.junit.Test
public void LinearProbingHashSTTest() {
test(new LinearProbingHashST());
}
+
private void test(UnorderedST st) {
+
String key1 = "a", key2 = "b";
int value1 = 1, value2 = 2;
+
st.put(key1, value1);
- Assert.assertTrue(st.get(key1) == value1);
+
+ Assert.assertEquals((int) st.get(key1), value1);
Assert.assertNull(st.get(key2));
+
st.put(key2, value2);
- Assert.assertTrue(st.get(key2) == value2);
- Assert.assertTrue(st.size() == 2);
+
+ Assert.assertEquals((int) st.get(key2), value2);
+ Assert.assertEquals(2, st.size());
+
st.put(key2, value1);
- Assert.assertTrue(st.get(key2) == value1);
+
+ Assert.assertEquals((int) st.get(key2), value1);
+
st.delete(key2);
+
Assert.assertNull(st.get(key2));
}
}
diff --git a/Sorting/Sorting.iml b/Sorting/Sorting.iml
deleted file mode 100644
index 3a8ffcf..0000000
--- a/Sorting/Sorting.iml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Sorting/src/Bubble.java b/Sorting/src/Bubble.java
index df91c74..22f698f 100644
--- a/Sorting/src/Bubble.java
+++ b/Sorting/src/Bubble.java
@@ -1,11 +1,12 @@
public class Bubble> extends Sort {
+
@Override
public void sort(T[] nums) {
int N = nums.length;
boolean hasSorted = false;
- for (int i = 0; i < N && !hasSorted; i++) {
+ for (int i = N - 1; i > 0 && !hasSorted; i--) {
hasSorted = true;
- for (int j = 0; j < N - i - 1; j++) {
+ for (int j = 0; j < i; j++) {
if (less(nums[j + 1], nums[j])) {
hasSorted = false;
swap(nums, j, j + 1);
diff --git a/Sorting/src/Down2UpMergeSort.java b/Sorting/src/Down2UpMergeSort.java
index aaa9b92..7f0b061 100644
--- a/Sorting/src/Down2UpMergeSort.java
+++ b/Sorting/src/Down2UpMergeSort.java
@@ -1,10 +1,14 @@
public class Down2UpMergeSort> extends MergeSort {
+
@Override
public void sort(T[] nums) {
int N = nums.length;
aux = (T[]) new Comparable[N];
- for (int sz = 1; sz < N; sz += sz)
- for (int lo = 0; lo < N - sz; lo += sz + sz)
+
+ for (int sz = 1; sz < N; sz += sz) {
+ for (int lo = 0; lo < N - sz; lo += sz + sz) {
merge(nums, lo, lo + sz - 1, Math.min(lo + sz + sz - 1, N - 1));
+ }
+ }
}
}
diff --git a/Sorting/src/Heap.java b/Sorting/src/Heap.java
index 41e3cf0..8ff44a8 100644
--- a/Sorting/src/Heap.java
+++ b/Sorting/src/Heap.java
@@ -3,52 +3,64 @@ public class Heap> {
private T[] heap;
private int N = 0;
+
public Heap(int maxN) {
this.heap = (T[]) new Comparable[maxN + 1];
}
+
public boolean isEmpty() {
return N == 0;
}
+
public int size() {
return N;
}
+
private boolean less(int i, int j) {
return heap[i].compareTo(heap[j]) < 0;
}
+
private void swap(int i, int j) {
T t = heap[i];
heap[i] = heap[j];
heap[j] = t;
}
+
private void swim(int k) {
+
while (k > 1 && less(k / 2, k)) {
swap(k / 2, k);
k = k / 2;
}
}
+
private void sink(int k) {
while (2 * k <= N) {
int j = 2 * k;
- if (j < N && less(j, j + 1))
+ if (j < N && less(j, j + 1)) {
j++;
- if (!less(k, j))
+ }
+ if (!less(k, j)) {
break;
+ }
swap(k, j);
k = j;
}
}
+
public void insert(T v) {
heap[++N] = v;
swim(N);
}
+
public T delMax() {
T max = heap[1];
swap(1, N--);
diff --git a/Sorting/src/HeapSort.java b/Sorting/src/HeapSort.java
index 96837a1..e3abdb2 100644
--- a/Sorting/src/HeapSort.java
+++ b/Sorting/src/HeapSort.java
@@ -1,12 +1,16 @@
public class HeapSort> extends Sort {
+
/**
* 数组第 0 个位置不能有元素
*/
@Override
public void sort(T[] nums) {
+
int N = nums.length - 1;
- for (int k = N / 2; k >= 1; k--)
+
+ for (int k = N / 2; k >= 1; k--) {
sink(nums, k, N);
+ }
while (N > 1) {
swap(nums, 1, N--);
@@ -14,18 +18,23 @@ public void sort(T[] nums) {
}
}
+
private void sink(T[] nums, int k, int N) {
+
while (2 * k <= N) {
int j = 2 * k;
- if (j < N && less(nums, j, j + 1))
+ if (j < N && less(nums, j, j + 1)) {
j++;
- if (!less(nums, k, j))
+ }
+ if (!less(nums, k, j)) {
break;
+ }
swap(nums, k, j);
k = j;
}
}
+
private boolean less(T[] nums, int i, int j) {
return nums[i].compareTo(nums[j]) < 0;
}
diff --git a/Sorting/src/HeapSortTest.java b/Sorting/src/HeapSortTest.java
index 71c14a1..e28cf57 100644
--- a/Sorting/src/HeapSortTest.java
+++ b/Sorting/src/HeapSortTest.java
@@ -7,13 +7,16 @@
* 需要单独创建一个测试类
*/
public class HeapSortTest {
+
@Test
- public void sort() throws Exception {
+ public void sort() {
+
Integer[] numsBefore = {0, 2, 3, 6, 5, 4, -1, -2, 0, Integer.MIN_VALUE, Integer.MAX_VALUE};
Integer[] numsAfter = {0, Integer.MIN_VALUE, -2, -1, 0, 2, 3, 4, 5, 6, Integer.MAX_VALUE};
+
HeapSort sort = new HeapSort<>();
sort.sort(numsBefore);
+
Assert.assertArrayEquals(numsBefore, numsAfter);
}
-
}
\ No newline at end of file
diff --git a/Sorting/src/HeapTest.java b/Sorting/src/HeapTest.java
index 8776257..266df13 100644
--- a/Sorting/src/HeapTest.java
+++ b/Sorting/src/HeapTest.java
@@ -1,18 +1,24 @@
import org.junit.Assert;
public class HeapTest {
+
@org.junit.Test
public void test() {
+
Heap heap = new Heap<>(10);
+
heap.insert(5);
heap.insert(4);
heap.insert(6);
heap.insert(1);
+
Assert.assertEquals(heap.size(), 4);
- Assert.assertTrue(heap.delMax() == 6);
- Assert.assertTrue(heap.delMax() == 5);
- Assert.assertTrue(heap.delMax() == 4);
- Assert.assertTrue(heap.delMax() == 1);
+
+ Assert.assertEquals(6, (int) heap.delMax());
+ Assert.assertEquals(5, (int) heap.delMax());
+ Assert.assertEquals(4, (int) heap.delMax());
+ Assert.assertEquals(1, (int) heap.delMax());
+
Assert.assertTrue(heap.isEmpty());
}
}
\ No newline at end of file
diff --git a/Sorting/src/Insertion.java b/Sorting/src/Insertion.java
index d3fa3c0..5e04f4e 100644
--- a/Sorting/src/Insertion.java
+++ b/Sorting/src/Insertion.java
@@ -1,9 +1,12 @@
public class Insertion> extends Sort {
+
@Override
public void sort(T[] nums) {
int N = nums.length;
- for (int i = 1; i < N; i++)
- for (int j = i; j > 0 && less(nums[j], nums[j - 1]); j--)
+ for (int i = 1; i < N; i++) {
+ for (int j = i; j > 0 && less(nums[j], nums[j - 1]); j--) {
swap(nums, j, j - 1);
+ }
+ }
}
}
diff --git a/Sorting/src/MergeSort.java b/Sorting/src/MergeSort.java
index abfe564..4234e9b 100644
--- a/Sorting/src/MergeSort.java
+++ b/Sorting/src/MergeSort.java
@@ -2,21 +2,28 @@ public abstract class MergeSort> extends Sort {
protected T[] aux;
+
protected void merge(T[] nums, int l, int m, int h) {
+
int i = l, j = m + 1;
- for (int k = l; k <= h; k++)
+ for (int k = l; k <= h; k++) {
aux[k] = nums[k]; // 将数据复制到辅助数组
+ }
for (int k = l; k <= h; k++) {
- if (i > m)
+ if (i > m) {
nums[k] = aux[j++];
- else if (j > h)
+
+ } else if (j > h) {
nums[k] = aux[i++];
- else if (aux[i].compareTo(nums[j]) <= 0)
+
+ } else if (aux[i].compareTo(nums[j]) <= 0) {
nums[k] = aux[i++]; // 先进行这一步,保证稳定性
- else
+
+ } else {
nums[k] = aux[j++];
+ }
}
}
}
diff --git a/Sorting/src/QuickSort.java b/Sorting/src/QuickSort.java
index 7ab7c03..b3d620a 100644
--- a/Sorting/src/QuickSort.java
+++ b/Sorting/src/QuickSort.java
@@ -3,25 +3,27 @@
import java.util.List;
public class QuickSort> extends Sort {
- @Override
- public void sort(T[] nums) {
- shuffle(nums);
- sort(nums, 0, nums.length - 1);
- }
- protected void sort(T[] nums, int l, int h) {
- if (h <= l)
- return;
- int j = partition(nums, l, h);
- sort(nums, l, j - 1);
- sort(nums, j + 1, h);
- }
+ @Override
+ public void sort(T[] nums) {
+ shuffle(nums);
+ sort(nums, 0, nums.length - 1);
+ }
- private void shuffle(T[] nums) {
- List list = Arrays.asList(nums);
- Collections.shuffle(list);
- list.toArray(nums);
+ protected void sort(T[] nums, int l, int h) {
+ if (h <= l) {
+ return;
}
+ int j = partition(nums, l, h);
+ sort(nums, l, j - 1);
+ sort(nums, j + 1, h);
+ }
+
+ private void shuffle(T[] nums) {
+ List list = Arrays.asList(nums);
+ Collections.shuffle(list);
+ list.toArray(nums);
+ }
private int partition(T[] nums, int l, int h) {
int i = l, j = h + 1;
@@ -29,8 +31,9 @@ private int partition(T[] nums, int l, int h) {
while (true) {
while (less(nums[++i], v) && i != h) ;
while (less(v, nums[--j]) && j != l) ;
- if (i >= j)
+ if (i >= j) {
break;
+ }
swap(nums, i, j);
}
swap(nums, l, j);
@@ -41,12 +44,16 @@ public T select(T[] nums, int k) {
int l = 0, h = nums.length - 1;
while (h > l) {
int j = partition(nums, l, h);
- if (j == k)
+
+ if (j == k) {
return nums[k];
- else if (j > k)
+
+ } else if (j > k) {
h = j - 1;
- else
+
+ } else {
l = j + 1;
+ }
}
return nums[k];
}
diff --git a/Sorting/src/Selection.java b/Sorting/src/Selection.java
index fbec81f..6e18101 100644
--- a/Sorting/src/Selection.java
+++ b/Sorting/src/Selection.java
@@ -1,12 +1,15 @@
public class Selection> extends Sort {
+
@Override
public void sort(T[] nums) {
int N = nums.length;
for (int i = 0; i < N; i++) {
int min = i;
- for (int j = i + 1; j < N; j++)
- if (less(nums[j], nums[min]))
+ for (int j = i + 1; j < N; j++) {
+ if (less(nums[j], nums[min])) {
min = j;
+ }
+ }
swap(nums, i, min);
}
}
diff --git a/Sorting/src/Shell.java b/Sorting/src/Shell.java
index 8d7ad7f..c8d6695 100644
--- a/Sorting/src/Shell.java
+++ b/Sorting/src/Shell.java
@@ -1,15 +1,21 @@
public class Shell> extends Sort {
+
@Override
public void sort(T[] nums) {
+
int N = nums.length;
int h = 1;
- while (h < N / 3)
+
+ while (h < N / 3) {
h = 3 * h + 1; // 1, 4, 13, 40, ...
+ }
while (h >= 1) {
- for (int i = h; i < N; i++)
- for (int j = i; j >= h && less(nums[j], nums[j - h]); j -= h)
+ for (int i = h; i < N; i++) {
+ for (int j = i; j >= h && less(nums[j], nums[j - h]); j -= h) {
swap(nums, j, j - h);
+ }
+ }
h = h / 3;
}
}
diff --git a/Sorting/src/Test.java b/Sorting/src/Test.java
index df8359c..364b0f0 100644
--- a/Sorting/src/Test.java
+++ b/Sorting/src/Test.java
@@ -18,47 +18,57 @@ public class Test {
{Integer.MIN_VALUE, Integer.MAX_VALUE}
};
+
@org.junit.Test
public void SelectionTest() {
test(new Selection<>());
}
+
@org.junit.Test
public void BubbleTest() {
test(new Bubble<>());
}
+
@org.junit.Test
public void InsertionTest() {
test(new Insertion<>());
}
+
@org.junit.Test
public void ShellTest() {
test(new Shell<>());
}
+
@org.junit.Test
public void Up2DownMergeSortTest() {
test(new Up2DownMergeSort<>());
}
+
@org.junit.Test
public void Down2UpMergeSortTest() {
test(new Down2UpMergeSort<>());
}
+
@org.junit.Test
public void QuickSortTest() {
test(new QuickSort<>());
}
+
@org.junit.Test
public void ThreeWayQuickSortTest() {
test(new ThreeWayQuickSort<>());
}
+
private void test(Sort sort) {
+
for (int i = 0; i < numsBefore.length; i++) {
sort.sort(numsBefore[i]);
Assert.assertArrayEquals(numsBefore[i], numsAfter[i]);
diff --git a/Sorting/src/ThreeWayQuickSort.java b/Sorting/src/ThreeWayQuickSort.java
index 4dc6c7a..60a5dd6 100644
--- a/Sorting/src/ThreeWayQuickSort.java
+++ b/Sorting/src/ThreeWayQuickSort.java
@@ -1,18 +1,21 @@
public class ThreeWayQuickSort> extends QuickSort {
+
@Override
protected void sort(T[] nums, int l, int h) {
- if (h <= l)
+ if (h <= l) {
return;
+ }
int lt = l, i = l + 1, gt = h;
T v = nums[l];
while (i <= gt) {
int cmp = nums[i].compareTo(v);
- if (cmp < 0)
+ if (cmp < 0) {
swap(nums, lt++, i++);
- else if (cmp > 0)
+ } else if (cmp > 0) {
swap(nums, i, gt--);
- else
+ } else {
i++;
+ }
}
sort(nums, l, lt - 1);
sort(nums, gt + 1, h);
diff --git a/Sorting/src/Up2DownMergeSort.java b/Sorting/src/Up2DownMergeSort.java
index 36ac3b4..ebf599a 100644
--- a/Sorting/src/Up2DownMergeSort.java
+++ b/Sorting/src/Up2DownMergeSort.java
@@ -1,4 +1,5 @@
public class Up2DownMergeSort> extends MergeSort {
+
@Override
public void sort(T[] nums) {
aux = (T[]) new Comparable[nums.length];
@@ -6,8 +7,9 @@ public void sort(T[] nums) {
}
private void sort(T[] nums, int l, int h) {
- if (h <= l)
+ if (h <= l) {
return;
+ }
int mid = l + (h - l) / 2;
sort(nums, l, mid);
sort(nums, mid + 1, h);
diff --git a/Stack/Stack.iml b/Stack/Stack.iml
deleted file mode 100644
index 3a8ffcf..0000000
--- a/Stack/Stack.iml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Stack/src/ArrayStack.java b/Stack/src/ArrayStack.java
index 2c019ea..1d21358 100644
--- a/Stack/src/ArrayStack.java
+++ b/Stack/src/ArrayStack.java
@@ -4,11 +4,14 @@
* 使用数组实现的可以动态调整大小的栈
*/
public class ArrayStack
- implements MyStack
- {
+
// 栈元素数组,只能通过转型来创建泛型数组
private Item[] a = (Item[]) new Object[1];
+
// 元素数量
private int N = 0;
+
@Override
public MyStack
- push(Item item) {
check();
@@ -16,48 +19,69 @@ public MyStack
- push(Item item) {
return this;
}
+
@Override
public Item pop() throws Exception {
- if (isEmpty())
+
+ if (isEmpty()) {
throw new Exception("stack is empty");
+ }
Item item = a[--N];
+
check();
- a[N] = null; // 避免对象游离
+
+ // 避免对象游离
+ a[N] = null;
+
return item;
}
+
private void check() {
- if (N >= a.length)
+
+ if (N >= a.length) {
resize(2 * a.length);
- else if (N > 0 && N <= a.length / 4)
+
+ } else if (N > 0 && N <= a.length / 4) {
resize(a.length / 2);
+ }
}
+
/**
* 调整数组大小,使得栈具有伸缩性
*/
private void resize(int size) {
+
Item[] tmp = (Item[]) new Object[size];
- for (int i = 0; i < N; i++)
+
+ for (int i = 0; i < N; i++) {
tmp[i] = a[i];
+ }
+
a = tmp;
}
+
@Override
public boolean isEmpty() {
return N == 0;
}
+
@Override
public int size() {
return N;
}
+
@Override
public Iterator
- iterator() {
+
// 返回逆序遍历的迭代器
return new Iterator
- () {
+
private int i = N;
@Override
@@ -70,5 +94,6 @@ public Item next() {
return a[--i];
}
};
+
}
}
\ No newline at end of file
diff --git a/Stack/src/ListStack.java b/Stack/src/ListStack.java
index d5752cf..8827b70 100644
--- a/Stack/src/ListStack.java
+++ b/Stack/src/ListStack.java
@@ -4,54 +4,75 @@
* 使用链表实现的栈
*/
public class ListStack
- implements MyStack
- {
+
private Node top = null;
private int N = 0;
+
private class Node {
Item item;
Node next;
}
+
@Override
public MyStack
- push(Item item) {
+
Node newTop = new Node();
+
newTop.item = item;
newTop.next = top;
+
top = newTop;
+
N++;
+
return this;
}
+
@Override
public Item pop() throws Exception {
- if (isEmpty())
+
+ if (isEmpty()) {
throw new Exception("stack is empty");
+ }
+
Item item = top.item;
+
top = top.next;
N--;
+
return item;
}
+
@Override
public boolean isEmpty() {
return N == 0;
}
+
@Override
public int size() {
return N;
}
+
@Override
public Iterator
- iterator() {
+
return new Iterator
- () {
+
private Node cur = top;
+
@Override
public boolean hasNext() {
return cur != null;
}
+
@Override
public Item next() {
Item item = cur.item;
@@ -59,5 +80,6 @@ public Item next() {
return item;
}
};
+
}
}
\ No newline at end of file
diff --git a/Stack/src/MyStack.java b/Stack/src/MyStack.java
index a50196f..643226e 100644
--- a/Stack/src/MyStack.java
+++ b/Stack/src/MyStack.java
@@ -1,4 +1,5 @@
public interface MyStack
- extends Iterable
- {
+
MyStack
- push(Item item);
Item pop() throws Exception;
@@ -6,4 +7,5 @@ public interface MyStack
- extends Iterable
- {
boolean isEmpty();
int size();
+
}
diff --git a/Stack/src/Test.java b/Stack/src/Test.java
index ba17adb..cd6dcfc 100644
--- a/Stack/src/Test.java
+++ b/Stack/src/Test.java
@@ -1,5 +1,7 @@
import org.junit.Assert;
+import static org.junit.Assert.assertTrue;
+
public class Test {
@org.junit.Test
@@ -7,21 +9,30 @@ public void ResizingArrayStackTest() throws Exception {
test(new ArrayStack<>());
}
+
@org.junit.Test
public void ListStackTest() throws Exception {
test(new ListStack<>());
}
+
private static void test(MyStack stack) throws Exception {
+
stack.push(1).push(2).push(3).push(4);
+
Assert.assertEquals(stack.size(), 4);
Assert.assertFalse(stack.isEmpty());
- for (Integer item : stack)
+
+ for (Integer item : stack) {
System.out.println(item);
- Assert.assertTrue(stack.pop() == 4);
- Assert.assertTrue(stack.pop() == 3);
- Assert.assertTrue(stack.pop() == 2);
- Assert.assertTrue(stack.pop() == 1);
- Assert.assertTrue(stack.isEmpty());
+ }
+
+ Assert.assertEquals(4, (int) stack.pop());
+ Assert.assertEquals(3, (int) stack.pop());
+ Assert.assertEquals(2, (int) stack.pop());
+ Assert.assertEquals(1, (int) stack.pop());
+
+ assertTrue(stack.isEmpty());
+
}
}
diff --git a/ThreeSum/ThreeSum.iml b/ThreeSum/ThreeSum.iml
deleted file mode 100644
index 9b05c67..0000000
--- a/ThreeSum/ThreeSum.iml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ThreeSum/src/BinarySearch.java b/ThreeSum/src/BinarySearch.java
index ff7018b..cfe898f 100644
--- a/ThreeSum/src/BinarySearch.java
+++ b/ThreeSum/src/BinarySearch.java
@@ -1,15 +1,24 @@
public class BinarySearch {
+
public static int search(int[] nums, int target) {
+
int l = 0, h = nums.length - 1;
+
while (l <= h) {
+
int m = l + (h - l) / 2;
- if (target == nums[m])
+
+ if (target == nums[m]) {
return m;
- else if (target > nums[m])
+
+ } else if (target > nums[m]) {
l = m + 1;
- else
+
+ } else {
h = m - 1;
+ }
}
+
return -1;
}
}
diff --git a/ThreeSum/src/BinarySearchTest.java b/ThreeSum/src/BinarySearchTest.java
index 1ef07da..b18920e 100644
--- a/ThreeSum/src/BinarySearchTest.java
+++ b/ThreeSum/src/BinarySearchTest.java
@@ -15,7 +15,7 @@ public class BinarySearchTest {
};
@org.junit.Test
- public void search() throws Exception {
+ public void search() {
for (int i = 0; i < nums.length; i++) {
Assert.assertEquals(BinarySearch.search(nums[i], targets[i]), expects[i]);
}
diff --git a/ThreeSum/src/RatioTest.java b/ThreeSum/src/RatioTest.java
index fd8f408..f6e11f8 100644
--- a/ThreeSum/src/RatioTest.java
+++ b/ThreeSum/src/RatioTest.java
@@ -2,21 +2,31 @@
* 倍率实验
*/
public class RatioTest {
+
public static void main(String[] args) {
+
int N = 500;
int loopTimes = 7;
double preTime = -1;
+
while (loopTimes-- > 0) {
+
int[] nums = new int[N];
+
StopWatch.start();
+
ThreeSum threeSum = new ThreeSumSlow();
+
int cnt = threeSum.count(nums);
System.out.println(cnt);
+
double elapsedTime = StopWatch.elapsedTime();
double ratio = preTime == -1 ? 0 : elapsedTime / preTime;
System.out.println(N + " " + elapsedTime + " " + ratio);
+
preTime = elapsedTime;
N *= 2;
+
}
}
}
\ No newline at end of file
diff --git a/ThreeSum/src/StopWatch.java b/ThreeSum/src/StopWatch.java
index 6718cb3..1f0a6b5 100644
--- a/ThreeSum/src/StopWatch.java
+++ b/ThreeSum/src/StopWatch.java
@@ -2,12 +2,15 @@
* 用于统计算法运行时间
*/
public class StopWatch {
+
private static long start;
-
- public static void start(){
+
+
+ public static void start() {
start = System.currentTimeMillis();
}
-
+
+
public static double elapsedTime() {
long now = System.currentTimeMillis();
return (now - start) / 1000.0;
diff --git a/ThreeSum/src/Test.java b/ThreeSum/src/Test.java
index 9a07006..aae0184 100644
--- a/ThreeSum/src/Test.java
+++ b/ThreeSum/src/Test.java
@@ -5,17 +5,21 @@ public class Test {
private final int[] nums = {-2, -1, 0, 1, 2};
private final int expect = 2;
+
@org.junit.Test
public void ThreeSumTest() {
test(new ThreeSumSlow());
}
+
@org.junit.Test
public void ThreeSumFastTest() {
test(new ThreeSumFast());
}
+
private void test(ThreeSum threeSum) {
Assert.assertEquals(threeSum.count(nums), expect);
}
+
}
\ No newline at end of file
diff --git a/ThreeSum/src/ThreeSumFast.java b/ThreeSum/src/ThreeSumFast.java
index 373de37..c0f85d9 100644
--- a/ThreeSum/src/ThreeSumFast.java
+++ b/ThreeSum/src/ThreeSumFast.java
@@ -1,19 +1,29 @@
import java.util.Arrays;
public class ThreeSumFast implements ThreeSum {
+
@Override
public int count(int[] nums) {
+
Arrays.sort(nums);
+
int N = nums.length;
int cnt = 0;
- for (int i = 0; i < N; i++)
+
+ for (int i = 0; i < N; i++) {
+
for (int j = i + 1; j < N; j++) {
+
int target = -nums[i] - nums[j];
int index = BinarySearch.search(nums, target);
+
// 应该注意这里的下标必须大于 j,否则会重复统计。
- if (index > j)
+ if (index > j) {
cnt++;
+ }
}
+ }
+
return cnt;
}
}
\ No newline at end of file
diff --git a/ThreeSum/src/ThreeSumSlow.java b/ThreeSum/src/ThreeSumSlow.java
index 9a0254b..080a167 100644
--- a/ThreeSum/src/ThreeSumSlow.java
+++ b/ThreeSum/src/ThreeSumSlow.java
@@ -3,11 +3,15 @@ public class ThreeSumSlow implements ThreeSum {
public int count(int[] nums) {
int N = nums.length;
int cnt = 0;
- for (int i = 0; i < N; i++)
- for (int j = i + 1; j < N; j++)
- for (int k = j + 1; k < N; k++)
- if (nums[i] + nums[j] + nums[k] == 0)
+ for (int i = 0; i < N; i++) {
+ for (int j = i + 1; j < N; j++) {
+ for (int k = j + 1; k < N; k++) {
+ if (nums[i] + nums[j] + nums[k] == 0) {
cnt++;
+ }
+ }
+ }
+ }
return cnt;
}
}
\ No newline at end of file
diff --git a/Union-Find/Union-Find.iml b/Union-Find/Union-Find.iml
deleted file mode 100644
index 3a8ffcf..0000000
--- a/Union-Find/Union-Find.iml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Union-Find/src/QuickFindUF.java b/Union-Find/src/QuickFindUF.java
index 08863d5..8c0072c 100644
--- a/Union-Find/src/QuickFindUF.java
+++ b/Union-Find/src/QuickFindUF.java
@@ -1,23 +1,30 @@
public class QuickFindUF extends UF {
+
public QuickFindUF(int N) {
super(N);
}
+
@Override
public int find(int p) {
return id[p];
}
+
@Override
public void union(int p, int q) {
+
int pID = find(p);
int qID = find(q);
- if (pID == qID)
+ if (pID == qID) {
return;
+ }
- for (int i = 0; i < id.length; i++)
- if (id[i] == pID)
+ for (int i = 0; i < id.length; i++) {
+ if (id[i] == pID) {
id[i] = qID;
+ }
+ }
}
}
diff --git a/Union-Find/src/QuickUnionUF.java b/Union-Find/src/QuickUnionUF.java
index 1b37500..dedce87 100644
--- a/Union-Find/src/QuickUnionUF.java
+++ b/Union-Find/src/QuickUnionUF.java
@@ -1,20 +1,28 @@
public class QuickUnionUF extends UF {
+
public QuickUnionUF(int N) {
super(N);
}
+
@Override
public int find(int p) {
- while (p != id[p])
+
+ while (p != id[p]) {
p = id[p];
+ }
return p;
}
+
@Override
public void union(int p, int q) {
+
int pRoot = find(p);
int qRoot = find(q);
- if (pRoot != qRoot)
+
+ if (pRoot != qRoot) {
id[pRoot] = qRoot;
+ }
}
}
diff --git a/Union-Find/src/Test.java b/Union-Find/src/Test.java
index e3a57b5..71e6351 100644
--- a/Union-Find/src/Test.java
+++ b/Union-Find/src/Test.java
@@ -4,27 +4,37 @@ public class Test {
private final int N = 10;
+
@org.junit.Test
public void QuickFindUFTest() {
test(new QuickFindUF(N));
}
+
@org.junit.Test
public void QuickUnionUFTest() {
test(new QuickUnionUF(N));
}
+
@org.junit.Test
public void WeightedQuickUnionUFTest() {
test(new WeightedQuickUnionUF(N));
}
+
private void test(UF uf) {
+
uf.union(0, 1);
+
Assert.assertTrue(uf.connected(0, 1));
Assert.assertFalse(uf.connected(0, 2));
+
uf.union(2, 3);
uf.union(1, 2);
+
Assert.assertTrue(uf.connected(0, 3));
+
}
+
}
diff --git a/Union-Find/src/UF.java b/Union-Find/src/UF.java
index b172ded..bc808e8 100644
--- a/Union-Find/src/UF.java
+++ b/Union-Find/src/UF.java
@@ -1,10 +1,12 @@
public abstract class UF {
+
protected int[] id;
public UF(int N) {
id = new int[N];
- for (int i = 0; i < N; i++)
+ for (int i = 0; i < N; i++) {
id[i] = i;
+ }
}
public boolean connected(int p, int q) {
diff --git a/Union-Find/src/WeightedQuickUnionUF.java b/Union-Find/src/WeightedQuickUnionUF.java
index b817dff..7686c60 100644
--- a/Union-Find/src/WeightedQuickUnionUF.java
+++ b/Union-Find/src/WeightedQuickUnionUF.java
@@ -3,25 +3,33 @@ public class WeightedQuickUnionUF extends UF {
// 保存节点的数量信息
private int[] sz;
+
public WeightedQuickUnionUF(int N) {
super(N);
this.sz = new int[N];
- for (int i = 0; i < N; i++)
+ for (int i = 0; i < N; i++) {
this.sz[i] = 1;
+ }
}
+
@Override
public int find(int p) {
- while (p != id[p])
+ while (p != id[p]) {
p = id[p];
+ }
return p;
}
+
@Override
public void union(int p, int q) {
+
int i = find(p);
int j = find(q);
+
if (i == j) return;
+
if (sz[i] < sz[j]) {
id[i] = j;
sz[j] += sz[i];
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..86387ba
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+ groupId
+ Algorithm
+ 1.0-SNAPSHOT
+
+
+
+ log4j
+ log4j
+ 1.2.17
+
+
+
+
\ No newline at end of file