├── .gitignore ├── .travis.yml ├── src └── main │ ├── resources │ ├── 基于同义词词林的词语相似度计算方法_田久乐.pdf │ └── log4j2.xml │ └── java │ └── cn │ └── codepub │ ├── patterns │ ├── proxy │ │ ├── CountImpl.java │ │ ├── StaticProxyHandler.java │ │ ├── JDKProxyHandler.java │ │ └── CGLibProxyHandler.java │ └── core │ │ ├── Singleton.java │ │ └── DeepClone.java │ └── algorithms │ ├── utils │ ├── Tree.java │ └── StackX.java │ ├── sorting │ ├── InsertSort.java │ ├── BubbleSort.java │ ├── SelectionSort.java │ ├── ShellSort.java │ └── QuickSort.java │ ├── matrix │ └── Matrix.java │ ├── stack │ ├── MinStack.java │ ├── CheckStackSequence.java │ ├── BracketsApp.java │ ├── PostfixApp.java │ └── InfixApp.java │ ├── strings │ ├── LevenshteinDistance.java │ ├── PatternStringMatch.java │ ├── LCS2.java │ ├── LCS3.java │ ├── Permutation.java │ ├── ReverseString.java │ ├── LCS.java │ ├── StringSort.java │ ├── JaccardSimilarityCoefficient.java │ ├── Manacher.java │ ├── Combination.java │ ├── BinarySearch.java │ └── LongestDecreasingSubSequence.java │ ├── commons │ ├── MaximumProduct.java │ ├── MajorityNumber.java │ ├── ConversionOfNumberSystems.java │ └── TopK.java │ ├── spelling │ └── ChineseToSpelling.java │ ├── trees │ ├── LevelTraverseBinaryTree.java │ ├── DepthFirstTraversal.java │ ├── VerifySequenceOfBST.java │ ├── TraverseBinaryTree.java │ └── GetPathsBySum.java │ ├── queue │ └── PriorityApp.java │ ├── multithread │ └── ThreadSynchronization.java │ ├── graph │ ├── utils │ │ └── UnionFindSet.java │ ├── Prim.java │ ├── Kruskal.java │ ├── FloydWarshall.java │ ├── DirectedGraphByAdjacencyMatrix.java │ ├── UndirectedGraphByAdjacencyMatrix.java │ ├── Dijkstra.java │ ├── DirectedGraphByAdjacencyList.java │ └── UndirectedGraphByAdjacencyList.java │ ├── arrays │ └── PrintArray.java │ └── similarity │ └── cilin │ └── WordSimilarity.java ├── pom.xml ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | Algorithms.iml 3 | /target/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 -------------------------------------------------------------------------------- /src/main/resources/基于同义词词林的词语相似度计算方法_田久乐.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shijiebei2009/Algorithms/HEAD/src/main/resources/基于同义词词林的词语相似度计算方法_田久乐.pdf -------------------------------------------------------------------------------- /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/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/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/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/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/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 | Stack9 | * 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/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 | Set7 | * 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/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 StackX8 | * 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/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/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/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/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/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/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, Queue8 | * 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/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 Stack7 | * 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 | ArrayList9 | * 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/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/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/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 | StackX5 | * 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/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/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/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/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/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/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/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/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/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 Queue12 | * 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 | Set11 | * 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 Stack9 | * 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.07 | * 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 | Stack11 | * 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 | StackX5 | * 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则是0115 | * 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/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 List11 | * 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 | *
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 | *
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 List13 | * 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 List7 | * 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/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 | Queue10 | * 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 | Queue9 | * 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 | Queue9 | * 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 | Queue9 | * 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 | Queue18 | * Created with IntelliJ IDEA. 2015/8/2 21:54 19 | *
20 | *21 | * ClassName:WordSimilarity 同义词词林扩展版计算词语相似度 22 | *
23 | *
24 | * Description:
25 | * "=" 代表 相等 同义
26 | * "#" 代表 不等 同类 属于相关词语
27 | * "@" 代表 自我封闭 独立 它在词典中既没有同义词, 也没有相关词
28 | *
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