├── .gitattributes ├── .gitignore ├── README.md ├── pom.xml └── src └── main └── java └── com └── appjishu ├── algorithm4j ├── backtrackingmethod │ └── EightQueen.java ├── binarysearchtree │ └── BSTree.java ├── binarytree │ ├── BinaryTreeTraversal.java │ └── Node.java ├── datastructure │ ├── LinearTable │ │ └── FibonacciSequence.java │ ├── MyHashMap.java │ ├── dijkstra │ │ ├── DijkstraTest.java │ │ ├── Graph.java │ │ └── Vertex.java │ ├── heap │ │ ├── HeapSort.java │ │ └── MaxHeap.java │ └── linkedlist │ │ ├── LinkedNode.java │ │ └── LinkedlistUtil.java ├── exam │ ├── FindKMax.java │ ├── FindKMaxOld.java │ ├── Jinchansushu.java │ ├── PerfectNumber.java │ └── SushuTest.java ├── search │ ├── BinarySearch.java │ └── FibonacciSearch.java └── sort │ ├── BubbleSort.java │ ├── BucketSort.java │ ├── InsertSort.java │ ├── MergeSort.java │ ├── QuickSort.java │ ├── QuickSortSimple.java │ ├── SelectionSort.java │ └── ShellSort.java └── test ├── FibonacciSearchTest.java └── QuickSortTest.java /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=java 2 | *.css linguist-language=java 3 | *.html linguist-language=java 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | /log/ 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | 20 | ### NetBeans ### 21 | /nbproject/private/ 22 | /build/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | 28 | bak.md 29 | /config/ 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #algorithm4j 2 | 3 | 用java实现的算法
4 | Algorithm implemented by Java 5 | 6 | http://appjishu.com 7 | 8 | package说明 9 | 10 | 1 com.appjishu.algorithm4j.datastructure 数据结构 11 | - heap 堆 12 | - LinearTable 线性表 13 | 14 | 15 | 2 com.appjishu.algorithm4j.sort 排序 16 | 17 | - BubbleSort 冒泡排序 18 | - InsertSort 插入排序 19 | - MegeSort 归并排序 20 | - QuickSort 快速排序 21 | - SelectionSort 选择排序 22 | - ShellSort 希尔排序 23 | 24 | 25 | 3 com.appjishu.algorithm4j.search 查找 26 | - BinarySearch 二分查找 27 | - FibonacciSearch 斐波那契查找 28 | 29 | 30 | 4 com.appjishu.algorithm4j.exam 算法题库 31 | 32 | - FindMax 寻找第K大的数 33 | - Jinchansushu 金蝉素数-找出所有的5位数的金蝉素数 34 | - PerfectNumber 1000以内的完数(完美数)完数 35 | - SushuTest 素数 36 | 37 | 38 |
39 |
40 |
41 |
42 | 43 | 44 | 45 | 后续不断完善中,算法是个长期的学习和复习过程 46 | 47 | 所有的排序算法的介绍,参考网友的文章 48 | 49 | 链接 50 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.appjishu 8 | algorithm4j 9 | 1.0-SNAPSHOT 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/backtrackingmethod/EightQueen.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.backtrackingmethod; 2 | 3 | /** 4 | * 回溯法解决八皇后问题 5 | * 一位数组实现,参考https://www.2cto.com/kf/201603/494773.html 6 | * 思路是按行来规定皇后,第一行放第一个皇后,第二行放第二个,然后通过遍历所有列,来判断下一个皇后能否放在该列。直到所有皇后都放完,或者放哪都不行。 7 | * 详细一点说,第一个皇后先放第一行第一列,然后第二个皇后放在第二行第一列、然后判断是否OK, 8 | * 然后第二列、第三列、依次把所有列都放完,找到一个合适,继续第三个皇后,还是第一列、第二列……直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解。 9 | * 然后回头继续第一个皇后放第二列,后面继续循环…… 10 | */ 11 | public class EightQueen { 12 | /** 13 | * 一共有多少个皇后(此时设置为8皇后在8X8棋盘,可以修改此值来设置N皇后问题) 14 | */ 15 | int max = 8; 16 | /** 17 | * 该数组保存结果,第一个皇后摆在array[0]列,第二个摆在array[1]列 18 | */ 19 | int[] array = new int[max]; 20 | 21 | public static void main(String[] args) { 22 | new EightQueen().check(0); 23 | } 24 | 25 | /** 26 | * n代表当前是第几个皇后 27 | * @param n 28 | * 皇后n在array[n]列 29 | */ 30 | private void check(int n) { 31 | //终止条件是最后一行已经摆完,由于每摆一步都会校验是否有冲突,所以只要最后一行摆完,说明已经得到了一个正确解 32 | if (n == max) { 33 | print(); 34 | return; 35 | } 36 | //从第一列开始放值,然后判断是否和本行本列本斜线有冲突,如果OK,就进入下一行的逻辑 37 | for (int i = 0; i < max; i++) { 38 | array[n] = i; 39 | if (judge(n)) { 40 | check(n + 1); 41 | } 42 | } 43 | } 44 | 45 | private boolean judge(int n) { 46 | for (int i = 0; i < n; i++) { 47 | if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[n] - array[i])) { 48 | return false; 49 | } 50 | } 51 | return true; 52 | } 53 | 54 | private void print() { 55 | for (int i = 0; i < array.length; i++) { 56 | System.out.print(array[i] + 1 + " "); 57 | } 58 | System.out.println(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/binarysearchtree/BSTree.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.binarysearchtree; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | public class BSTree> { 9 | 10 | private BSTNode mRoot; // 根结点 11 | 12 | public class BSTNode> { 13 | T key; // 关键字(键值) 14 | BSTNode left; // 左孩子 15 | BSTNode right; // 右孩子 16 | BSTNode parent; // 父结点 17 | 18 | public BSTNode(T key, BSTNode parent, BSTNode left, BSTNode right) { 19 | this.key = key; 20 | this.parent = parent; 21 | this.left = left; 22 | this.right = right; 23 | } 24 | } 25 | 26 | /* 27 | * 将结点插入到二叉树中 28 | * 29 | * 参数说明: 30 | * tree 二叉树的 31 | * z 插入的结点 32 | */ 33 | private void insert(BSTree bst, BSTNode z) { 34 | int cmp; 35 | BSTNode y = null; 36 | BSTNode x = bst.mRoot; 37 | 38 | // 查找z的插入位置 39 | while (x != null) { 40 | y = x; 41 | cmp = z.key.compareTo(x.key); 42 | if (cmp < 0) 43 | x = x.left; 44 | else 45 | x = x.right; 46 | } 47 | 48 | z.parent = y; 49 | if (y == null) 50 | bst.mRoot = z; 51 | else { 52 | cmp = z.key.compareTo(y.key); 53 | if (cmp < 0) 54 | y.left = z; 55 | else 56 | y.right = z; 57 | } 58 | } 59 | 60 | /* 61 | * 新建结点(key),并将其插入到二叉树中 62 | * 63 | * 参数说明: 64 | * tree 二叉树的根结点 65 | * key 插入结点的键值 66 | */ 67 | public void insert(T key) { 68 | BSTNode z = new BSTNode(key, null, null, null); 69 | 70 | // 如果新建结点失败,则返回。 71 | if (z != null) 72 | insert(this, z); 73 | } 74 | 75 | /* 76 | * 找结点(x)的前驱结点。即,查找"二叉树中数据值小于该结点"的"最大结点"。 77 | */ 78 | public BSTNode predecessor(BSTNode x) { 79 | // 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。 80 | if (x.left != null) 81 | return maximum(x.left); 82 | 83 | // 如果x没有左孩子。则x有以下两种可能: 84 | // (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。 85 | // (01) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。 86 | BSTNode y = x.parent; 87 | while ((y != null) && (x == y.left)) { 88 | x = y; 89 | y = y.parent; 90 | } 91 | 92 | return y; 93 | } 94 | 95 | /* 96 | * 找结点(x)的后继结点。即,查找"二叉树中数据值大于该结点"的"最小结点"。 97 | */ 98 | public BSTNode successor(BSTNode x) { 99 | // 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。 100 | if (x.right != null) 101 | return minimum(x.right); 102 | 103 | // 如果x没有右孩子。则x有以下两种可能: 104 | // (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。 105 | // (02) x是"一个右孩子",则查找"x的最低的父结点,并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。 106 | BSTNode y = x.parent; 107 | while ((y != null) && (x == y.right)) { 108 | x = y; 109 | y = y.parent; 110 | } 111 | 112 | return y; 113 | } 114 | 115 | /* 116 | * 查找最大结点:返回tree为根结点的二叉树的最大结点。 117 | */ 118 | private BSTNode maximum(BSTNode tree) { 119 | if (tree == null) 120 | return null; 121 | 122 | while (tree.right != null) 123 | tree = tree.right; 124 | return tree; 125 | } 126 | 127 | public T maximum() { 128 | BSTNode p = maximum(mRoot); 129 | if (p != null) 130 | return p.key; 131 | 132 | return null; 133 | } 134 | 135 | /* 136 | * 查找最小结点:返回tree为根结点的二叉树的最小结点。 137 | */ 138 | private BSTNode minimum(BSTNode tree) { 139 | if (tree == null) 140 | return null; 141 | 142 | while (tree.left != null) 143 | tree = tree.left; 144 | return tree; 145 | } 146 | 147 | public T minimum() { 148 | BSTNode p = minimum(mRoot); 149 | if (p != null) 150 | return p.key; 151 | 152 | return null; 153 | } 154 | 155 | /* 156 | * (递归实现)查找"二叉树x"中键值为key的节点 157 | */ 158 | private BSTNode search(BSTNode x, T key) { 159 | if (x == null) 160 | return x; 161 | 162 | int cmp = key.compareTo(x.key); 163 | if (cmp < 0) 164 | return search(x.left, key); 165 | else if (cmp > 0) 166 | return search(x.right, key); 167 | else 168 | return x; 169 | } 170 | 171 | public BSTNode search(T key) { 172 | return search(mRoot, key); 173 | } 174 | 175 | /* 176 | * (非递归实现)查找"二叉树x"中键值为key的节点 177 | */ 178 | private BSTNode iterativeSearch(BSTNode x, T key) { 179 | while (x != null) { 180 | int cmp = key.compareTo(x.key); 181 | 182 | if (cmp < 0) 183 | x = x.left; 184 | else if (cmp > 0) 185 | x = x.right; 186 | else 187 | return x; 188 | } 189 | 190 | return x; 191 | } 192 | 193 | public BSTNode iterativeSearch(T key) { 194 | return iterativeSearch(mRoot, key); 195 | } 196 | 197 | public static void main(String[] args){ 198 | List list = new ArrayList(); 199 | list.add(3); 200 | list.add(1); 201 | list.add(9); 202 | list.add(5); 203 | Collections.sort(list); 204 | 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/binarytree/BinaryTreeTraversal.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.binarytree; 2 | 3 | /** 4 | * 二叉树的先序遍历,中序遍历,后序遍历的递归实现 5 | * 对于左,根,右 6 | * 先序遍历: 根最先, 根->左->右 7 | * 中序遍历: 跟在中间, 左->根 -> 右 8 | * 后序遍历: 根在最后, 左->右->根 9 | */ 10 | public class BinaryTreeTraversal { 11 | /** 12 | * @author yaobo 13 | * 二叉树的先序中序后序排序 14 | */ 15 | public Node init() {//注意必须逆序建立,先建立子节点,再逆序往上建立,因为非叶子结点会使用到下面的节点,而初始化是按顺序初始化的,不逆序建立会报错 16 | Node J = new Node(8, null, null); 17 | Node H = new Node(4, null, null); 18 | Node G = new Node(2, null, null); 19 | Node F = new Node(7, null, J); 20 | Node E = new Node(5, H, null); 21 | Node D = new Node(1, null, G); 22 | Node C = new Node(9, F, null); 23 | Node B = new Node(3, D, E); 24 | Node A = new Node(6, B, C); 25 | return A; //返回根节点 26 | } 27 | 28 | public void printNode(Node node) { 29 | System.out.print(node.getData()); 30 | } 31 | 32 | public void thePreTraversal(Node root) { //先序遍历 33 | printNode(root); 34 | if (root.getLeftNode() != null) { //使用递归进行遍历左孩子 35 | thePreTraversal(root.getLeftNode()); 36 | } 37 | if (root.getRightNode() != null) { //递归遍历右孩子 38 | thePreTraversal(root.getRightNode()); 39 | } 40 | } 41 | 42 | public void theMidOrderTraversal(Node root) { //中序遍历 43 | if (root.getLeftNode() != null) { 44 | theMidOrderTraversal(root.getLeftNode()); 45 | } 46 | printNode(root); 47 | if (root.getRightNode() != null) { 48 | theMidOrderTraversal(root.getRightNode()); 49 | } 50 | } 51 | 52 | 53 | public void thePostOrderTraversal(Node root) { //后序遍历 54 | if (root.getLeftNode() != null) { 55 | thePostOrderTraversal(root.getLeftNode()); 56 | } 57 | if (root.getRightNode() != null) { 58 | thePostOrderTraversal(root.getRightNode()); 59 | } 60 | printNode(root); 61 | } 62 | 63 | public static void main(String[] args) { 64 | BinaryTreeTraversal tree = new BinaryTreeTraversal(); 65 | Node root = tree.init(); 66 | System.out.println("先序遍历"); 67 | tree.thePreTraversal(root); 68 | System.out.println(""); 69 | System.out.println("中序遍历"); 70 | tree.theMidOrderTraversal(root); 71 | System.out.println(""); 72 | System.out.println("后序遍历"); 73 | tree.thePostOrderTraversal(root); 74 | System.out.println(""); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/binarytree/Node.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.binarytree; 2 | 3 | /** 4 | * Referenced by 5 | */ 6 | public class Node { 7 | private int data; 8 | private Node leftNode; 9 | private Node rightNode; 10 | 11 | public Node(int data, Node leftNode, Node rightNode) { 12 | this.data = data; 13 | this.leftNode = leftNode; 14 | this.rightNode = rightNode; 15 | } 16 | 17 | public int getData() { 18 | return data; 19 | } 20 | 21 | public void setData(int data) { 22 | this.data = data; 23 | } 24 | 25 | public Node getLeftNode() { 26 | return leftNode; 27 | } 28 | 29 | public void setLeftNode(Node leftNode) { 30 | this.leftNode = leftNode; 31 | } 32 | 33 | public Node getRightNode() { 34 | return rightNode; 35 | } 36 | 37 | public void setRightNode(Node rightNode) { 38 | this.rightNode = rightNode; 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/datastructure/LinearTable/FibonacciSequence.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.datastructure.LinearTable; 2 | 3 | /** 4 | * https://www.jb51.net/article/45596.htm 5 | * 算法复杂度分析,参考网页文章 6 | * https://blog.csdn.net/a1456123a/article/details/48849923 7 | * https://bbs.pediy.com/thread-123051.htm 8 | */ 9 | public class FibonacciSequence { 10 | public static void main(String[] args) { 11 | // 0, 1, 1, 2, 3, 5, 8 12 | int result = f(6); 13 | System.out.println("f(6)=" + result); 14 | } 15 | 16 | private static int f(int n) { 17 | int result = -1; 18 | int temp1 = 0; 19 | int temp2 = 1; 20 | for (int index = 0; index <= n; index++) { 21 | if (index == 0) { 22 | result = temp1; 23 | } else if (index == 1) { 24 | result = temp2; 25 | } else { 26 | result = temp1 + temp2; 27 | if (result < 0) { 28 | result = -2; 29 | break; 30 | } 31 | temp1 = temp2; 32 | temp2 = result; 33 | } 34 | } 35 | 36 | return result; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/datastructure/MyHashMap.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.datastructure; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * 基于HashTable 哈希表简历的HashMap 7 | * Hash 拉链法解决哈希冲突 8 | * 源码参考了文章https://blog.csdn.net/null_xv/article/details/79753450 9 | *

10 | * 名词解释: 冲突解决技术可以分为两类:开散列方法( open hashing,也称为拉链法,separate chaining ) 11 | * 和闭散列方法( closed hashing,也称为开地址方法,open addressing )。 12 | * 这两种方法的不同之处在于:开散列法把发生冲突的关键码存储在散列表主表之外,而闭散列法把发生冲突的关键码存储在表中另一个槽内。 13 | * 这里的源码,是采用了拉链法Separate Chaining method 14 | */ 15 | public class MyHashMap { 16 | public static void main(String[] args) { 17 | MyHashMap map = new MyHashMap(); 18 | String key = "test-key"; 19 | map.put(key, "vvv1"); 20 | String value = (String) map.get(key); 21 | System.out.println("map.get()=" + value); 22 | } 23 | 24 | Node[] nodes; 25 | int intsize; 26 | 27 | private MyHashMap(int intsize) { 28 | this.intsize = intsize; 29 | nodes = new Node[intsize]; 30 | } 31 | 32 | /** 33 | * 初始化大小,需要优化 34 | */ 35 | public MyHashMap() { 36 | this(1024 * 1024); 37 | } 38 | 39 | public boolean isEmpty() { 40 | return intsize == 0; 41 | } 42 | 43 | public void put(Object key, Object value) { 44 | int h = hash(key); 45 | int index = (nodes.length - 1) & h; 46 | Node newNode = new Node(index, key, value); 47 | if (nodes[index] == null) { 48 | nodes[index] = newNode; 49 | } else { 50 | Node lastNode = nodes[index].getLastNode(); 51 | lastNode.setNext(newNode); 52 | } 53 | } 54 | 55 | public Object get(Object key) { 56 | int h = hash(key); 57 | int index = (nodes.length-1) & h; 58 | Node startNode = nodes[index]; 59 | if (startNode == null) { 60 | return null; 61 | } else if (startNode.getKey() == key) { 62 | return startNode.getValue(); 63 | } else { 64 | Node node = startNode.getNode(key); 65 | if (node == null) { 66 | return null; 67 | } 68 | return node.getValue(); 69 | } 70 | } 71 | 72 | /** 73 | * 计算hash值,即在数组中的索引,以后进行优化 74 | * 75 | * @param key 76 | * @return 77 | */ 78 | public static final int hash(Object key) { 79 | int h; 80 | return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 81 | } 82 | } 83 | 84 | class Node { 85 | Object key; 86 | Object value; 87 | int index; 88 | Node next; 89 | 90 | public Node(int index, Object key, Object value) { 91 | this.key = key; 92 | this.value = value; 93 | this.index = index; 94 | } 95 | 96 | public boolean isLast() { 97 | return this.next == null; 98 | } 99 | 100 | /** 101 | * 获取链表中与key相同的节点 102 | * 103 | * @param key 104 | * @return 105 | */ 106 | public Node getNode(Object key) { 107 | if (key == this.key) { 108 | return this; 109 | } 110 | if (next != null) { 111 | return next.getNode(key); 112 | } 113 | return null; 114 | } 115 | 116 | public Node getLastNode() { 117 | if (this.next == null) { 118 | return this; 119 | } 120 | return this.next.getLastNode(); 121 | } 122 | 123 | public Node getNext() { 124 | return next; 125 | } 126 | 127 | public void setNext(Node next) { 128 | this.next = next; 129 | } 130 | 131 | public Object getKey() { 132 | return key; 133 | } 134 | 135 | public Object getValue() { 136 | return value; 137 | } 138 | } -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/datastructure/dijkstra/DijkstraTest.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.datastructure.dijkstra; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Dijkstra算法是最短路径算法中为人熟知的一种,是单起点全路径算法。该算法被称为 8 | * 是“贪心算法”的成功典范。本文接下来将尝试以最通俗的语言来介绍这个伟大的算法, 9 | * 并赋予java实现代码。 10 | * 参考博客https://www.cnblogs.com/junyuhuang/p/4544747.html 11 | */ 12 | public class DijkstraTest { 13 | 14 | public static void main(String[] args){ 15 | List vertexs = new ArrayList(); 16 | Vertex a = new Vertex("A", 0); 17 | Vertex b = new Vertex("B"); 18 | Vertex c = new Vertex("C"); 19 | Vertex d = new Vertex("D"); 20 | Vertex e = new Vertex("E"); 21 | Vertex f = new Vertex("F"); 22 | vertexs.add(a); 23 | vertexs.add(b); 24 | vertexs.add(c); 25 | vertexs.add(d); 26 | vertexs.add(e); 27 | vertexs.add(f); 28 | int[][] edges = { 29 | {Integer.MAX_VALUE,6,3,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE}, 30 | {6,Integer.MAX_VALUE,2,5,Integer.MAX_VALUE,Integer.MAX_VALUE}, 31 | {3,2,Integer.MAX_VALUE,3,4,Integer.MAX_VALUE}, 32 | {Integer.MAX_VALUE,5,3,Integer.MAX_VALUE,5,3}, 33 | {Integer.MAX_VALUE,Integer.MAX_VALUE,4,5,Integer.MAX_VALUE,5}, 34 | {Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,3,5,Integer.MAX_VALUE} 35 | 36 | }; 37 | Graph graph = new Graph(vertexs, edges); 38 | graph.printGraph(); 39 | graph.search(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/datastructure/dijkstra/Graph.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.datastructure.dijkstra; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.PriorityQueue; 6 | import java.util.Queue; 7 | 8 | public class Graph { 9 | 10 | /* 11 | * 顶点 12 | */ 13 | private List vertexs; 14 | 15 | /* 16 | * 边 17 | */ 18 | private int[][] edges; 19 | 20 | /* 21 | * 没有访问的顶点 22 | */ 23 | private Queue unVisited; 24 | 25 | public Graph(List vertexs, int[][] edges) { 26 | this.vertexs = vertexs; 27 | this.edges = edges; 28 | initUnVisited(); 29 | } 30 | 31 | /* 32 | * 搜索各顶点最短路径 33 | */ 34 | public void search(){ 35 | while(!unVisited.isEmpty()){ 36 | Vertex vertex = unVisited.element(); 37 | //顶点已经计算出最短路径,设置为"已访问" 38 | vertex.setMarked(true); 39 | //获取所有"未访问"的邻居 40 | List neighbors = getNeighbors(vertex); 41 | //更新邻居的最短路径 42 | updatesDistance(vertex, neighbors); 43 | pop(); 44 | } 45 | System.out.println("search over"); 46 | } 47 | 48 | /* 49 | * 更新所有邻居的最短路径 50 | */ 51 | private void updatesDistance(Vertex vertex, List neighbors){ 52 | for(Vertex neighbor: neighbors){ 53 | updateDistance(vertex, neighbor); 54 | } 55 | } 56 | 57 | /* 58 | * 更新邻居的最短路径 59 | */ 60 | private void updateDistance(Vertex vertex, Vertex neighbor){ 61 | int distance = getDistance(vertex, neighbor) + vertex.getPath(); 62 | if(distance < neighbor.getPath()){ 63 | neighbor.setPath(distance); 64 | } 65 | } 66 | 67 | /* 68 | * 初始化未访问顶点集合 69 | */ 70 | private void initUnVisited() { 71 | unVisited = new PriorityQueue(); 72 | for (Vertex v : vertexs) { 73 | unVisited.add(v); 74 | } 75 | } 76 | 77 | /* 78 | * 从未访问顶点集合中删除已找到最短路径的节点 79 | */ 80 | private void pop() { 81 | unVisited.poll(); 82 | } 83 | 84 | /* 85 | * 获取顶点到目标顶点的距离 86 | */ 87 | private int getDistance(Vertex source, Vertex destination) { 88 | int sourceIndex = vertexs.indexOf(source); 89 | int destIndex = vertexs.indexOf(destination); 90 | return edges[sourceIndex][destIndex]; 91 | } 92 | 93 | /* 94 | * 获取顶点所有(未访问的)邻居 95 | */ 96 | private List getNeighbors(Vertex v) { 97 | List neighbors = new ArrayList(); 98 | int position = vertexs.indexOf(v); 99 | Vertex neighbor = null; 100 | int distance; 101 | for (int i = 0; i < vertexs.size(); i++) { 102 | if (i == position) { 103 | //顶点本身,跳过 104 | continue; 105 | } 106 | distance = edges[position][i]; //到所有顶点的距离 107 | if (distance < Integer.MAX_VALUE) { 108 | //是邻居(有路径可达) 109 | neighbor = getVertex(i); 110 | if (!neighbor.isMarked()) { 111 | //如果邻居没有访问过,则加入list; 112 | neighbors.add(neighbor); 113 | } 114 | } 115 | } 116 | return neighbors; 117 | } 118 | 119 | /* 120 | * 根据顶点位置获取顶点 121 | */ 122 | private Vertex getVertex(int index) { 123 | return vertexs.get(index); 124 | } 125 | 126 | /* 127 | * 打印图 128 | */ 129 | public void printGraph() { 130 | int verNums = vertexs.size(); 131 | for (int row = 0; row < verNums; row++) { 132 | for (int col = 0; col < verNums; col++) { 133 | if(Integer.MAX_VALUE == edges[row][col]){ 134 | System.out.print("X"); 135 | System.out.print(" "); 136 | continue; 137 | } 138 | System.out.print(edges[row][col]); 139 | System.out.print(" "); 140 | } 141 | System.out.println(); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/datastructure/dijkstra/Vertex.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.datastructure.dijkstra; 2 | 3 | public class Vertex implements Comparable{ 4 | 5 | /** 6 | * 节点名称(A,B,C,D) 7 | */ 8 | private String name; 9 | 10 | /** 11 | * 最短路径长度 12 | */ 13 | private int path; 14 | 15 | /** 16 | * 节点是否已经出列(是否已经处理完毕) 17 | */ 18 | private boolean isMarked; 19 | 20 | public Vertex(String name){ 21 | this.name = name; 22 | this.path = Integer.MAX_VALUE; //初始设置为无穷大 23 | this.setMarked(false); 24 | } 25 | 26 | public Vertex(String name, int path){ 27 | this.name = name; 28 | this.path = path; 29 | this.setMarked(false); 30 | } 31 | 32 | @Override 33 | public int compareTo(Vertex o) { 34 | return o.path > path?-1:1; 35 | } 36 | 37 | public boolean isMarked() { 38 | return isMarked; 39 | } 40 | 41 | public void setMarked(boolean marked) { 42 | isMarked = marked; 43 | } 44 | 45 | public String getName() { 46 | return name; 47 | } 48 | 49 | public void setName(String name) { 50 | this.name = name; 51 | } 52 | 53 | public int getPath() { 54 | return path; 55 | } 56 | 57 | public void setPath(int path) { 58 | this.path = path; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/datastructure/heap/HeapSort.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.datastructure.heap; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by on 2016/12/17. 7 | * 参考其它人的博客https://www.cnblogs.com/chengxiao/p/6129630.html 8 | * 堆排序demo 9 | */ 10 | public class HeapSort { 11 | public static void main(String []args){ 12 | int []arr = {9,8,7,6,5,4,3,2,1}; 13 | sort(arr); 14 | System.out.println(Arrays.toString(arr)); 15 | } 16 | public static void sort(int []arr){ 17 | //1.构建大顶堆 18 | for(int i=arr.length/2-1;i>=0;i--){ 19 | //从第一个非叶子结点从下至上,从右至左调整结构 20 | adjustHeap(arr,i,arr.length); 21 | } 22 | //2.调整堆结构+交换堆顶元素与末尾元素 23 | for(int j=arr.length-1;j>0;j--){ 24 | swap(arr,0,j);//将堆顶元素与末尾元素进行交换 25 | adjustHeap(arr,0,j);//重新对堆进行调整 26 | } 27 | 28 | } 29 | 30 | /** 31 | * 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上) 32 | * @param arr 33 | * @param i 34 | * @param length 35 | */ 36 | public static void adjustHeap(int []arr,int i,int length){ 37 | int temp = arr[i];//先取出当前元素i 38 | for(int k=i*2+1;ktemp){//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换) 43 | arr[i] = arr[k]; 44 | i = k; 45 | }else{ 46 | break; 47 | } 48 | } 49 | arr[i] = temp;//将temp值放到最终的位置 50 | } 51 | 52 | /** 53 | * 交换元素 54 | * @param arr 55 | * @param a 56 | * @param b 57 | */ 58 | public static void swap(int []arr,int a ,int b){ 59 | int temp=arr[a]; 60 | arr[a] = arr[b]; 61 | arr[b] = temp; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/datastructure/heap/MaxHeap.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.datastructure.heap; 2 | 3 | /** 4 | * 二叉堆(最大堆) 5 | * 6 | * @author skywang 7 | * @date 2014/03/07 8 | */ 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public class MaxHeap> { 14 | 15 | private List mHeap; // 队列(实际上是动态数组ArrayList的实例) 16 | 17 | public MaxHeap() { 18 | this.mHeap = new ArrayList(); 19 | } 20 | 21 | /* 22 | * 最大堆的向下调整算法 23 | * 24 | * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。 25 | * 26 | * 参数说明: 27 | * start -- 被下调节点的起始位置(一般为0,表示从第1个开始) 28 | * end -- 截至范围(一般为数组中最后一个元素的索引) 29 | */ 30 | protected void filterdown(int start, int end) { 31 | int c = start; // 当前(current)节点的位置 32 | int l = 2*c + 1; // 左(left)孩子的位置 33 | T tmp = mHeap.get(c); // 当前(current)节点的大小 34 | 35 | while(l <= end) { 36 | int cmp = mHeap.get(l).compareTo(mHeap.get(l+1)); 37 | // "l"是左孩子,"l+1"是右孩子 38 | if(l < end && cmp<0) 39 | l++; // 左右两孩子中选择较大者,即mHeap[l+1] 40 | cmp = tmp.compareTo(mHeap.get(l)); 41 | if(cmp >= 0) 42 | break; //调整结束 43 | else { 44 | mHeap.set(c, mHeap.get(l)); 45 | c = l; 46 | l = 2*l + 1; 47 | } 48 | } 49 | mHeap.set(c, tmp); 50 | } 51 | 52 | /* 53 | * 删除最大堆中的data 54 | * 55 | * 返回值: 56 | * 0,成功 57 | * -1,失败 58 | */ 59 | public int remove(T data) { 60 | // 如果"堆"已空,则返回-1 61 | if(mHeap.isEmpty() == true) 62 | return -1; 63 | 64 | // 获取data在数组中的索引 65 | int index = mHeap.indexOf(data); 66 | if (index==-1) 67 | return -1; 68 | 69 | int size = mHeap.size(); 70 | mHeap.set(index, mHeap.get(size-1));// 用最后元素填补 71 | mHeap.remove(size - 1); // 删除最后的元素 72 | 73 | if (mHeap.size() > 1) 74 | filterdown(index, mHeap.size()-1); // 从index号位置开始自上向下调整为最小堆 75 | 76 | return 0; 77 | } 78 | 79 | /* 80 | * 最大堆的向上调整算法(从start开始向上直到0,调整堆) 81 | * 82 | * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。 83 | * 84 | * 参数说明: 85 | * start -- 被上调节点的起始位置(一般为数组中最后一个元素的索引) 86 | */ 87 | protected void filterup(int start) { 88 | int c = start; // 当前节点(current)的位置 89 | int p = (c-1)/2; // 父(parent)结点的位置 90 | T tmp = mHeap.get(c); // 当前节点(current)的大小 91 | 92 | while(c > 0) { 93 | int cmp = mHeap.get(p).compareTo(tmp); 94 | if(cmp >= 0) 95 | break; 96 | else { 97 | mHeap.set(c, mHeap.get(p)); 98 | c = p; 99 | p = (p-1)/2; 100 | } 101 | } 102 | mHeap.set(c, tmp); 103 | } 104 | 105 | /* 106 | * 将data插入到二叉堆中 107 | */ 108 | public void insert(T data) { 109 | int size = mHeap.size(); 110 | 111 | mHeap.add(data); // 将"数组"插在表尾 112 | filterup(size); // 向上调整堆 113 | } 114 | 115 | @Override 116 | public String toString() { 117 | StringBuilder sb = new StringBuilder(); 118 | for (int i=0; i tree=new MaxHeap(); 128 | 129 | System.out.printf("== 依次添加: "); 130 | for(i=0; i arr[high] || low > high) { 15 | return -1; 16 | } 17 | 18 | int middle = (low + high) / 2; //初始中间位置 19 | if (arr[middle] > key) { 20 | //比关键字大则关键字在左区域 21 | return recursionBinarySearch(arr, key, low, middle - 1); 22 | } else if (arr[middle] < key) { 23 | //比关键字小则关键字在右区域 24 | return recursionBinarySearch(arr, key, middle + 1, high); 25 | } else { 26 | return middle; 27 | } 28 | 29 | } 30 | 31 | /** 32 | * 不使用递归的二分查找 33 | * title:commonBinarySearch 34 | * 35 | * @param arr 36 | * @param key 37 | * @return 关键字位置 38 | */ 39 | public static int commonBinarySearch(int[] arr, int key) { 40 | int low = 0; 41 | int high = arr.length - 1; 42 | int middle = 0; //定义middle 43 | 44 | if (key < arr[low] || key > arr[high] || low > high) { 45 | return -1; 46 | } 47 | 48 | while (low <= high) { 49 | middle = (low + high) / 2; 50 | if (arr[middle] > key) { 51 | //比关键字大则关键字在左区域 52 | high = middle - 1; 53 | } else if (arr[middle] < key) { 54 | //比关键字小则关键字在右区域 55 | low = middle + 1; 56 | } else { 57 | return middle; 58 | } 59 | } 60 | 61 | return -1; //最后仍然没有找到,则返回-1 62 | } 63 | 64 | 65 | public static void main(String[] args) { 66 | 67 | int[] arr = {1, 3, 5, 7, 9, 11}; 68 | int key = 5; 69 | // int position = recursionBinarySearch(arr,key,0,arr.length - 1); 70 | 71 | int position = commonBinarySearch(arr, key); 72 | 73 | if (position == -1) { 74 | System.out.println("查找的是" + key + ",序列中没有该数!"); 75 | } else { 76 | System.out.println("查找的是" + key + ",找到位置为:" + position); 77 | } 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/search/FibonacciSearch.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.search; 2 | 3 | import java.util.Arrays; 4 | 5 | /* 6 | *----- 斐波那契查找------ 7 | * 1.斐波那契实在二分查找基础上,用斐波那契数列来进行分割 8 | * 2.在斐波那契数列上找一个略大于查找元素表个数的值f(n) 9 | * 3.将查找元素表个数扩充到f(n) 如果要补充元素用最后一个元素补充 10 | * 4.完成后对f(n)个元素进行斐波那契分割,即分割成 前面f(n-1)个元素,后面f(n-2)个元素 11 | * 5.对要查找元素的那个部分进行递归 12 | * 6.就平均性能而言 优于折半查找 但是若一直在左边长半区查找则低于折半查找 13 | * 14 | * 参考文章https://blog.csdn.net/qq_41056506/article/details/81874439 15 | * 16 | * 避免递归(子函数嵌套多,导致栈溢出, 改成用迭代-for循环 17 | * 采用https://www.jb51.net/article/45596.htm 18 | * 里面的方法三 19 | * */ 20 | public class FibonacciSearch { 21 | private static int maxsize = 20; 22 | 23 | //生成斐波那契数列 24 | public static int[] fibonacci() { 25 | int[] f = new int[maxsize]; 26 | f[0] = 1; 27 | f[1] = 1; 28 | for (int i = 2; i < maxsize; i++) { 29 | f[i] = f[i - 1] + f[i - 2]; 30 | } 31 | return f; 32 | } 33 | 34 | //查找 35 | public static int search(int[] a, int key) { 36 | int low = 0; 37 | int high = a.length - 1; 38 | int k = 0; //斐波那契分割数值下标 39 | int mid = 0; 40 | int f[] = fibonacci(); //获得斐波那契数列 41 | //获得斐波那契分割数值下标 42 | while (high > f[k] - 1) { 43 | k++; 44 | } 45 | 46 | //利用Java工具类Arrays 构造新数组并指向 数组 a[] 47 | int[] temp = Arrays.copyOf(a, f[k]); 48 | 49 | //对新构造的数组进行 元素补充 50 | for (int i = high + 1; i < temp.length; i++) { 51 | temp[i] = a[high]; 52 | } 53 | 54 | while (low <= high) { 55 | //由于前面部分有f[k-1]个元素 56 | mid = low + f[k - 1] - 1; 57 | if (key < temp[mid]) {//关键字小于切割位置元素 继续在前部分查找 58 | high = mid - 1; 59 | /*全部元素=前部元素+后部元素 60 | * f[k]=f[k-1]+f[k-2] 61 | * 因为前部有f[k-1]个元素,所以可以继续拆分f[k-1]=f[k-2]+f[k-3] 62 | * 即在f[k-1]的前部继续查找 所以k-- 63 | * 即下次循环 mid=f[k-1-1]-1 64 | * */ 65 | k--; 66 | } else if (key > temp[mid]) {//关键字大于切个位置元素 则查找后半部分 67 | low = mid + 1; 68 | /*全部元素=前部元素+后部元素 69 | * f[k]=f[k-1]+f[k-2] 70 | * 因为后部有f[k-2]个元素,所以可以继续拆分f[k-2]=f[k-3]+f[k-4] 71 | * 即在f[k-2]的前部继续查找 所以k-=2 72 | * 即下次循环 mid=f[k-1-2]-1 73 | * */ 74 | k -= 2; 75 | } else { 76 | if (mid <= high) { 77 | return mid; 78 | } else { 79 | return high; 80 | } 81 | } 82 | } 83 | return -1; 84 | } 85 | 86 | public static void main(String[] args) { 87 | int[] a = {1, 3, 5, 7, 9, 11, 12}; 88 | int i = search(a, 5); 89 | System.out.println("5在:" + (i + 1)); 90 | int j = search(a, 12); 91 | System.out.println("12在:" + (j + 1)); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/sort/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.sort; 2 | 3 | public class BubbleSort { 4 | public static void main(String[] args) { 5 | int source[] = new int[]{53, 27, 36, 15, 69, 42}; 6 | System.out.print("初始关键字:"); 7 | printArray(source); 8 | System.out.println(""); 9 | doBubbleSort(source); 10 | System.out.print("\n\n排序后结果:"); 11 | printArray(source); 12 | } 13 | 14 | private static void printArray(int[] source) { 15 | for (int i = 0; i < source.length; i++) { 16 | System.out.print("\t" + source[i]); 17 | } 18 | System.out.println(); 19 | } 20 | 21 | private static void doBubbleSort(int[] source) { 22 | for (int i = 0; i < source.length; i++) { 23 | for (int j = 0; j < source.length - i - 1; j++) { 24 | if (source[j] > source[j + 1]) { 25 | int tmp = source[j]; 26 | source[j] = source[j + 1]; 27 | source[j + 1] = tmp; 28 | } 29 | } 30 | 31 | if (i < source.length - 1) { 32 | System.out.print("第" + (i + 1) + "趟排序:"); 33 | printArray(source); 34 | } 35 | } 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/sort/BucketSort.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.sort; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * 桶排序 7 | * 桶排序假设输入元素均匀而独立的分布在区间[0,1)上; 8 | * 桶排序的核心思想是,将[0,1)分为n个大小相同的子区间, 9 | * 上一个区间里的元素都比下一个区间里的元素小,然后对 10 | * 所有区间里的元素排序,最后顺序输出所有区间里的元素, 11 | * 达到对所有元素排序的目的。 12 | * 13 | * @author liushaoming 14 | */ 15 | public class BucketSort { 16 | public void sort(Double[] a) { 17 | int n = a.length; 18 | 19 | /** 20 | * 创建链表(桶)集合并初始化,集合中的链表用于存放相应的元素 21 | */ 22 | int bucketNum = 10; // 桶数 23 | LinkedList> buckets = new LinkedList>(); 24 | for (int i = 0; i < bucketNum; i++) { 25 | LinkedList bucket = new LinkedList(); 26 | buckets.add(bucket); 27 | } 28 | // 把元素放进相应的桶中 29 | for (int i = 0; i < n; i++) { 30 | int index = (int) (a[i] * bucketNum); 31 | buckets.get(index).add(a[i]); 32 | } 33 | // 对每个桶中的元素排序,并放进a中 34 | int index = 0; 35 | for (LinkedList linkedList : buckets) { 36 | int size = linkedList.size(); 37 | if (size == 0) { 38 | continue; 39 | } 40 | /** 41 | * 把LinkedList转化为Double[]的原因是,之前已经实现了 42 | * 对数组进行排序的算法 43 | */ 44 | Double[] temp = new Double[size]; 45 | for (int i = 0; i < temp.length; i++) { 46 | temp[i] = linkedList.get(i); 47 | } 48 | // 利用插入排序对temp排序 49 | // TODO 这里忽略掉插入排序, 使用任何一种比较排序的实现都可以 50 | // new InsertSort().sort(temp); 51 | for (int i = 0; i < temp.length; i++) { 52 | a[index] = temp[i]; 53 | index++; 54 | } 55 | } 56 | 57 | } 58 | 59 | public static void main(String[] args) { 60 | Double[] a = new Double[]{0.3, 0.6, 0.5}; 61 | new BucketSort().sort(a); 62 | for (int i = 0; i < a.length; i++) { 63 | System.out.println(a[i]); 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/sort/InsertSort.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.sort; 2 | 3 | /** 4 | * 插入排序 5 | * 所谓插入排序法,就是检查第i个数字,如果在它的左边的数字比它大,进行交换,这个动作一直继续下去,直到这个数字的左边数字比它还要小,就可以停止了。插入排序法主要的回圈有两个变数:i和j,每一次执行这个回圈,就会将第i个数字放到左边恰当的位置去。 6 | * 二、算法描述 7 | *

8 | * 1、从第一个元素开始,该元素可以认为已经被排序。 9 | * 2、取出下一个元素,在已经排序的元素序列中从后向前扫描。 10 | * 3、如果该元素(已排序)大于新元素,则将该元素移到下一位置。 11 | * 4、重复步骤3,直到找到已排序的元素小于或者等于新元素的位置。 12 | * 5、将新元素插入到该位置。 13 | * 6、重复步骤2。 14 | *

15 | * 三、效率分析 16 | *

17 | * 如果目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况如下。 18 | * 最好情况:序列已经是升序排列了,在这种情况下,需要进行的比较操作需(n-1)次即可。 19 | * 最坏情况:序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。 20 | * 直接插入排序属于稳定的排序,最坏时间复杂度为O(n^2),最好时间复杂度为O(n),空间复杂度为O(1)。 21 | * 插入排序的赋值操作是比较操作的次数加上(n-1)次。 22 | * 因此,插入排序不适合对于数据量比较大的排序应用。 23 | */ 24 | public class InsertSort { 25 | public static void doInsertSort(int[] source) { 26 | int i, j; 27 | int insertNode;// 要插入的数据 28 | // 从数组的第二个元素开始循环将数组中的元素插入 29 | for (i = 1; i < source.length; i++) { 30 | // 设置数组中的第2个元素为第一次循环要插入的数据 31 | insertNode = source[i]; 32 | j = i - 1; 33 | // 如果要插入的元素小于第j个元素,就将第j个元素向后移 34 | while ((j >= 0) && insertNode < source[j]) { 35 | source[j + 1] = source[j]; 36 | j--; 37 | } 38 | // 直到要插入的元素不小于第j个元素,将insertNote插入到数组中 39 | source[j + 1] = insertNode; 40 | System.out.print("第" + i + "趟排序:"); 41 | printArray(source); 42 | } 43 | } 44 | 45 | private static void printArray(int[] source) { 46 | for (int i = 0; i < source.length; i++) { 47 | System.out.print("\t" + source[i]); 48 | } 49 | System.out.println(); 50 | } 51 | 52 | public static void main(String[] args) { 53 | int source[] = new int[]{53, 27, 36, 15, 69, 42}; 54 | System.out.print("初始关键字:"); 55 | printArray(source); 56 | System.out.println(""); 57 | doInsertSort(source); 58 | 59 | System.out.print("\n\n排序后结果:"); 60 | printArray(source); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/sort/MergeSort.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.sort; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 归并排序-包括二路归并排序和多路归并排序,这里实现的是二路归并排序 7 | * 归并排序采用了分治法策略 8 | * 参考文档 https://www.cnblogs.com/chengxiao/p/6194356.html 9 | */ 10 | public class MergeSort { 11 | public static void main(String[] args) { 12 | int[] arr = {9, 8, 7, 6, 5, 4, 3, 2, 1}; 13 | sort(arr); 14 | System.out.println(Arrays.toString(arr)); 15 | } 16 | 17 | public static void sort(int[] arr) { 18 | int[] temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间 19 | sort(arr, 0, arr.length - 1, temp); 20 | } 21 | 22 | private static void sort(int[] arr, int left, int right, int[] temp) { 23 | if (left < right) { 24 | int mid = (left + right) / 2; 25 | sort(arr, left, mid, temp);//左边归并排序,使得左子序列有序 26 | sort(arr, mid + 1, right, temp);//右边归并排序,使得右子序列有序 27 | merge(arr, left, mid, right, temp);//将两个有序子数组合并操作 28 | } 29 | } 30 | 31 | private static void merge(int[] arr, int left, int mid, int right, int[] temp) { 32 | int i = left;//左序列指针 33 | int j = mid + 1;//右序列指针 34 | int t = 0;//临时数组指针 35 | while (i <= mid && j <= right) { 36 | if (arr[i] <= arr[j]) { // 这里判断条件带上arr[i]==arr[j]是为了保证排序的稳定性(关键字相等的情况下,原来 37 | // 在左边的元素,排序后仍然在左边 38 | temp[t++] = arr[i++]; 39 | } else { 40 | temp[t++] = arr[j++]; 41 | } 42 | } 43 | while (i <= mid) {//将左边剩余元素填充进temp中 44 | temp[t++] = arr[i++]; 45 | } 46 | while (j <= right) {//将右序列剩余元素填充进temp中 47 | temp[t++] = arr[j++]; 48 | } 49 | t = 0; 50 | //将temp中的元素全部拷贝到原数组中 51 | while (left <= right) { 52 | arr[left++] = temp[t++]; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/sort/QuickSort.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.sort; 2 | 3 | /** 4 | * 快速排序,顾名思义,是一种速度快,效率高的排序算法。 5 | * 快排原理: 6 | *         在要排的数(比如数组A)中选择一个中心值key(比如A[0]),通过一趟排序将数组A分成两部分,其中以key为中心,key右边都比key大,key左边的都key小,然后对这两部分分别重复这个过程,直到整个有序。 7 | *         整个快排的过程就简化为了一趟排序的过程,然后递归调用就行了。 8 | *         一趟排序的方法: 9 | * 1,定义i=0,j=A.lenght-1,i为第一个数的下标,j为最后一个数下标 10 | * 2,从数组的最后一个数Aj从右往左找,找到第一小于key的数,记为Aj; 11 | * 3,从数组的第一个数Ai 从左往右找,找到第一个大于key的数,记为Ai; 12 | * 4,交换Ai 和Aj  13 | * 5,重复这个过程,直到 i=j 14 | * 6,调整key的位置,把A[i] 和key交换 15 | * 假设要排的数组为:A[8] ={ 5 2 8 9 2 3 4 9 } 16 | *            选择 key = 5, 开始时 i=0,j=7 17 | *   index       0    1    2    3    4    5    6    7 18 | * 19 | * 开始:       5    2    8    9    2    3    4    9 20 | *                   i                                         j   21 | * 第一次找    5    2    8    9    2    3    4    9 22 | *                               i                       j 23 | * 交换:       5    2    4    9    2    3    8    9  24 | *                               i                       j 25 | * 第二次找    5    2    4    9    2    3    8    9 26 | *                                     i           j 27 | * 交换:       5    2    4    3    2    9    8    9 28 | *                                     i            j 29 | * 第三次找     5    2    4    3    2    9    8    9 30 | *                                           ij    31 | * 调整key:  2    5    4    3    5    9    8    9 32 | *                                            ij 33 | * --------------------- 34 | * 作者:Yexiaofen 35 | * 来源:CSDN 36 | * 原文:https://blog.csdn.net/Yexiaofen/article/details/78018204 37 | * 版权声明:本文为博主原创文章,转载请附上博文链接! 38 | */ 39 | public class QuickSort { 40 | 41 | public static void main(String[] args) { 42 | System.out.println("Hello World"); 43 | int[] a = {12, 20, 5, 16, 15, 1, 30, 45, 23, 9}; 44 | int start = 0; 45 | int end = a.length - 1; 46 | sort(a, start, end); 47 | for (int i = 0; i < a.length; i++) { 48 | System.out.println(a[i]); 49 | } 50 | } 51 | 52 | public static void sort(int[] a, int low, int high) { 53 | int start = low; 54 | int end = high; 55 | int key = a[low]; 56 | 57 | while (end > start) { 58 | //从后往前比较 59 | while (end > start && a[end] >= key) //如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较 60 | end--; 61 | if (a[end] <= key) { 62 | int temp = a[end]; 63 | a[end] = a[start]; 64 | a[start] = temp; 65 | } 66 | //从前往后比较 67 | while (end > start && a[start] <= key)//如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置 68 | start++; 69 | if (a[start] >= key) { 70 | int temp = a[start]; 71 | a[start] = a[end]; 72 | a[end] = temp; 73 | } 74 | //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用 75 | } 76 | 77 | //递归 78 | if (start > low) sort(a, low, start - 1);//左边序列。第一个索引位置到关键值索引-1 79 | if (end < high) sort(a, end + 1, high);//右边序列。从关键值索引+1到最后一个 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/sort/QuickSortSimple.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.sort; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 快速排序,java的最简单实现 7 | * https://blog.csdn.net/Yexiaofen/article/details/78018204 8 | */ 9 | public class QuickSortSimple { 10 | 11 | public static void main(String[] args) { 12 | int[] a = {12, 20, 5, 16, 15, 1, 30, 45, 23, 9}; 13 | System.out.println(Arrays.toString(a)); 14 | int start = 0; 15 | int end = a.length - 1; 16 | System.out.println("Start to sort..."); 17 | sort(a, start, end); 18 | System.out.println(Arrays.toString(a)); 19 | } 20 | 21 | private static void sort(int[] a, int low, int high) { 22 | //1,找到递归算法的出口 23 | if (low > high) { 24 | return; 25 | } 26 | 27 | //2, 初始化变量 28 | int i = low; 29 | int j = high; 30 | // 3. 保存key值 31 | int key = a[low]; 32 | 33 | //4,完成一趟排序 34 | while (i < j) { 35 | //4.1 ,从右往左找到第一个小于key的数 36 | while (i < j && a[j] >= key) { 37 | j--; 38 | } 39 | // 4.2 从左往右找到第一个大于key的数 40 | while (i < j && a[i] <= key) { 41 | i++; 42 | } 43 | 44 | //4.3 交换 45 | if (i < j) { 46 | int temp = a[i]; 47 | a[i] = a[j]; 48 | a[j] = temp; 49 | } 50 | } 51 | 52 | // 4.4,调整key的位置, 把a[i]与a[low](等于key)交换值 53 | int temp = a[i]; 54 | a[i] = a[low]; 55 | a[low] = temp; 56 | 57 | //5, 对key左边的数快排 58 | sort(a, low, i - 1); 59 | //5, 对key左边的数快排 60 | sort(a, i + 1, high); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/sort/SelectionSort.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.sort; 2 | 3 | /** 4 | * 选择排序 5 | * a) 原理:每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕。也就是: 6 | * 每一趟在n-i+1(i=1,2,…n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。 7 | * 基于此思想的算法主要有简单选择排序、树型选择排序和堆排序。(这里只介绍常用的简单选择排序) 8 | * 堆排序参考 {@link com.appjishu.algorithm4j.datastructure.heap.HeapSort } 9 | *

10 | * b) 简单选择排序的基本思想:给定数组: 11 | * int[] arr={里面n个数据};第1趟排序,在待排序数据arr[1]~arr[n]中选出最小的数据, 12 | * 将它与arrr[1]交换;第2趟,在待排序数据arr[2]~arr[n]中选出最小的数据,将它与r[2]交换; 13 | * 以此类推,第i趟在待排序数据arr[i]~arr[n]中选出最小的数据,将它与r[i]交换,直到全部排序完成。 14 | */ 15 | public class SelectionSort { 16 | public static void main(String[] args) { 17 | int[] arr = {1, 3, 2, 45, 65, 33, 12}; 18 | System.out.println("交换之前:"); 19 | for (int num : arr) { 20 | System.out.print(num + " "); 21 | } 22 | //选择排序的优化 23 | for (int i = 0; i < arr.length - 1; i++) {// 做第i趟排序 24 | int k = i; 25 | for (int j = k + 1; j < arr.length; j++) {// 选最小的记录 26 | if (arr[j] < arr[k]) { 27 | k = j; //记下目前找到的最小值所在的位置 28 | } 29 | } 30 | //在内层循环结束,也就是找到本轮循环的最小的数以后,再进行交换 31 | if (i != k) { //交换a[i]和a[k] 32 | int temp = arr[i]; 33 | arr[i] = arr[k]; 34 | arr[k] = temp; 35 | } 36 | } 37 | System.out.println(); 38 | System.out.println("交换后:"); 39 | for (int num : arr) { 40 | System.out.print(num + " "); 41 | } 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /src/main/java/com/appjishu/algorithm4j/sort/ShellSort.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.algorithm4j.sort; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 希尔排序-插入排序的一种 7 | * 参考了大神的文档https://www.cnblogs.com/chengxiao/p/6104371.html 8 | */ 9 | public class ShellSort { 10 | public static void main(String []args){ 11 | int []arr ={1,4,2,7,9,8,3,6}; 12 | sort(arr); 13 | System.out.println(Arrays.toString(arr)); 14 | 15 | // int []arr1 ={1,4,2,7,9,8,3,6}; 16 | // sort1(arr1); 17 | // System.out.println(Arrays.toString(arr1)); 18 | } 19 | 20 | /** 21 | * 希尔排序 针对有序序列在插入时采用交换法 22 | * @param arr 23 | */ 24 | public static void sort(int []arr){ 25 | //增量gap,并逐步缩小增量 26 | for(int gap=arr.length/2;gap>0;gap/=2){ 27 | //从第gap个元素,逐个对其所在组进行直接插入排序操作 28 | for(int i=gap;i=0 && arr[j]0;gap/=2){ 46 | //从第gap个元素,逐个对其所在组进行直接插入排序操作 47 | for(int i=gap;i=0 && temp f[k] - 1) { 24 | k++; 25 | } 26 | 27 | int[] temp = Arrays.copyOf(a, f[k]); 28 | 29 | //填充 30 | for (int j = high+1; j < temp.length; j++) { 31 | temp[j] = a[high]; 32 | } 33 | 34 | while (low <= high) { 35 | // 前面部分有f[k-1] 个元素 36 | int mid = low + f[k-1] - 1; 37 | if (key < temp[mid]) { 38 | high = mid - 1; 39 | k--; 40 | } else if (key > temp[mid]) { 41 | low = mid + 1; 42 | k -= 2; 43 | } else { 44 | if (mid <= high) { 45 | return mid; 46 | } else { 47 | return high; 48 | } 49 | } 50 | } 51 | 52 | return -1; 53 | } 54 | 55 | private static int[] fibonacci() { 56 | int[] f = new int[maxsize]; 57 | f[0] = 1; 58 | f[1] = 1; 59 | for (int i = 2; i < maxsize; i++) { 60 | f[i] = f[i - 1] + f[i - 2]; 61 | } 62 | return f; 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/appjishu/test/QuickSortTest.java: -------------------------------------------------------------------------------- 1 | package com.appjishu.test; 2 | 3 | public class QuickSortTest { 4 | public static void main(String[] args) { 5 | System.out.println("Hello World"); 6 | int[] a = {12, 20, 5, 16, 15, 1, 30, 45, 23, 9}; 7 | int start = 0; 8 | int end = a.length - 1; 9 | sort(a, start, end); 10 | for (int i = 0; i < a.length; i++) { 11 | System.out.println(a[i]); 12 | } 13 | } 14 | 15 | private static void sort(int[] a, int low, int high) { 16 | int start = low; 17 | int end = high; 18 | int key = a[low]; 19 | 20 | while (end > start) { 21 | while(end > start && a[end] >= key) 22 | end--; 23 | if (a[end] <= key) { 24 | int temp = a[start]; 25 | a[start] = a[end]; 26 | a[end] = temp; 27 | } 28 | 29 | while (end > start && a[start] <= key) 30 | start++; 31 | if (a[start] >= key) { 32 | 33 | } 34 | } 35 | } 36 | } 37 | --------------------------------------------------------------------------------