├── .gitignore ├── README.md ├── src ├── test │ └── java │ │ └── com │ │ └── rann │ │ ├── sort │ │ ├── SelectSortTest.java │ │ ├── HeapSortTest.java │ │ ├── MergeSortTest.java │ │ ├── InsertionSortTest.java │ │ ├── RadixSortTest.java │ │ ├── HalfSearchTest.java │ │ ├── ShellSortTest.java │ │ ├── BubbleSortTest.java │ │ ├── QuickSortTest.java │ │ └── SortPerformanceTest.java │ │ └── datastructure │ │ ├── tree │ │ ├── AVLTreeTest.java │ │ └── BTreeTest.java │ │ └── jcollections │ │ └── IArrayListTest.java └── main │ ├── java │ └── com │ │ └── rann │ │ ├── util │ │ └── GCD.java │ │ ├── sort │ │ ├── HalfSearch.java │ │ ├── InsertionSort.java │ │ ├── SelectSort.java │ │ ├── ShellSort.java │ │ ├── BubbleSort.java │ │ ├── MergeSort.java │ │ ├── HeapSort.java │ │ ├── QuickSort.java │ │ └── RadixSort.java │ │ ├── hash │ │ ├── HashUtil.java │ │ ├── ConsistentHashWithoutVN.java │ │ └── ConsistentHashWithVN.java │ │ └── datastructure │ │ ├── jcollections │ │ ├── IList.java │ │ └── IArrayList.java │ │ └── tree │ │ ├── BTree.java │ │ └── AVLTree.java │ └── scala │ └── com │ └── scala │ ├── sort │ ├── InsertSortScala.scala │ ├── SelectSortScala.scala │ ├── HalfSearchScala.scala │ ├── BubbleSortScala.scala │ ├── QuickSortScala.scala │ ├── HeapSortScala.scala │ └── MergeSortScala.scala │ └── oj │ └── Knapsack.scala ├── pom.xml └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /target 3 | algorithm.iml 4 | /.settings 5 | *.iml 6 | .classpath 7 | .project -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## algorithm 2 | 3 | 1. 八大排序 二分查找 4 | 2. 实现自己的List和ArrayList 5 | 3. 二叉树遍历算法(递归 & 非递归)AVLTree 6 | 4. 一致性Hash算法 7 | 5. 其他 -------------------------------------------------------------------------------- /src/test/java/com/rann/sort/SelectSortTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | public class SelectSortTest { 8 | 9 | @Test 10 | public void testSelectSort() { 11 | int[] a = {28, 16, 32, 12, 60, 2, 5, 72}; 12 | new SelectSort().selectSort(a); 13 | assertArrayEquals(a, new int[]{2,5,12,16,28,32,60,72}); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/rann/sort/HeapSortTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | import org.junit.Test; 4 | 5 | public class HeapSortTest { 6 | @Test 7 | public void testHeapSort() { 8 | int[] a = {28, 16, 32, 12, 60, 2, 5, 72}; 9 | new HeapSort().heapSort(a); 10 | System.out.println("======堆排序排序测试======"); 11 | for (int i = 0; i < a.length; ++i) { 12 | System.out.print(a[i] + " "); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/rann/sort/MergeSortTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | import org.junit.Test; 4 | 5 | public class MergeSortTest { 6 | @Test 7 | public void testMergeSort() { 8 | int[] a = {28, 16, 32, 12, 60, 2, 5, 72}; 9 | new MergeSort().mergeSort(a, 0, a.length-1); 10 | System.out.println("======归并排序测试======"); 11 | for (int i = 0; i < a.length; ++i) { 12 | System.out.print(a[i] + " "); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/rann/sort/InsertionSortTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | import org.junit.Test; 4 | 5 | public class InsertionSortTest { 6 | @Test 7 | public void testInsertionSort() { 8 | int[] a = {28, 16, 32, 12, 60, 2, 5, 72}; 9 | new InsertionSort().insertionSort(a); 10 | System.out.println("======插入排序测试======"); 11 | for (int i = 0; i < a.length; ++i) { 12 | System.out.print(a[i] + " "); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/rann/sort/RadixSortTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | import org.junit.Test; 4 | 5 | public class RadixSortTest { 6 | @Test 7 | public void testRadixSort() { 8 | int[] a = {28, 16, 321, 121, 60, 2, 5, 72}; 9 | new RadixSort().radixSort(a, 0, a.length-1, 3); 10 | System.out.println("======基数排序测试======"); 11 | for (int i = 0; i < a.length; i++) { 12 | System.out.print(a[i] + " "); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/rann/sort/HalfSearchTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | import org.junit.Test; 4 | 5 | public class HalfSearchTest { 6 | @Test 7 | public void testHalfSearch() { 8 | int[] a = {1, 3, 4, 4, 4, 8, 9, 10, 11}; 9 | int index = new HalfSearch().halfSearch(a, 0, a.length - 1, 4); 10 | System.out.println("======折半查找测试======"); 11 | System.out.println("该数的索引是" + index); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/rann/sort/ShellSortTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | import org.junit.Test; 4 | 5 | public class ShellSortTest { 6 | @Test 7 | public void testShellSort() { 8 | int[] a = {28, 16, 32, 12, 60, 2, 5, 72}; 9 | new ShellSort().shellSort(a); 10 | System.out.println("======希尔排序测试======"); 11 | for (int i = 0; i < a.length; i++) { 12 | System.out.print(a[i] + " "); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/rann/sort/BubbleSortTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | import org.junit.Test; 4 | 5 | public class BubbleSortTest { 6 | 7 | @Test 8 | public void testBubbleSort() { 9 | int[] a = {28, 16, 32, 12, 60, 2, 5, 72}; 10 | new BubbleSort().bubbleSort(a); 11 | System.out.println("======冒泡排序测试======"); 12 | for (int i = 0; i < a.length; ++i) { 13 | System.out.print(a[i] + " "); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/rann/util/GCD.java: -------------------------------------------------------------------------------- 1 | package com.rann.util; 2 | 3 | /** 4 | * Created by taoxiaoran on 16/3/31. 5 | */ 6 | 7 | // 公约数表示为f(a,b),并且有a>=b>0 8 | // 欧几里德就给了我们一个很好的定理,f(a,b)=f(b,a%b)。 9 | public class GCD { 10 | public int getGCD(int a, int b) { 11 | if (b > a) { 12 | int tmp = a; 13 | a = b; 14 | b = tmp; 15 | } 16 | if (b == 0) { 17 | return a; 18 | } 19 | 20 | return getGCD(b, a % b); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/rann/sort/QuickSortTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | import org.junit.Test; 4 | import static org.junit.Assert.*; 5 | import java.util.Arrays; 6 | 7 | public class QuickSortTest { 8 | @Test 9 | public void testQuickSort() { 10 | int[] a = {28, 16, 32, 12, 60, 2, 5, 72}; 11 | // new QuickSort().quickSort(a, 0, a.length - 1); 12 | new QuickSort().quickSortNonRecur(a, 0, a.length - 1); 13 | String expect = "[2, 5, 12, 16, 28, 32, 60, 72]"; 14 | assertEquals(expect, Arrays.toString(a)); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/rann/sort/HalfSearch.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | /** 4 | * Created by Lemonjing on 2015/4/18. 5 | * Github: Lemonjing 6 | * 折半查找 7 | */ 8 | public class HalfSearch { 9 | public int halfSearch(int[] a, int low, int high, int x) { 10 | while (low <= high) { 11 | int mid = (low + high) / 2; 12 | if (x < a[mid]) { 13 | high = mid - 1; 14 | } else if (x > a[mid]) { 15 | low = mid + 1; 16 | } else 17 | return mid; 18 | } 19 | return -1; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/com/rann/datastructure/tree/AVLTreeTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.datastructure.tree; 2 | 3 | /** 4 | * Created by Lemonjing on 2016/3/17 0017. 5 | * Github: Lemonjing 6 | * email: xmusaber@163.com 7 | */ 8 | 9 | public class AVLTreeTest { 10 | public static void main(String[] args) { 11 | // 插入And 遍历 12 | AVLTree t = new AVLTree(); 13 | t.insert(1); 14 | t.insert(3); 15 | t.insert(4); 16 | t.insert(6); 17 | t.insert(7); 18 | 19 | t.traverse(t, "pre"); 20 | t.traverse(t, "in"); 21 | t.traverse(t, "post"); 22 | 23 | // 打印 24 | t.display(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/rann/sort/InsertionSort.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | /** 4 | * 插入排序 - 稳定 5 | * 复杂度:O(n^2) - O(n) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度] 6 | */ 7 | public class InsertionSort { 8 | public void insertionSort(int[] a) { 9 | if (null == a || a.length < 2) { 10 | return; 11 | } 12 | for (int i = 1; i < a.length; i++) { 13 | // 暂存当前值 14 | int temp = a[i]; 15 | int j = i - 1; 16 | while (j >= 0 && temp < a[j]) { 17 | // 后移 18 | a[j + 1] = a[j]; 19 | j--; 20 | } 21 | // 当前值归位 22 | a[j + 1] = temp; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/scala/com/scala/sort/InsertSortScala.scala: -------------------------------------------------------------------------------- 1 | package com.scala.sort 2 | 3 | /** 4 | * Created by Lemonjing on 2018/4/30. 5 | * Github: Lemonjing 6 | */ 7 | object InsertSortScala { 8 | 9 | def insertSort(a: Array[Int]): Unit = { 10 | if (a == null || a.length < 2) { 11 | return 12 | } 13 | for (i <- 1 until a.length) { 14 | val temp = a(i) 15 | var j = i - 1 16 | while (j >= 0 && temp < a(j)) { 17 | a(j+1) = a(j) 18 | j -= 1 19 | } 20 | a(j + 1) = temp 21 | } 22 | } 23 | 24 | def main(args: Array[String]): Unit = { 25 | val arr = Array(28, 16, 32, 12, 60, 2, 5, 72) 26 | insertSort(arr) 27 | arr.foreach(println) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/rann/sort/SelectSort.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | /** 4 | * 选择排序 - 不稳定 5 | * 复杂度:O(n^2) - O(n^2) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度] 6 | */ 7 | public class SelectSort { 8 | public void selectSort(int[] a) { 9 | if (null == a || a.length < 2) { 10 | return; 11 | } 12 | for (int i = 0; i < a.length; i++) { 13 | int k = i; 14 | for (int j = i + 1; j < a.length; j++) { 15 | if (a[j] < a[k]) { 16 | k = j; 17 | } 18 | } 19 | if (k != i) { 20 | int temp = a[k]; 21 | a[k] = a[i]; 22 | a[i] = temp; 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/scala/com/scala/sort/SelectSortScala.scala: -------------------------------------------------------------------------------- 1 | package com.scala.sort 2 | 3 | /** 4 | * Created by Lemonjing on 2018/4/30. 5 | * Github: Lemonjing 6 | */ 7 | object SelectSortScala { 8 | 9 | def selectSort(a:Array[Int]):Unit = { 10 | if (a == null || a.length < 2) { 11 | return 12 | } 13 | for (i <- 0 until a.length) { 14 | var k = i 15 | for (j <- i + 1 until a.length) { 16 | if (a(j) < a(k)) { 17 | k = j 18 | } 19 | } 20 | if (k != i) { 21 | val temp = a(i) 22 | a(i) = a(k) 23 | a(k) = temp 24 | } 25 | } 26 | } 27 | 28 | def main(args: Array[String]): Unit = { 29 | val arr = Array(28, 16, 32, 12, 60, 2, 5, 72) 30 | selectSort(arr) 31 | arr.foreach(println) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/rann/hash/HashUtil.java: -------------------------------------------------------------------------------- 1 | package com.rann.hash; 2 | 3 | /** 4 | * Created by hztaoran on 2016/7/11. 5 | */ 6 | public class HashUtil { 7 | /** 8 | * 使用FNV1_32_HASH算法计算hash值 9 | * 10 | * @param str 11 | * @return 12 | */ 13 | public static int FNV1_32_HASH(String str) { 14 | final int p = 16777619; 15 | int hash = (int) 2166136261L; 16 | for (int i = 0; i < str.length(); i++) { 17 | hash = (hash ^ str.charAt(i)) * p; 18 | } 19 | hash += hash << 13; 20 | hash ^= hash >> 7; 21 | hash += hash << 3; 22 | hash ^= hash >> 17; 23 | hash += hash << 5; 24 | // 如果算出来的值为负数则取其绝对值 25 | if (hash < 0) 26 | hash = Math.abs(hash); 27 | return hash; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/rann/sort/ShellSort.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | /** 4 | * 缩小增量排序(希尔排序)- 不稳定 5 | * 复杂度 小于O(n^2) 平均 O(nlgn) 最差O(n^s)[1 0; d /= 2) { 13 | // 从1B开始先和1A比较 然后2A与2B...然后再1C向前与同组的比较 14 | for (int i = d; i < a.length; i++) { 15 | // 内部直接插入 16 | int temp = a[i]; 17 | int j = i - d; 18 | while (j >= 0 && temp < a[j]) { 19 | a[j + d] = a[j]; 20 | j -= d; 21 | } 22 | a[j + d] = temp; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/scala/com/scala/sort/HalfSearchScala.scala: -------------------------------------------------------------------------------- 1 | package com.scala.sort 2 | 3 | /** 4 | * Created by Lemonjing on 2018/4/18. 5 | * Github: Lemonjing 6 | * 折半查找 7 | */ 8 | object HalfSearchScala { 9 | def halfSearch(a: Array[Int], k: Int):Int = { 10 | if (a == null || a.length <= 0) { 11 | return -1 12 | } 13 | var low = 0 14 | var high = a.length -1 15 | while (low <= high) { 16 | val mid = (low + high) / 2 17 | if (k < a(mid)) { 18 | high = mid - 1 19 | } else if (k > a(mid)) { 20 | low = mid + 1 21 | } else { 22 | return mid 23 | } 24 | } 25 | -1 26 | } 27 | 28 | def main(args: Array[String]): Unit = { 29 | val arr = Array(1,2,3,4,5,6) 30 | println(java.util.Arrays.binarySearch(arr, 4)) 31 | println(halfSearch(arr, 4)) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/rann/sort/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | /** 4 | * 冒泡排序 - 稳定 5 | * 复杂度:O(n^2) - O(n) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度] 6 | */ 7 | public class BubbleSort { 8 | public void bubbleSort(int[] a) { 9 | if (null == a || a.length < 2) { 10 | return; 11 | } 12 | boolean flag; 13 | for (int i = 0; i < a.length - 1; i++) { 14 | flag = false; 15 | for (int j = 0; j < a.length - 1 - i; j++) { 16 | if (a[j] > a[j + 1]) { 17 | int temp = a[j]; 18 | a[j] = a[j + 1]; 19 | a[j + 1] = temp; 20 | flag = true; 21 | } 22 | } 23 | if (false == flag) { 24 | return; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/com/scala/sort/BubbleSortScala.scala: -------------------------------------------------------------------------------- 1 | package com.scala.sort 2 | 3 | /** 4 | * Created by Lemonjing on 2018/4/29. 5 | * Github: Lemonjing 6 | */ 7 | object BubbleSortScala { 8 | 9 | def bubbleSort(a: Array[Int]): Unit = { 10 | if (a == null || a.length < 2) { 11 | return 12 | } 13 | for (i <- 0 until a.length) { 14 | var flag: Boolean = false 15 | for (j <- 0 until a.length -1 - i) { 16 | if (a(j) > a(j+1)) { 17 | val temp = a(j+1) 18 | a(j+1) = a(j) 19 | a(j) = temp 20 | flag = true 21 | } 22 | } 23 | if (flag == false) { 24 | return 25 | } 26 | } 27 | } 28 | 29 | def main(args: Array[String]): Unit = { 30 | val arr = Array(28, 16, 32, 12, 60, 2, 5, 72) 31 | bubbleSort(arr) 32 | arr.foreach(println) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/com/rann/datastructure/jcollections/IArrayListTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.datastructure.jcollections; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.*; 8 | import static org.hamcrest.core.Is.*; 9 | 10 | /** 11 | * Created by hztaoran on 2016/7/18. 12 | */ 13 | public class IArrayListTest { 14 | 15 | IArrayList ilist = null; 16 | 17 | @Before 18 | public void setUp() throws Exception { 19 | ilist = new IArrayList<>(); 20 | } 21 | 22 | @Test 23 | public void logic() { 24 | ilist.add(1); 25 | assertThat(ilist.size(), is(1)); 26 | ilist.add(2); 27 | ilist.add(3); 28 | } 29 | 30 | @After 31 | public void tearDown() throws Exception { 32 | ilist.clear(); 33 | ilist = null; 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/test/java/com/rann/datastructure/tree/BTreeTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.datastructure.tree; 2 | 3 | /** 4 | * Created by Lemonjing on 2016/3/17 0017. 5 | * Github: Lemonjing 6 | * email: xmusaber@163.com 7 | */ 8 | public class BTreeTest { 9 | public static void main(String[] args) { 10 | int[] a = {5, 8, 10, 4}; 11 | BTree t = new BTree(); 12 | 13 | for (int i = 0; i < a.length; i++) { 14 | t.buildBTree(t.root, a[i]); 15 | } 16 | 17 | System.out.println("前序遍历:"); 18 | t.preOrder(t.root); 19 | System.out.println("前序非递归遍历:"); 20 | t.preOrder2(t.root); 21 | System.out.println("中序遍历:"); 22 | t.inOrder(t.root); 23 | System.out.println("中序非递归遍历:"); 24 | t.inOrder2(t.root); 25 | System.out.println("后序遍历:"); 26 | t.postOrder(t.root); 27 | System.out.println("后序非遍历:"); 28 | t.postOrder(t.root); 29 | System.out.println("层序遍历:"); 30 | t.levelOrder(t.root); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/scala/com/scala/sort/QuickSortScala.scala: -------------------------------------------------------------------------------- 1 | package com.scala.sort 2 | 3 | /** 4 | * Created by Lemonjing on 2015/4/24. 5 | * Github: Lemonjing 6 | */ 7 | object QuickSortScala { 8 | def quickSort(a: Array[Int], low: Int, high: Int): Unit = { 9 | if (a == null || a.length < 2) { 10 | return 11 | } 12 | if (low < high) { 13 | val mid = partition(a, low, high) 14 | quickSort(a, low, mid - 1) 15 | quickSort(a, mid + 1, high) 16 | } 17 | } 18 | 19 | private def partition(a: Array[Int], low: Int, high: Int): Int = { 20 | val pivot = a(low) 21 | var _low = low 22 | var _high = high 23 | 24 | while (_low < _high) { 25 | while (_low < _high && a(_high) >= pivot) { 26 | _high -= 1 27 | } 28 | a(_low) = a(_high) 29 | while (_low < _high && a(_low) <= pivot) { 30 | _low += 1 31 | } 32 | a(_high) = a(_low) 33 | } 34 | a(_low) = pivot 35 | _low 36 | } 37 | 38 | def main(args: Array[String]): Unit = { 39 | val arr = Array(28, 16, 32, 12, 60, 2, 5, 72) 40 | quickSort(arr, 0, arr.length - 1) 41 | arr.foreach(println) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/scala/com/scala/sort/HeapSortScala.scala: -------------------------------------------------------------------------------- 1 | package com.scala.sort 2 | 3 | /** 4 | * Created by Lemonjing on 2018/4/30. 5 | * Github: Lemonjing 6 | */ 7 | object HeapSortScala { 8 | 9 | def heapSort(a: Array[Int]): Unit = { 10 | if (a == null || a.length < 2) { 11 | return 12 | } 13 | buildMaxHeap(a) 14 | for (i <- 0 until a.length reverse) { 15 | val temp = a(i) 16 | a(i) = a(0) 17 | a(0) = temp 18 | adjustHeap(a, i, 0) 19 | } 20 | } 21 | 22 | private def buildMaxHeap(a: Array[Int]): Unit = { 23 | val mid = a.length / 2 24 | for (i <- 0 until mid reverse) { 25 | adjustHeap(a, a.length, i) 26 | } 27 | } 28 | 29 | private def adjustHeap(a: Array[Int], size: Int, parent: Int):Unit = { 30 | val left = 2 * parent + 1 31 | val right = 2 * parent + 2 32 | var largest = parent 33 | while (left < size && a(left) > a(largest)) { 34 | largest = left 35 | } 36 | while (right < size && a(right) > a(largest)) { 37 | largest = right 38 | } 39 | if (largest != parent) { 40 | val temp = a(largest) 41 | a(largest) = a(parent) 42 | a(parent) = temp 43 | adjustHeap(a, size, largest) 44 | } 45 | } 46 | 47 | def main(args: Array[String]): Unit = { 48 | val arr = Array(28, 16, 32, 12, 60, 2, 5, 72) 49 | heapSort(arr) 50 | arr.foreach(println) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/scala/com/scala/sort/MergeSortScala.scala: -------------------------------------------------------------------------------- 1 | package com.scala.sort 2 | 3 | /** 4 | * Created by Lemonjing on 2018/4/30. 5 | * Github: Lemonjing 6 | */ 7 | object MergeSortScala { 8 | 9 | def mergeSort(a: Array[Int], low:Int, high:Int): Unit = { 10 | if (a == null || a.length < 2) { 11 | return 12 | } 13 | val mid = (low + high) /2 14 | if (low < high) { 15 | mergeSort(a, low, mid) 16 | mergeSort(a, mid+1, high) 17 | merge(a, low, mid, high) 18 | } 19 | } 20 | 21 | def merge(a:Array[Int], low:Int, mid:Int, high:Int):Unit = { 22 | val temp:Array[Int] = new Array[Int](high - low + 1) 23 | var i = low 24 | var j = mid + 1 25 | var k = 0 26 | 27 | while (i <= mid && j<= high) { 28 | if (a(i) < a(j)) { 29 | temp(k) = a(i) 30 | i += 1 31 | k += 1 32 | } else { 33 | temp(k) = a(j) 34 | j += 1 35 | k += 1 36 | } 37 | } 38 | 39 | while (i <= mid) { 40 | temp(k) = a(i) 41 | i += 1 42 | k += 1 43 | } 44 | 45 | while (j <= high) { 46 | temp(k) = a(j) 47 | j += 1 48 | k += 1 49 | } 50 | 51 | for (t <- 0 until temp.length) { 52 | a(low + t) = temp(t) 53 | } 54 | } 55 | 56 | def main(args: Array[String]): Unit = { 57 | val arr = Array(28, 16, 32, 12, 60, 2, 5, 72) 58 | mergeSort(arr, 0, arr.length - 1) 59 | arr.foreach(println) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/rann/sort/MergeSort.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | /** 4 | * 归并排序(申请一个临时数组) - 稳定 5 | * 复杂度:O(nlogn) - O(nlgn) - O(nlgn) - O(n)[平均 - 最好 - 最坏 - 空间复杂度] 6 | */ 7 | public class MergeSort { 8 | // 排序 9 | public void mergeSort(int[] a, int low, int high) { 10 | if (null == a || a.length < 2) { 11 | return; 12 | } 13 | int mid = (low + high) / 2; 14 | if (low < high) { 15 | // 左边排序 16 | mergeSort(a, low, mid); 17 | // 右边排序 18 | mergeSort(a, mid + 1, high); 19 | // 有序序列合并 20 | merge(a, low, mid, high); 21 | } 22 | } 23 | 24 | // 合并 25 | private void merge(int a[], int low, int mid, int high) { 26 | // 临时数组 27 | int[] temp = new int[high - low + 1]; 28 | // 左指针 29 | int i = low; 30 | // 右指针 31 | int j = mid + 1; 32 | // 临时数组索引 33 | int k = 0; 34 | 35 | while (i <= mid && j <= high) { 36 | if (a[i] < a[j]) { 37 | temp[k++] = a[i++]; 38 | } else { 39 | temp[k++] = a[j++]; 40 | } 41 | } 42 | 43 | // 把左边剩余的数移入数组 44 | while (i <= mid) { 45 | temp[k++] = a[i++]; 46 | } 47 | 48 | // 把右边剩余的数移入数组 49 | while (j <= high) { 50 | temp[k++] = a[j++]; 51 | } 52 | 53 | // 注意这里是low + t 54 | for (int t = 0; t < temp.length; t++) { 55 | a[low + t] = temp[t]; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/rann/sort/HeapSort.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | /** 4 | * 堆排序 - 不稳定 5 | * 复杂度:O(nlogn) - O(nlgn) - O(nlgn) - O(1)[平均 - 最好 - 最坏 - 空间复杂度] 6 | */ 7 | public class HeapSort { 8 | public void heapSort(int[] a) { 9 | if (null == a || a.length < 2) { 10 | return; 11 | } 12 | 13 | buildMaxHeap(a); 14 | 15 | for (int i = a.length - 1; i >= 0; i--) { 16 | int temp = a[0]; 17 | a[0] = a[i]; 18 | a[i] = temp; 19 | 20 | adjustHeap(a, i, 0); 21 | } 22 | } 23 | 24 | // 建堆 25 | private void buildMaxHeap(int[] a) { 26 | int mid = a.length / 2; 27 | for (int i = mid; i >= 0; i--) { 28 | adjustHeap(a, a.length, i); 29 | } 30 | } 31 | 32 | // 递归调整堆 33 | private void adjustHeap(int[] a, int size, int parent) { 34 | int left = 2 * parent + 1; 35 | int right = 2 * parent + 2; 36 | int largest = parent; 37 | 38 | if (left < size && a[left] > a[largest]) { 39 | largest = left; 40 | } 41 | 42 | if (right < size && a[right] > a[largest]) { 43 | largest = right; 44 | } 45 | 46 | if (parent != largest) { 47 | int temp = a[parent]; 48 | a[parent] = a[largest]; 49 | a[largest] = temp; 50 | adjustHeap(a, size, largest); 51 | } 52 | } 53 | 54 | // 维护了一个最大堆 55 | // public static void main(String[] args) { 56 | // int[] a = {4, 5, 3, 2, 1, 6, 7, 8, 9, 10}; 57 | // new HeapSort().heapSort(a); 58 | // } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/rann/datastructure/jcollections/IList.java: -------------------------------------------------------------------------------- 1 | package com.rann.datastructure.jcollections; 2 | 3 | /** 4 | * 实现自己的List接口 5 | */ 6 | public interface IList { 7 | /** 8 | * 列表元素总个数 9 | * @return 10 | */ 11 | int size(); 12 | 13 | /** 14 | * 列表个数为0时返回true 15 | * @return 16 | */ 17 | boolean isEmpty(); 18 | 19 | /** 20 | * 判断是否存在某个元素 21 | * @param o 22 | * @return 23 | */ 24 | boolean contains(Object o); 25 | 26 | /** 27 | * 添加元素 28 | * @param element 29 | * @return 30 | */ 31 | boolean add(E element); 32 | 33 | /** 34 | * 指定位置添加 35 | * @param index 36 | * @param element 37 | */ 38 | void add(int index, E element); 39 | 40 | /** 41 | * 获取指定位置元素 42 | * @param index 43 | * @return 44 | */ 45 | E get(int index); 46 | 47 | /** 48 | * 替换指定位置元素 49 | * @param index 50 | * @param element 51 | * @return 52 | */ 53 | E set(int index, E element); 54 | 55 | /** 56 | * 删除元素 57 | * @param o 58 | * @return 59 | */ 60 | boolean remove(Object o); 61 | 62 | /** 63 | * 删除指定位置元素 64 | * @param index 65 | * @return 66 | */ 67 | E remove(int index); 68 | 69 | /** 70 | * 第一次出现的索引 71 | * @param o 72 | * @return 73 | */ 74 | int indexOf(Object o); 75 | 76 | /** 77 | * 最后出现的索引 78 | * @param o 79 | * @return 80 | */ 81 | int lastIndexOf(Object o); 82 | 83 | /** 84 | * 清空列表 85 | * remove all elements from the list 86 | */ 87 | void clear(); 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/rann/sort/QuickSort.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * 快速排序 - 不稳定 7 | * 复杂度:O(nlgn) - O(nlgn) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度] 8 | * 栈空间 O(lgn) - O(n) 9 | */ 10 | public class QuickSort { 11 | // 递归,固定基准 12 | public void quickSort(int[] a, int low, int high) { 13 | if (null == a || a.length < 2) { 14 | return; 15 | } 16 | if (low < high) { 17 | int mid = partition(a, low, high); 18 | quickSort(a, low, mid - 1); 19 | quickSort(a, mid + 1, high); 20 | } 21 | } 22 | 23 | // 非递归,固定基准 24 | public void quickSortNonRecur(int[] a, int low, int high) { 25 | if (null == a || a.length < 2) { 26 | return; 27 | } 28 | Stack stack = new Stack<>(); 29 | stack.push(low); 30 | stack.push(high); 31 | while (!stack.isEmpty()) { 32 | high = stack.pop(); 33 | low = stack.pop(); 34 | if (low < high) { 35 | int mid = partition(a, low, high); 36 | stack.push(low); 37 | stack.push(mid - 1); 38 | stack.push(mid + 1); 39 | stack.push(high); 40 | } 41 | } 42 | } 43 | 44 | private int partition(int[] a, int low, int high) { 45 | int pivot = a[low]; 46 | 47 | while (low < high) { 48 | // 注意等于,否则当全部待排序数字都相同的时候会死循环 49 | while (low < high && a[high] >= pivot) { 50 | high--; 51 | } 52 | a[low] = a[high]; 53 | // 注意等于,否则当全部待排序数字都相同的时候会死循环 54 | while (low < high && a[low] <= pivot) { 55 | low++; 56 | } 57 | a[high] = a[low]; 58 | } 59 | a[low] = pivot; 60 | 61 | return low; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/rann/hash/ConsistentHashWithoutVN.java: -------------------------------------------------------------------------------- 1 | package com.rann.hash; 2 | 3 | import java.util.SortedMap; 4 | import java.util.TreeMap; 5 | 6 | /** 7 | * 不带虚拟结点的一致性Hash算法 8 | * @author 哓哓 9 | * 10 | */ 11 | public class ConsistentHashWithoutVN { 12 | 13 | /** 14 | * 待加入Hash环的服务器列表 15 | */ 16 | private static String[] servers = { "192.168.0.0:111", "192.168.0.1:111", "192.168.0.2:111", "192.168.0.3:111", 17 | "192.168.0.4:111" }; 18 | 19 | /** 20 | * key表示服务器的hash值,value表示服务器的名称 21 | */ 22 | private static SortedMap sortedMap = new TreeMap<>(); 23 | 24 | /** 25 | * 程序初始化,将所有服务器加入集合 26 | */ 27 | static { 28 | for (int i = 0; i < servers.length; i++) { 29 | int hash = getHash(servers[i]); 30 | System.out.println("[" + servers[i] + "]加入集群中, 其Hash值为" + hash); 31 | sortedMap.put(hash, servers[i]); 32 | } 33 | } 34 | 35 | /** 36 | * 使用FNV1_32_HASH算法计算hash值 37 | * @param str 38 | * @return 39 | */ 40 | private static int getHash(String str) { 41 | final int p = 16777619; 42 | int hash = (int) 2166136261L; 43 | for (int i = 0; i < str.length(); i++) { 44 | hash = (hash ^ str.charAt(i)) * p; 45 | } 46 | hash += hash << 13; 47 | hash ^= hash >> 7; 48 | hash += hash << 3; 49 | hash ^= hash >> 17; 50 | hash += hash << 5; 51 | 52 | // 如果算出来的值为负数则取其绝对值 53 | if (hash < 0) 54 | hash = Math.abs(hash); 55 | return hash; 56 | } 57 | 58 | private static String matchServer(String node) { 59 | // 待路由结点的Hash值 60 | int hash = getHash(node); 61 | // 得到大于该Hash值的子Map 62 | SortedMap subMap = sortedMap.tailMap(hash); 63 | // 顺时针的第一个Key 64 | Integer i = subMap.firstKey(); 65 | // 返回路由到的服务器名称 66 | return subMap.get(i); 67 | } 68 | 69 | public static void main(String[] args) { 70 | 71 | String[] nodes = {"127.0.0.1:1111", "221.226.0.1:2222", "10.211.0.1:3333"}; 72 | for (int i = 0; i < nodes.length; i++) { 73 | System.out.println("[" + nodes[i] + "]的hash值为" + getHash(nodes[i]) + ",被路由到的服务器为[" 74 | + matchServer(nodes[i]) + "]"); 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/scala/com/scala/oj/Knapsack.scala: -------------------------------------------------------------------------------- 1 | package com.scala.oj 2 | 3 | /** 4 | * Created by Lemonjing on 2018/6/5. 5 | * Github: Lemonjing 6 | * 7 | * 01背包状态转移方程:dp(i,j) = Max(dp(i-1,j), dp(i-1, j-w[i]) + v[i]) 一维数组法内循环逆序 8 | * 完全背包(物品数目无限)状态转移方程:f[i][j] = Max(f[i-1][j],f[i][j-w(i)]+v[i]) 一维数组法内循环正序 9 | * 多重背包解法:多重背包问题限定了一种物品的个数,解决多重背包问题,只需要把它转化为0-1背包问题即可。 10 | * 比如,有2件价值为5,重量为2的同一物品,我们就可以分为物品a和物品b,a和b的价值都为5,重量都为2,但我们把它们视作不同的物品。 11 | */ 12 | object Knapsack { 13 | 14 | // 二维数组法 15 | def Knapsack01(w: Array[Int], v: Array[Int], capacity: Int, n: Int): Int = { 16 | val maxValue = Array.ofDim[Int](n + 1, capacity + 1) 17 | for (i <- 1 until n + 1) { 18 | for (j <- 1 until capacity + 1) { 19 | if (j >= w(i - 1)) { 20 | maxValue(i)(j) = math.max(maxValue(i - 1)(j), maxValue(i - 1)(j - w(i - 1)) + v(i - 1)) 21 | } else { 22 | // 二维数组放不下要加入这一行 23 | maxValue(i)(j) = maxValue(i - 1)(j) 24 | } 25 | } 26 | } 27 | maxValue(n)(capacity) 28 | } 29 | 30 | // 一维数组法(数组压缩) 31 | def Knapsack01WithCompact(w: Array[Int], v: Array[Int], capacity: Int, n: Int): Int = { 32 | val maxValue = Array.ofDim[Int](capacity + 1) 33 | for (i <- 1 until n + 1) { 34 | for (j <- w(i - 1) until capacity + 1 reverse) { 35 | maxValue(j) = math.max(maxValue(j), maxValue(j - w(i - 1)) + v(i - 1)) 36 | } 37 | } 38 | maxValue(capacity) 39 | } 40 | 41 | def KnapsackComplete(w: Array[Int], v: Array[Int], capacity: Int, n: Int): Int = { 42 | val maxValue = Array.ofDim[Int](capacity + 1) 43 | for (i <- 1 until n + 1) { 44 | // 注意完全背包一维数组法内循环的正序 45 | for (j <- w(i - 1) until capacity + 1) { 46 | maxValue(j) = math.max(maxValue(j), maxValue(j - w(i - 1)) + v(i - 1)) 47 | } 48 | } 49 | maxValue(capacity) 50 | } 51 | 52 | def main(args: Array[String]): Unit = { 53 | val capacity = 10 54 | val n = 3 55 | val w = Array(3, 11, 5) 56 | val v = Array(4, 5, 6) 57 | println(Knapsack01(w, v, capacity, n)) 58 | println(Knapsack01WithCompact(w, v, capacity, n)) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/rann/sort/RadixSort.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | /** 4 | * 基数排序 稳定 5 | * 复杂度: O(d(n+r)) r为基数d为位数 空间复杂度O(n+r) 6 | */ 7 | public class RadixSort { 8 | // 基数排序 9 | public void radixSort(int[] a, int begin, int end, int digit) { 10 | // 基数 11 | final int radix = 10; 12 | // 桶中的数据统计 13 | int[] count = new int[radix]; 14 | int[] bucket = new int[end - begin + 1]; 15 | 16 | // 按照从低位到高位的顺序执行排序过程 17 | for (int i = 1; i <= digit; i++) { 18 | // 清空桶中的数据统计 19 | for (int j = 0; j < radix; j++) { 20 | count[j] = 0; 21 | } 22 | 23 | // 统计各个桶将要装入的数据个数 24 | for (int j = begin; j <= end; j++) { 25 | int index = getDigit(a[j], i); 26 | count[index]++; 27 | } 28 | 29 | // count[i]表示第i个桶的右边界索引 30 | for (int j = 1; j < radix; j++) { 31 | count[j] = count[j] + count[j - 1]; 32 | } 33 | 34 | // 将数据依次装入桶中 35 | // 这里要从右向左扫描,保证排序稳定性 36 | for (int j = end; j >= begin; j--) { 37 | int index = getDigit(a[j], i); 38 | bucket[count[index] - 1] = a[j]; 39 | count[index]--; 40 | } 41 | 42 | // 取出,此时已是对应当前位数有序的表 43 | for (int j = 0; j < bucket.length; j++) { 44 | a[j] = bucket[j]; 45 | } 46 | } 47 | } 48 | 49 | // 获取x的第d位的数字,其中最低位d=1 50 | private int getDigit(int x, int d) { 51 | String div = "1"; 52 | while (d >= 2) { 53 | div += "0"; 54 | d--; 55 | } 56 | return x / Integer.parseInt(div) % 10; 57 | } 58 | 59 | // // Test getDigit 60 | // public static void main(String[] args) { 61 | // System.out.println(new RadixSort().getDigit(123, 1)); 62 | // System.out.println(new RadixSort().getDigit(123, 2)); 63 | // System.out.println(new RadixSort().getDigit(123, 3)); 64 | // System.out.println(new RadixSort().getDigit(1211, 1)); 65 | // System.out.println(new RadixSort().getDigit(1211, 2)); 66 | // System.out.println(new RadixSort().getDigit(1211, 3)); 67 | // System.out.println(new RadixSort().getDigit(1211, 4)); 68 | // } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/rann/hash/ConsistentHashWithVN.java: -------------------------------------------------------------------------------- 1 | package com.rann.hash; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.SortedMap; 6 | import java.util.TreeMap; 7 | 8 | /** 9 | * 带虚拟结点的一致性Hash算法 10 | * 11 | * @author hztaoran 12 | */ 13 | public class ConsistentHashWithVN { 14 | /** 15 | * 待加入Hash环的服务器列表 16 | */ 17 | private static String[] servers = {"192.168.0.0:111", "192.168.0.1:111", "192.168.0.2:111", "192.168.0.3:111", 18 | "192.168.0.4:111"}; 19 | 20 | /** 21 | * 真实结点列表,考虑到服务器上线、下线的场景,即添加、删除的场景会比较频繁,这里使用LinkedList会更好 22 | */ 23 | private static List realNodes = new LinkedList<>(); 24 | 25 | /** 26 | * key表示虚拟结点服务器的hash值,value表示虚拟结点服务器的名称 27 | */ 28 | private static SortedMap virtualNodes = new TreeMap<>(); 29 | 30 | /** 31 | * 虚拟结点数目(一个真实结点对应VN_SUM个虚拟结点) 32 | */ 33 | private static final int VN_SUM = 5; 34 | 35 | /** 36 | * 加所有服务器加入集合 37 | */ 38 | static { 39 | for (int i = 0; i < servers.length; i++) { 40 | realNodes.add(servers[i]); 41 | } 42 | 43 | for (String str : realNodes) { 44 | for (int i = 0; i < VN_SUM; i++) { 45 | String virtualNodeName = str + "&VN" + String.valueOf(i); 46 | int hash = HashUtil.FNV1_32_HASH(virtualNodeName); 47 | System.out.println("虚拟节点[" + virtualNodeName + "]被添加, hash值为" + hash); 48 | virtualNodes.put(hash, virtualNodeName); 49 | } 50 | } 51 | System.out.println("\n===========路由映射==============\n"); 52 | } 53 | 54 | private static String matchServer(String node) { 55 | // 待路由结点的Hash值 56 | int hash = HashUtil.FNV1_32_HASH(node); 57 | // 得到大于该Hash值的子Map 58 | SortedMap subMap = virtualNodes.tailMap(hash); 59 | // 顺时针的第一个Key 60 | Integer i = subMap.firstKey(); 61 | // 截取 62 | String virtualNode = subMap.get(i); 63 | 64 | // 返回路由到的服务器名称 65 | return virtualNode.substring(0, virtualNode.indexOf("&")); 66 | } 67 | 68 | public static void main(String[] args) { 69 | 70 | String[] nodes = {"127.0.0.1:1111", "221.226.0.1:2222", "10.211.0.1:3333", "112.74.15.218:80"}; 71 | for (int i = 0; i < nodes.length; i++) { 72 | System.out.println( 73 | "[" + nodes[i] + "]的hash值为" + HashUtil.FNV1_32_HASH(nodes[i]) + ",被路由到的服务器为[" + matchServer(nodes[i]) + "]"); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.rann 8 | algorithm 9 | 1.0-SNAPSHOT 10 | algorithm 11 | https://github.com/it-interview/algorithm 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | junit 20 | junit 21 | 4.12 22 | 23 | 24 | org.slf4j 25 | slf4j-api 26 | 1.6.2 27 | 28 | 29 | org.slf4j 30 | slf4j-log4j12 31 | 1.6.2 32 | 33 | 34 | org.apache.commons 35 | commons-lang3 36 | 3.1 37 | 38 | 39 | org.springframework 40 | spring-webmvc 41 | 4.3.0.RELEASE 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.apache.maven.plugins 49 | maven-compiler-plugin 50 | 51 | 1.8 52 | 1.8 53 | ${project.build.sourceEncoding} 54 | 55 | 56 | 57 | 58 | org.scala-tools 59 | maven-scala-plugin 60 | 2.15.2 61 | 62 | 63 | 64 | compile 65 | testCompile 66 | 67 | 68 | 69 | 70 | 2.11.11 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/main/java/com/rann/datastructure/tree/BTree.java: -------------------------------------------------------------------------------- 1 | package com.rann.datastructure.tree; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | import java.util.Stack; 6 | 7 | /** 8 | * Created by Lemonjing on 2016/3/17 0017. 9 | * Github: Lemonjing 10 | * 二叉树遍历算法(递归非递归) 11 | */ 12 | public class BTree { 13 | 14 | public Node root; 15 | 16 | private class Node { 17 | private int data; 18 | private Node leftChild; 19 | private Node rightChild; 20 | 21 | public Node(int data) { 22 | this.leftChild = null; 23 | this.rightChild = null; 24 | this.data = data; 25 | } 26 | } 27 | 28 | /** 29 | * 空树 30 | */ 31 | public BTree() { 32 | root = null; 33 | } 34 | 35 | /** 36 | * 创建二叉树 37 | * 38 | * @param node 39 | * @param data 40 | */ 41 | public void buildBTree(Node node, int data) { 42 | if (root == null) { 43 | root = new Node(data); 44 | return; 45 | } else { 46 | if (data < node.data) { 47 | if (node.leftChild == null) { 48 | node.leftChild = new Node(data); 49 | } else { 50 | buildBTree(node.leftChild, data); 51 | } 52 | } else { 53 | if (node.rightChild == null) { 54 | node.rightChild = new Node(data); 55 | } else { 56 | buildBTree(node.rightChild, data); 57 | } 58 | } 59 | } 60 | } 61 | 62 | /** 63 | * 前序 64 | * 65 | * @param node 66 | */ 67 | public void preOrder(Node node) { 68 | if (node != null) { 69 | System.out.println(node.data); 70 | preOrder(node.leftChild); 71 | preOrder(node.rightChild); 72 | } 73 | } 74 | 75 | /** 76 | * 前序非递归 77 | * 78 | * @param node 79 | */ 80 | public void preOrder2(Node node) { 81 | Stack stack = new Stack<>(); 82 | while (node != null || !stack.isEmpty()) { 83 | while (node != null) { 84 | stack.push(node); 85 | System.out.println(node.data); 86 | node = node.leftChild; 87 | } 88 | node = stack.pop(); 89 | node = node.rightChild; 90 | } 91 | } 92 | 93 | /** 94 | * 中序 95 | * 96 | * @param node 97 | */ 98 | public void inOrder(Node node) { 99 | if (node != null) { 100 | inOrder(node.leftChild); 101 | System.out.println(node.data); 102 | inOrder(node.rightChild); 103 | } 104 | } 105 | 106 | /** 107 | * 中序非递归 108 | * 109 | * @param node 110 | */ 111 | public void inOrder2(Node node) { 112 | Stack stack = new Stack<>(); 113 | while (node != null || !stack.isEmpty()) { 114 | while (node != null) { 115 | stack.push(node); 116 | node = node.leftChild; 117 | } 118 | node = stack.pop(); 119 | System.out.println(node.data); 120 | node = node.rightChild; 121 | } 122 | } 123 | 124 | /** 125 | * 后序 126 | * 127 | * @param node 128 | */ 129 | public void postOrder(Node node) { 130 | if (node != null) { 131 | postOrder(node.leftChild); 132 | postOrder(node.rightChild); 133 | System.out.println(node.data); 134 | } 135 | } 136 | 137 | /** 138 | * 后序非递归 139 | * 140 | * @param node 141 | */ 142 | public void postOrder2(Node node) { 143 | Stack stack = new Stack<>(); 144 | Node flagNode = null; 145 | while (node != null || !stack.isEmpty()) { 146 | while (node != null) { 147 | stack.push(node); 148 | node = node.leftChild; 149 | } 150 | node = stack.peek(); 151 | if (node.rightChild == null || node.rightChild == flagNode) { 152 | System.out.println(node.data); 153 | flagNode = node; 154 | stack.pop(); 155 | node = null; 156 | } else { 157 | node = node.rightChild; 158 | } 159 | } 160 | } 161 | 162 | /** 163 | * 层序遍历 164 | * 165 | * @param node 166 | */ 167 | public void levelOrder(Node node) { 168 | if (node != null) { 169 | Queue q = new LinkedList(); 170 | q.offer(node); 171 | while (!q.isEmpty()) { 172 | Node temp = q.poll(); 173 | System.out.println(temp.data); 174 | if (temp.leftChild != null) { 175 | q.offer(temp.leftChild); 176 | } 177 | if (temp.rightChild != null) { 178 | q.offer(temp.rightChild); 179 | } 180 | } 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/main/java/com/rann/datastructure/jcollections/IArrayList.java: -------------------------------------------------------------------------------- 1 | package com.rann.datastructure.jcollections; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 实现自己的ArrayList 7 | * 8 | * @param 9 | * @author hztaoran 10 | */ 11 | public class IArrayList implements IList { 12 | 13 | // 默认装载因子 14 | private static final int DEFAULT_CAPACITY = 10; 15 | 16 | private int size; 17 | 18 | private Object[] elementData; 19 | 20 | public IArrayList() { 21 | this(DEFAULT_CAPACITY); 22 | } 23 | 24 | public IArrayList(int initialCapacity) { 25 | if (initialCapacity < 0) { 26 | throw new IllegalArgumentException("capacity < 0"); 27 | } 28 | elementData = new Object[initialCapacity]; 29 | } 30 | 31 | @Override 32 | public int size() { 33 | return size; 34 | } 35 | 36 | @Override 37 | public boolean isEmpty() { 38 | return 0 == size; 39 | } 40 | 41 | @Override 42 | public boolean contains(Object o) { 43 | return indexOf(o) >= 0; 44 | } 45 | 46 | /** 47 | * 末尾添加 48 | * @param element 49 | * @return 50 | */ 51 | @Override 52 | public boolean add(E element) { 53 | ensureCapacity(size + 1); 54 | elementData[size++] = element; 55 | 56 | return true; 57 | } 58 | 59 | /** 60 | * 指定索引添加时元素后移 61 | * @param index 62 | * @param element 63 | */ 64 | @Override 65 | public void add(int index, E element) { 66 | if (index > size || index < 0) { 67 | throw new IndexOutOfBoundsException("index out of bounds"); 68 | } 69 | ensureCapacity(size + 1); 70 | System.arraycopy(elementData, index, elementData, index + 1, size - index); 71 | } 72 | 73 | @Override 74 | public E get(int index) { 75 | rangeCheck(index); 76 | 77 | return (E)elementData[index]; 78 | } 79 | 80 | @Override 81 | public E set(int index, E element) { 82 | rangeCheck(index); 83 | E oldValue = (E)elementData[index]; 84 | elementData[index] = element; 85 | 86 | return oldValue; 87 | } 88 | 89 | @Override 90 | public boolean remove(Object o) { 91 | if (null == o) { 92 | for (int i = 0; i < size; i++) { 93 | if (null == elementData[i]) { 94 | fastRemove(i); 95 | return true; 96 | } 97 | } 98 | } else { 99 | for (int i = 0; i < size; i++) { 100 | if (o.equals(elementData[i])) { 101 | fastRemove(i); 102 | return true; 103 | } 104 | } 105 | } 106 | 107 | return false; 108 | } 109 | 110 | @Override 111 | public E remove(int index) { 112 | rangeCheck(index); 113 | E oldValue = (E)elementData[index]; 114 | fastRemove(index); 115 | 116 | return oldValue; 117 | } 118 | 119 | @Override 120 | public int indexOf(Object o) { 121 | if (o == null) { 122 | for (int i = 0; i < size; i++) { 123 | if (null == elementData[i]) { 124 | return i; 125 | } 126 | } 127 | } else { 128 | for (int i = 0; i < size; i++) { 129 | if (o.equals(elementData[i])) { 130 | return i; 131 | } 132 | } 133 | } 134 | return -1; 135 | } 136 | 137 | @Override 138 | public int lastIndexOf(Object o) { 139 | if (o == null) { 140 | for (int i = size - 1; i >= 0; i--) { 141 | if (null == elementData[i]) { 142 | return i; 143 | } 144 | } 145 | } else { 146 | for (int i = size - 1; i >= 0; i--) { 147 | if (o.equals(elementData[i])) { 148 | return i; 149 | } 150 | } 151 | } 152 | return -1; 153 | } 154 | 155 | @Override 156 | public void clear() { 157 | for (int i = 0; i < size; i++) { 158 | elementData[i] = null; 159 | } 160 | size = 0; 161 | } 162 | 163 | /** 164 | * 扩容 165 | * @param minCapacity 166 | */ 167 | private void ensureCapacity(int minCapacity) { 168 | int oldCapacity = elementData.length; 169 | if (minCapacity > oldCapacity) { 170 | int newCapacity = (3 * oldCapacity) / 2 + 1; 171 | elementData = Arrays.copyOf(elementData, newCapacity); 172 | } 173 | } 174 | 175 | /** 176 | * 判断指定索引 177 | * @param index 178 | */ 179 | private void rangeCheck(int index) { 180 | if (index >= size || index < 0) { 181 | throw new IndexOutOfBoundsException("index out of bounds, index"); 182 | } 183 | } 184 | 185 | /** 186 | * 删除元素的移动 187 | * @param index 188 | */ 189 | private void fastRemove(int index) { 190 | int numMoved = size - index - 1; 191 | if (numMoved > 0) { 192 | System.arraycopy(elementData, index + 1, elementData, index, numMoved); 193 | } 194 | elementData[--size] = null; 195 | } 196 | } -------------------------------------------------------------------------------- /src/test/java/com/rann/sort/SortPerformanceTest.java: -------------------------------------------------------------------------------- 1 | package com.rann.sort; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.BufferedWriter; 5 | import java.io.FileInputStream; 6 | import java.io.FileOutputStream; 7 | import java.io.InputStreamReader; 8 | import java.io.OutputStreamWriter; 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.List; 12 | import java.util.Random; 13 | 14 | /** 15 | * 改进的希尔排序效果显著 16 | * 17 | * @author 哓哓 18 | */ 19 | public class SortPerformanceTest { 20 | private static final int MAX_SIZE = 10000; 21 | 22 | public static void main(String[] args) { 23 | // 启用下行代码随机生成指定MAX_SIZE规模的文本数据并存入数组 24 | new SortPerformanceTest().createBenchMark(); 25 | System.out.println("正在读取" + MAX_SIZE + "组测试数据并执行不同排序方法,请等待..."); 26 | System.out.println("======开始分析======"); 27 | 28 | Long insertionSortTime = new SortPerformanceTest().insertionSortPerformance(); 29 | System.out.println(MAX_SIZE + "组随机数据插入排序耗时:" + insertionSortTime + "ms"); 30 | 31 | Long shellSortTime = new SortPerformanceTest().shellSortPerformance(); 32 | System.out.println(MAX_SIZE + "组随机数据希尔排序(改进)耗时:" + shellSortTime + "ms"); 33 | 34 | Long bubbleSortTime = new SortPerformanceTest().bubbleSortPerformance(); 35 | System.out.println(MAX_SIZE + "组随机数据冒泡排序耗时:" + bubbleSortTime + "ms"); 36 | 37 | Long selectSortTime = new SortPerformanceTest().selectSortPerformance(); 38 | System.out.println(MAX_SIZE + "组随机数据选择排序耗时:" + selectSortTime + "ms"); 39 | 40 | Long mergeSortTime = new SortPerformanceTest().mergeSortPerformance(); 41 | System.out.println(MAX_SIZE + "组随机数据归并排序耗时:" + mergeSortTime + "ms"); 42 | 43 | Long qucikSortTime = new SortPerformanceTest().qucikSortPerformance(); 44 | System.out.println(MAX_SIZE + "组随机数据快速排序耗时:" + qucikSortTime + "ms"); 45 | 46 | Long heapSortTime = new SortPerformanceTest().heapSortPerformance(); 47 | System.out.println(MAX_SIZE + "组随机数据堆排序耗时:" + heapSortTime + "ms"); 48 | 49 | Long radixSortTime = new SortPerformanceTest().radixSortPerformance(); 50 | System.out.println(MAX_SIZE + "组随机数据基数排序耗时:" + radixSortTime + "ms"); 51 | 52 | Long apiArraysSortTime = new SortPerformanceTest().apiArraysSortPerformance(); 53 | System.out.println(MAX_SIZE + "组随机数据java.util.Arrays.sort(改进的快排)耗时:" + apiArraysSortTime + "ms"); 54 | 55 | System.out.println("======结束分析======"); 56 | } 57 | 58 | // 1.插入时间测试 59 | private Long insertionSortPerformance() { 60 | int[] a = readBenchMark(); 61 | Long start = System.currentTimeMillis(); 62 | new InsertionSort().insertionSort(a); 63 | Long end = System.currentTimeMillis(); 64 | 65 | return end - start; 66 | } 67 | 68 | // 2.希尔(改进)时间测试 69 | private Long shellSortPerformance() { 70 | int[] a = readBenchMark(); 71 | Long start = System.currentTimeMillis(); 72 | new ShellSort().shellSort(a); 73 | Long end = System.currentTimeMillis(); 74 | 75 | return end - start; 76 | } 77 | 78 | // 3.冒泡时间测试 79 | private Long bubbleSortPerformance() { 80 | int[] a = readBenchMark(); 81 | Long start = System.currentTimeMillis(); 82 | new BubbleSort().bubbleSort(a); 83 | Long end = System.currentTimeMillis(); 84 | 85 | return end - start; 86 | } 87 | 88 | // 4.选择排序 89 | private Long selectSortPerformance() { 90 | int[] a = readBenchMark(); 91 | Long start = System.currentTimeMillis(); 92 | new SelectSort().selectSort(a); 93 | Long end = System.currentTimeMillis(); 94 | 95 | return end - start; 96 | } 97 | 98 | // 5.归并时间测试 99 | private Long mergeSortPerformance() { 100 | int[] a = readBenchMark(); 101 | Long start = System.currentTimeMillis(); 102 | new MergeSort().mergeSort(a, 0, a.length - 1); 103 | Long end = System.currentTimeMillis(); 104 | 105 | return end - start; 106 | } 107 | 108 | // 6.快排时间测试 109 | private Long qucikSortPerformance() { 110 | int[] a = readBenchMark(); 111 | Long start = System.currentTimeMillis(); 112 | new QuickSort().quickSort(a, 0, a.length - 1); 113 | Long end = System.currentTimeMillis(); 114 | 115 | return end - start; 116 | } 117 | 118 | // 7.堆排时间测试 119 | private Long heapSortPerformance() { 120 | int[] a = readBenchMark(); 121 | Long start = System.currentTimeMillis(); 122 | new HeapSort().heapSort(a); 123 | Long end = System.currentTimeMillis(); 124 | 125 | return end - start; 126 | } 127 | 128 | // 8.基数时间测试 129 | private Long radixSortPerformance() { 130 | int[] a = readBenchMark(); 131 | Long start = System.currentTimeMillis(); 132 | new RadixSort().radixSort(a, 0, a.length - 1, 4); 133 | Long end = System.currentTimeMillis(); 134 | 135 | return end - start; 136 | } 137 | 138 | // 9.Java.util.Arrays调优的快速排序时间测试 139 | private Long apiArraysSortPerformance() { 140 | int[] a = readBenchMark(); 141 | Long start = System.currentTimeMillis(); 142 | Arrays.sort(a); 143 | Long end = System.currentTimeMillis(); 144 | 145 | return end - start; 146 | } 147 | 148 | private void createBenchMark() { 149 | // 随机产生MAX_SIZE个5000范围的随机数测试数据 150 | Random rand = new Random(System.currentTimeMillis()); 151 | List list = new ArrayList<>(); 152 | for (int i = 0; i < MAX_SIZE; i++) { 153 | list.add(String.valueOf(rand.nextInt(5000))); 154 | } 155 | // 文件IO 156 | BufferedWriter bw; 157 | try { 158 | bw = new BufferedWriter( 159 | new OutputStreamWriter(new FileOutputStream("src/test/resources/benchmark.txt"), "UTF-8")); 160 | for (String val : list) { 161 | bw.write(val); 162 | bw.write(','); 163 | } 164 | bw.close(); 165 | } catch (Exception e) { 166 | e.printStackTrace(); 167 | } 168 | } 169 | 170 | private int[] readBenchMark() { 171 | BufferedReader br; 172 | int[] a = new int[MAX_SIZE]; 173 | int count = 0; 174 | try { 175 | br = new BufferedReader( 176 | new InputStreamReader(new FileInputStream("src/test/resources/benchmark.txt"), "UTF-8")); 177 | String line = null; 178 | while (null != (line = br.readLine())) { 179 | String[] strArr = line.split(","); 180 | for (String s : strArr) { 181 | a[count++] = Integer.parseInt(s); 182 | } 183 | } 184 | 185 | br.close(); 186 | } catch (Exception e) { 187 | e.printStackTrace(); 188 | } 189 | 190 | return a; 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/main/java/com/rann/datastructure/tree/AVLTree.java: -------------------------------------------------------------------------------- 1 | package com.rann.datastructure.tree; 2 | 3 | /** 4 | * Created by Lemonjing on 2016/3/16 0016. 5 | */ 6 | public class AVLTree> { 7 | 8 | private T data; 9 | private AVLTree parent; 10 | private AVLTree leftChild; 11 | private AVLTree rightChild; 12 | private int height; 13 | 14 | public AVLTree() { 15 | this(null); 16 | } 17 | 18 | public AVLTree(T t) { 19 | data = t; 20 | parent = null; 21 | leftChild = null; 22 | rightChild = null; 23 | height = (t == null ? -1 : 0); 24 | } 25 | 26 | /** 27 | * 取得根结点 28 | * @return 29 | */ 30 | public AVLTree getRoot() { 31 | if (data == null) { 32 | return null; 33 | } 34 | AVLTree root = this; 35 | while (root.parent != null) { 36 | root = root.parent; 37 | } 38 | return root; 39 | } 40 | 41 | // =======getters============= 42 | public AVLTree getLeftChild() { 43 | return leftChild; 44 | } 45 | 46 | public AVLTree getRightChild() { 47 | return rightChild; 48 | } 49 | 50 | public AVLTree getParent() { 51 | return parent; 52 | } 53 | 54 | public int getHeight() { 55 | return updateHeight(); 56 | } 57 | 58 | public T getData() { 59 | return data; 60 | } 61 | 62 | //========================== 63 | 64 | private boolean isEmpty() { 65 | return data == null; 66 | } 67 | 68 | public int getLeftHeight() { 69 | return leftChild == null ? -1 : leftChild.height; 70 | } 71 | 72 | public int getRightHeight() { 73 | return rightChild == null ? -1 : rightChild.height; 74 | } 75 | 76 | private int updateHeight() { 77 | if (data == null) { 78 | height = -1; 79 | return height; 80 | } 81 | int right = getRightHeight(); 82 | int left = getLeftHeight(); 83 | 84 | height = left > right ? (1+left) : (1+right); 85 | 86 | return height; 87 | } 88 | 89 | private AVLTree rootInsert(T t) { 90 | int cp = t.compareTo(data); 91 | 92 | // 比较结果为0,更新元素 93 | if (cp == 0) { 94 | data = t; 95 | } 96 | 97 | // 比当前结点小 98 | if (cp < 0) { 99 | if (leftChild == null) { 100 | leftChild = new AVLTree(t); 101 | leftChild.parent = this; 102 | } else { 103 | leftChild.rootInsert(t); 104 | } 105 | } else { 106 | if (rightChild == null) { 107 | rightChild = new AVLTree(t); 108 | rightChild.parent = this; 109 | } else { 110 | rightChild.rootInsert(t); 111 | } 112 | } 113 | 114 | /** 115 | * 处理插入引起的不平衡 116 | */ 117 | return process(); 118 | } 119 | 120 | private AVLTree process() { 121 | 122 | int lh = getLeftHeight(); 123 | int rh = getRightHeight(); 124 | 125 | AVLTree root = this; 126 | 127 | if (lh - rh == 2) { 128 | if (leftChild.getLeftHeight() >= leftChild.getRightHeight()) { 129 | // LL型 右旋 130 | root = rotateRight(this); 131 | } else { 132 | // LR型 左旋+右旋 133 | rotateLeft(leftChild); 134 | root = rotateRight(this); 135 | } 136 | } else if (rh - lh == 2) { 137 | if (rightChild.getLeftHeight() >= rightChild.getRightHeight()) { 138 | // RR型 左旋 139 | rotateLeft(this); 140 | } else { 141 | // RL型 右旋+左旋 142 | rotateRight(rightChild); 143 | root = rotateLeft(this); 144 | } 145 | } 146 | // 更新当前根结点的高度 147 | root.updateHeight(); 148 | 149 | return root; 150 | } 151 | 152 | public AVLTree insert(T t) { 153 | if (t == null) 154 | return this; 155 | // 特殊情形:当前是空结点 156 | if (data == null) { 157 | data = t; 158 | updateHeight(); 159 | return this; 160 | } 161 | AVLTree root = getRoot(); // 根结点 162 | 163 | return root.rootInsert(t); 164 | } 165 | 166 | /** 167 | * LL型 - 右旋 168 | * @param tree 169 | * @return 170 | */ 171 | private AVLTree rotateRight(AVLTree tree) { 172 | if (tree == null || tree.leftChild == null) { 173 | return tree; 174 | } 175 | AVLTree root = tree.leftChild; 176 | tree.leftChild = root.rightChild; 177 | if (tree.leftChild != null) { 178 | tree.leftChild.parent = tree; 179 | } 180 | root.rightChild = tree; 181 | root.parent = tree.parent; 182 | tree.parent = root; 183 | if (root.parent != null) { 184 | if (root.parent.leftChild == tree) { 185 | root.parent.leftChild = root; 186 | } else { 187 | root.parent.rightChild = root; 188 | } 189 | } 190 | tree.updateHeight(); 191 | root.updateHeight(); 192 | 193 | return root; 194 | } 195 | 196 | /** 197 | * RR型 - 左旋 198 | * @param tree 199 | */ 200 | private AVLTree rotateLeft(AVLTree tree) { 201 | if (tree == null || tree.rightChild == null) { 202 | return tree; 203 | } 204 | AVLTree root = tree.rightChild; 205 | tree.rightChild = root.leftChild; 206 | if (tree.rightChild != null) { 207 | tree.rightChild.parent = tree; 208 | } 209 | root.leftChild = tree; 210 | root.parent = tree.parent; 211 | tree.parent = root; 212 | if (root.parent != null) { 213 | if (root.parent.leftChild == tree) { 214 | root.parent.leftChild = root; 215 | } else { 216 | root.parent.rightChild = root; 217 | } 218 | } 219 | tree.updateHeight(); 220 | root.updateHeight(); 221 | 222 | return root; 223 | } 224 | 225 | /** 226 | * 打印整个树 227 | */ 228 | public void display() { 229 | this.getRoot().displayHolder(); 230 | } 231 | 232 | /** 233 | * 递归打印 234 | */ 235 | private void displayHolder(){ 236 | //空节点、叶子节点不打印 237 | if(data==null) 238 | return; 239 | System.out.println("树信息:"); 240 | System.out.println(String.format("H=%2d, %s->(%s,%s)", 241 | height, 242 | data.toString(), 243 | leftChild == null ? null : leftChild.data.toString(), 244 | rightChild == null ? null : rightChild.data.toString())); 245 | if(leftChild!=null) 246 | leftChild.displayHolder(); 247 | if(rightChild!=null) 248 | rightChild.displayHolder(); 249 | } 250 | 251 | /** 252 | * 先序遍历 253 | * @param t 根结点 254 | */ 255 | private void preOrderTraverse(AVLTree t) { 256 | if (t != null) { 257 | System.out.println(t.data); 258 | preOrderTraverse(t.leftChild); 259 | preOrderTraverse(t.rightChild); 260 | } 261 | } 262 | /** 263 | * 中序遍历 从大到小打印 264 | * @param t 根结点 265 | */ 266 | private void inOrderTraverse(AVLTree t) { 267 | if (t != null) { 268 | inOrderTraverse(t.leftChild); 269 | System.out.println(t.data); 270 | inOrderTraverse(t.rightChild); 271 | } 272 | } 273 | 274 | /** 275 | * 后序遍历 276 | * @param t 根结点 277 | */ 278 | private void postOrderTraverse(AVLTree t) { 279 | if (t != null) { 280 | postOrderTraverse(t.leftChild); 281 | postOrderTraverse(t.rightChild); 282 | System.out.println(t.data); 283 | } 284 | } 285 | 286 | /** 287 | * 遍历方法 288 | * @param t 任意结点 289 | * @param mode 模式 290 | */ 291 | public void traverse (AVLTree t, String mode) { 292 | AVLTree root = t.getRoot(); 293 | if (mode.equals("pre")) { 294 | System.out.println("先序遍历:"); 295 | preOrderTraverse(root); 296 | } else if (mode.equals("in")) { 297 | System.out.println("中序遍历:"); 298 | inOrderTraverse(root); 299 | } else { 300 | System.out.println("后序遍历:"); 301 | postOrderTraverse(root); 302 | } 303 | } 304 | 305 | public AVLTree rootFind(T t) { 306 | if (t != null && data != null) { 307 | int cp = t.compareTo(data); 308 | if (cp == 0) 309 | return this; 310 | if (cp > 0) { 311 | return rightChild == null ? null : rightChild.rootFind(t); 312 | } 313 | return leftChild == null ? null : leftChild.rootFind(t); 314 | } 315 | 316 | return null; 317 | } 318 | 319 | } 320 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------