├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── pom.xml └── src └── main ├── java └── cn │ └── codepub │ ├── algorithms │ ├── arrays │ │ └── PrintArray.java │ ├── commons │ │ ├── ConversionOfNumberSystems.java │ │ ├── MajorityNumber.java │ │ ├── MaximumProduct.java │ │ └── TopK.java │ ├── graph │ │ ├── Dijkstra.java │ │ ├── DirectedGraphByAdjacencyList.java │ │ ├── DirectedGraphByAdjacencyMatrix.java │ │ ├── FloydWarshall.java │ │ ├── Kruskal.java │ │ ├── Prim.java │ │ ├── UndirectedGraphByAdjacencyList.java │ │ ├── UndirectedGraphByAdjacencyMatrix.java │ │ └── utils │ │ │ └── UnionFindSet.java │ ├── matrix │ │ └── Matrix.java │ ├── multithread │ │ └── ThreadSynchronization.java │ ├── queue │ │ └── PriorityApp.java │ ├── similarity │ │ └── cilin │ │ │ └── WordSimilarity.java │ ├── sorting │ │ ├── BubbleSort.java │ │ ├── InsertSort.java │ │ ├── QuickSort.java │ │ ├── SelectionSort.java │ │ └── ShellSort.java │ ├── spelling │ │ └── ChineseToSpelling.java │ ├── stack │ │ ├── BracketsApp.java │ │ ├── CheckStackSequence.java │ │ ├── InfixApp.java │ │ ├── MinStack.java │ │ └── PostfixApp.java │ ├── strings │ │ ├── BinarySearch.java │ │ ├── Combination.java │ │ ├── JaccardSimilarityCoefficient.java │ │ ├── LCS.java │ │ ├── LCS2.java │ │ ├── LCS3.java │ │ ├── LevenshteinDistance.java │ │ ├── LongestDecreasingSubSequence.java │ │ ├── Manacher.java │ │ ├── PatternStringMatch.java │ │ ├── Permutation.java │ │ ├── ReverseString.java │ │ └── StringSort.java │ ├── trees │ │ ├── DepthFirstTraversal.java │ │ ├── GetPathsBySum.java │ │ ├── LevelTraverseBinaryTree.java │ │ ├── TraverseBinaryTree.java │ │ └── VerifySequenceOfBST.java │ └── utils │ │ ├── StackX.java │ │ └── Tree.java │ └── patterns │ ├── core │ ├── DeepClone.java │ └── Singleton.java │ └── proxy │ ├── CGLibProxyHandler.java │ ├── CountImpl.java │ ├── JDKProxyHandler.java │ └── StaticProxyHandler.java └── resources ├── cilin.txt ├── log4j2.xml └── 基于同义词词林的词语相似度计算方法_田久乐.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | Algorithms.iml 3 | /target/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | 3 | Apache License 4 | Version 2.0, January 2004 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, 12 | and distribution as defined by Sections 1 through 9 of this document. 13 | 14 | "Licensor" shall mean the copyright owner or entity authorized by 15 | the copyright owner that is granting the License. 16 | 17 | "Legal Entity" shall mean the union of the acting entity and all 18 | other entities that control, are controlled by, or are under common 19 | control with that entity. For the purposes of this definition, 20 | "control" means (i) the power, direct or indirect, to cause the 21 | direction or management of such entity, whether by contract or 22 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | outstanding shares, or (iii) beneficial ownership of such entity. 24 | 25 | "You" (or "Your") shall mean an individual or Legal Entity 26 | exercising permissions granted by this License. 27 | 28 | "Source" form shall mean the preferred form for making modifications, 29 | including but not limited to software source code, documentation 30 | source, and configuration files. 31 | 32 | "Object" form shall mean any form resulting from mechanical 33 | transformation or translation of a Source form, including but 34 | not limited to compiled object code, generated documentation, 35 | and conversions to other media types. 36 | 37 | "Work" shall mean the work of authorship, whether in Source or 38 | Object form, made available under the License, as indicated by a 39 | copyright notice that is included in or attached to the work 40 | (an example is provided in the Appendix below). 41 | 42 | "Derivative Works" shall mean any work, whether in Source or Object 43 | form, that is based on (or derived from) the Work and for which the 44 | editorial revisions, annotations, elaborations, or other modifications 45 | represent, as a whole, an original work of authorship. For the purposes 46 | of this License, Derivative Works shall not include works that remain 47 | separable from, or merely link (or bind by name) to the interfaces of, 48 | the Work and Derivative Works thereof. 49 | 50 | "Contribution" shall mean any work of authorship, including 51 | the original version of the Work and any modifications or additions 52 | to that Work or Derivative Works thereof, that is intentionally 53 | submitted to Licensor for inclusion in the Work by the copyright owner 54 | or by an individual or Legal Entity authorized to submit on behalf of 55 | the copyright owner. For the purposes of this definition, "submitted" 56 | means any form of electronic, verbal, or written communication sent 57 | to the Licensor or its representatives, including but not limited to 58 | communication on electronic mailing lists, source code control systems, 59 | and issue tracking systems that are managed by, or on behalf of, the 60 | Licensor for the purpose of discussing and improving the Work, but 61 | excluding communication that is conspicuously marked or otherwise 62 | designated in writing by the copyright owner as "Not a Contribution." 63 | 64 | "Contributor" shall mean Licensor and any individual or Legal Entity 65 | on behalf of whom a Contribution has been received by Licensor and 66 | subsequently incorporated within the Work. 67 | 68 | 2. Grant of Copyright License. Subject to the terms and conditions of 69 | this License, each Contributor hereby grants to You a perpetual, 70 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 71 | copyright license to reproduce, prepare Derivative Works of, 72 | publicly display, publicly perform, sublicense, and distribute the 73 | Work and such Derivative Works in Source or Object form. 74 | 75 | 3. Grant of Patent License. Subject to the terms and conditions of 76 | this License, each Contributor hereby grants to You a perpetual, 77 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | (except as stated in this section) patent license to make, have made, 79 | use, offer to sell, sell, import, and otherwise transfer the Work, 80 | where such license applies only to those patent claims licensable 81 | by such Contributor that are necessarily infringed by their 82 | Contribution(s) alone or by combination of their Contribution(s) 83 | with the Work to which such Contribution(s) was submitted. If You 84 | institute patent litigation against any entity (including a 85 | cross-claim or counterclaim in a lawsuit) alleging that the Work 86 | or a Contribution incorporated within the Work constitutes direct 87 | or contributory patent infringement, then any patent licenses 88 | granted to You under this License for that Work shall terminate 89 | as of the date such litigation is filed. 90 | 91 | 4. Redistribution. You may reproduce and distribute copies of the 92 | Work or Derivative Works thereof in any medium, with or without 93 | modifications, and in Source or Object form, provided that You 94 | meet the following conditions: 95 | 96 | (a) You must give any other recipients of the Work or 97 | Derivative Works a copy of this License; and 98 | 99 | (b) You must cause any modified files to carry prominent notices 100 | stating that You changed the files; and 101 | 102 | (c) You must retain, in the Source form of any Derivative Works 103 | that You distribute, all copyright, patent, trademark, and 104 | attribution notices from the Source form of the Work, 105 | excluding those notices that do not pertain to any part of 106 | the Derivative Works; and 107 | 108 | (d) If the Work includes a "NOTICE" text file as part of its 109 | distribution, then any Derivative Works that You distribute must 110 | include a readable copy of the attribution notices contained 111 | within such NOTICE file, excluding those notices that do not 112 | pertain to any part of the Derivative Works, in at least one 113 | of the following places: within a NOTICE text file distributed 114 | as part of the Derivative Works; within the Source form or 115 | documentation, if provided along with the Derivative Works; or, 116 | within a display generated by the Derivative Works, if and 117 | wherever such third-party notices normally appear. The contents 118 | of the NOTICE file are for informational purposes only and 119 | do not modify the License. You may add Your own attribution 120 | notices within Derivative Works that You distribute, alongside 121 | or as an addendum to the NOTICE text from the Work, provided 122 | that such additional attribution notices cannot be construed 123 | as modifying the License. 124 | 125 | You may add Your own copyright statement to Your modifications and 126 | may provide additional or different license terms and conditions 127 | for use, reproduction, or distribution of Your modifications, or 128 | for any such Derivative Works as a whole, provided Your use, 129 | reproduction, and distribution of the Work otherwise complies with 130 | the conditions stated in this License. 131 | 132 | 5. Submission of Contributions. Unless You explicitly state otherwise, 133 | any Contribution intentionally submitted for inclusion in the Work 134 | by You to the Licensor shall be under the terms and conditions of 135 | this License, without any additional terms or conditions. 136 | Notwithstanding the above, nothing herein shall supersede or modify 137 | the terms of any separate license agreement you may have executed 138 | with Licensor regarding such Contributions. 139 | 140 | 6. Trademarks. This License does not grant permission to use the trade 141 | names, trademarks, service marks, or product names of the Licensor, 142 | except as required for reasonable and customary use in describing the 143 | origin of the Work and reproducing the content of the NOTICE file. 144 | 145 | 7. Disclaimer of Warranty. Unless required by applicable law or 146 | agreed to in writing, Licensor provides the Work (and each 147 | Contributor provides its Contributions) on an "AS IS" BASIS, 148 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 149 | implied, including, without limitation, any warranties or conditions 150 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any 153 | risks associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, 156 | whether in tort (including negligence), contract, or otherwise, 157 | unless required by applicable law (such as deliberate and grossly 158 | negligent acts) or agreed to in writing, shall any Contributor be 159 | liable to You for damages, including any direct, indirect, special, 160 | incidental, or consequential damages of any character arising as a 161 | result of this License or out of the use or inability to use the 162 | Work (including but not limited to damages for loss of goodwill, 163 | work stoppage, computer failure or malfunction, or any and all 164 | other commercial damages or losses), even if such Contributor 165 | has been advised of the possibility of such damages. 166 | 167 | 9. Accepting Warranty or Additional Liability. While redistributing 168 | the Work or Derivative Works thereof, You may choose to offer, 169 | and charge a fee for, acceptance of support, warranty, indemnity, 170 | or other liability obligations and/or rights consistent with this 171 | License. However, in accepting such obligations, You may act only 172 | on Your own behalf and on Your sole responsibility, not on behalf 173 | of any other Contributor, and only if You agree to indemnify, 174 | defend, and hold each Contributor harmless for any liability 175 | incurred by, or claims asserted against, such Contributor by reason 176 | of your accepting any such warranty or additional liability. 177 | 178 | END OF TERMS AND CONDITIONS 179 | 180 | APPENDIX: How to apply the Apache License to your work. 181 | 182 | To apply the Apache License to your work, attach the following 183 | boilerplate notice, with the fields enclosed by brackets "[]" 184 | replaced with your own identifying information. (Don't include 185 | the brackets!) The text should be enclosed in the appropriate 186 | comment syntax for the file format. We also recommend that a 187 | file or class name and description of purpose be included on the 188 | same "printed page" as the copyright notice for easier 189 | identification within third-party archives. 190 | 191 | Copyright http://codepub.cn 192 | 193 | Licensed under the Apache License, Version 2.0 (the "License"); 194 | you may not use this file except in compliance with the License. 195 | You may obtain a copy of the License at 196 | 197 | http://www.apache.org/licenses/LICENSE-2.0 198 | 199 | Unless required by applicable law or agreed to in writing, software 200 | distributed under the License is distributed on an "AS IS" BASIS, 201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | See the License for the specific language governing permissions and 203 | limitations under the License. 204 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Algorithms [![Build Status](https://api.travis-ci.org/shijiebei2009/Algorithms.svg?branch=master)](https://travis-ci.org/shijiebei2009/Algorithms) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) 2 | ========== 3 | 4 | Algorithms playground for common questions solved in Java syntax. 5 | 6 | This repository contains my solution for some common algorithms. I've created this repository to learn about algorithms and improve solving different common computer science problems. I'll try to add more solutions if I have time :) 7 | 8 | Each solved problem has a program written in Java. Every solution is tested and some problems contains more than one solution with different implementations. 9 | 10 | You can check the solution executing tests inside tests directory. Some of this problems have been resolved using TDD. 11 | 12 | Problems 13 | 14 | -------- 15 | 16 | ### Arrays 17 | 18 | * [Clockwise print array - 顺时针打印数组](src/main/java/cn/codepub/algorithms/arrays/PrintArray.java) 19 | 20 | ### Commons 21 | 22 | * [Hex conversion utility - 进制转换工具](src/main/java/cn/codepub/algorithms/commons/ConversionOfNumberSystems.java) 23 | * [Majority number - 大多数,超过一半的数](src/main/java/cn/codepub/algorithms/commons/MajorityNumber.java) 24 | * [Maximum product - 最大乘积](src/main/java/cn/codepub/algorithms/commons/MaximumProduct.java) 25 | * [TOPK algorithm - TOPK算法](src/main/java/cn/codepub/algorithms/commons/TopK.java) 26 | 27 | ### Graph 28 | 29 | * [Dijkstra algorithm - 迪杰斯特拉算法](src/main/java/cn/codepub/algorithms/graph/Dijkstra.java) 30 | * [Directed graph depth first and breadth-first by adjacency table - 邻接表实现有向图深度优先和广度优先](src/main/java/cn/codepub/algorithms/graph/DirectedGraphByAdjacencyList.java) 31 | * [Directed graph depth first and breadth-first by adjacency matrix - 邻接矩阵实现有向图深度优先和广度优先](src/main/java/cn/codepub/algorithms/graph/DirectedGraphByAdjacencyMatrix.java) 32 | * [Floyd warshall - 弗洛伊德算法](src/main/java/cn/codepub/algorithms/graph/FloydWarshall.java) 33 | * [Kruskal - 克鲁斯卡尔算法](src/main/java/cn/codepub/algorithms/graph/Kruskal.java) 34 | * [Prim - 普里姆算法](src/main/java/cn/codepub/algorithms/graph/Prim.java) 35 | * [Undirected graph depth first and breadth-first by adjacency table - 邻接表实现无向图深度优先和广度优先](src/main/java/cn/codepub/algorithms/graph/UndirectedGraphByAdjacencyList.java) 36 | * [Undirected graph depth first and breadth-first by adjacency matrix - 邻接矩阵实现无向图深度优先和广度优先](src/main/java/cn/codepub/algorithms/graph/UndirectedGraphByAdjacencyMatrix.java) 37 | 38 | ### Matrix 39 | 40 | * [Matrix multiplication - 方阵乘法](src/main/java/cn/codepub/algorithms/matrix/Matrix.java) 41 | 42 | ### Multithread 43 | 44 | * [Thread synchronization - 线程同步](src/main/java/cn/codepub/algorithms/multithread/ThreadSynchronization.java) 45 | 46 | ### Queue 47 | 48 | * [Simple priority queue - 简单的优先级队列](src/main/java/cn/codepub/algorithms/queue/PriorityApp.java) 49 | 50 | ### Similarity 51 | 52 | * [Words similarity by Tongyici CiLin - 基于同义词词林的词语相似度](src/main/java/cn/codepub/algorithms/similarity/cilin/WordSimilarity.java) 53 | 54 | ### Sorting Algorithm 55 | 56 | * [Bubble sort - 冒泡排序](src/main/java/cn/codepub/algorithms/sorting/BubbleSort.java) 57 | * [Insertion sort - 插入排序](src/main/java/cn/codepub/algorithms/sorting/InsertSort.java) 58 | * [Quick sort - 快速排序](src/main/java/cn/codepub/algorithms/sorting/QuickSort.java) 59 | * [Selection sort - 选择排序](src/main/java/cn/codepub/algorithms/sorting/SelectionSort.java) 60 | * [Shell sort - 希尔排序](src/main/java/cn/codepub/algorithms/sorting/ShellSort.java) 61 | 62 | ### Chinese to Spelling 63 | 64 | * [Chinese to spelling - 中文转拼音](src/main/java/cn/codepub/algorithms/spelling/ChineseToSpelling.java) 65 | 66 | ### Stack 67 | 68 | * [Analyzing brackets match - 判断括号是否匹配](src/main/java/cn/codepub/algorithms/stack/BracketsApp.java) 69 | * [Check stack sequence - 检查栈的弹出序列](src/main/java/cn/codepub/algorithms/stack/CheckStackSequence.java) 70 | * [Infix expression turn to postfix expression - 中缀表达式转后缀表达式](src/main/java/cn/codepub/algorithms/stack/InfixApp.java) 71 | * [Maintain a minimum number of stacks - 保持最小数的栈](src/main/java/cn/codepub/algorithms/stack/MinStack.java) 72 | * [Postfix expression evaluation - 后缀表达式求值](src/main/java/cn/codepub/algorithms/stack/PostfixApp.java) 73 | 74 | ### Strings 75 | 76 | * [Binary search - 二分查找](src/main/java/cn/codepub/algorithms/strings/BinarySearch.java) 77 | * [Combination - 组合](src/main/java/cn/codepub/algorithms/strings/Combination.java) 78 | * [Jaccard similarity coefficient - 杰卡德相似度系数](src/main/java/cn/codepub/algorithms/strings/JaccardSimilarityCoefficient.java) 79 | * [Longest common subsequence - 最长公共子序列](src/main/java/cn/codepub/algorithms/strings/LCS.java) 80 | * [Longest common substring 1 - 最长公共子串1](src/main/java/cn/codepub/algorithms/strings/LCS2.java) 81 | * [Longest common substring 2 - 最长公共子串2](src/main/java/cn/codepub/algorithms/strings/LCS3.java) 82 | * [Levenshtein distance - 编辑距离](src/main/java/cn/codepub/algorithms/strings/LevenshteinDistance.java) 83 | * [Longest decreasing subsequence - 最长递减子序列](src/main/java/cn/codepub/algorithms/strings/LongestDecreasingSubSequence.java) 84 | * [Pattern string match - 模式串查找](src/main/java/cn/codepub/algorithms/strings/PatternStringMatch.java) 85 | * [Permutation - 全排列](src/main/java/cn/codepub/algorithms/strings/Permutation.java) 86 | * [Reverse string - 反转字符串](src/main/java/cn/codepub/algorithms/strings/ReverseString.java) 87 | * [Lexicographical - 字典序排序](src/main/java/cn/codepub/algorithms/strings/StringSort.java) 88 | * [Manacher algorithms - 最长回文字符串](src/main/java/cn/codepub/algorithms/strings/Manacher.java) 89 | 90 | ### Trees 91 | 92 | * [Depth-first traversal of a binary tree - 二叉树的深度优先遍历](src/main/java/cn/codepub/algorithms/trees/DepthFirstTraversal.java) 93 | * [Get all path by given a number - 二叉树中结点值的和为输入整数的所有路径](src/main/java/cn/codepub/algorithms/trees/GetPathsBySum.java) 94 | * [Level binary tree traversal - 二叉树的层次遍历](src/main/java/cn/codepub/algorithms/trees/LevelTraverseBinaryTree.java) 95 | * [Binary tree traversal - 二叉树的遍历](src/main/java/cn/codepub/algorithms/trees/TraverseBinaryTree.java) 96 | * [Verify sequence Of binary search tree - 验证二叉搜索树序列](src/main/java/cn/codepub/algorithms/trees/VerifySequenceOfBST.java) 97 | 98 | ### Design Patterns 99 | 100 | * [Deep clone - 深拷贝](src/main/java/cn/codepub/patterns/core/DeepClone.java) 101 | * [Singleton - 单例](src/main/java/cn/codepub/patterns/core/Singleton.java) 102 | * [Static proxy - 静态代理](src/main/java/cn/codepub/patterns/proxy/StaticProxyHandler.java) 103 | * [JDK dynamic proxy - JDK实现动态代理](src/main/java/cn/codepub/patterns/proxy/JDKProxyHandler.java) 104 | * [CGLib dynamic proxy - CGLib实现动态代理](src/main/java/cn/codepub/patterns/proxy/CGLibProxyHandler.java) 105 | 106 | Author 107 | ------------ 108 | 109 | * Developed By [Xu Wang](http://codepub.cn) 110 | 111 | License 112 | ------- 113 | 114 | Copyright 2015 Xu Wang 115 | 116 | Licensed under the Apache License, Version 2.0 (the "License"); 117 | you may not use this file except in compliance with the License. 118 | You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 119 | 120 | Unless required by applicable law or agreed to in writing, software 121 | distributed under the License is distributed on an "AS IS" BASIS, 122 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123 | See the License for the specific language governing permissions and 124 | limitations under the License. -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | cn.codepub 8 | algorithms 9 | 1.0-SNAPSHOT 10 | 11 | 2.7 12 | 4.13.1 13 | 3.4 14 | 2.17.1 15 | 1.8 16 | 1.16.12 17 | 20.0 18 | 19 | 20 | 21 | 22 | org.apache.maven.plugins 23 | maven-compiler-plugin 24 | 2.5.1 25 | 26 | ${version.jdk} 27 | ${version.jdk} 28 | ${version.jdk} 29 | 30 | 31 | 32 | 33 | 34 | 35 | commons-io 36 | commons-io 37 | ${version.commons.io} 38 | 39 | 40 | junit 41 | junit 42 | ${version.junit} 43 | 44 | 45 | cglib 46 | cglib 47 | 3.1 48 | 49 | 50 | org.apache.commons 51 | commons-lang3 52 | ${version.commons.lang3} 53 | 54 | 55 | com.github.stuxuhai 56 | jpinyin 57 | 1.0 58 | 59 | 60 | org.apache.logging.log4j 61 | log4j-core 62 | ${version.log4j} 63 | 64 | 65 | org.apache.logging.log4j 66 | log4j-api 67 | ${version.log4j} 68 | 69 | 70 | org.projectlombok 71 | lombok 72 | ${version.lombok} 73 | 74 | 75 | com.google.guava 76 | guava 77 | ${version.guava} 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/arrays/PrintArray.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.arrays; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | *

8 | * Created with IntelliJ IDEA. 2015/10/29 21:29 9 | *

10 | *

11 | * ClassName:PrintArray 12 | *

13 | *

14 | * Description:顺时针打印二位数组 15 | *

16 | * 17 | * @author Wang Xu 18 | * @version V1.0.0 19 | * @since V1.0.0 20 | */ 21 | public class PrintArray { 22 | static int nums[][]; 23 | static List list = new ArrayList<>(); 24 | 25 | public static void main(String[] args) { 26 | nums = new int[][]{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}, {16, 17, 18, 19, 20}, {21, 22, 23, 24, 25}}; 27 | moveRight(0, 0, nums.length, nums[0].length, 0, nums.length * nums[0].length); 28 | System.out.println(list); 29 | list.clear(); 30 | nums = new int[][]{{1}, {2}}; 31 | moveRight(0, 0, nums.length, nums[0].length, 0, nums.length * nums[0].length); 32 | System.out.println(list); 33 | list.clear(); 34 | } 35 | 36 | private static void moveRight(int curRow, int curCol, int rows, int cols, int temp, int size) { 37 | if (size <= 0) { 38 | return; 39 | } 40 | if (curCol + 1 < cols - temp) { 41 | list.add(nums[curRow][curCol]); 42 | curCol++; 43 | size--; 44 | moveRight(curRow, curCol, rows, cols, temp, size); 45 | } else { 46 | moveDown(curRow, curCol--, rows, cols, temp, size); 47 | } 48 | } 49 | 50 | private static void moveDown(int curRow, int curCol, int rows, int cols, int temp, int size) { 51 | if (size <= 0) { 52 | return; 53 | } 54 | if (curRow + 1 < rows - temp) { 55 | list.add(nums[curRow][curCol]); 56 | size--; 57 | curRow++; 58 | moveDown(curRow, curCol, rows, cols, temp, size); 59 | } else { 60 | moveLeft(curRow--, curCol, rows, cols, temp, size); 61 | } 62 | } 63 | 64 | private static void moveLeft(int curRow, int curCol, int rows, int cols, int temp, int size) { 65 | if (size <= 0) { 66 | return; 67 | } 68 | if (curCol - 1 >= temp - 1) { 69 | list.add(nums[curRow][curCol]); 70 | size--; 71 | curCol--; 72 | moveLeft(curRow, curCol, rows, cols, temp, size); 73 | } else { 74 | moveUp(curRow, ++curCol, rows, cols, temp + 1, size); 75 | } 76 | 77 | } 78 | 79 | private static void moveUp(int curRow, int curCol, int rows, int cols, int temp, int size) { 80 | if (size <= 0) { 81 | return; 82 | } 83 | if (curRow - 1 > temp - 1) { 84 | curRow--; 85 | list.add(nums[curRow][curCol]); 86 | size--; 87 | moveUp(curRow, curCol, rows, cols, temp, size); 88 | } else { 89 | moveRight(curRow, ++curCol, rows, cols, temp, size); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/commons/ConversionOfNumberSystems.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.commons; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | /** 7 | *

8 | * Created with IntelliJ IDEA. 2015/12/12 15:35 9 | *

10 | *

11 | * ClassName:ConversionOfNumberSystems 12 | *

13 | *

14 | * Description:任意进制位转换系统 15 | *

16 | * 17 | * @author Wang Xu 18 | * @version V1.0.0 19 | * @since V1.0.0 20 | */ 21 | public class ConversionOfNumberSystems { 22 | /** 23 | * 第一种方法 24 | * 25 | * @param number 需要进行进制转换的数字 26 | * @param base 需要转为几进制 27 | * @return 28 | */ 29 | public static String conversion(int number, int base) { 30 | StringBuilder sb = new StringBuilder(); 31 | while (number > 0) { 32 | int i = number % base; 33 | switch (i) { 34 | case 11: 35 | sb.append("A"); 36 | break; 37 | case 12: 38 | sb.append("B"); 39 | break; 40 | case 13: 41 | sb.append("C"); 42 | break; 43 | case 14: 44 | sb.append("D"); 45 | break; 46 | case 15: 47 | sb.append("E"); 48 | break; 49 | default: 50 | sb.append(i); 51 | } 52 | number /= base; 53 | 54 | } 55 | return sb.reverse().toString(); 56 | } 57 | 58 | /** 59 | * 第二种方法 60 | * 61 | * @param num 需要转换进制的数字 62 | * @param base 需要转成几进制 63 | * @return 转换结果 64 | */ 65 | public static String baseString(int num, int base) { 66 | String str, digit = "0123456789abcdef"; 67 | if (num == 0) { 68 | return ""; 69 | } else { 70 | str = baseString(num / base, base); 71 | return str + digit.charAt(num % base); 72 | } 73 | } 74 | 75 | @Test 76 | public void test() { 77 | System.out.println(conversion(1024, 16)); 78 | System.out.println(baseString(1024, 16)); 79 | Assert.assertEquals(conversion(1024, 16), baseString(1024, 16)); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/commons/MajorityNumber.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.commons; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | *

7 | * Created with IntelliJ IDEA. 2015/10/22 11:00 8 | *

9 | *

10 | * ClassName:MajorityNumber 11 | *

12 | *

13 | * Description:获取某个出现次数超过一半的元素 14 | *

15 | * 16 | * @author Wang Xu 17 | * @version V1.0.0 18 | * @since V1.0.0 19 | */ 20 | public class MajorityNumber { 21 | public static void main(String[] args) { 22 | int[] nums = new int[]{1, 2, 3, 2, 2, 4, 2, 5, 8, 2}; 23 | ArrayList a = new ArrayList(); 24 | for (int i : nums) { 25 | a.add(i); 26 | } 27 | System.out.println(new MajorityNumber().majorityNumber(a)); 28 | } 29 | 30 | public int majorityNumber(ArrayList nums) { 31 | int candidate1 = 0, candidate2 = 0; 32 | int count1, count2; 33 | count1 = count2 = 0; 34 | for (int i = 0; i < nums.size(); i++) { 35 | if (candidate1 == nums.get(i)) { 36 | count1++; 37 | } else if (candidate2 == nums.get(i)) { 38 | count2++; 39 | } else if (count1 == 0) { 40 | candidate1 = nums.get(i); 41 | count1 = 1; 42 | } else if (count2 == 0) { 43 | candidate2 = nums.get(i); 44 | count2 = 1; 45 | } else { 46 | count1--; 47 | count2--; 48 | } 49 | } 50 | count1 = count2 = 0; 51 | for (int i = 0; i < nums.size(); i++) { 52 | if (nums.get(i) == candidate1) { 53 | count1++; 54 | } else if (nums.get(i) == candidate2) { 55 | count2++; 56 | } 57 | } 58 | return count1 > count2 ? candidate1 : candidate2; 59 | } 60 | } -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/commons/MaximumProduct.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.commons; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | *

7 | * Created with IntelliJ IDEA. 15/12/17 16:53 8 | *

9 | *

10 | * ClassName:MaximumProduct(最大乘积) 11 | *

12 | *

13 | * Description:输入n个元素组成的序列S,你需要找出一个乘积最大的连续子序列。如果这个最大的乘积不是正数,应输出0表示无解。 14 | * 1<=n<=18:表示不超过18个元素 15 | * -10<=Si<=10:表示每个元素的绝对值不大于10 16 | *

17 | * 18 | * @author Wang Xu 19 | * @version V1.0.0 20 | * @since V1.0.0 21 | */ 22 | public class MaximumProduct { 23 | 24 | /** 25 | * 连续子序列必有开始和结束,所以采用暴力破解法,枚举开始元素和结束元素 26 | * 27 | * @param arrs 28 | * @return 最大乘积结果 29 | */ 30 | public static long getMaximumProduct(long[] arrs) { 31 | long max = 0; 32 | //以i作为开始,以j作为结束 33 | for (int i = 0; i < arrs.length - 1; i++) { 34 | for (int j = i + 1; j < arrs.length; j++) { 35 | long temp = 1; 36 | for (int k = i; k <= j; k++) { 37 | temp *= arrs[k]; 38 | } 39 | if (temp > max) { 40 | max = temp; 41 | } 42 | 43 | } 44 | } 45 | return max; 46 | } 47 | 48 | @Test 49 | public void test() { 50 | long[] arr = new long[]{2, 4, -3}; 51 | long maximumProduct = getMaximumProduct(arr); 52 | System.out.println(maximumProduct); 53 | arr = new long[]{2, 5, -1, 2, -1}; 54 | maximumProduct = getMaximumProduct(arr); 55 | System.out.println(maximumProduct); 56 | } 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/commons/TopK.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.commons; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Comparator; 6 | import java.util.PriorityQueue; 7 | import java.util.Queue; 8 | import java.util.Random; 9 | 10 | /** 11 | *

12 | * Created with IntelliJ IDEA. 15/12/17 11:03 13 | *

14 | *

15 | * ClassName:TopK 16 | *

17 | *

18 | * Description:思考利用JDK的PriorityQueue实现TopK问题,TopK问题说的是:输入n个整数,输出其中最小的k个 19 | *

20 | * 21 | * @author Wang Xu 22 | * @version V1.0.0 23 | * @since V1.0.0 24 | */ 25 | public class TopK { 26 | 27 | private static Queue queue; 28 | 29 | /** 30 | * 从n个整数中查找最小的k个 31 | * 32 | * @param n 33 | * @param k 34 | * @return 35 | */ 36 | public static boolean getTopK(int n, int k) { 37 | queue = new PriorityQueue<>(k, new Comparator() { 38 | @Override 39 | public int compare(Integer o1, Integer o2) { 40 | return o2.compareTo(o1); 41 | } 42 | }); 43 | 44 | if (n < k) { 45 | System.err.println("输入的n和k不合法!"); 46 | return false; 47 | } 48 | 49 | Random random = new Random(); 50 | //先加入k个再说 51 | for (int i = 0; i < k; i++) { 52 | queue.add(random.nextInt()); 53 | } 54 | //这个时候,队列已满,若再想加入,那么必须是比队列中最大的元素小的才可以加入 55 | for (int i = k; i < n; i++) { 56 | int i1 = random.nextInt(); 57 | if (queue.peek() > i1) { 58 | queue.poll(); 59 | queue.add(i1); 60 | } 61 | 62 | } 63 | return true; 64 | } 65 | 66 | /** 67 | * 因为队列是一个大根堆,所以如果想从小到大输出的话,需要借助其它方式,最简单的是利用递归同样可以实现 68 | * 69 | * @param queue 70 | */ 71 | public static void printTopK(Queue queue) { 72 | if (!queue.isEmpty()) { 73 | Object remove = queue.remove(); 74 | printTopK(queue); 75 | System.out.println(remove); 76 | } 77 | } 78 | 79 | @Test 80 | public void test() { 81 | boolean topK = getTopK(5, 10); 82 | if (topK) { 83 | printTopK(queue); 84 | } 85 | topK = getTopK(100, 100); 86 | if (topK) { 87 | printTopK(queue); 88 | } 89 | topK = getTopK(10000, 10); 90 | if (topK) { 91 | printTopK(queue); 92 | } 93 | 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/graph/Dijkstra.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.graph; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Arrays; 5 | import java.util.Queue; 6 | 7 | /** 8 | *

9 | * Created with IntelliJ IDEA. 2015/12/14 10:06 10 | *

11 | *

12 | * ClassName:Dijkstra 13 | *

14 | *

15 | * Description:使用迪杰斯特拉算法解决单源最短路径 16 | *

17 | * 18 | * @author Wang Xu 19 | * @version V1.0.0 20 | * @since V1.0.0 21 | */ 22 | public class Dijkstra { 23 | 24 | //顶点数组 25 | public Vertex[] vertexes; 26 | 27 | //顶点类 28 | class Vertex { 29 | char name;//顶点名称 30 | Edge firstEdge;//顶点所连的第一条边 31 | 32 | public Vertex(char name) { 33 | this.name = name; 34 | } 35 | } 36 | 37 | //边类 38 | class Edge { 39 | Vertex endVertex;//边所连的末尾节点 40 | int value;//边的权值,注意使用迪杰斯特拉不允许权值为负值 41 | Edge next = null;//该边的起点所连的另一头边,采用邻接表结构存储 42 | 43 | public Edge(int value) { 44 | this.value = value; 45 | } 46 | } 47 | 48 | @org.junit.Test 49 | public void create() { 50 | //构造图 51 | Edge edge2 = new Edge(2); 52 | Edge edge3 = new Edge(3); 53 | Edge edge1 = new Edge(1); 54 | Edge edge4 = new Edge(4); 55 | Edge edge8 = new Edge(8); 56 | Edge edge7 = new Edge(7); 57 | Edge edge5 = new Edge(5); 58 | 59 | 60 | Vertex v0 = new Vertex('0'); 61 | Vertex v1 = new Vertex('1'); 62 | Vertex v2 = new Vertex('2'); 63 | Vertex v3 = new Vertex('3'); 64 | Vertex v4 = new Vertex('4'); 65 | 66 | edge2.next = edge4; 67 | edge2.endVertex = v1; 68 | edge4.endVertex = v4; 69 | v0.firstEdge = edge2; 70 | 71 | edge3.endVertex = v2; 72 | v1.firstEdge = edge3; 73 | 74 | edge1.next = edge5; 75 | edge1.endVertex = v4; 76 | edge5.endVertex = v3; 77 | v2.firstEdge = edge1; 78 | 79 | edge7.endVertex = v3; 80 | v4.firstEdge = edge7; 81 | 82 | edge8.endVertex = v0; 83 | v3.firstEdge = edge8; 84 | vertexes = new Vertex[]{v0, v1, v2, v3, v4}; 85 | //寻找最短路径数组 86 | Dijkstra.getShortestPath(vertexes); 87 | 88 | } 89 | 90 | /** 91 | * 求得单源最短路径 92 | * 93 | * @param vertexes 94 | */ 95 | public static void getShortestPath(Vertex[] vertexes) { 96 | int[] dist = new int[vertexes.length]; 97 | char[] pred = new char[vertexes.length]; 98 | 99 | Queue queue = new ArrayDeque<>(); 100 | for (int i = 0; i < vertexes.length; i++) { 101 | dist[i] = Integer.MAX_VALUE; 102 | pred[i] = '-'; 103 | } 104 | dist[0] = 0;//表示源到源自身为0 105 | pred[0] = '0'; 106 | 107 | //通常情况下,是按照优先级高低插入队列,而优先级高低的衡量标准是离源点距离的远近,但是此并不为必要条件,所以你可以以其它顺序插入队列 108 | //以v0,v1,v2,v3,v4的顺序插入队列 109 | //for (int i = 0; i < vertexes.length; i++) { 110 | // queue.add(vertexes[i]); 111 | //} 112 | 113 | //以v0,v1,v4,v2,v3的顺序插入队列 114 | queue.add(vertexes[0]); 115 | queue.add(vertexes[1]); 116 | queue.add(vertexes[4]); 117 | queue.add(vertexes[2]); 118 | queue.add(vertexes[3]); 119 | System.out.println(Arrays.toString(dist)); 120 | for (Vertex v : queue) { 121 | System.out.print("顶点数组为:" + v.name + "\t"); 122 | } 123 | System.out.println(); 124 | while (!queue.isEmpty()) { 125 | Vertex vertex = queue.remove(); 126 | // Graph.Vertex vertex = queue.peek(); 127 | int u = getNo(vertexes, vertex.name); 128 | if (-1 == u) { 129 | System.err.println("该顶点不存在:" + vertex.name); 130 | break; 131 | } 132 | Edge firstEdge = vertex.firstEdge; 133 | while (firstEdge != null) { 134 | int w = firstEdge.value;//获取边的权值 135 | int v = getNo(vertexes, firstEdge.endVertex.name); 136 | if (-1 == v) { 137 | System.err.println("该顶点不存在:" + firstEdge.endVertex.name); 138 | } 139 | int newW = dist[u] + w; 140 | if (newW < 0) { 141 | newW = Integer.MAX_VALUE;//如果溢出,需要重新置为最大整数值,原因是:最大整数值加任意大于0的值就会溢出,变为最小正整数值 142 | } 143 | 144 | if (newW < dist[v]) { 145 | System.out.print("(" + "0" + "," + vertex.name + ")" + "+" + "(" + vertex.name + "," + firstEdge.endVertex.name + ")" + "<" + "" + 146 | "(0," + 147 | firstEdge 148 | .endVertex 149 | .name + ")"); 150 | System.out.println("\t更新距离数组\t" + "(0," + firstEdge.endVertex.name + ")=" + newW); 151 | dist[v] = newW; 152 | pred[v] = vertex.name; 153 | } else { 154 | System.out.println("(" + "0" + "," + vertex.name + ")" + "+" + "(" + vertex.name + "," + firstEdge.endVertex.name + ")" + ">" + 155 | "" + 156 | "(0," + 157 | firstEdge 158 | .endVertex 159 | .name + ")"); 160 | 161 | } 162 | firstEdge = firstEdge.next; 163 | } 164 | 165 | } 166 | System.out.println("距离数组为:" + Arrays.toString(dist)); 167 | //注意,最终的最短路径可以经过pred数组推导出来,很简单 168 | System.out.println("路径数组为:" + Arrays.toString(pred)); 169 | } 170 | 171 | /** 172 | * 根据节点的名称返回节点在数组中的序号 173 | * 174 | * @param vertexes 175 | * @param name 176 | * @return 177 | */ 178 | private static int getNo(Vertex[] vertexes, char name) { 179 | for (int i = 0; i < vertexes.length; i++) { 180 | if (vertexes[i].name == name) { 181 | return i; 182 | } 183 | } 184 | return -1; 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/graph/DirectedGraphByAdjacencyList.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.graph; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Queue; 5 | import java.util.Scanner; 6 | 7 | /** 8 | *

9 | * Created with IntelliJ IDEA. 2015/12/2 20:33 10 | *

11 | *

12 | * ClassName:UndirectedGraphByAdjacencyList 13 | *

14 | *

15 | * Description:使用邻接表实现的无向图深度优先及广度优先 16 | *

17 | * 18 | * @author Wang Xu 19 | * @version V1.0.0 20 | * @since V1.0.0 21 | */ 22 | public class DirectedGraphByAdjacencyList { 23 | public static void main(String[] args) { 24 | DirectedGraphByAdjacencyList undirectedGraphAdjacencyList = new DirectedGraphByAdjacencyList(); 25 | undirectedGraphAdjacencyList.createGraph(); 26 | undirectedGraphAdjacencyList.depthFirstSearch(); 27 | undirectedGraphAdjacencyList.breadthFirstSearch(); 28 | } 29 | 30 | private void breadthFirstSearch() { 31 | boolean visited[] = new boolean[vertexes.length]; 32 | Queue queue = new ArrayDeque(); 33 | System.out.println("\nBreadth First Search:"); 34 | for (int i = 0; i < vertexes.length; i++) { 35 | if (!visited[i]) { 36 | queue.add(i); 37 | } 38 | while (!queue.isEmpty()) { 39 | Integer remove = queue.remove(); 40 | if (!visited[remove]) { 41 | String data = vertexes[remove].data; 42 | System.out.print(data + "\t"); 43 | visited[remove] = true; 44 | } 45 | Edge firstEdge = vertexes[remove].firstEdge; 46 | while (firstEdge != null) { 47 | if (!visited[firstEdge.vertex]) { 48 | queue.add(firstEdge.vertex); 49 | } 50 | firstEdge = firstEdge.nextEdge; 51 | } 52 | 53 | } 54 | 55 | 56 | } 57 | } 58 | 59 | public void depthFirstSearch() { 60 | System.out.println("\nDepth First Search:"); 61 | boolean[] visited = new boolean[vertexes.length]; 62 | for (int i = 0; i < vertexes.length; i++) { 63 | if (!visited[i]) { 64 | depthFirstSearch(visited, i); 65 | } 66 | } 67 | } 68 | 69 | private void depthFirstSearch(boolean[] visited, int i) { 70 | System.out.print(vertexes[i].data + "\t"); 71 | visited[i] = true; 72 | Edge firstEdge = vertexes[i].firstEdge; 73 | while (firstEdge != null) { 74 | if (!visited[firstEdge.vertex]) { 75 | depthFirstSearch(visited, firstEdge.vertex); 76 | } 77 | firstEdge = firstEdge.nextEdge; 78 | } 79 | } 80 | 81 | 82 | //邻接表中边对应的链表的顶点 83 | private class Edge { 84 | int vertex;//该边所指向顶点的位置 85 | Edge nextEdge;//指向下一条弧的指针 86 | } 87 | 88 | //邻接表中表的顶点 89 | private class Vertex { 90 | String data;//顶点信息 91 | Edge firstEdge;//指向第一条依附该顶点的弧 92 | } 93 | 94 | private Vertex[] vertexes;//顶点数组 95 | 96 | 97 | /** 98 | * 根据用户输入构造图 99 | */ 100 | public void createGraph() { 101 | Scanner scanner = new Scanner(System.in); 102 | System.out.println("please input vertex number:"); 103 | int vertexNum = scanner.nextInt(); 104 | System.out.println("please input edge number:"); 105 | int edgeNum = scanner.nextInt(); 106 | 107 | //无向图有n个顶点,最多有n*(n-1)/2条边 108 | // vertex: n = > edge: (n-1)*n/2 109 | if (vertexNum < 1 || edgeNum < 1 || edgeNum > (vertexNum - 1) * vertexNum / 2) { 110 | System.err.println("input error, invalid vertex or edges!"); 111 | return; 112 | } 113 | 114 | //init vertex and edges 115 | vertexes = new Vertex[vertexNum]; 116 | System.out.println("input the vertex by space:"); 117 | for (int i = 0; i < vertexNum; i++) { 118 | vertexes[i] = new Vertex(); 119 | vertexes[i].data = scanner.next(); 120 | vertexes[i].firstEdge = null; 121 | } 122 | 123 | 124 | System.out.println("input the edge between vertex by pair:"); 125 | for (int i = 0; i < edgeNum; i++) { 126 | String v1 = scanner.next(); 127 | String v2 = scanner.next(); 128 | int start = getPosition(v1); 129 | int end = getPosition(v2); 130 | if (start == -1 || end == -1) { 131 | System.err.println(v1 + " or " + v2 + " are invalid!"); 132 | } 133 | if (vertexes[start].firstEdge == null) { 134 | Edge edge = new Edge(); 135 | edge.vertex = end; 136 | edge.nextEdge = null; 137 | vertexes[start].firstEdge = edge; 138 | } else { 139 | Edge firstEdge = vertexes[start].firstEdge; 140 | while (firstEdge.nextEdge != null) { 141 | firstEdge = firstEdge.nextEdge; 142 | } 143 | Edge edge = new Edge(); 144 | edge.vertex = end; 145 | edge.nextEdge = null; 146 | firstEdge.nextEdge = edge; 147 | } 148 | 149 | } 150 | System.out.println("打印顶点如下:"); 151 | for (int i = 0; i < vertexes.length; i++) { 152 | String data = vertexes[i].data; 153 | System.out.print(data + "\t"); 154 | } 155 | System.out.println("\n打印边的邻接表如下:"); 156 | for (int i = 0; i < vertexes.length; i++) { 157 | Edge firstEdge = vertexes[i].firstEdge; 158 | System.out.print(vertexes[i].data); 159 | while (firstEdge != null) { 160 | System.out.print("--" + vertexes[firstEdge.vertex].data); 161 | firstEdge = firstEdge.nextEdge; 162 | } 163 | System.out.print("\t"); 164 | } 165 | } 166 | 167 | private int getPosition(String v1) { 168 | for (int i = 0; i < vertexes.length; i++) { 169 | if (vertexes[i].data.equals(v1)) { 170 | return i; 171 | } 172 | } 173 | return -1; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/graph/DirectedGraphByAdjacencyMatrix.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.graph; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Arrays; 5 | import java.util.Queue; 6 | import java.util.Scanner; 7 | 8 | /** 9 | *

10 | * Created with IntelliJ IDEA. 2015/12/3 22:15 11 | *

12 | *

13 | * ClassName:DirectedGraphByAdjacencyMatrix 14 | *

15 | *

16 | * Description:使用邻接矩阵实现有向图的深度优先及广度优先 17 | *

18 | * 19 | * @author Wang Xu 20 | * @version V1.0.0 21 | * @since V1.0.0 22 | */ 23 | public class DirectedGraphByAdjacencyMatrix { 24 | private String[] vertex;//顶点集合 25 | private int[][] edges;//边的集合 26 | 27 | public static void main(String[] args) { 28 | DirectedGraphByAdjacencyMatrix directedGraphByAdjacencyMatrix = new DirectedGraphByAdjacencyMatrix(); 29 | directedGraphByAdjacencyMatrix.createGraph(); 30 | directedGraphByAdjacencyMatrix.depthFirstSearch(); 31 | directedGraphByAdjacencyMatrix.breadthFirstSearch(); 32 | } 33 | 34 | public void breadthFirstSearch() { 35 | //设置访问标记数组 36 | System.out.println("\nBreadth First Search:"); 37 | boolean[] visited = new boolean[vertex.length]; 38 | Queue queue = new ArrayDeque<>(); 39 | for (int i = 0; i < vertex.length; i++) { 40 | if (!visited[i]) { 41 | System.out.print(vertex[i] + "\t"); 42 | queue.add(i); 43 | visited[i] = true; 44 | } 45 | while (!queue.isEmpty()) { 46 | int remove = queue.remove(); 47 | int count = 0; 48 | for (int j = getNextVertex(remove, count); j >= 0; j = getNextVertex(remove, count)) { 49 | if (!visited[j]) { 50 | visited[j] = true; 51 | System.out.print(vertex[j] + "\t"); 52 | queue.add(j); 53 | } else { 54 | count++; 55 | } 56 | } 57 | } 58 | } 59 | } 60 | 61 | /** 62 | * 寻找与当前点有边相连的下一个顶点 63 | * 64 | * @param row 查找该行 65 | * @param col 从该列开始查找 66 | * @return 67 | */ 68 | private int getNextVertex(int row, int col) { 69 | for (int j = col; j < edges[row].length; j++) { 70 | if (edges[row][j] == 1) { 71 | return j; 72 | } 73 | } 74 | return -1; 75 | } 76 | 77 | /** 78 | * 根据用户输入构造图 79 | */ 80 | public void createGraph() { 81 | Scanner scanner = new Scanner(System.in); 82 | System.out.println("please input vertex number:"); 83 | int vertexNum = scanner.nextInt(); 84 | System.out.println("please input edge number:"); 85 | int edgeNum = scanner.nextInt(); 86 | 87 | //无向图有n个顶点,最多有n*(n-1)/2条边 88 | // vertex: n = > edge: (n-1)*n/2 89 | if (vertexNum < 1 || edgeNum < 1 || edgeNum > (vertexNum - 1) * vertexNum / 2) { 90 | System.err.println("input error, invalid vertex or edges!"); 91 | return; 92 | } 93 | 94 | //init vertex and edges 95 | vertex = new String[vertexNum]; 96 | edges = new int[vertexNum][vertexNum]; 97 | System.out.println("input the vertex by space:"); 98 | for (int i = 0; i < vertexNum; i++) { 99 | vertex[i] = scanner.next(); 100 | } 101 | 102 | System.out.println("input the edge between vertex by pair:"); 103 | for (int i = 0; i < edgeNum; i++) { 104 | String v1 = scanner.next(); 105 | String v2 = scanner.next(); 106 | int start = getPosition(v1); 107 | int end = getPosition(v2); 108 | if (start == -1 || end == -1) { 109 | System.err.println(v1 + " or " + v2 + " are invalid!"); 110 | } 111 | //更新边的邻接矩阵 112 | edges[start][end] = 1; 113 | } 114 | System.out.println("打印顶点如下:" + Arrays.toString(vertex)); 115 | System.out.println("打印边的邻接矩阵如下:"); 116 | for (int temp[] : edges) { 117 | System.out.println(Arrays.toString(temp)); 118 | } 119 | } 120 | 121 | /** 122 | * 对外暴露的调用接口 123 | */ 124 | public void depthFirstSearch() { 125 | //设置访问标记数组 126 | boolean[] visited = new boolean[vertex.length]; 127 | 128 | System.out.println("Depth First Search:"); 129 | for (int i = 0; i < vertex.length; i++) { 130 | if (!visited[i]) { 131 | depthFirstSearch(visited, i); 132 | } 133 | } 134 | 135 | } 136 | 137 | /** 138 | * 内部递归的深度优先实现 139 | * 140 | * @param visited 141 | * @param i 142 | */ 143 | private void depthFirstSearch(boolean[] visited, int i) { 144 | visited[i] = true; 145 | System.out.print(vertex[i] + "\t"); 146 | int count = 0; 147 | for (int j = getNextVertex(i, count); j >= 0; j = getNextVertex(i, count)) { 148 | if (!visited[j]) { 149 | depthFirstSearch(visited, j); 150 | } else { 151 | count++; 152 | } 153 | } 154 | } 155 | 156 | /** 157 | * 返回顶点在集合中的位置 158 | * 159 | * @param s 160 | * @return 161 | */ 162 | public int getPosition(String s) { 163 | for (int i = 0; i < vertex.length; i++) { 164 | if (vertex[i].equalsIgnoreCase(s)) { 165 | return i; 166 | } 167 | } 168 | return -1; 169 | } 170 | 171 | } 172 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/graph/FloydWarshall.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.graph; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | *

7 | * Created with IntelliJ IDEA. 2015/12/14 15:45 8 | *

9 | *

10 | * ClassName:FloydWarshall 11 | *

12 | *

13 | * Description:使用弗洛伊德算法求所有点对最短路径,而弗洛伊德的核心就是用动态规划 14 | * 动态规划有两个令人激动的特性:它专注解决较小的,有条件限制的问题。当限制条件很严格时,函数将会非常简单,系统地松弛限制条件,直到最后产生希望得到的结果 15 | *

16 | * 17 | * @author Wang Xu 18 | * @version V1.0.0 19 | * @since V1.0.0 20 | */ 21 | public class FloydWarshall { 22 | //顶点数组 23 | public Vertex[] vertexes; 24 | private static char[][] pred;//路径矩阵 25 | 26 | //顶点类 27 | class Vertex { 28 | char name;//顶点名称 29 | Edge firstEdge;//顶点所连的第一条边 30 | 31 | public Vertex(char name) { 32 | this.name = name; 33 | } 34 | } 35 | 36 | //边类 37 | class Edge { 38 | Vertex endVertex;//边所连的末尾节点 39 | int value;//边的权值,注意使用迪杰斯特拉不允许权值为负值 40 | Edge next = null;//该边的起点所连的另一头边,采用邻接表结构存储 41 | 42 | public Edge(int value) { 43 | this.value = value; 44 | } 45 | } 46 | 47 | @org.junit.Test 48 | public void create() { 49 | Vertex v0 = new Vertex('0'); 50 | Vertex v1 = new Vertex('1'); 51 | Vertex v2 = new Vertex('2'); 52 | Vertex v3 = new Vertex('3'); 53 | Vertex v4 = new Vertex('4'); 54 | Edge edge2 = new Edge(2); 55 | edge2.endVertex = v1; 56 | Edge edge4 = new Edge(4); 57 | edge4.endVertex = v4; 58 | edge2.next = edge4; 59 | v0.firstEdge = edge2; 60 | 61 | Edge edge3 = new Edge(3); 62 | edge3.endVertex = v2; 63 | v1.firstEdge = edge3; 64 | 65 | Edge edge1 = new Edge(1); 66 | Edge edge5 = new Edge(5); 67 | edge1.endVertex = v4; 68 | edge5.endVertex = v3; 69 | edge1.next = edge5; 70 | v2.firstEdge = edge1; 71 | 72 | 73 | Edge edge7 = new Edge(7); 74 | edge7.endVertex = v3; 75 | v4.firstEdge = edge7; 76 | 77 | Edge edge8 = new Edge(8); 78 | edge8.endVertex = v0; 79 | v3.firstEdge = edge8; 80 | 81 | vertexes = new Vertex[]{v0, v1, v2, v3, v4}; 82 | getShortestPathByDp(vertexes); 83 | 84 | } 85 | 86 | public static void getShortestPathByDp(Vertex[] vertexes) { 87 | int size = vertexes.length; 88 | int[][] dist = new int[size][size]; 89 | pred = new char[size][size]; 90 | for (int i = 0; i < size; i++) { 91 | int j = 0; 92 | for (; j < size; j++) { 93 | dist[i][j] = Integer.MAX_VALUE; 94 | pred[i][j] = '-'; 95 | } 96 | dist[i][i] = 0; 97 | Edge firstEdge = vertexes[i].firstEdge; 98 | while (firstEdge != null) { 99 | int no = getNo(vertexes, firstEdge.endVertex.name); 100 | dist[i][no] = firstEdge.value; 101 | pred[i][no] = vertexes[i].name; 102 | firstEdge = firstEdge.next; 103 | } 104 | } 105 | 106 | 107 | for (int i = 0; i < size; i++) { 108 | for (int j = 0; j < size; j++) { 109 | for (int k = 0; k < size; k++) { 110 | int newLen = dist[j][i] + dist[i][k]; 111 | if (newLen < 0) { 112 | newLen = Integer.MAX_VALUE;//说明溢出了,那么重新置为最大整数值 113 | } 114 | if (newLen < dist[j][k]) { 115 | dist[j][k] = newLen; 116 | pred[j][k] = pred[i][k]; 117 | } 118 | } 119 | } 120 | } 121 | //dist[i][j]即表示在有向图中,从vi到vj的最短路径 122 | for (int[] d : dist) { 123 | System.out.println(Arrays.toString(d)); 124 | } 125 | System.out.println("-------------------------"); 126 | for (char[] d : pred) { 127 | System.out.println(Arrays.toString(d)); 128 | } 129 | 130 | String s = constructShortestPath(4, 2); 131 | System.out.println("4->2的最短路径是;" + s); 132 | } 133 | 134 | private static int getNo(Vertex[] vertexes, char name) { 135 | for (int i = 0; i < vertexes.length; i++) { 136 | if (vertexes[i].name == name) { 137 | return i; 138 | } 139 | } 140 | return -1; 141 | } 142 | 143 | //从已知的pred矩阵中构造出最短路径 144 | 145 | /** 146 | * @param start 起始点 147 | * @param end 结束点 148 | * @return 起始点->结束的之间的最短路径 149 | */ 150 | public static String constructShortestPath(int start, int end) { 151 | StringBuilder sb = new StringBuilder(); 152 | sb.append(end + "-"); 153 | int temp = end; 154 | while (temp != start) { 155 | char c = pred[start][temp]; 156 | if (c == '-') { 157 | return start + "和" + end + "之间不存在最短路径!"; 158 | } 159 | temp = Integer.valueOf(String.valueOf(c)); 160 | sb.append(temp + "-"); 161 | } 162 | sb.deleteCharAt(sb.length() - 1); 163 | return sb.reverse().toString(); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/graph/Kruskal.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.graph; 2 | 3 | import cn.codepub.algorithms.graph.utils.UnionFindSet; 4 | import org.junit.Test; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.PriorityQueue; 9 | import java.util.Queue; 10 | 11 | /** 12 | *

13 | * Created with IntelliJ IDEA. 15/12/16 15:39 14 | *

15 | *

16 | * ClassName:Kruskal 17 | *

18 | *

19 | * Description:使用克鲁斯卡尔算法求最小生成树,该算法的核心是一个不相交集,也就是说若加入当前边不形成回路的话即合法,否则不合法 20 | * 而实现不相交集最常用的方法就是使用并查集,借助于实现的并查集来实现克鲁斯卡尔算法 21 | *

22 | * 23 | * @author Wang Xu 24 | * @version V1.0.0 25 | * @since V1.0.0 26 | */ 27 | public class Kruskal { 28 | private static List vertexList = new ArrayList<>();//顶点集 29 | /** 30 | * 实现一个匿名类,提供了基于边的权值的比较器 31 | */ 32 | public static final Queue QUEUE = new PriorityQueue<>((e1, e2) -> { 33 | if (e1.value == e2.value) { 34 | return 0; 35 | } else { 36 | return e1.value > e2.value ? 1 : -1; 37 | } 38 | }); 39 | 40 | private static List visitedEdges = new ArrayList<>();//已访问的边集 41 | private static List edgeList = new ArrayList<>();//边集 42 | 43 | private static class Vertex { 44 | char name;//顶点名称 45 | 46 | public Vertex(char name) { 47 | this.name = name; 48 | } 49 | 50 | @Override 51 | public String toString() { 52 | return String.valueOf(name); 53 | } 54 | } 55 | 56 | private static class Edge { 57 | Vertex start;//边的起始点 58 | Vertex end;//边的终结点 59 | int value;//边的权值 60 | 61 | public Edge(Vertex a, Vertex b, int val) { 62 | this.start = a; 63 | this.end = b; 64 | this.value = val; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return "顶点是:" + this.start.name + "-->" + this.end.name + ",权值:" + this.value; 70 | } 71 | } 72 | 73 | /** 74 | * 添加边的函数 75 | * 76 | * @param a 起始点 77 | * @param b 终结点 78 | * @param val 边的权值 79 | */ 80 | public static void addEdge(Vertex a, Vertex b, int val) { 81 | Edge edge = new Edge(a, b, val); 82 | edgeList.add(edge); 83 | } 84 | 85 | public static void minimumSpanningTree() { 86 | UnionFindSet unionFindSet = new UnionFindSet(vertexList.size()); 87 | // 加入优先级队列 88 | QUEUE.addAll(edgeList); 89 | // queue.addAll(edgeList.stream().collect(Collectors.toList())); 90 | while (!QUEUE.isEmpty()) { 91 | Edge remove = QUEUE.remove(); 92 | Vertex start = remove.start;//获取起始点 93 | Vertex end = remove.end;//获取终结点 94 | int startNo = getVertexNo(vertexList, start.name);//得到起点编号 95 | int endNo = getVertexNo(vertexList, end.name);//得到终点编号 96 | int father1 = unionFindSet.findSet(startNo); 97 | int father2 = unionFindSet.findSet(endNo); 98 | if (father1 != father2) {//说明两棵树不在同一棵子树 99 | unionFindSet.union(startNo, endNo);//合并之 100 | visitedEdges.add(remove);//将当前访问的边加入已访问列表 101 | } 102 | } 103 | } 104 | 105 | private static int getVertexNo(List vertexList, char name) { 106 | for (int i = 0; i < vertexList.size(); i++) { 107 | if (vertexList.get(i).name == name) { 108 | return i; 109 | } 110 | } 111 | return -1; 112 | } 113 | 114 | @Test 115 | public void create() { 116 | //构造图 117 | Vertex v0 = new Vertex('0'); 118 | Vertex v1 = new Vertex('1'); 119 | Vertex v2 = new Vertex('2'); 120 | Vertex v3 = new Vertex('3'); 121 | Vertex v4 = new Vertex('4'); 122 | vertexList.add(v0); 123 | vertexList.add(v1); 124 | vertexList.add(v2); 125 | vertexList.add(v3); 126 | vertexList.add(v4); 127 | addEdge(v0, v1, 2); 128 | addEdge(v1, v2, 3); 129 | addEdge(v2, v4, 1); 130 | addEdge(v0, v4, 4); 131 | addEdge(v0, v3, 8); 132 | addEdge(v2, v3, 5); 133 | addEdge(v4, v3, 7); 134 | minimumSpanningTree(); 135 | System.out.println("使用克鲁斯卡尔算法选取的边是:"); 136 | System.out.println(visitedEdges); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/graph/Prim.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.graph; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | *

10 | * Created with IntelliJ IDEA. 15/12/16 10:33 11 | *

12 | *

13 | * ClassName:Prim 14 | *

15 | *

16 | * Description:使用Prim算法实现最小生成树,注意最小生成树所使用的图是无向图,所以其存储结构应区别于有向图 17 | *

18 | * 19 | * @author Wang Xu 20 | * @version V1.0.0 21 | * @since V1.0.0 22 | */ 23 | public class Prim { 24 | private static class Vertex { 25 | char name;//顶点名称 26 | 27 | public Vertex(char name) { 28 | this.name = name; 29 | } 30 | 31 | public Vertex() { 32 | 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return String.valueOf(this.name); 38 | } 39 | } 40 | 41 | private static class Edge { 42 | Vertex start;//边的开始顶点 43 | Vertex end;//边的结束顶点 44 | int value;//权值 45 | 46 | public Edge(Vertex start, Vertex end, int value) { 47 | this.start = start; 48 | this.end = end; 49 | this.value = value; 50 | } 51 | } 52 | 53 | private static List vertexList = new ArrayList<>();//节点集 54 | private static List visitedVertex = new ArrayList<>();//已经访问的节点集 55 | private static List edgeList = new ArrayList<>();//边集合 56 | 57 | public static void addEdge(Vertex a, Vertex b, int val) { 58 | Edge edge = new Edge(a, b, val); 59 | edgeList.add(edge); 60 | } 61 | 62 | 63 | /** 64 | * 使用Prim算法求最小生成树 65 | */ 66 | public static void minimumSpanningTree() { 67 | //随机选择第0个作为开始 68 | visitedVertex.add(vertexList.get(0)); 69 | for (int i = 1; i < vertexList.size(); i++) {//其实并不需要遍历vertexList,需要做的只是剩余几个节点遍历几次即可,因为最终的目的是将所有的节点都加入已访问列表,而我们已经随机选择从第0个开始了,第0个已经被首先加入 70 | int temp = Integer.MAX_VALUE;//遍历取得权值最小的边,且该边属于start和end节点 71 | Vertex tempVertex = new Vertex(); 72 | //从已访问列表中查找边,将其作为start,寻找start和end之间满足条件的边 73 | for (Vertex start : visitedVertex) { 74 | for (int j = 0; j < edgeList.size(); j++) { 75 | Edge edge = edgeList.get(j); 76 | if (edge.start.name == start.name && !containVertex(edge.end.name)) { 77 | //说明在start和end之间存在边,并且边的权值也可以获得 78 | int weight = edge.value; 79 | if (weight < temp) { 80 | temp = weight; 81 | tempVertex = edge.end;//如若选择该边,那么将顶点加入已访问列表 82 | } 83 | } 84 | } 85 | } 86 | visitedVertex.add(tempVertex); 87 | } 88 | 89 | } 90 | 91 | /** 92 | * 测试当前顶点是否已加入“已访问顶点列表” 93 | * 94 | * @param name 95 | * @return 96 | */ 97 | private static boolean containVertex(char name) { 98 | for (int i = 0; i < visitedVertex.size(); i++) { 99 | if (visitedVertex.get(i).name == name) { 100 | return true; 101 | } 102 | } 103 | return false; 104 | } 105 | 106 | @Test 107 | public void create() { 108 | //构造图 109 | Vertex v0 = new Vertex('0'); 110 | Vertex v1 = new Vertex('1'); 111 | Vertex v2 = new Vertex('2'); 112 | Vertex v3 = new Vertex('3'); 113 | Vertex v4 = new Vertex('4'); 114 | vertexList.add(v0); 115 | vertexList.add(v1); 116 | vertexList.add(v2); 117 | vertexList.add(v3); 118 | vertexList.add(v4); 119 | addEdge(v0, v1, 2); 120 | addEdge(v1, v2, 3); 121 | addEdge(v2, v4, 1); 122 | addEdge(v0, v4, 4); 123 | addEdge(v0, v3, 8); 124 | addEdge(v2, v3, 5); 125 | addEdge(v4, v3, 7); 126 | 127 | minimumSpanningTree(); 128 | System.out.println(visitedVertex); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/graph/UndirectedGraphByAdjacencyList.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.graph; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Queue; 5 | import java.util.Scanner; 6 | 7 | /** 8 | *

9 | * Created with IntelliJ IDEA. 2015/12/2 20:33 10 | *

11 | *

12 | * ClassName:UndirectedGraphByAdjacencyList 13 | *

14 | *

15 | * Description:使用邻接表实现的无向图深度优先及广度优先 16 | *

17 | * 18 | * @author Wang Xu 19 | * @version V1.0.0 20 | * @since V1.0.0 21 | */ 22 | public class UndirectedGraphByAdjacencyList { 23 | public static void main(String[] args) { 24 | // test data following 25 | // please input vertex number: 26 | // 7 27 | // please input edge number: 28 | // 7 29 | // input the vertex by space: 30 | // a b c d e f g 31 | // input the edge between vertex by pair: 32 | // a c a d a f b c c d e g f g 33 | // 打印顶点如下: 34 | // a b c d e f g 35 | // 打印边的邻接表如下: 36 | // a--c--d--f b--c c--a--b--d d--a--c e--g f--a--g g--e--f 37 | // Depth First Search: 38 | // a c b d f g e 39 | // Breadth First Search: 40 | // a c d f b g e 41 | // Process finished with exit code 0 42 | UndirectedGraphByAdjacencyList undirectedGraphAdjacencyList = new UndirectedGraphByAdjacencyList(); 43 | undirectedGraphAdjacencyList.createGraph(); 44 | undirectedGraphAdjacencyList.depthFirstSearch(); 45 | undirectedGraphAdjacencyList.breadthFirstSearch(); 46 | } 47 | 48 | private void breadthFirstSearch() { 49 | boolean visited[] = new boolean[vertexes.length]; 50 | Queue queue = new ArrayDeque(); 51 | System.out.println("\nBreadth First Search:"); 52 | for (int i = 0; i < vertexes.length; i++) { 53 | if (!visited[i]) { 54 | queue.add(i); 55 | } 56 | while (!queue.isEmpty()) { 57 | Integer remove = queue.remove(); 58 | if (!visited[remove]) { 59 | String data = vertexes[remove].data; 60 | System.out.print(data + "\t"); 61 | visited[remove] = true; 62 | } 63 | Edge firstEdge = vertexes[remove].firstEdge; 64 | while (firstEdge != null) { 65 | if (!visited[firstEdge.vertex]) { 66 | queue.add(firstEdge.vertex); 67 | } 68 | firstEdge = firstEdge.nextEdge; 69 | } 70 | 71 | } 72 | 73 | 74 | } 75 | } 76 | 77 | public void depthFirstSearch() { 78 | System.out.println("\nDepth First Search:"); 79 | boolean[] visited = new boolean[vertexes.length]; 80 | for (int i = 0; i < vertexes.length; i++) { 81 | if (!visited[i]) { 82 | depthFirstSearch(visited, i); 83 | } 84 | } 85 | } 86 | 87 | private void depthFirstSearch(boolean[] visited, int i) { 88 | System.out.print(vertexes[i].data + "\t"); 89 | visited[i] = true; 90 | Edge firstEdge = vertexes[i].firstEdge; 91 | while (firstEdge != null) { 92 | if (!visited[firstEdge.vertex]) { 93 | depthFirstSearch(visited, firstEdge.vertex); 94 | } 95 | firstEdge = firstEdge.nextEdge; 96 | } 97 | } 98 | 99 | 100 | //邻接表中边对应的链表的顶点 101 | private class Edge { 102 | int vertex;//该边所指向顶点的位置 103 | Edge nextEdge;//指向下一条弧的指针 104 | } 105 | 106 | //邻接表中表的顶点 107 | private class Vertex { 108 | String data;//顶点信息 109 | Edge firstEdge;//指向第一条依附该顶点的弧 110 | } 111 | 112 | private Vertex[] vertexes;//顶点数组 113 | 114 | 115 | /** 116 | * 根据用户输入构造图 117 | */ 118 | public void createGraph() { 119 | Scanner scanner = new Scanner(System.in); 120 | System.out.println("please input vertex number:"); 121 | int vertexNum = scanner.nextInt(); 122 | System.out.println("please input edge number:"); 123 | int edgeNum = scanner.nextInt(); 124 | 125 | //无向图有n个顶点,最多有n*(n-1)/2条边 126 | // vertex: n = > edge: (n-1)*n/2 127 | if (vertexNum < 1 || edgeNum < 1 || edgeNum > (vertexNum - 1) * vertexNum / 2) { 128 | System.err.println("input error, invalid vertex or edges!"); 129 | return; 130 | } 131 | 132 | //init vertex and edges 133 | vertexes = new Vertex[vertexNum]; 134 | System.out.println("input the vertex by space:"); 135 | for (int i = 0; i < vertexNum; i++) { 136 | vertexes[i] = new Vertex(); 137 | vertexes[i].data = scanner.next(); 138 | vertexes[i].firstEdge = null; 139 | } 140 | 141 | 142 | System.out.println("input the edge between vertex by pair:"); 143 | for (int i = 0; i < edgeNum; i++) { 144 | String v1 = scanner.next(); 145 | String v2 = scanner.next(); 146 | int start = getPosition(v1); 147 | int end = getPosition(v2); 148 | if (start == -1 || end == -1) { 149 | System.err.println(v1 + " or " + v2 + " are invalid!"); 150 | } 151 | if (vertexes[start].firstEdge == null) { 152 | Edge edge = new Edge(); 153 | edge.vertex = end; 154 | edge.nextEdge = null; 155 | vertexes[start].firstEdge = edge; 156 | } else { 157 | Edge firstEdge = vertexes[start].firstEdge; 158 | while (firstEdge.nextEdge != null) { 159 | firstEdge = firstEdge.nextEdge; 160 | } 161 | Edge edge = new Edge(); 162 | edge.vertex = end; 163 | edge.nextEdge = null; 164 | firstEdge.nextEdge = edge; 165 | } 166 | 167 | //无向图,需要进行双向链接 168 | if (vertexes[end].firstEdge == null) { 169 | Edge edge = new Edge(); 170 | edge.vertex = start; 171 | edge.nextEdge = null; 172 | vertexes[end].firstEdge = edge; 173 | } else { 174 | Edge firstEdge = vertexes[end].firstEdge; 175 | while (firstEdge.nextEdge != null) { 176 | firstEdge = firstEdge.nextEdge; 177 | } 178 | Edge edge = new Edge(); 179 | edge.vertex = start; 180 | edge.nextEdge = null; 181 | firstEdge.nextEdge = edge; 182 | } 183 | } 184 | System.out.println("打印顶点如下:"); 185 | for (int i = 0; i < vertexes.length; i++) { 186 | String data = vertexes[i].data; 187 | System.out.print(data + "\t"); 188 | } 189 | System.out.println("\n打印边的邻接表如下:"); 190 | for (int i = 0; i < vertexes.length; i++) { 191 | Edge firstEdge = vertexes[i].firstEdge; 192 | System.out.print(vertexes[i].data); 193 | while (firstEdge != null) { 194 | System.out.print("--" + vertexes[firstEdge.vertex].data); 195 | firstEdge = firstEdge.nextEdge; 196 | } 197 | System.out.print("\t"); 198 | } 199 | } 200 | 201 | private int getPosition(String v1) { 202 | for (int i = 0; i < vertexes.length; i++) { 203 | if (vertexes[i].data.equals(v1)) { 204 | return i; 205 | } 206 | } 207 | return -1; 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/graph/UndirectedGraphByAdjacencyMatrix.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.graph; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Arrays; 5 | import java.util.Queue; 6 | import java.util.Scanner; 7 | 8 | /** 9 | *

10 | * Created with IntelliJ IDEA. 2015/12/1 18:21 11 | *

12 | *

13 | * ClassName:UndirectedGraphByAdjacencyMatrix 14 | *

15 | *

16 | * Description:使用邻接矩阵实现无向图的深度优先及广度优先 17 | *

18 | * 19 | * @author Wang Xu 20 | * @version V1.0.0 21 | * @since V1.0.0 22 | */ 23 | 24 | public class UndirectedGraphByAdjacencyMatrix { 25 | private String[] vertex;//顶点集合 26 | private int[][] edges;//边的集合 27 | 28 | public static void main(String[] args) { 29 | UndirectedGraphByAdjacencyMatrix undirectedGraphByAdjacencyMatrix = new UndirectedGraphByAdjacencyMatrix(); 30 | undirectedGraphByAdjacencyMatrix.createGraph();//创建图 31 | // test data following 32 | // please input vertex number: 33 | // 7 34 | // please input edge number: 35 | // 7 36 | // input the vertex by space: 37 | // a b c d e f g 38 | // input the edge between vertex by pair: 39 | // a c a d a f b c c d e g f g 40 | undirectedGraphByAdjacencyMatrix.depthFirstSearch();//开始深度优先 41 | undirectedGraphByAdjacencyMatrix.breadthFirstSearch(); 42 | 43 | } 44 | 45 | public void breadthFirstSearch() { 46 | //设置访问标记数组 47 | System.out.println("\nBreadth First Search:"); 48 | boolean[] visited = new boolean[vertex.length]; 49 | Queue queue = new ArrayDeque<>(); 50 | for (int i = 0; i < vertex.length; i++) { 51 | if (!visited[i]) { 52 | System.out.print(vertex[i] + "\t"); 53 | queue.add(i); 54 | visited[i] = true; 55 | } 56 | while (!queue.isEmpty()) { 57 | int remove = queue.remove(); 58 | int count = 0; 59 | for (int j = getNextVertex(remove, count); j >= 0; j = getNextVertex(remove, count)) { 60 | if (!visited[j]) { 61 | visited[j] = true; 62 | System.out.print(vertex[j] + "\t"); 63 | queue.add(j); 64 | } else { 65 | count++; 66 | } 67 | } 68 | } 69 | } 70 | } 71 | 72 | /** 73 | * 根据用户输入构造图 74 | */ 75 | public void createGraph() { 76 | Scanner scanner = new Scanner(System.in); 77 | System.out.println("please input vertex number:"); 78 | int vertexNum = scanner.nextInt(); 79 | System.out.println("please input edge number:"); 80 | int edgeNum = scanner.nextInt(); 81 | 82 | //无向图有n个顶点,最多有n*(n-1)/2条边 83 | // vertex: n = > edge: (n-1)*n/2 84 | if (vertexNum < 1 || edgeNum < 1 || edgeNum > (vertexNum - 1) * vertexNum / 2) { 85 | System.err.println("input error, invalid vertex or edges!"); 86 | return; 87 | } 88 | 89 | //init vertex and edges 90 | vertex = new String[vertexNum]; 91 | edges = new int[vertexNum][vertexNum]; 92 | System.out.println("input the vertex by space:"); 93 | for (int i = 0; i < vertexNum; i++) { 94 | vertex[i] = scanner.next(); 95 | } 96 | 97 | System.out.println("input the edge between vertex by pair:"); 98 | for (int i = 0; i < edgeNum; i++) { 99 | String v1 = scanner.next(); 100 | String v2 = scanner.next(); 101 | int start = getPosition(v1); 102 | int end = getPosition(v2); 103 | if (start == -1 || end == -1) { 104 | System.err.println(v1 + " or " + v2 + " are invalid!"); 105 | } 106 | //更新边的邻接矩阵 107 | edges[start][end] = 1; 108 | edges[end][start] = 1; 109 | } 110 | System.out.println("打印顶点如下:" + Arrays.toString(vertex)); 111 | System.out.println("打印边的邻接矩阵如下:"); 112 | for (int temp[] : edges) { 113 | System.out.println(Arrays.toString(temp)); 114 | } 115 | } 116 | 117 | /** 118 | * 对外暴露的调用接口 119 | */ 120 | public void depthFirstSearch() { 121 | //设置访问标记数组 122 | boolean[] visited = new boolean[vertex.length]; 123 | 124 | System.out.println("Depth First Search:"); 125 | for (int i = 0; i < vertex.length; i++) { 126 | if (!visited[i]) { 127 | depthFirstSearch(visited, i); 128 | } 129 | } 130 | 131 | } 132 | 133 | /** 134 | * 内部递归的深度优先实现 135 | * 136 | * @param visited 137 | * @param i 138 | */ 139 | private void depthFirstSearch(boolean[] visited, int i) { 140 | visited[i] = true; 141 | System.out.print(vertex[i] + "\t"); 142 | int count = 0; 143 | for (int j = getNextVertex(i, count); j >= 0; j = getNextVertex(i, count)) { 144 | if (!visited[j]) { 145 | depthFirstSearch(visited, j); 146 | } else { 147 | count++; 148 | } 149 | } 150 | } 151 | 152 | /** 153 | * 寻找与当前点有边相连的下一个顶点 154 | * 155 | * @param row 查找该行 156 | * @param col 从该列开始查找 157 | * @return 158 | */ 159 | private int getNextVertex(int row, int col) { 160 | for (int j = col; j < edges[row].length; j++) { 161 | if (edges[row][j] == 1) { 162 | return j; 163 | } 164 | } 165 | return -1; 166 | } 167 | 168 | /** 169 | * 返回顶点在集合中的位置 170 | * 171 | * @param s 172 | * @return 173 | */ 174 | public int getPosition(String s) { 175 | for (int i = 0; i < vertex.length; i++) { 176 | if (vertex[i].equalsIgnoreCase(s)) { 177 | return i; 178 | } 179 | } 180 | return -1; 181 | } 182 | 183 | } 184 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/graph/utils/UnionFindSet.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.graph.utils; 2 | 3 | /** 4 | *

5 | * Created with IntelliJ IDEA. 15/12/16 16:34 6 | *

7 | *

8 | * ClassName:UnionFindSet 9 | *

10 | *

11 | * Description:实现一个Java版并查集,应用于克鲁斯卡尔算法 12 | *

13 | * 14 | * @author Wang Xu 15 | * @version V1.0.0 16 | * @since V1.0.0 17 | */ 18 | public class UnionFindSet { 19 | public int[] father;//father[i]=i表示本集合且i是集合对应的树的根,father[i]=j表示j是i的父节点 20 | public int[] rank;//rank[i]代表集合的秩,比如子孙个数或者树的高度等。用于合并集合,秩小的合并到秩大的 21 | private int DEFAULT_SIZE = 2 << 9;//设置默认值为1024 22 | 23 | public UnionFindSet() { 24 | init(); 25 | } 26 | 27 | public UnionFindSet(int size) { 28 | DEFAULT_SIZE = size; 29 | init(); 30 | } 31 | 32 | /** 33 | * 利用默认值做初始化工作 34 | */ 35 | private void init() { 36 | father = new int[DEFAULT_SIZE]; 37 | rank = new int[DEFAULT_SIZE]; 38 | makeSet(); 39 | } 40 | 41 | /** 42 | * 初始化集合 43 | */ 44 | public void makeSet() { 45 | for (int i = 0; i < father.length; i++) { 46 | father[i] = i; 47 | rank[i] = 0; 48 | } 49 | } 50 | 51 | /** 52 | * 查找一个元素所在的集合,其精髓是找到这个元素所在的集合的祖先,如果需要判断两个元素是否属于同一个集合,只要看他们所在集合的祖先是否相同即可 53 | * 54 | * @param x 55 | * @return 56 | */ 57 | public int findSet(int x) { 58 | if (x != father[x]) { 59 | //在递归查找的时候进行了路径压缩,所谓的路径压缩其实非常简单,就是将该树的祖先置为每个节点的父节点 60 | father[x] = findSet(father[x]); 61 | } 62 | return father[x]; 63 | } 64 | 65 | /** 66 | * 合并树,将秩小的合并到大的 67 | * 68 | * @param x 69 | * @param y 70 | */ 71 | public void union(int x, int y) { 72 | x = findSet(x); 73 | y = findSet(y); 74 | if (x == y) { 75 | return; 76 | } 77 | if (rank[x] > rank[y]) { 78 | father[y] = x; 79 | } else if (rank[x] < rank[y]) { 80 | father[x] = y; 81 | } else {//任意合并一个即可 82 | rank[y]++; 83 | father[x] = y; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/matrix/Matrix.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.matrix; 2 | 3 | /** 4 | *

5 | * Created with IntelliJ IDEA. 2015/10/10 20:37 6 | *

7 | *

8 | * ClassName:Matrix 9 | *

10 | *

11 | * Description:方阵的乘法 12 | *

13 | * 14 | * @author Wang Xu 15 | * @version V1.0.0 16 | * @since V1.0.0 17 | */ 18 | public class Matrix { 19 | static int[][] a = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; 20 | static int[][] b = new int[][]{{1, 2, 3}, {1, 2, 3}, {1, 2, 3}}; 21 | static int[][] c = new int[a.length][b.length]; 22 | 23 | public static void main(String[] args) { 24 | for (int i = 0; i < a.length; i++) { 25 | for (int j = 0; j < a[i].length; j++) { 26 | for (int k = 0; k < b[j].length; k++) { 27 | c[i][j] += a[i][k] * b[k][j]; 28 | } 29 | } 30 | } 31 | for (int temp[] : c) { 32 | for (int col : temp) { 33 | System.out.print(col + "\t"); 34 | } 35 | System.out.println(); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/multithread/ThreadSynchronization.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.multithread; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | *

7 | * Created with IntelliJ IDEA. 2015/10/29 21:43 8 | *

9 | *

10 | * ClassName:ThreadSynchronization 11 | *

12 | *

13 | * Description:开启三个线程,这三个线程的ID分别是A,B,C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示,例如ABCABC... 14 | *

15 | * 16 | * @author Wang Xu 17 | * @version V1.0.0 18 | * @since V1.0.0 19 | */ 20 | public class ThreadSynchronization extends Thread { 21 | 22 | private AtomicInteger synObj;//全局共享的同步计数器 23 | private String name;//每个线程的ID 24 | private int flag;//每个线程的标识,用来判断该第几个线程打印了 25 | 26 | private int count = 0;//记录打印次数 27 | 28 | public ThreadSynchronization(AtomicInteger synObj, String name, int flag) { 29 | this.synObj = synObj; 30 | this.name = name; 31 | this.flag = flag; 32 | } 33 | 34 | @Override 35 | public void run() { 36 | while (true) { 37 | synchronized (synObj) { 38 | if (synObj.get() % 3 == flag) { 39 | synObj.set(synObj.get() + 1); 40 | System.out.print(name); 41 | count++; 42 | synObj.notifyAll(); 43 | if (count == 10) { 44 | break; 45 | } 46 | } else { 47 | try { 48 | synObj.wait(); 49 | } catch (InterruptedException e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | } 54 | } 55 | } 56 | 57 | public static void main(String[] args) { 58 | AtomicInteger atomicInteger = new AtomicInteger(0); 59 | ThreadSynchronization tp = new ThreadSynchronization(atomicInteger, "A", 0); 60 | ThreadSynchronization tp1 = new ThreadSynchronization(atomicInteger, "B", 1); 61 | ThreadSynchronization tp2 = new ThreadSynchronization(atomicInteger, "C", 2); 62 | tp.start(); 63 | tp1.start(); 64 | tp2.start(); 65 | } 66 | } -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/queue/PriorityApp.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.queue; 2 | 3 | /** 4 | *

5 | * Created with IntelliJ IDEA. 2016/1/8 19:57 6 | *

7 | *

8 | * ClassName:PriorityApp 9 | *

10 | *

11 | * Description:Implements a simple priority queue 12 | *

13 | * 14 | * @author Wang Xu 15 | * @version V1.0.0 16 | * @since V1.0.0 17 | */ 18 | 19 | 20 | public class PriorityApp { 21 | public static void main(String[] args) { 22 | PriorityQ thePQ = new PriorityApp().new PriorityQ(5); 23 | thePQ.insert(30); 24 | thePQ.insert(50); 25 | thePQ.insert(10); 26 | thePQ.insert(40); 27 | thePQ.insert(20); 28 | while (!thePQ.isEmpty()) { 29 | long item = thePQ.remove(); 30 | System.out.print(item + " "); 31 | } 32 | } 33 | 34 | class PriorityQ { 35 | private int maxSize; 36 | private long[] queArray; 37 | private int nItems; 38 | 39 | public PriorityQ(int s) { 40 | maxSize = s; 41 | queArray = new long[maxSize]; 42 | nItems = 0; 43 | } 44 | 45 | public void insert(long item) { 46 | int j; 47 | if (nItems == 0) { 48 | queArray[nItems++] = item; 49 | 50 | } else { 51 | for (j = nItems - 1; j >= 0; j--) { 52 | if (item > queArray[j]) { 53 | queArray[j + 1] = queArray[j]; 54 | } else { 55 | break; 56 | } 57 | 58 | } 59 | queArray[j + 1] = item; 60 | nItems++; 61 | } 62 | } 63 | 64 | public long remove() { 65 | return queArray[--nItems]; 66 | } 67 | 68 | public long peekMin() { 69 | return queArray[nItems - 1]; 70 | } 71 | 72 | public boolean isEmpty() { 73 | return nItems == 0; 74 | } 75 | 76 | public boolean isFull() { 77 | return nItems == maxSize; 78 | } 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/similarity/cilin/WordSimilarity.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.similarity.cilin; 2 | 3 | import com.google.common.base.Preconditions; 4 | import lombok.extern.log4j.Log4j2; 5 | import org.apache.commons.io.IOUtils; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.junit.Test; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.util.*; 12 | 13 | import static java.lang.Math.PI; 14 | import static java.lang.Math.cos; 15 | 16 | /** 17 | *

18 | * Created with IntelliJ IDEA. 2015/8/2 21:54 19 | *

20 | *

21 | * ClassName:WordSimilarity 同义词词林扩展版计算词语相似度 22 | *

23 | *

24 | * Description:
25 | * "=" 代表 相等 同义
26 | * "#" 代表 不等 同类 属于相关词语
27 | * "@" 代表 自我封闭 独立 它在词典中既没有同义词, 也没有相关词
28 | *

29 | * 30 | * @author Wang Xu 31 | * @version V1.0.0 32 | * @since V1.0.0 33 | */ 34 | @Log4j2 35 | //注意使用Log4j2的注解,那么在pom中必须引入2.x版本的log4j,如果使用Log4j注解,pom中引入1.x版本的log4j 36 | //相应的配置文件也要一致,2.x版本配置文件为log4j2.xml,1.x版本配置文件为log4j.xml 37 | public class WordSimilarity { 38 | /** 39 | * when we use Lombok's Annotation, such as @Log4j 40 | * 41 | * @Log4j
42 | * public class LogExample { 43 | * } 44 | *

45 | * will generate: 46 | * public class LogExample { 47 | * private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.Logger.getLogger(LogExample.class); 48 | * } 49 | *

50 | */ 51 | //定义一些常数先 52 | private static final double a = 0.65; 53 | private static final double b = 0.8; 54 | private static final double c = 0.9; 55 | private static final double d = 0.96; 56 | private static final double e = 0.5; 57 | private static final double f = 0.1; 58 | 59 | private static final double degrees = 180; 60 | 61 | 62 | //存放的是以词为key,以该词的编码为values的List集合,其中一个词可能会有多个编码 63 | private static Map> wordsEncode = new HashMap>(); 64 | //存放的是以编码为key,以该编码多对应的词为values的List集合,其中一个编码可能会有多个词 65 | private static Map> encodeWords = new HashMap>(); 66 | 67 | /** 68 | * 读取同义词词林并将其注入wordsEncode和encodeWords 69 | */ 70 | private static void readCiLin() { 71 | 72 | InputStream input = WordSimilarity.class.getClass().getResourceAsStream("/cilin.txt"); 73 | List contents = null; 74 | try { 75 | contents = IOUtils.readLines(input); 76 | 77 | for (String content : contents) { 78 | content = Preconditions.checkNotNull(content); 79 | String[] strsArr = content.split(" "); 80 | String[] strs = Preconditions.checkNotNull(strsArr); 81 | String encode = null; 82 | int length = strs.length; 83 | if (length > 1) { 84 | encode = strs[0];//获取编码 85 | } 86 | ArrayList encodeWords_values = new ArrayList(); 87 | for (int i = 1; i < length; i++) { 88 | encodeWords_values.add(strs[i]); 89 | } 90 | encodeWords.put(encode, encodeWords_values);//以编码为key,其后所有值为value 91 | for (int i = 1; i < length; i++) { 92 | String key = strs[i]; 93 | if (wordsEncode.containsKey(strs[i])) { 94 | ArrayList values = wordsEncode.get(key); 95 | values.add(encode); 96 | //重新放置回去 97 | wordsEncode.put(key, values);//以某个value为key,其可能的所有编码为value 98 | } else { 99 | ArrayList temp = new ArrayList(); 100 | temp.add(encode); 101 | wordsEncode.put(key, temp); 102 | } 103 | } 104 | } 105 | } catch (IOException e) { 106 | e.printStackTrace(); 107 | System.err.println("load dictionary failed!"); 108 | log.error(e.getMessage()); 109 | } 110 | } 111 | 112 | /** 113 | * 对外暴露的接口,返回两个词的相似度的计算结果 114 | * 115 | * @param word1 116 | * @param word2 117 | * @return 相似度值 118 | */ 119 | public static double getSimilarity(String word1, String word2) { 120 | //在计算时候再加载,实现懒加载 121 | readCiLin(); 122 | 123 | //如果比较词没有出现在同义词词林中,则相似度为0 124 | if (!wordsEncode.containsKey(word1) || !wordsEncode.containsKey(word2)) { 125 | return 0; 126 | } 127 | //获取第一个词的编码 128 | ArrayList encode1 = getEncode(word1); 129 | //获取第二个词的编码 130 | ArrayList encode2 = getEncode(word2); 131 | 132 | double maxValue = 0;//最终的计算结果值,取所有相似度里面结果最大的那个 133 | for (String e1 : encode1) { 134 | for (String e2 : encode2) { 135 | log.info(e1); 136 | log.info(e2); 137 | String commonStr = getCommonStr(e1, e2); 138 | int length = StringUtils.length(commonStr); 139 | double k = getK(e1, e2); 140 | double n = getN(commonStr); 141 | log.info("k-->" + k); 142 | log.info("n-->" + n); 143 | log.info("encode length-->" + length); 144 | double res = 0; 145 | //如果有一个以“@”那么表示自我封闭,肯定不在一棵树上,直接返回f 146 | if (e1.endsWith("@") || e2.endsWith("@") || 0 == length) { 147 | if (f > maxValue) { 148 | maxValue = f; 149 | } 150 | continue; 151 | } 152 | if (1 == length) { 153 | //说明在第二层上计算 154 | res = a * cos(n * PI / degrees) * ((n - k + 1) / n); 155 | } else if (2 == length) { 156 | //说明在第三层上计算 157 | res = b * cos(n * PI / degrees) * ((n - k + 1) / n); 158 | } else if (4 == length) { 159 | //说明在第四层上计算 160 | res = c * cos(n * PI / degrees) * ((n - k + 1) / n); 161 | } else if (5 == length) { 162 | //说明在第五层上计算 163 | res = d * cos(n * PI / degrees) * ((n - k + 1) / n); 164 | } else { 165 | //注意不存在前面七个字符相同,而结尾不同的情况,所以这个分支一定是8个字符都相同,那么只需比较结尾即可 166 | if (e1.endsWith("=") && e2.endsWith("=")) { 167 | //说明两个完全相同 168 | res = 1; 169 | } else if (e1.endsWith("#") && e2.endsWith("#")) { 170 | //只有结尾不同,说明结尾是“#” 171 | res = e; 172 | } 173 | } 174 | log.info("res: " + res); 175 | if (res > maxValue) { 176 | maxValue = res; 177 | } 178 | } 179 | } 180 | return maxValue; 181 | } 182 | 183 | /** 184 | * 判断一个词在同义词词林中是否是自我封闭的,是否是独立的 185 | * 186 | * @param source 187 | * @return 188 | */ 189 | private boolean isIndependent(String source) { 190 | Iterator iter = wordsEncode.keySet().iterator(); 191 | while (iter.hasNext()) { 192 | String key = iter.next(); 193 | if (StringUtils.equalsIgnoreCase(key, source)) { 194 | ArrayList values = wordsEncode.get(key); 195 | for (String value : values) { 196 | if (value.endsWith("@")) { 197 | return true; 198 | } 199 | } 200 | } 201 | 202 | } 203 | return false; 204 | } 205 | 206 | /** 207 | * 根据word的内容,返回其对应的编码 208 | * 209 | * @param word 210 | * @return 211 | */ 212 | protected static ArrayList getEncode(String word) { 213 | return wordsEncode.get(word); 214 | } 215 | 216 | /** 217 | * 计算N的值,N表示所在分支层分支数,如:人 Aa01A01= 和 少儿 Ab04B01=,以A开头的子分支只有14个 218 | * 这一点在论文中说的非常不清晰,所以以国人的文章进行编码真是痛苦 219 | * 220 | * @param encodeHead 输入两个字符串的公共开头 221 | * @return 经过计算之后得到N的值 222 | */ 223 | protected static int getN(String encodeHead) { 224 | int length = StringUtils.length(encodeHead); 225 | switch (length) { 226 | case 1: 227 | return getCount(encodeHead, 2); 228 | case 2: 229 | return getCount(encodeHead, 4); 230 | case 4: 231 | return getCount(encodeHead, 5); 232 | case 5: 233 | return getCount(encodeHead, 7); 234 | default: 235 | return 0; 236 | } 237 | } 238 | 239 | protected static int getCount(String encodeHead, int end) { 240 | Set res = new HashSet(); 241 | Iterator iter = encodeWords.keySet().iterator(); 242 | while (iter.hasNext()) { 243 | String curr = iter.next(); 244 | if (curr.startsWith(encodeHead)) { 245 | String temp = curr.substring(0, end); 246 | if (res.contains(temp)) { 247 | continue; 248 | } else { 249 | res.add(temp); 250 | } 251 | } 252 | } 253 | return res.size(); 254 | } 255 | 256 | /** 257 | * @param encode1 第一个编码 258 | * @param encode2 第二个编码 259 | * @return 这两个编码对应的分支间的距离,用k表示 260 | */ 261 | protected static int getK(String encode1, String encode2) { 262 | String temp1 = encode1.substring(0, 1); 263 | String temp2 = encode2.substring(0, 1); 264 | if (StringUtils.equalsIgnoreCase(temp1, temp2)) { 265 | temp1 = encode1.substring(1, 2); 266 | temp2 = encode2.substring(1, 2); 267 | } else { 268 | return Math.abs(temp1.charAt(0) - temp2.charAt(0)); 269 | } 270 | if (StringUtils.equalsIgnoreCase(temp1, temp2)) { 271 | temp1 = encode1.substring(2, 4); 272 | temp2 = encode2.substring(2, 4); 273 | } else { 274 | return Math.abs(temp1.charAt(0) - temp2.charAt(0)); 275 | } 276 | if (StringUtils.equalsIgnoreCase(temp1, temp2)) { 277 | temp1 = encode1.substring(4, 5); 278 | temp2 = encode2.substring(4, 5); 279 | } else { 280 | return Math.abs(Integer.valueOf(temp1) - Integer.valueOf(temp2)); 281 | } 282 | if (StringUtils.equalsIgnoreCase(temp1, temp2)) { 283 | temp1 = encode1.substring(5, 7); 284 | temp2 = encode2.substring(5, 7); 285 | } else { 286 | return Math.abs(temp1.charAt(0) - temp2.charAt(0)); 287 | } 288 | return Math.abs(Integer.valueOf(temp1) - Integer.valueOf(temp2)); 289 | } 290 | 291 | /** 292 | * 获取编码的公共部分字符串 293 | * 294 | * @param encode1 295 | * @param encode2 296 | * @return 297 | */ 298 | protected static String getCommonStr(String encode1, String encode2) { 299 | int length = StringUtils.length(encode1); 300 | StringBuilder sb = new StringBuilder(); 301 | 302 | for (int i = 0; i < length; i++) { 303 | if (encode1.charAt(i) == encode2.charAt(i)) { 304 | sb.append(encode1.charAt(i)); 305 | } else { 306 | break; 307 | } 308 | } 309 | int sbLen = StringUtils.length(sb); 310 | //注意第三层和第五层均有两个字符,所以长度不可能出现3和6的情况 311 | if (sbLen == 3 || sbLen == 6) { 312 | sb.deleteCharAt(sbLen - 1); 313 | } 314 | 315 | return String.valueOf(sb); 316 | } 317 | 318 | @Test 319 | public void testGetN() { 320 | readCiLin(); 321 | int a = getN("A"); 322 | System.out.println(a); 323 | } 324 | 325 | @Test 326 | public void testGetK() { 327 | int k = getK("Aa01A01=", "Aa01A01="); 328 | System.out.println(k); 329 | } 330 | 331 | @Test 332 | public void testGetCommonStr() { 333 | String commonStr = getCommonStr("Aa01A01=", "Aa01A03="); 334 | System.out.println(commonStr); 335 | } 336 | 337 | @Test 338 | public void testGetSimilarity() { 339 | readCiLin(); 340 | double similarity = getSimilarity("人民", "国民"); 341 | System.out.println("人民--" + "国民:" + similarity); 342 | similarity = getSimilarity("人民", "群众"); 343 | System.out.println("人民--" + "群众:" + similarity); 344 | similarity = getSimilarity("人民", "党群"); 345 | System.out.println("人民--" + "党群:" + similarity); 346 | similarity = getSimilarity("人民", "良民"); 347 | System.out.println("人民--" + "良民:" + similarity); 348 | similarity = getSimilarity("人民", "同志"); 349 | System.out.println("人民--" + "同志:" + similarity); 350 | similarity = getSimilarity("人民", "成年人"); 351 | System.out.println("人民--" + "成年人:" + similarity); 352 | similarity = getSimilarity("人民", "市民"); 353 | System.out.println("人民--" + "市民:" + similarity); 354 | similarity = getSimilarity("人民", "亲属"); 355 | System.out.println("人民--" + "亲属:" + similarity); 356 | similarity = getSimilarity("人民", "志愿者"); 357 | System.out.println("人民--" + "志愿者:" + similarity); 358 | similarity = getSimilarity("人民", "先锋"); 359 | System.out.println("人民--" + "先锋:" + similarity); 360 | } 361 | 362 | @Test 363 | public void testGetSimilarity2() { 364 | readCiLin(); 365 | double similarity = getSimilarity("非洲人", "亚洲人"); 366 | System.out.println(similarity); 367 | double similarity1 = getSimilarity("地震", "电"); 368 | System.out.println(similarity1); 369 | } 370 | 371 | } 372 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/sorting/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.sorting; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | *

9 | * Created with IntelliJ IDEA. 2016/1/8 19:37 10 | *

11 | *

12 | * ClassName:BubbleSort 13 | *

14 | *

15 | * Description:冒泡排序 16 | *

17 | * 18 | * @author Wang Xu 19 | * @version V1.0.0 20 | * @since V1.0.0 21 | */ 22 | public class BubbleSort { 23 | public void bubbleSort(int[] nums) { 24 | for (int i = 0; i < nums.length; i++) { 25 | for (int j = nums.length - 1; j > i; j--) { 26 | if (nums[i] > nums[j]) { 27 | swap(nums, i, j); 28 | } 29 | } 30 | } 31 | } 32 | 33 | public void swap(int[] nums, int one, int two) { 34 | int temp = nums[one]; 35 | nums[one] = nums[two]; 36 | nums[two] = temp; 37 | } 38 | 39 | @Test 40 | public void test() { 41 | int[] nums = new int[]{7, 3, 4, 23, 3, 9}; 42 | bubbleSort(nums); 43 | System.out.println(Arrays.toString(nums)); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/sorting/InsertSort.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.sorting; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | *

7 | * Created with IntelliJ IDEA. 2015/10/17 22:30 8 | *

9 | *

10 | * ClassName:InsertSort 11 | *

12 | *

13 | * Description:插入排序 14 | *

15 | * 16 | * @author Wang Xu 17 | * @version V1.0.0 18 | * @since V1.0.0 19 | */ 20 | public class InsertSort { 21 | public static void main(String[] args) { 22 | int[] nums = new int[]{9090, 4, 5, 2, 3, 1, 4, 5, 4, 4, 8989, 4}; 23 | for (int i = 1; i < nums.length; i++) { 24 | for (int j = i; j > 0; j--) { 25 | if (nums[j] < nums[j - 1]) { 26 | swap(nums, j, j - 1); 27 | } 28 | } 29 | } 30 | System.out.println(Arrays.toString(nums)); 31 | 32 | } 33 | 34 | //交换函数 35 | private static void swap(int[] nums, int first, int second) { 36 | int temp = nums[first]; 37 | nums[first] = nums[second]; 38 | nums[second] = temp; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/sorting/QuickSort.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.sorting; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | *

7 | * Created with IntelliJ IDEA. 2015/10/21 14:42 8 | *

9 | *

10 | * ClassName:QuickSort 11 | *

12 | *

13 | * Description:快速排序 14 | *

15 | * 16 | * @author Wang Xu 17 | * @version V1.0.0 18 | * @since V1.0.0 19 | */ 20 | public class QuickSort { 21 | public static void main(String[] args) { 22 | int[] nums = new int[]{3, 4, 5, 9, 1, 2, 33, 11, 22}; 23 | new QuickSort().quickSort(nums, 0, nums.length - 1); 24 | System.out.println(Arrays.toString(nums)); 25 | } 26 | 27 | public void quickSort(int nums[], int start, int end) { 28 | if (start >= end) { 29 | return; 30 | } 31 | int left = start; 32 | int right = end - 1; 33 | int mid = nums[end]; 34 | while (left < right) { 35 | while (nums[left] < mid && left < right) { 36 | left++; 37 | } 38 | 39 | while (nums[right] > mid && left < right) { 40 | right--; 41 | } 42 | swap(nums, left, right); 43 | } 44 | 45 | if (nums[left] > mid) { 46 | swap(nums, left, end); 47 | } else { 48 | left++; 49 | } 50 | quickSort(nums, start, left - 1); 51 | quickSort(nums, left + 1, end); 52 | } 53 | 54 | private void swap(int nums[], int left, int right) { 55 | int temp = nums[left]; 56 | nums[left] = nums[right]; 57 | nums[right] = temp; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/sorting/SelectionSort.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.sorting; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | *

9 | * Created with IntelliJ IDEA. 2016/1/8 19:43 10 | *

11 | *

12 | * ClassName:SelectionSort 13 | *

14 | *

15 | * Description:选择排序 16 | *

17 | * 18 | * @author Wang Xu 19 | * @version V1.0.0 20 | * @since V1.0.0 21 | */ 22 | public class SelectionSort { 23 | public void selectionSort(int[] nums) { 24 | int min; 25 | for (int i = 0; i < nums.length; i++) { 26 | min = i; 27 | for (int j = i + 1; j < nums.length; j++) { 28 | if (nums[j] < nums[min]) { 29 | min = j; 30 | } 31 | } 32 | swap(nums, i, min); 33 | } 34 | } 35 | 36 | public void swap(int[] nums, int one, int two) { 37 | int temp = nums[one]; 38 | nums[one] = nums[two]; 39 | nums[two] = temp; 40 | } 41 | 42 | @Test 43 | public void test() { 44 | int[] nums = new int[]{9, 3, 4, 22, 33, 1, 9, 11, 10}; 45 | selectionSort(nums); 46 | System.out.println(Arrays.toString(nums)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/sorting/ShellSort.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.sorting; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | *

7 | * Created with IntelliJ IDEA. 2015/10/19 10:17 8 | *

9 | *

10 | * ClassName:ShellSort 11 | *

12 | *

13 | * Description:希尔排序 14 | *

15 | * 16 | * @author Wang Xu 17 | * @version V1.0.0 18 | * @since V1.0.0 19 | */ 20 | public class ShellSort { 21 | public static void main(String[] args) { 22 | int[] nums = new int[]{9, 8, 7, 6, 4, 1, 11, 12, 122, 122, 1222, 12222, 14433}; 23 | int length = nums.length; 24 | int d = 1; 25 | while (d < length / 3) { 26 | //之所以对d进行这种操作,是因为如下性质:使用递增序列1, 4, 13, 40, 121, 364…的希尔排序所需的比较次数不会超出N的若干倍乘以递增序列的长度 27 | d = d * 3 + 1; 28 | } 29 | while (d >= 1) { 30 | for (int i = d; i < length; i++) { 31 | for (int j = i; j >= d; j -= d) { 32 | if (nums[j - d] > nums[j]) { 33 | swap(nums, j, j - d); 34 | } 35 | } 36 | } 37 | d = d / 3; 38 | } 39 | 40 | System.out.println(Arrays.toString(nums)); 41 | } 42 | 43 | private static void swap(int[] nums, int first, int second) { 44 | int temp = nums[first]; 45 | nums[first] = nums[second]; 46 | nums[second] = temp; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/spelling/ChineseToSpelling.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.spelling; 2 | 3 | import com.github.stuxuhai.jpinyin.PinyinFormat; 4 | import com.github.stuxuhai.jpinyin.PinyinHelper; 5 | 6 | /** 7 | *

8 | * Created with IntelliJ IDEA. 2015/12/12 23:47 9 | *

10 | *

11 | * ClassName:ChineseToSpelling 12 | *

13 | *

14 | * Description:使用JPinyin组件将汉字转成拼音 15 | *

16 | * 17 | * @author Wang Xu 18 | * @version V1.0.0 19 | * @since V1.0.0 20 | */ 21 | public class ChineseToSpelling { 22 | /** 23 | * 24 | */ 25 | public static String convertChineseToSpelling(String chinese, SpellingFormat spellingFormat) { 26 | String res = null; 27 | switch (spellingFormat) { 28 | case WITH_TONE_MARK: 29 | res = PinyinHelper.convertToPinyinString(chinese, ",", PinyinFormat.WITH_TONE_MARK); // nǐ,hǎo,shì,jiè 30 | break; 31 | case WITH_TONE_NUMBER: 32 | res = PinyinHelper.convertToPinyinString(chinese, ",", PinyinFormat.WITH_TONE_NUMBER); // ni3,hao3,shi4,jie4 33 | break; 34 | case WITHOUT_TONE: 35 | res = PinyinHelper.convertToPinyinString(chinese, ",", PinyinFormat.WITHOUT_TONE); // ni,hao,shi,jie 36 | break; 37 | case SHORT_PINYIN: 38 | res = PinyinHelper.getShortPinyin(chinese); // nhsj 39 | break; 40 | default: 41 | res = "ERROR"; 42 | } 43 | return res; 44 | } 45 | } 46 | 47 | enum SpellingFormat { 48 | WITH_TONE_MARK, WITH_TONE_NUMBER, WITHOUT_TONE, SHORT_PINYIN; 49 | } -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/stack/BracketsApp.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.stack; 2 | 3 | import cn.codepub.algorithms.utils.StackX; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | 9 | /** 10 | *

11 | * Created with IntelliJ IDEA. 2016/1/8 20:17 12 | *

13 | *

14 | * ClassName:BracketsApp 15 | *

16 | *

17 | * Description:判断括号是否匹配,For Example:(((()))) 18 | *

19 | * 20 | * @author Wang Xu 21 | * @version V1.0.0 22 | * @since V1.0.0 23 | */ 24 | 25 | public class BracketsApp { 26 | public static void main(String[] args) throws IOException { 27 | String input; 28 | while (true) { 29 | System.out.println("Enter string containing delimiters:"); 30 | System.out.flush(); 31 | input = getString(); 32 | if (input.equals("")) { 33 | break; 34 | } 35 | BracketChecker theChecker = new BracketChecker(input); 36 | theChecker.check(); 37 | } 38 | } 39 | 40 | public static String getString() throws IOException { 41 | InputStreamReader isr = new InputStreamReader(System.in); 42 | BufferedReader br = new BufferedReader(isr); 43 | String str = br.readLine(); 44 | return str; 45 | } 46 | } 47 | 48 | class BracketChecker { 49 | private String input; 50 | 51 | public BracketChecker(String in) { 52 | this.input = in; 53 | } 54 | 55 | public void check() { 56 | int stackSize = input.length(); 57 | StackX theStack = new StackX(stackSize); 58 | for (int j = 0; j < input.length(); j++) { 59 | char ch = input.charAt(j); 60 | switch (ch) { 61 | case '{': 62 | case '[': 63 | case '(': 64 | theStack.push(ch); 65 | break; 66 | case '}': 67 | case ']': 68 | case ')': 69 | if (!theStack.isEmpty()) { 70 | char chx = theStack.pop(); 71 | if ((ch == '}' && chx != '{') || (ch == ']' && chx != '[') 72 | || (ch == ')' && chx != '(')) { 73 | System.out.println("Error:" + ch + " at " + (j + 1)); 74 | } 75 | } else { 76 | System.out.println("Error:" + ch + " at " + (j + 1)); 77 | } 78 | default: 79 | break; 80 | } 81 | } 82 | if (!theStack.isEmpty()) { 83 | System.out.println("Error:missing right delimiter"); 84 | } else { 85 | System.out.println("It is legitimate!"); 86 | } 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/stack/CheckStackSequence.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.stack; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | *

7 | * Created with IntelliJ IDEA. 2015/10/29 21:43 8 | *

9 | *

10 | * ClassName:CheckStackSequence 11 | *

12 | *

13 | * Description: 14 | * 题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。 15 | * 例如序列1,2,3,4,5是某栈的压栈序列,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但是4,3,5,1,2就不可能是其弹出序列 16 | *

17 | * 解题思路:既然是判断栈的弹栈序列是否合法,那么就用一个栈来模拟弹出序列即可,最后栈空说明全部弹出,合法,否则栈非空说明不合法 18 | * ① 如果下一个弹出元素和刚好要入栈元素一致,两者都向后走 19 | * ② 如果下一个弹出元素和栈顶元素一致,那么先弹栈再入栈 20 | * ③ 如果下一个弹出元素和要入栈元素不一致,且和栈顶元素也不一致,那么将要入栈元素压栈 21 | * ④ 最后如果按照弹栈序列能将栈弹空,那么说明序列合法,否则不合法 22 | *

23 | *

24 | * 25 | * @author Wang Xu 26 | * @version V1.0.0 27 | * @since V1.0.0 28 | */ 29 | public class CheckStackSequence { 30 | public static void main(String[] args) { 31 | int[] nums1 = new int[]{1, 2, 3, 4, 5}; 32 | int[] nums2 = new int[]{4, 5, 3, 2, 1}; 33 | boolean check = check(nums1, nums2); 34 | System.out.println(check); 35 | 36 | int[] nums3 = new int[]{1, 4, 5, 2, 3}; 37 | boolean check1 = check(nums1, nums3); 38 | System.out.println(check1); 39 | 40 | int[] nums4 = new int[]{4, 3, 5, 1, 2}; 41 | boolean check2 = check(nums1, nums4); 42 | System.out.println(check2); 43 | 44 | int[] nums5 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; 45 | int[] nums6 = new int[]{3, 8, 7, 9, 6, 5, 4, 2, 1}; 46 | boolean check3 = check(nums5, nums6); 47 | System.out.println(check3); 48 | 49 | } 50 | 51 | /** 52 | * @param nums1 入栈序列 53 | * @param nums2 出栈序列 54 | * @return 出栈序列是否合法 55 | */ 56 | public static boolean check(int[] nums1, int[] nums2) { 57 | Stack stack = new Stack(); 58 | int current = 0; 59 | for (int i = 0; i < nums1.length; i++) { 60 | if (nums2[current] == nums1[i]) {//说明该元素入栈之后即刻出栈,所以将i和current递增即刻 61 | current++; 62 | } else { 63 | //如果在下一个元素入栈之前有元素要弹栈,那么需要先弹栈再入栈 64 | if (!stack.isEmpty() && nums2[current] == stack.peek()) { 65 | current++; 66 | stack.pop(); 67 | stack.push(nums1[i]);//别忘记将新的元素入栈 68 | } else { 69 | //直接入栈 70 | stack.push(nums1[i]); 71 | } 72 | } 73 | } 74 | //剩下的栈内元素都是依次出栈即可 75 | while (current < nums2.length && nums2[current] == stack.peek() && !stack.isEmpty()) { 76 | current++; 77 | stack.pop(); 78 | } 79 | if (stack.isEmpty()) { 80 | return true; 81 | } 82 | return false; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/stack/InfixApp.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.stack; 2 | 3 | import cn.codepub.algorithms.utils.StackX; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | 9 | /** 10 | *

11 | * Created with IntelliJ IDEA. 2016/1/8 19:16 12 | *

13 | *

14 | * ClassName:InfixApp 15 | *

16 | *

17 | * Description:中缀表达式转后缀表达式,For Example
18 | * Enter infix:
19 | * 2+4-4+3*2
20 | * Postfix is 24+4-32*+
21 | *

22 | * 23 | * @author Wang Xu 24 | * @version V1.0.0 25 | * @since V1.0.0 26 | */ 27 | public class InfixApp { 28 | public static void main(String[] args) throws IOException { 29 | String input, output; 30 | while (true) { 31 | System.out.println("Enter infix:"); 32 | System.out.flush(); 33 | input = getString(); 34 | if (input.equals("")) { 35 | break; 36 | } 37 | InToPost theTrans = new InToPost(input); 38 | output = theTrans.doTrans(); 39 | System.out.println("Postfix is " + output + "\n"); 40 | } 41 | 42 | } 43 | 44 | public static String getString() throws IOException { 45 | InputStreamReader isr = new InputStreamReader(System.in); 46 | BufferedReader br = new BufferedReader(isr); 47 | String s = br.readLine(); 48 | return s; 49 | } 50 | 51 | } 52 | 53 | 54 | class InToPost { 55 | private StackX theStack; 56 | private String input; 57 | private String output = ""; 58 | 59 | public InToPost(String in) { 60 | input = in; 61 | int stackSize = input.length(); 62 | theStack = new StackX(stackSize); 63 | } 64 | 65 | public String doTrans() { 66 | for (int j = 0; j < input.length(); j++) { 67 | char ch = input.charAt(j); 68 | theStack.displayStack("For " + ch + " "); 69 | switch (ch) { 70 | case '+': 71 | case '-': 72 | gotOper(ch, 1); 73 | break; 74 | case '*': 75 | case '/': 76 | gotOper(ch, 2); 77 | break; 78 | case '(': 79 | theStack.push(ch); 80 | break; 81 | case ')': 82 | gotParen(ch); 83 | break; 84 | default: 85 | output = output + ch; 86 | break; 87 | } 88 | } 89 | while (!theStack.isEmpty()) { 90 | theStack.displayStack("While "); 91 | output = output + theStack.pop(); 92 | } 93 | theStack.displayStack("End "); 94 | return output; 95 | } 96 | 97 | public void gotOper(char opThis, int prec1) { 98 | while (!theStack.isEmpty()) { 99 | char opTop = theStack.pop(); 100 | if (opTop == '(') { 101 | theStack.push(opTop); 102 | break; 103 | } else { 104 | int prec2; 105 | if (opTop == '+' || opTop == '-') { 106 | prec2 = 1; 107 | } else { 108 | prec2 = 2; 109 | } 110 | if (prec2 < prec1) { 111 | theStack.push(opTop); 112 | break; 113 | } else { 114 | output = output + opTop; 115 | } 116 | } 117 | } 118 | theStack.push(opThis); 119 | } 120 | 121 | public void gotParen(char ch) { 122 | while (!theStack.isEmpty()) { 123 | char chx = theStack.pop(); 124 | if (chx == '(') { 125 | break; 126 | } else { 127 | output = output + chx; 128 | } 129 | } 130 | } 131 | } 132 | 133 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/stack/MinStack.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.stack; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | *

7 | * Created with IntelliJ IDEA. 2015/10/29 12:22 8 | *

9 | *

10 | * ClassName:MinStack 11 | *

12 | *

13 | * Description: 14 | * 题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push及pop的时间复杂度都是O(1) 15 | *

16 | * 17 | * @author Wang Xu 18 | * @version V1.0.0 19 | * @since V1.0.0 20 | */ 21 | public class MinStack { 22 | public static void main(String[] args) { 23 | Stack numberStack = new Stack<>();//存储元素的栈 24 | Stack minStack = new Stack<>();//到当前元素为止,栈顶始终是最小的一个元素 25 | int nums[] = new int[]{3, 4, 2, 1, 9}; 26 | for (int i : nums) { 27 | numberStack.push(i); 28 | if (!minStack.isEmpty() && i > minStack.peek()) {//与minStack的栈顶元素比较,如果比其大,将栈顶元素再次入栈 29 | minStack.push(minStack.peek()); 30 | } else {//如果比其小,说明当前最小的元素是i,将i入栈 31 | minStack.push(i); 32 | } 33 | } 34 | System.out.println(numberStack); 35 | System.out.println(minStack); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/stack/PostfixApp.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.stack; 2 | 3 | 4 | import cn.codepub.algorithms.utils.StackX; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.InputStreamReader; 8 | 9 | /** 10 | *

11 | * Created with IntelliJ IDEA. 2016/1/8 19:04 12 | *

13 | *

14 | * ClassName:PostfixApp 15 | *

16 | *

17 | * Description:求解后缀表达式,For Example
18 | * Enter postfix:34*2/
19 | * 3 Stack(bottom->top):
20 | * 4 Stack(bottom->top):3
21 | * Stack(bottom->top):3 4
22 | * 2 Stack(bottom->top):12
23 | * / Stack(bottom->top):12 2
24 | * Evaluates to 6
25 | *

26 | * 27 | * @author Wang Xu 28 | * @version V1.0.0 29 | * @since V1.0.0 30 | */ 31 | public class PostfixApp { 32 | public static void main(String[] args) throws Exception { 33 | String input; 34 | int output; 35 | while (true) { 36 | System.out.print("Enter postfix:"); 37 | System.out.flush(); 38 | input = getString(); 39 | if (input.equals("")) { 40 | break; 41 | } 42 | ParsePost aParse = new ParsePost(input); 43 | output = aParse.doParse(); 44 | System.out.println("Evaluates to " + output); 45 | } 46 | } 47 | 48 | public static String getString() throws Exception { 49 | InputStreamReader isr = new InputStreamReader(System.in); 50 | BufferedReader buf = new BufferedReader(isr); 51 | String s = buf.readLine(); 52 | return s; 53 | } 54 | } 55 | 56 | 57 | class ParsePost { 58 | private StackX theStack; 59 | private String input; 60 | 61 | public ParsePost(String s) { 62 | input = s; 63 | } 64 | 65 | public int doParse() { 66 | theStack = new StackX(20); 67 | char ch; 68 | int j; 69 | int num1, num2, interAns; 70 | for (j = 0; j < input.length(); j++) { 71 | ch = input.charAt(j); 72 | theStack.displayStack("" + ch + " "); 73 | if (ch >= '0' && ch <= '9') { 74 | theStack.push((int) (ch - '0')); 75 | } else { 76 | num2 = theStack.pop(); 77 | num1 = theStack.pop(); 78 | switch (ch) { 79 | case '+': 80 | interAns = num1 + num2; 81 | break; 82 | case '-': 83 | interAns = num1 - num2; 84 | break; 85 | case '*': 86 | interAns = num1 * num2; 87 | break; 88 | case '/': 89 | interAns = num1 / num2; 90 | break; 91 | default: 92 | interAns = 0; 93 | break; 94 | } 95 | theStack.push(interAns); 96 | } 97 | } 98 | interAns = theStack.pop(); 99 | return interAns; 100 | } 101 | } -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/BinarySearch.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | /** 4 | *

5 | * Created with IntelliJ IDEA. 2015/10/15 17:15 6 | *

7 | *

8 | * ClassName:BinarySearch 9 | *

10 | *

11 | * Description:二分查找 12 | * 注意点:数组在传递进来之前一定是排好序的数组,采用递归实现的方法一定要提供出口 13 | *

14 | * 15 | * @author Wang Xu 16 | * @version V1.0.0 17 | * @since V1.0.0 18 | */ 19 | public class BinarySearch { 20 | 21 | /** 22 | * 递归方式实现二分查找 23 | * 24 | * @param nums 查找的数组 25 | * @param start 开始下标 26 | * @param end 结束下标 27 | * @param key 查找元素 28 | * @return 查找元素的下标,当未查到的时候,返回-1 29 | */ 30 | private static int recursionBinarySearch(int[] nums, int start, int end, int key) { 31 | if (start > end) { 32 | return -1; 33 | } 34 | int mid = start + ((end - start) >> 1); 35 | if (nums[mid] == key) { 36 | return mid; 37 | } else if (nums[mid] > key) { 38 | //说明key在当前分组的左半边 39 | return recursionBinarySearch(nums, start, mid - 1, key); 40 | } else { 41 | //在右半边 42 | return recursionBinarySearch(nums, mid + 1, end, key); 43 | } 44 | 45 | 46 | } 47 | 48 | /** 49 | * 非递归方式实现二分查找 50 | * 51 | * @param nums 查找的数组 52 | * @param key 查找元素 53 | * @return 查找元素的下标,当未查到返回-1 54 | */ 55 | private static int nonRecursionBinarySearch(int[] nums, int key) { 56 | int start = 0; 57 | int end = nums.length - 1; 58 | while (start <= end) { 59 | //防止(start + end) >>1 溢出 60 | //JDK中的Arrays.binarySearch使用(low + high) >>> 1; 61 | int mid = start + ((end - start) >> 1); 62 | if (nums[mid] == key) { 63 | return mid; 64 | } else if (nums[mid] > key) { 65 | end = mid - 1; 66 | } else { 67 | start = mid + 1; 68 | } 69 | } 70 | return -1; 71 | } 72 | 73 | public static void main(String[] args) { 74 | int[] nums = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 11}; 75 | int i = recursionBinarySearch(nums, 0, nums.length - 1, 11); 76 | System.out.println(i); 77 | i = recursionBinarySearch(nums, 0, nums.length - 1, 12); 78 | System.out.println(i); 79 | i = recursionBinarySearch(nums, 0, nums.length - 1, 0); 80 | System.out.println(i); 81 | i = nonRecursionBinarySearch(nums, 11); 82 | System.out.println(i); 83 | i = nonRecursionBinarySearch(nums, 12); 84 | System.out.println(i); 85 | i = nonRecursionBinarySearch(nums, 0); 86 | System.out.println(i); 87 | nums = new int[]{1}; 88 | i = recursionBinarySearch(nums, 0, nums.length - 1, 1); 89 | System.out.println(i); 90 | i = nonRecursionBinarySearch(nums, 1); 91 | System.out.println(i); 92 | } 93 | } -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/Combination.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | /** 4 | *

5 | * Created with IntelliJ IDEA. 2015/10/30 21:43 6 | *

7 | *

8 | * ClassName:Combination 9 | *

10 | *

11 | * Description:组合:一般地,从m个不同的元素中,任取n(n≤m)个元素为一组,叫作从m个不同元素中取出n个元素的一个组合 12 | *

13 | * 14 | * @author Wang Xu 15 | * @version V1.0.0 16 | * @since V1.0.0 17 | */ 18 | public class Combination { 19 | 20 | static StringBuilder sb = new StringBuilder(); 21 | 22 | public static void main(String[] args) { 23 | char[] strs = new char[]{'a', 'b', 'c', 'd', 'e'}; 24 | for (int i = 1; i <= strs.length; i++) { 25 | combination(strs, 0, i); 26 | } 27 | 28 | System.out.println("测试第二种方法"); 29 | combination(); 30 | } 31 | 32 | /** 33 | * 第一种方法 34 | * 35 | * @param strs 需要操作的字符数组 36 | * @param start 从哪里开始取 37 | * @param number 取几个字符 38 | */ 39 | public static void combination(char[] strs, int start, int number) { 40 | //定义函数出口先 41 | if (number <= 0 || start >= strs.length) { 42 | System.out.println(sb.toString()); 43 | return; 44 | } 45 | //选取当前字符的话,需要将number-1 46 | sb.append(strs[start]); 47 | combination(strs, start + 1, number - 1); 48 | //不选取当前字符的话,number不变 49 | sb.deleteCharAt(sb.length() - 1); 50 | //注意因为还需要从start+1的位置开始取number个字符,那么如果剩下的字符不足number就没必要去取了 51 | if (strs.length - start > number) { 52 | combination(strs, start + 1, number); 53 | } 54 | 55 | } 56 | 57 | /** 58 | * 第二种方法 59 | * 基本思路:求全组合,则假设原有元素n个,则最终组合结果是2^n个。原因是: 用位操作方法:假设元素原本有:a,b,c三个,则1表示取该元素,0表示不取。故去a则是001,取ab则是011
60 | * 所以一共三位,每个位上有两个选择0,1。所以是2^n个结果。这些结果的位图值都是0,1,2....2^n。所以可以类似全真表一样,从值0到值2^n依次输出结果:即:000,001,010,011,100,101,110,111
61 | * 对应输出组合结果为:空,a,b,ab,c,ac,bc,abc. 这个输出顺序刚好跟数字0~2^n结果递增顺序一样 取法的二进制数其实就是从0到2^n-1的十进制数 62 | */ 63 | public static void combination() { 64 | String[] str = {"a", "b", "c"}; 65 | int n = str.length; // 元素个数。 66 | // 求出位图全组合的结果个数:2^n 67 | int nbit = 1 << n; // “<<” 表示 左移:各二进位全部左移若干位,高位丢弃,低位补0。:即求出2^n=2Bit。 68 | // System.out.println("全组合结果个数为:" + nbit + ",二进制:" + Integer.toBinaryString(nbit)); 69 | for (int i = 0; i < nbit; i++) { // 结果有nbit个。输出结果从数字小到大输出:即输出0,1,2,3,....2^n。 70 | // System.out.print("组合数值 " + i + " 对应编码为: "); 71 | for (int j = 0; j < n; j++) { // 每个数二进制最多可以左移n次,即遍历完所有可能的变化新二进制数值了 72 | int tmp = 1 << j; 73 | // System.out.println("->" + Integer.toBinaryString(tmp)); 74 | if ((tmp & i) != 0) { // & 表示与。两个位都为1时,结果才为1 75 | System.out.print(str[j]); 76 | } 77 | } 78 | System.out.println(); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/JaccardSimilarityCoefficient.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | import com.google.common.base.Preconditions; 4 | import com.google.common.collect.Sets; 5 | import org.apache.commons.lang3.StringUtils; 6 | 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | /** 11 | *

12 | * Created with IntelliJ IDEA. 2015/8/9 14:22 13 | *

14 | *

15 | * ClassName:JaccardSimilarityCoefficient 16 | *

17 | *

18 | * Description:杰卡德相似系数,是衡量两个集合的相似度的一种指标,J(A,B)=|A∩B|/|A∪B| 19 | * 杰卡德距离,是衡量两个集合中不同元素占所有元素的比例来衡量两个集合的区分度,Ja(A,B)=1-J(A,B) 20 | *

21 | * 22 | * @author Wang Xu 23 | * @version V1.0.0 24 | * @since V1.0.0 25 | */ 26 | public class JaccardSimilarityCoefficient { 27 | public double getJSC(String str1, String str2) { 28 | if (StringUtils.isEmpty(str1) && StringUtils.isEmpty(str2)) { 29 | return 1; 30 | } 31 | Set s1 = new HashSet(); 32 | Set s2 = new HashSet(); 33 | str1 = Preconditions.checkNotNull(str1); 34 | str2 = Preconditions.checkNotNull(str2); 35 | char[] chars1 = str1.toCharArray(); 36 | char[] chars2 = str2.toCharArray(); 37 | for (char c : chars1) { 38 | s1.add(c); 39 | } 40 | for (char c : chars2) { 41 | s2.add(c); 42 | } 43 | 44 | //求交集 45 | Set intersection = new HashSet(); 46 | intersection.addAll(s1); 47 | intersection.retainAll(s2); 48 | 49 | //求并集 50 | Set union = new HashSet(); 51 | union.addAll(s1); 52 | union.addAll(s2); 53 | 54 | return (double) intersection.size() / union.size(); 55 | } 56 | 57 | public static double calcBySets(String s0, String s1) { 58 | if (s0.isEmpty() && s1.isEmpty()) { 59 | return 1.0; 60 | } 61 | 62 | Set words0 = new HashSet(); 63 | Set words1 = new HashSet(); 64 | for (int i = 0; i < s0.length(); i++) { 65 | words0.add(s0.charAt(i)); 66 | } 67 | for (int i = 0; i < s1.length(); i++) { 68 | words1.add(s1.charAt(i)); 69 | } 70 | 71 | double intersect = Sets.intersection(words0, words1).size(); 72 | double union = Sets.union(words0, words1).size(); 73 | 74 | System.out.println(Sets.union(words0, words1)); 75 | return intersect / union; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/LCS.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.junit.Test; 5 | 6 | /** 7 | *

8 | * Created with IntelliJ IDEA. 9 | *

10 | *

11 | * ClassName:LCS 12 | *

13 | *

14 | * Description:最长公共子序列 15 | *

16 | * 17 | * @author Wang Xu 18 | * @version V1.0.0 19 | */ 20 | public class LCS { 21 | public static String lcsBase(String inputX, String inputY) { 22 | if (StringUtils.isEmpty(inputX) || StringUtils.isEmpty(inputY) || inputX.length() == 0 || inputY.length() == 0) { 23 | return ""; 24 | } else { 25 | char x = inputX.charAt(0); 26 | char y = inputY.charAt(0); 27 | if (x == y) { 28 | return lcsBase(inputX.substring(1), inputY.substring(1)) + x; 29 | } else { 30 | return getMax(lcsBase(inputX.substring(1), inputY), lcsBase(inputX, inputY.substring(1))); 31 | } 32 | 33 | } 34 | } 35 | 36 | private static String getMax(String x, String y) { 37 | Integer xLen = 0; 38 | Integer yLen = 0; 39 | if (StringUtils.isEmpty(x)) { 40 | xLen = 0; 41 | } else { 42 | xLen = x.length(); 43 | } 44 | if (StringUtils.isEmpty(y)) { 45 | yLen = 0; 46 | } else { 47 | yLen = y.length(); 48 | } 49 | 50 | if (xLen >= yLen) { 51 | return x; 52 | } else { 53 | return y; 54 | } 55 | } 56 | 57 | @Test 58 | public void test() { 59 | // 蓬安县房屋瓦片被震 60 | String base1 = "落广西陕西震感强烈"; 61 | String base2 = "汶川地震致重庆4名学生死亡100多人受伤"; 62 | String s = lcsBase(base1, base2); 63 | System.out.println(StringUtils.reverse(s)); 64 | 65 | String s2 = lcsBase("1233433236676", "98723765655423"); 66 | 67 | System.out.println(StringUtils.reverse(s2)); 68 | 69 | String s1 = lcsBase("123s212346我的大中国啊33z", "33z的大中国"); 70 | System.out.println(StringUtils.reverse(s1)); 71 | 72 | Integer a = 10000, b = 1000; 73 | Integer c = 100, d = 100; 74 | System.out.println(a == b); 75 | System.out.println(c == d); 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/LCS2.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.junit.Test; 5 | 6 | /** 7 | *

8 | * Created with IntelliJ IDEA. 9 | *

10 | *

11 | * ClassName:LCS2 12 | *

13 | *

14 | * Description:最长公共子串算法 15 | *

16 | * 17 | * @author Wang Xu 18 | * @version V1.0.0 19 | */ 20 | public class LCS2 { 21 | private static Integer getComLen(String firstStr, String secondStr) { 22 | Integer comLen = 0; 23 | while (StringUtils.isNotEmpty(firstStr) && StringUtils.isNotEmpty(secondStr)) { 24 | if (firstStr.charAt(0) == secondStr.charAt(0)) { 25 | comLen += 1; 26 | firstStr = firstStr.substring(1); 27 | secondStr = secondStr.substring(1); 28 | } else { 29 | break; 30 | } 31 | } 32 | return comLen; 33 | } 34 | 35 | private static String lcsBase(String inputX, String inputY) { 36 | Integer maxComLen = 0; 37 | Integer commonIndex = 0; 38 | 39 | for (int i = 0; i < inputX.length(); i++) { 40 | for (int j = 0; j < inputY.length(); j++) { 41 | Integer comLen = getComLen(inputX.substring(i), inputY.substring(j)); 42 | if (comLen > maxComLen) { 43 | maxComLen = comLen; 44 | commonIndex = i; 45 | } 46 | } 47 | } 48 | return inputX.substring(commonIndex, commonIndex + maxComLen); 49 | } 50 | 51 | @Test 52 | public void test() { 53 | String s1 = "abcy交罚款撒了德萨 e"; 54 | String s2 = "abcx交罚款dfdsafdsa范德萨 e"; 55 | String s = lcsBase(s1, s2); 56 | System.out.println(s); 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/LCS3.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.junit.Test; 5 | 6 | /** 7 | *

8 | * Created with IntelliJ IDEA. 9 | *

10 | *

11 | * ClassName:LCS3 12 | *

13 | *

14 | * Description:使用动态规划解决最长公共子串 15 | *

16 | * 17 | * @author Wang Xu 18 | * @version V1.0.0 19 | */ 20 | public class LCS3 { 21 | public static String lcsDp(String inputX, String inputY) { 22 | int xLen = 0; 23 | int yLen = 0; 24 | int maxLen = 0, maxIndex = 0; 25 | 26 | if (StringUtils.isEmpty(inputX)) { 27 | xLen = 0; 28 | } else { 29 | xLen = inputX.length(); 30 | } 31 | if (StringUtils.isEmpty(inputY)) { 32 | yLen = 0; 33 | } else { 34 | yLen = inputY.length(); 35 | } 36 | 37 | int dp[][] = new int[xLen][yLen]; 38 | for (int i = 0; i < xLen; i++) { 39 | for (int j = 0; j < yLen; j++) { 40 | if (inputX.charAt(i) == inputY.charAt(j)) { 41 | if (i != 0 && j != 0) { 42 | dp[i][j] = dp[i - 1][j - 1] + 1; 43 | } 44 | if (0 == i || 0 == j) { 45 | dp[i][j] = 1; 46 | } 47 | if (dp[i][j] > maxLen) { 48 | maxLen = dp[i][j]; 49 | maxIndex = i + 1 - maxLen; 50 | } 51 | } 52 | 53 | } 54 | 55 | } 56 | return inputX.substring(maxIndex, maxIndex + maxLen); 57 | } 58 | 59 | @Test 60 | public void test() { 61 | String s1 = "我是美abc国中defg国中间人"; 62 | String s2 = "我是abdde我是美中国中国中国人"; 63 | String s = lcsDp(s1, s2); 64 | System.out.println(s); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/LevenshteinDistance.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.junit.Test; 5 | 6 | /** 7 | *

8 | * Created with IntelliJ IDEA. 9 | *

10 | *

11 | * ClassName:LevenshteinDistance 12 | *

13 | *

14 | * Description:编辑距离算法 15 | *

16 | * 17 | * @author Wang Xu 18 | * @version V1.0.0 19 | */ 20 | public class LevenshteinDistance { 21 | public static int leDistance(String inputX, String inputY) { 22 | int xLen = StringUtils.length(inputX) + 1; 23 | int yLen = StringUtils.length(inputY) + 1; 24 | int[][] dp = new int[xLen][yLen]; 25 | for (int i = 0; i < xLen; i++) { 26 | dp[i][0] = i; 27 | } 28 | for (int j = 0; j < yLen; j++) { 29 | dp[0][j] = j; 30 | } 31 | for (int i = 1; i < xLen; i++) { 32 | for (int j = 1; j < yLen; j++) { 33 | if (inputX.charAt(i - 1) == inputY.charAt(j - 1)) { 34 | dp[i][j] = dp[i - 1][j - 1]; 35 | } else { 36 | dp[i][j] = 1 + Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]); 37 | } 38 | 39 | } 40 | } 41 | return dp[xLen - 1][yLen - 1]; 42 | } 43 | 44 | @Test 45 | public void test() { 46 | int leDistance = LevenshteinDistance.leDistance("", "aa"); 47 | System.out.println(leDistance); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/LongestDecreasingSubSequence.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 求解思路(以递减子序列为例): 8 | * 1.用dp[i]代表以当前第i个字符为结尾时,所持有的最长递减子序列的长度 9 | * 2.初始化所有的dp[i]值为1,之后再一步步更新之 10 | * 3.如果nums[i-1]比nums[i]大,那么dp[i]=dp[i-1]+1 11 | * 4.否则的话,要取0<=j<=i之间最大那个dp[j],且该dp[j]满足nums[j]>nums[i],这种情况说明中间跳过了几个元素 12 | * 5.对于满足条件的dp[j]将dp[j]+1赋值给dp[i] 13 | */ 14 | public class LongestDecreasingSubSequence { 15 | public static void main(String[] args) { 16 | int[] nums = new int[]{1, 2, 3, 19, 12, 5, 4, 2, 3, 7, 9, 10, 6, 8, 3, 4, 3, 2, 1}; 17 | LongestDecreasingSubSequence longestSubSequence = new LongestDecreasingSubSequence(); 18 | List longestDecreaseSubSequence = longestSubSequence.getLongestDecreaseSubSequence(nums); 19 | System.out.println(longestDecreaseSubSequence); 20 | List longestIncreaseSubSequence = longestSubSequence.getLongestIncreaseSubSequence(nums); 21 | System.out.println(longestIncreaseSubSequence); 22 | 23 | } 24 | 25 | /** 26 | * @param nums 数组 27 | * @return 最长递减子序列链表 28 | */ 29 | public List getLongestDecreaseSubSequence(int[] nums) { 30 | int[] dp = new int[nums.length]; 31 | int[] priors = new int[nums.length];//用于记录当前以该元素为最小元素的递减序列中该元素的前驱节点,用于打印序列 32 | for (int i = 0; i < dp.length; i++) { 33 | dp[i] = 1; 34 | } 35 | List result = new ArrayList<>();//存储递减子序列 36 | int max = 0;//存储子序列的长度 37 | int endIndex = 0;//存储子序列的最后一个元素的下标 38 | for (int i = 1; i < nums.length; i++) { 39 | if (nums[i - 1] > nums[i]) {//说明连续 40 | dp[i] = dp[i - 1] + 1; 41 | priors[i] = i - 1; 42 | } else {//不连续的话要从第一个开始比较,取最长的一个 43 | for (int j = 0; j < i; j++) { 44 | if (nums[j] > nums[i] && (dp[j] + 1) > dp[i]) { 45 | dp[i] = dp[j] + 1; 46 | priors[i] = j; 47 | } 48 | } 49 | } 50 | if (dp[i] > max) { 51 | max = dp[i]; 52 | endIndex = i; 53 | } 54 | } 55 | 56 | //将子序列取出加入链表,作为结果返回 57 | while (max > 0) { 58 | result.add(0, nums[endIndex]); 59 | endIndex = priors[endIndex];//priors数组中依次存储的是以当前元素作为子序列的前一个节点的下标 60 | max--; 61 | } 62 | return result; 63 | } 64 | 65 | /** 66 | * @param nums 数组 67 | * @return 最长递增子序列链表 68 | */ 69 | public List getLongestIncreaseSubSequence(int[] nums) { 70 | int[] dp = new int[nums.length]; 71 | int[] priors = new int[nums.length]; 72 | for (int i = 0; i < dp.length; i++) { 73 | dp[i] = 1; 74 | } 75 | List result = new ArrayList<>();//存储递减子序列 76 | int max = 0; 77 | int endIndex = 0; 78 | for (int i = 1; i < nums.length; i++) { 79 | if (nums[i - 1] < nums[i]) {//说明连续 80 | dp[i] = dp[i - 1] + 1; 81 | priors[i] = i - 1; 82 | } else {//不连续的话要从第一个开始比较,取最长的一个 83 | for (int j = 0; j < i; j++) { 84 | if (nums[j] < nums[i] && (dp[j] + 1) > dp[i]) { 85 | dp[i] = dp[j] + 1; 86 | priors[i] = j; 87 | } 88 | } 89 | } 90 | if (dp[i] > max) { 91 | max = dp[i]; 92 | endIndex = i; 93 | } 94 | } 95 | //将子序列取出加入链表,作为结果返回 96 | while (max > 0) { 97 | result.add(0, nums[endIndex]); 98 | endIndex = priors[endIndex];//priors数组中依次存储的是以当前元素作为子序列的前一个节点的下标 99 | max--; 100 | } 101 | return result; 102 | 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/Manacher.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | *

9 | * Created by wangxu on 2016/12/23 10:46. 10 | *

11 | *

12 | * Description: 最长回文子串Manacher算法 13 | * ① 在每个字符之间插入一个特殊字符(如ab插入后#a#b#),将所有的奇数和偶数字符串统一成奇数字符串处理 14 | * ② 用一个辅助数组P,P[id]记录的是以字符str[id]为中心的最长回文串半径 15 | * ③ 那么得到直径为P[id]*2-1(因为原点只有一个),这里面特殊字符始终比真实的字符串多一个,所以再减去一个特出字符P[id]*2-1-1 16 | * ④ 剩下的特殊字符和真实字符各占一半(P[id]*2-1-1)/2=P[id]-1,代表真正的以id为中心的最长回文串 17 | * ⑤ 那么max(P[id])-1就是该字符串的最长回文子串,剩下的就是求P[id]数组了 18 | *

19 | * 20 | * @author Wang Xu 21 | * @version V1.0.0 22 | * @since V1.0.0

23 | * WebSite: http://codepub.cn

24 | * Licence: Apache v2 License 25 | */ 26 | public class Manacher { 27 | public static void main(String[] args) { 28 | String str = "tattarrattat"; 29 | str = "SatireVeritas"; 30 | Manacher manacher = new Manacher(); 31 | int maxPalindrome = manacher.getMaxPalindrome(str.toLowerCase()); 32 | System.out.println(maxPalindrome); 33 | str = "abababbaba"; 34 | maxPalindrome= manacher.getMaxPalindrome(str.toLowerCase()); 35 | System.out.println(maxPalindrome); 36 | } 37 | 38 | private int getMaxPalindrome(String str) { 39 | int P[];//记录以字符S[i]为中心的最长回文子串向左/向右扩张的半径,包含其自身 40 | int id = 0;//已知右边界的最长回文子串的中心坐标 41 | int maxR = 0;//已知的最长回文子串的右边界坐标 42 | String join = "#" + StringUtils.join(str.toCharArray(), '#') + "#"; 43 | char[] chars = join.toCharArray(); 44 | P = new int[join.length()]; 45 | for (int i = 1; i < P.length; i++) { 46 | int j = id - (i - id);//j是i相对于id的对称点,那么i i) { 48 | if (maxR - i > P[j]) { 49 | P[i] = P[j]; 50 | } else { 51 | P[i] = maxR - i;//这时最多只能确保i能延展到maxR,对于超过maxR的部分不能确保是否回文,所以其延展半径为(maxR-i) 52 | } 53 | } else { 54 | //仅包含其自身 55 | P[i] = 1; 56 | } 57 | //尝试扩展 58 | while ((i - P[i] >= 0) && (i + P[i] < P.length) && chars[i + P[i]] == chars[i - P[i]]) { 59 | //如果又发现一对回文,延展半径加1 60 | P[i]++; 61 | } 62 | //更新maxR和id 63 | if (i + P[i] > maxR) { 64 | //超过了子串的最右边界 65 | maxR = i + P[i]; 66 | id = i; 67 | } 68 | } 69 | Arrays.sort(P);//升序排列 70 | return P[P.length - 1] - 1; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/PatternStringMatch.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | /** 4 | *

5 | * Created with IntelliJ IDEA. 2015/10/22 15:17 6 | *

7 | *

8 | * ClassName:test 9 | *

10 | *

11 | * Description:模式串查找,当模式串出现在文本中的时候,返回匹配的开始索引值,否则未查到返回-1 12 | *

13 | * 14 | * @author Wang Xu 15 | * @version V1.0.0 16 | * @since V1.0.0 17 | */ 18 | public class PatternStringMatch { 19 | public static void main(String[] args) { 20 | PatternStringMatch patternStringMatch = new PatternStringMatch(); 21 | int search = patternStringMatch.search("abcdefghi", "ih"); 22 | System.out.println(search); 23 | int search2 = patternStringMatch.search("abddfdjskfjd", "jd"); 24 | System.out.println(search2); 25 | } 26 | 27 | /** 28 | * @param text 29 | * @param pat 30 | * @return 约定:查到了返回匹配的索引值,否则未查到则返回-1 31 | */ 32 | private static int search(String text, String pat) { 33 | int patLen = pat.length(); 34 | int textLen = text.length(); 35 | int step = textLen - patLen; 36 | if (step < 0) { 37 | return -1;//模式串比文本串长,肯定不存在匹配情况 38 | } 39 | for (int i = 0; i <= step; i++) { 40 | int j; 41 | for (j = 0; j < patLen; j++) { 42 | if (pat.charAt(j) != text.charAt(i + j)) { 43 | break; 44 | } 45 | } 46 | if (j == patLen) {//模式串已经走到结尾了,那么i在文本串中正好是匹配到的模式串的开始索引 47 | return i; 48 | } 49 | } 50 | return -1; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/Permutation.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | /** 4 | *

5 | * Created with IntelliJ IDEA. 2015/10/30 19:37 6 | *

7 | *

8 | * ClassName:Permutation 9 | *

10 | *

11 | * Description:全排列 12 | * 第一步,排列的精髓是交换和顺序处理,比如,考虑[1,2,3,4]排列,实际上是,1和1,2,3,4分别交换得来 13 | * 1和1交换:[1],[2,3,4] 14 | * 1和2交换:[2],[1,3,4] 15 | * 1和3交换:[3],[2,1,4] 16 | * 1和4交换:[4],[2,3,1] 17 | *

18 | * 那么下面分别考虑上面的四个结果,比如,考虑 19 | * [1],[2,3,4] 20 | *

21 | * 第二步,我们把[1]固定不变,考虑[2,3,4],把它看成是2和2,3,4分别交换,得到如下结果: 22 | * [1]固定,2和2交换:[1],[2],[3,4] 23 | * [1]固定,2和3交换:[1],[3],[2,4] 24 | * [1]固定,2和4交换:[1],[4],[3,2] 25 | *

26 | * 这个时候,再分别考虑第二步之后的三个结果,比如,考虑 27 | * [1],[2],[3,4] 28 | *

29 | * 第三步,我们把[1],[2]固定不变,考虑[3,4],把它看成是3和3,4分别交换,得到如下结果: 30 | * [1][2]固定,3和3交换:[1],[2],[3],[4] 31 | * [1][2]固定,3和4交换:[1],[2],[4],[3] 32 | *

33 | * 从上面分析可以看出,其实第二步就是对第一步的部分递归,同样,第三步也是对第二步的部分递归,当最右边只有一个数字的时候,我们就进行输出 34 | * 35 | * @author Wang Xu 36 | * @version V1.0.0 37 | * @since V1.0.0 38 | */ 39 | public class Permutation { 40 | static StringBuilder sb = new StringBuilder(); 41 | 42 | public static void main(String[] args) { 43 | char[] strs = new char[]{'a', 'b', 'c'}; 44 | permutation(strs, 0, strs.length); 45 | } 46 | 47 | public static void permutation(char[] strs, int start, int end) { 48 | if (start >= end) { 49 | System.out.println(sb.toString()); 50 | return; 51 | } 52 | for (int i = start; i < end; i++) { 53 | swap(strs, start, i); 54 | sb.append(strs[start]); 55 | permutation(strs, start + 1, end); 56 | swap(strs, start, i); 57 | sb.deleteCharAt(start); 58 | } 59 | } 60 | 61 | private static void swap(char[] chars, int first, int second) { 62 | char temp = chars[first]; 63 | chars[first] = chars[second]; 64 | chars[second] = temp; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/ReverseString.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | import cn.codepub.algorithms.utils.StackX; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.InputStreamReader; 7 | 8 | /** 9 | *

10 | * Created with IntelliJ IDEA. 2016/1/8 19:32 11 | *

12 | *

13 | * ClassName:ReverseString 14 | *

15 | *

16 | * Description:反转字符串,例如abc->cba 17 | *

18 | * 19 | * @author Wang Xu 20 | * @version V1.0.0 21 | * @since V1.0.0 22 | */ 23 | public class ReverseString { 24 | private String input; 25 | private String output = "";//默认是null,所以此处将""赋值给它 26 | 27 | public ReverseString(String in) { 28 | input = in; 29 | } 30 | 31 | public String doRev() { 32 | int stackSize = input.length(); 33 | StackX theStack = new StackX(stackSize); 34 | for (int j = 0; j < input.length(); j++) { 35 | char ch = input.charAt(j); 36 | theStack.push(ch); 37 | } 38 | while (!theStack.isEmpty()) { 39 | char ch = theStack.pop(); 40 | output = output + ch; 41 | } 42 | return output; 43 | } 44 | 45 | public static String getString() throws Exception { 46 | InputStreamReader isr = new InputStreamReader(System.in, "UTF-8"); 47 | BufferedReader br = new BufferedReader(isr); 48 | String s = br.readLine(); 49 | return s; 50 | } 51 | 52 | public static void main(String[] args) throws Exception { 53 | String input, output; 54 | while (true) { 55 | System.out.println("Enter a String:"); 56 | System.out.flush(); 57 | input = ReverseString.getString(); 58 | if (input.equals("")) { 59 | break; 60 | } 61 | ReverseString reverse = new ReverseString(input); 62 | output = reverse.doRev(); 63 | System.out.println("Reversed:" + output); 64 | 65 | } 66 | 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/strings/StringSort.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.strings; 2 | 3 | 4 | import java.util.Arrays; 5 | 6 | /** 7 | *

8 | * Created with IntelliJ IDEA. 2015/12/1 14:18 9 | *

10 | *

11 | * ClassName:StringSort 12 | *

13 | *

14 | * Description:实现一个简单的字符串按照字典序排序,不区分大小写 15 | *

16 | * 17 | * @author Wang Xu 18 | * @version V1.0.0 19 | * @since V1.0.0 20 | */ 21 | public class StringSort { 22 | 23 | public static void main(String[] args) { 24 | String[] strs = new String[]{"alphabet", "alligator", "alternate", "alternative"}; 25 | bubbleSort(strs); 26 | System.out.println(Arrays.toString(strs)); 27 | } 28 | 29 | /** 30 | * 实现排序函数的主体 31 | * 32 | * @param strs 需要排序的字符串数组 33 | */ 34 | public static void bubbleSort(String[] strs) { 35 | for (int i = 0; i < strs.length; i++) { 36 | for (int j = strs.length - 1; j > i; j--) { 37 | int compare = compare(strs[i], strs[j]); 38 | if (compare > 0) { 39 | //说明前面一个大 40 | String temp = strs[i]; 41 | strs[i] = strs[j]; 42 | strs[j] = temp; 43 | } 44 | } 45 | } 46 | } 47 | 48 | /** 49 | * 辅助排序函数 50 | * 51 | * @param s1 52 | * @param s2 53 | * @return 1 前者大;-1 后者大;0 两者相等 54 | */ 55 | private static int compare(String s1, String s2) { 56 | s1 = s1.toLowerCase();//全转小写 57 | s2 = s2.toLowerCase(); 58 | int len1 = s1.length(); 59 | int len2 = s2.length(); 60 | int count = len1 < len2 ? len1 : len2; 61 | for (int i = 0; i < count; i++) { 62 | int first = (int) s1.charAt(i);//将字母强转为ASCII码 63 | int second = (int) s2.charAt(i); 64 | if (first < second) { 65 | return -1;//前一个小 66 | } else if (first > second) { 67 | return 1;//后一个小 68 | } else { 69 | continue; 70 | } 71 | } 72 | //如果全部比较完了,则谁短谁小 73 | if (len1 < len2) { 74 | return -1; 75 | } else if (len1 > len2) { 76 | return 1; 77 | } else { 78 | return 0; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/trees/DepthFirstTraversal.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.trees; 2 | 3 | import cn.codepub.algorithms.utils.Tree; 4 | 5 | import java.util.Stack; 6 | 7 | /** 8 | *

9 | * Created with IntelliJ IDEA. 2015/10/30 17:32 10 | *

11 | *

12 | * ClassName:DepthFirstTraversal 13 | *

14 | *

15 | * Description:二叉树的深度优先遍历 16 | *

17 | * 18 | * @author Wang Xu 19 | * @version V1.0.0 20 | * @since V1.0.0 21 | */ 22 | public class DepthFirstTraversal { 23 | static Stack stack = new Stack(); 24 | 25 | public static void main(String[] args) { 26 | Tree root = new Tree(1); 27 | Tree l1 = new Tree(3); 28 | Tree l2 = new Tree(9); 29 | Tree l3 = new Tree(11); 30 | Tree r1 = new Tree(5); 31 | Tree r2 = new Tree(12); 32 | Tree r3 = new Tree(13); 33 | root.left = l1; 34 | root.right = r1; 35 | l1.left = l2; 36 | l2.left = l3; 37 | l3.right = r2; 38 | l3.left = new Tree(14); 39 | r2.right = r3; 40 | 41 | Tree r4 = new Tree(88); 42 | r1.right = r4; 43 | dfs(root); 44 | } 45 | 46 | public static void dfs(Tree root) { 47 | if (null == root) { 48 | return; 49 | } 50 | //设置访问标记 51 | root.isVisited = true; 52 | //入栈 53 | stack.push(root); 54 | //访问结点 55 | //开始弹栈 56 | if (!stack.isEmpty()) { 57 | Tree pop = stack.pop(); 58 | System.out.print(pop.value + "\t"); 59 | if (pop.left != null && !pop.left.isVisited) { 60 | dfs(pop.left); 61 | } 62 | if (pop.right != null && !pop.right.isVisited) { 63 | dfs(pop.right); 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/trees/GetPathsBySum.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.trees; 2 | 3 | import cn.codepub.algorithms.utils.Tree; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Stack; 8 | 9 | /** 10 | *

11 | * Created with IntelliJ IDEA. 2015/10/30 16:38 12 | *

13 | *

14 | * ClassName:GetPathsBySum 15 | *

16 | *

17 | * Description: 18 | * 题目:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。 19 | * 从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。 20 | *

21 | * 22 | * @author Wang Xu 23 | * @version V1.0.0 24 | * @since V1.0.0 25 | */ 26 | public class GetPathsBySum { 27 | static Stack stack = new Stack(); 28 | static List> pathsList = new ArrayList<>(); 29 | 30 | public static void main(String[] args) { 31 | Tree root = new Tree(10);//给定的树 32 | Tree l1 = new Tree(5); 33 | Tree l2 = new Tree(4); 34 | Tree r1 = new Tree(12); 35 | Tree r2 = new Tree(7); 36 | root.left = l1; 37 | root.right = r1; 38 | l1.left = l2; 39 | l1.right = r2; 40 | int num = 22;//给定的整数 41 | dfs(root, new ArrayList()); 42 | //这样就获取到了所有路径的集合 43 | for (List list : pathsList) { 44 | int temp = 0; 45 | for (Tree t : list) { 46 | temp += t.value; 47 | } 48 | if (temp == num) { 49 | System.out.println(list); 50 | } 51 | } 52 | } 53 | 54 | /** 55 | * 使用变体的深度优先遍历,存储下来每一条路径 56 | * 在压栈的时候,同时将结点加入链表,在弹栈的时候,先判断是否是叶子结点,是的话,则输出一条路径,然后直接移除此结点 57 | * 58 | * @param root 59 | */ 60 | public static void dfs(Tree root, List path) { 61 | if (null == root) { 62 | return; 63 | } 64 | //设置访问标记 65 | root.isVisited = true; 66 | //入栈 67 | stack.push(root); 68 | //加入链表 69 | path.add(root); 70 | //开始弹栈 71 | while (!stack.isEmpty()) { 72 | //在弹栈的同时也要将该结点从路径中移除,但是在移除前要判断是否已经是一条完整的路径,如果是一条完整的路径,则存储之 73 | Tree pop = stack.pop(); 74 | if (pop.left != null && !pop.left.isVisited) { 75 | dfs(pop.left, path); 76 | } 77 | if (pop.right != null && !pop.right.isVisited) { 78 | dfs(pop.right, path); 79 | } 80 | if (pop.left == null && pop.right == null) { 81 | //说明到了叶子结点了 82 | pathsList.add(new ArrayList<>(path)); 83 | } 84 | path.remove(pop);//从一条路径中移除 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/trees/LevelTraverseBinaryTree.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.trees; 2 | 3 | import cn.codepub.algorithms.utils.Tree; 4 | 5 | import java.util.ArrayDeque; 6 | import java.util.Queue; 7 | 8 | /** 9 | *

10 | * Created with IntelliJ IDEA. 2015/10/30 13:38 11 | *

12 | *

13 | * ClassName:LevelTraverseBinaryTree 14 | *

15 | *

16 | * Description:二叉树的层次遍历 17 | * 题目:从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印 18 | *

19 | * 20 | * @author Wang Xu 21 | * @version V1.0.0 22 | * @since V1.0.0 23 | */ 24 | public class LevelTraverseBinaryTree { 25 | public static void main(String[] args) { 26 | Queue queue = new ArrayDeque<>(); 27 | Tree root = new Tree(1); 28 | Tree l1 = new Tree(3); 29 | Tree l2 = new Tree(9); 30 | Tree l3 = new Tree(11); 31 | Tree r1 = new Tree(5); 32 | Tree r2 = new Tree(12); 33 | Tree r3 = new Tree(13); 34 | root.left = l1; 35 | root.right = r1; 36 | l1.left = l2; 37 | l2.left = l3; 38 | l3.right = r2; 39 | r2.right = r3; 40 | levelTraverse(root, queue); 41 | } 42 | 43 | public static void levelTraverse(Tree root, Queue queue) { 44 | if (root == null) { 45 | return; 46 | } 47 | queue.add(root); 48 | while (!queue.isEmpty()) { 49 | Tree remove = queue.remove(); 50 | System.out.print(remove.value + "\t"); 51 | if (remove.left != null) { 52 | queue.add(remove.left); 53 | } 54 | if (remove.right != null) { 55 | queue.add(remove.right); 56 | } 57 | 58 | } 59 | } 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/trees/TraverseBinaryTree.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.trees; 2 | 3 | import cn.codepub.algorithms.utils.Tree; 4 | 5 | /** 6 | *

7 | * Created with IntelliJ IDEA. 2015/10/30 14:16 8 | *

9 | *

10 | * ClassName:TraverseTree 11 | *

12 | *

13 | * Description:提供对二叉树的三种遍历方式:先序遍历,中序遍历,后序遍历 14 | *

15 | * 16 | * @author Wang Xu 17 | * @version V1.0.0 18 | * @since V1.0.0 19 | */ 20 | public class TraverseBinaryTree { 21 | public static void main(String[] args) { 22 | Tree root = new Tree(1); 23 | Tree l1 = new Tree(3); 24 | Tree l2 = new Tree(9); 25 | Tree l3 = new Tree(11); 26 | Tree r1 = new Tree(5); 27 | Tree r2 = new Tree(12); 28 | Tree r3 = new Tree(13); 29 | root.left = l1; 30 | root.right = r1; 31 | l1.left = l2; 32 | l2.left = l3; 33 | l3.right = r2; 34 | r2.right = r3; 35 | System.out.println("先序遍历"); 36 | preOrder(root); 37 | System.out.println("\n中序遍历"); 38 | inOrder(root); 39 | System.out.println("\n后序遍历"); 40 | postOrder(root); 41 | } 42 | 43 | public static void preOrder(Tree root) { 44 | if (root == null) { 45 | return; 46 | } 47 | System.out.print(root.value + "\t"); 48 | if (root.left != null) { 49 | preOrder(root.left); 50 | } 51 | if (root.right != null) { 52 | preOrder(root.right); 53 | } 54 | } 55 | 56 | public static void inOrder(Tree root) { 57 | if (root == null) { 58 | return; 59 | } 60 | if (root.left != null) { 61 | inOrder(root.left); 62 | } 63 | System.out.print(root.value + "\t"); 64 | if (root.right != null) { 65 | inOrder(root.right); 66 | } 67 | } 68 | 69 | public static void postOrder(Tree root) { 70 | if (root == null) { 71 | return; 72 | } 73 | if (root.left != null) { 74 | postOrder(root.left); 75 | } 76 | if (root.right != null) { 77 | postOrder(root.right); 78 | } 79 | System.out.print(root.value + "\t"); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/trees/VerifySequenceOfBST.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.trees; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | *

7 | * Created with IntelliJ IDEA. 2015/10/30 14:56 8 | *

9 | *

10 | * ClassName:VerifySequenceOfBST 11 | *

12 | *

13 | * Description: 14 | * 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果,如果是则返回true,否则返回false 15 | * 假设输入的数组的任意两个数字都互不相同 16 | *

17 | * 18 | * @author Wang Xu 19 | * @version V1.0.0 20 | * @since V1.0.0 21 | */ 22 | public class VerifySequenceOfBST { 23 | public static void main(String[] args) { 24 | int[] nums = new int[]{5, 7, 6, 9, 11, 10, 8}; 25 | boolean verify = verify(nums); 26 | System.out.println(verify); 27 | nums = new int[]{7, 4, 6, 5}; 28 | verify = verify(nums); 29 | System.out.println(verify); 30 | } 31 | 32 | public static boolean verify(int[] sequences) { 33 | if (null == sequences || sequences.length <= 1) { 34 | return true; 35 | } 36 | int root = sequences[sequences.length - 1]; 37 | int index = 0; 38 | //寻找左右子树的分割点 39 | while (index < sequences.length && sequences[index] < root) { 40 | index++; 41 | } 42 | //校验右子树应该是全大于root值 43 | for (int i = index; i < sequences.length; i++) { 44 | if (sequences[i] < root) { 45 | return false; 46 | } 47 | } 48 | boolean left = true; 49 | //如果index==0,说明根节点之前所有元素都属于右子树,无需判断左子树 50 | if (index > 0) { 51 | left = verify(Arrays.copyOf(sequences, index)); 52 | } 53 | boolean right = true; 54 | //如果index>=length-1,根节点之前所有元素都属于左子树,无需判断右子树 55 | if (index < sequences.length - 1) { 56 | right = verify(Arrays.copyOfRange(sequences, index, sequences.length - 1)); 57 | } 58 | return left && right; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/utils/StackX.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.utils; 2 | 3 | /** 4 | *

5 | * Created with IntelliJ IDEA. 2016/1/8 19:18 6 | *

7 | *

8 | * ClassName:StackX 9 | *

10 | *

11 | * Description:公用的自定义Stack,支持泛型操作 12 | *

13 | * 14 | * @author Wang Xu 15 | * @version V1.0.0 16 | * @since V1.0.0 17 | */ 18 | public class StackX { 19 | private int maxSize; 20 | private Object[] stackArray; 21 | private int top; 22 | 23 | public StackX() { 24 | 25 | } 26 | 27 | public StackX(int s) { 28 | maxSize = s; 29 | stackArray = new Object[maxSize]; 30 | top = -1; 31 | } 32 | 33 | public void push(T j) { 34 | stackArray[++top] = j; 35 | } 36 | 37 | public T pop() { 38 | return (T) stackArray[top--]; 39 | } 40 | 41 | public T peek() { 42 | return (T) stackArray[top]; 43 | } 44 | 45 | public boolean isEmpty() { 46 | return (top == -1); 47 | } 48 | 49 | public int size() { 50 | return top + 1; 51 | } 52 | 53 | public T peekN(int n) { 54 | return (T) stackArray[n]; 55 | } 56 | 57 | public void displayStack(String s) { 58 | System.out.print(s); 59 | System.out.print("Stack(bottom->top):"); 60 | for (int j = 0; j < size(); j++) { 61 | System.out.print(peekN(j) + " "); 62 | } 63 | System.out.println(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/algorithms/utils/Tree.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.algorithms.utils; 2 | 3 | /** 4 | *

5 | * Created with IntelliJ IDEA. 2015/10/30 14:50 6 | *

7 | *

8 | * ClassName:Tree 9 | *

10 | *

11 | * Description:公用的树定义 12 | *

13 | * 14 | * @author Wang Xu 15 | * @version V1.0.0 16 | * @since V1.0.0 17 | */ 18 | public class Tree { 19 | public Tree left;//左子树 20 | public Tree right;//右子树 21 | public int value;//结点值 22 | public boolean isVisited;//是否访问 23 | 24 | public Tree() { 25 | 26 | } 27 | 28 | public Tree(int value) { 29 | this.value = value; 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return String.valueOf(this.value); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/patterns/core/DeepClone.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.patterns.core; 2 | 3 | import java.io.*; 4 | import java.util.Hashtable; 5 | 6 | /** 7 | *

8 | * Created with IntelliJ IDEA. 2015/11/8 21:43 9 | *

10 | *

11 | * ClassName:DeepClone 12 | *

13 | *

14 | * Description:implements a deep clone for yourself 15 | *

16 | * 17 | * @author Wang Xu 18 | * @version V1.0.0 19 | * @since V1.0.0 20 | */ 21 | public class DeepClone { 22 | public static void main(String[] args) { 23 | MyPerson son = new MyPerson("son", 1); 24 | MyPerson myPerson = new MyPerson("father", 11); 25 | myPerson.son = son; 26 | try { 27 | MyPerson deepClone = (MyPerson) myPerson.deepClone(); 28 | //修改原值 29 | myPerson.son.name = "newSon"; 30 | //可以看到完成了深拷贝,拷贝的引用变量son的name属性并未更改 31 | System.out.println(deepClone.son.name); 32 | } catch (IOException e) { 33 | e.printStackTrace(); 34 | } catch (ClassNotFoundException e) { 35 | e.printStackTrace(); 36 | } 37 | 38 | 39 | } 40 | } 41 | 42 | class MyPerson implements Cloneable, Serializable { 43 | public String name; 44 | public int age; 45 | public MyPerson son; 46 | 47 | public MyPerson(String name, int age) { 48 | this.name = name; 49 | this.age = age; 50 | } 51 | 52 | public MyPerson(String name, int age, MyPerson son) { 53 | this(name, age); 54 | this.son = son; 55 | } 56 | 57 | public Object deepClone() throws IOException, ClassNotFoundException { 58 | ByteArrayOutputStream bo = new ByteArrayOutputStream(); 59 | ObjectOutputStream oo = new ObjectOutputStream(bo); 60 | oo.writeObject(this); 61 | ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray()); 62 | ObjectInputStream oi = new ObjectInputStream(bi); 63 | return oi.readObject(); 64 | } 65 | 66 | Hashtable hashtable = new Hashtable(); 67 | 68 | @Override 69 | protected Object clone() throws CloneNotSupportedException { 70 | MyPerson myPerson = null; 71 | try { 72 | myPerson = (MyPerson) super.clone(); 73 | myPerson.son = (MyPerson) son.clone(); 74 | } catch (CloneNotSupportedException e) { 75 | e.printStackTrace(); 76 | } 77 | return myPerson; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/patterns/core/Singleton.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.patterns.core; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | *

8 | * Created with IntelliJ IDEA. 2015/10/22 13:55 9 | *

10 | *

11 | * ClassName:Singleton 12 | *

13 | *

14 | * Description:饿汉模式天生线程安全,而且实现简单,在此不予提供,本类为懒汉模式,使用双跳检测的多线程安全的单例模式 15 | *

16 | * 17 | * @author Wang Xu 18 | * @version V1.0.0 19 | * @since V1.0.0 20 | */ 21 | public class Singleton { 22 | private Singleton() { 23 | 24 | } 25 | 26 | private static volatile Singleton singleton; 27 | 28 | public static Singleton getInstance() { 29 | if (singleton == null) { 30 | synchronized (Singleton.class) { 31 | if (singleton == null) { 32 | singleton = new Singleton(); 33 | } 34 | } 35 | } 36 | return singleton; 37 | } 38 | 39 | public static void main(String[] args) { 40 | Set set = new HashSet<>(); 41 | for (int i = 0; i < 10; i++) { 42 | Singleton singleton = Singleton.getInstance(); 43 | boolean add = set.add(singleton); 44 | //可以看到除了第一次,之后每次获取的实例和第一次都是同一实例 45 | System.out.println(add); 46 | } 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/patterns/proxy/CGLibProxyHandler.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.patterns.proxy; 2 | 3 | import net.sf.cglib.proxy.Enhancer; 4 | import net.sf.cglib.proxy.MethodInterceptor; 5 | import net.sf.cglib.proxy.MethodProxy; 6 | 7 | import java.lang.reflect.Method; 8 | 9 | /** 10 | *

11 | * Created with IntelliJ IDEA. 2015/10/21 22:16 12 | *

13 | *

14 | * ClassName:CGLibProxyHandler 15 | *

16 | *

17 | * Description:使用CGLib实现动态代理 18 | * 为什么要有CGLib动态代理呢?因为JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,CGLib是针对类来实现代理的 19 | * 它的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理 20 | *

21 | * 22 | * @author Wang Xu 23 | * @version V1.0.0 24 | * @since V1.0.0 25 | */ 26 | public class CGLibProxyHandler implements MethodInterceptor { 27 | 28 | private Object tar;//被代理对象 29 | 30 | /** 31 | * @param tar 使用被代理对象 32 | * @return 需要将返回结果强转成被代理对象 33 | */ 34 | public Object getInstance(Object tar) { 35 | this.tar = tar; 36 | Enhancer enhancer = new Enhancer(); 37 | //设置被代理对象为代理类的超类 38 | enhancer.setSuperclass(this.tar.getClass()); 39 | //设置回调方法 40 | enhancer.setCallback(this); 41 | //创建代理对象 42 | return enhancer.create(); 43 | } 44 | 45 | /** 46 | * 回调方法 47 | * 48 | * @param o 49 | * @param method 50 | * @param objects 51 | * @param methodProxy 52 | * @return 53 | * @throws Throwable 54 | */ 55 | @Override 56 | public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 57 | System.out.println("before method invoke..."); 58 | System.out.println(method); 59 | Object res = methodProxy.invokeSuper(o, objects); 60 | System.out.println("after method invoke..."); 61 | return res; 62 | } 63 | 64 | @org.junit.Test 65 | public void testCGLibProxy() { 66 | System.out.println("-----------使用CGLib动态代理-----------"); 67 | CGLibProxyHandler cgLibProxyHandler = new CGLibProxyHandler(); 68 | Count count = (Count) cgLibProxyHandler.getInstance(new CountImpl()); 69 | count.queryCount(); 70 | count.updateCount(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/patterns/proxy/CountImpl.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.patterns.proxy; 2 | 3 | /** 4 | * 静态代理、JDK动态代理、CGLib代理的辅助类 5 | */ 6 | interface Count { 7 | //定义查询账户方法 8 | void queryCount(); 9 | 10 | //定义更新账户方法 11 | void updateCount(); 12 | } 13 | 14 | public class CountImpl implements Count { 15 | @Override 16 | public void queryCount() { 17 | System.out.println("the method of query count..."); 18 | } 19 | 20 | @Override 21 | public void updateCount() { 22 | System.out.println("the method of update count..."); 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/java/cn/codepub/patterns/proxy/JDKProxyHandler.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.patterns.proxy; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | import java.lang.reflect.Proxy; 6 | 7 | /** 8 | *

9 | * Created with IntelliJ IDEA. 2015/10/21 20:11 10 | *

11 | *

12 | * ClassName:ProxyHanlder 13 | *

14 | *

15 | * Description:使用JDK实现的动态代理 16 | * 动态代理的主要作用有三 17 | * ① Proxy类的代码量可以得到控制,由静态代理可以看出,随着业务变得庞大,代理类也会变得庞大,而动态代理不会出现这种情况 18 | * ② 可以实现AOP编程,其实Spring中的AOP就是一个很好的应用实例 19 | * ③ 可以解耦合,通过参数传递的形式就可以判断真实类,而不需要事先实例化,从而更加灵活多变 20 | *

21 | * 22 | * @author Wang Xu 23 | * @version V1.0.0 24 | * @since V1.0.0 25 | */ 26 | public class JDKProxyHandler implements InvocationHandler { 27 | private Object tar; 28 | 29 | public JDKProxyHandler() { 30 | 31 | } 32 | 33 | public JDKProxyHandler(Object tar) { 34 | this.tar = tar; 35 | } 36 | 37 | public Object bind(Object tar) { 38 | this.tar = tar; 39 | return Proxy.newProxyInstance(tar.getClass().getClassLoader(), tar.getClass().getInterfaces(), this); 40 | } 41 | 42 | @Override 43 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 44 | Object result; 45 | System.out.println("before method invoke..."); 46 | System.out.println("Method: " + method); 47 | result = method.invoke(tar, args); 48 | System.out.println("after method invoke..."); 49 | return result; 50 | } 51 | 52 | public static void testDynamicProxy() { 53 | System.out.println("-----------使用JDK动态代理-----------"); 54 | Count count = (Count) new JDKProxyHandler().bind(new CountImpl()); 55 | count.queryCount(); 56 | count.updateCount(); 57 | } 58 | 59 | public static void main(String[] args) { 60 | testDynamicProxy(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/cn/codepub/patterns/proxy/StaticProxyHandler.java: -------------------------------------------------------------------------------- 1 | package cn.codepub.patterns.proxy; 2 | 3 | /** 4 | *

5 | * Created with IntelliJ IDEA. 2015/10/21 19:33 6 | *

7 | *

8 | * ClassName:CountProxy 9 | *

10 | *

11 | * Description:静态代理的实现 12 | *

13 | * 14 | * @author Wang Xu 15 | * @version V1.0.0 16 | * @since V1.0.0 17 | */ 18 | public class StaticProxyHandler implements Count { 19 | private Count count; 20 | 21 | //默认构造器 22 | public StaticProxyHandler() { 23 | 24 | } 25 | 26 | //接收被代理类实例的构造器 27 | public StaticProxyHandler(Count count) { 28 | this.count = count; 29 | } 30 | 31 | @Override 32 | public void queryCount() { 33 | System.out.println("before method invoke..."); 34 | //调用委托类的方法 35 | count.queryCount(); 36 | System.out.println("after method invoke..."); 37 | } 38 | 39 | @Override 40 | public void updateCount() { 41 | System.out.println("before method invoke..."); 42 | //调用委托类的方法 43 | count.updateCount(); 44 | System.out.println("after method invoke..."); 45 | } 46 | 47 | public static void main(String[] args) { 48 | testStaticProxy(); 49 | } 50 | 51 | public static void testStaticProxy() { 52 | System.out.println("-----------使用静态代理-----------"); 53 | CountImpl countImpl = new CountImpl(); 54 | StaticProxyHandler staticProxyHandler = new StaticProxyHandler(countImpl); 55 | staticProxyHandler.queryCount(); 56 | staticProxyHandler.updateCount(); 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/resources/基于同义词词林的词语相似度计算方法_田久乐.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shijiebei2009/Algorithms/7cc1f17734b3f0ba42767dc8d10cb9f2b563f5ec/src/main/resources/基于同义词词林的词语相似度计算方法_田久乐.pdf --------------------------------------------------------------------------------