├── .github ├── FUNDING.yml └── workflows │ └── build.yml ├── .gitignore ├── README.md ├── doc ├── a-star.gif ├── avl.gif ├── bellman_ford.gif ├── binary-and-linear-search.gif ├── binary_tree.jpg ├── bubble-sort.gif ├── dijkstra.gif ├── doubly_linked_list.jpg ├── graph.jpg ├── graph_adjacent_matrix.png ├── heap-sort.gif ├── huffman.png ├── insertion-sort.gif ├── linked_list.jpg ├── merge-sort.gif ├── mini-max.gif ├── priorityqueue.png ├── queue.jpg ├── quick-sort.gif ├── selection-sort.gif ├── shell-sort.gif ├── singly_circular_linked_list.jpg └── stack.jpg ├── pom.xml └── src ├── main └── java │ └── dsa │ ├── ai │ └── graph │ │ ├── minimax │ │ ├── Board.java │ │ ├── Cell.java │ │ └── Minimax.java │ │ └── path │ │ ├── BellmanFord.java │ │ ├── Dijkstra.java │ │ └── astar │ │ ├── AStar.java │ │ ├── Grid2d.java │ │ └── Node.java │ ├── graph │ ├── Edge.java │ ├── Graph.java │ ├── GraphMatrix.java │ └── Vertex.java │ ├── list │ ├── CircularLinkedList.java │ ├── DoublyLinkedList.java │ ├── LinkedList.java │ └── SinglyLinkedList.java │ ├── queue │ ├── Queue.java │ ├── QueueArray.java │ ├── QueueLinkedList.java │ └── priority │ │ ├── MaxPQ.java │ │ └── MinPQ.java │ ├── search │ ├── BinarySearch.java │ └── SequentialSearch.java │ ├── sort │ ├── BubbleSort.java │ ├── HeapSort.java │ ├── InsertionSort.java │ ├── MergeSort.java │ ├── QuickSort.java │ ├── RadixSort.java │ ├── SelectionSort.java │ └── ShellSort.java │ ├── stack │ ├── Stack.java │ ├── StackArray.java │ └── StackLinkedList.java │ └── tree │ ├── avl │ └── AVLTree.java │ ├── bst │ ├── BSTNode.java │ └── BinarySearchTree.java │ └── huffman │ ├── BitStream.java │ └── HuffmanTree.java └── test └── java ├── AllTests.java └── dsa ├── ai └── graph │ ├── BellmanFordTest.java │ ├── DijkstraTest.java │ ├── astar │ └── AStarTest.java │ └── minimax │ └── MiniMaxTest.java ├── graph ├── BFSTest.java └── DFSTest.java ├── list ├── CircularLinkedListTest.java ├── DoublyLinkedListTest.java └── SinglyLinkedListTest.java ├── queue ├── MaxPQTest.java ├── MinPQTest.java └── QueueArrayTest.java ├── search ├── BinarySearchTest.java └── SequentialSearchTest.java ├── sort ├── AllSortTest.java ├── BubbleSortTest.java ├── HeapSortTest.java ├── InsertionSortTest.java ├── MergeSortTest.java ├── QuickSortTest.java ├── RadixSortTest.java ├── SelectionSortTest.java └── ShellSortTest.java ├── stack └── StackArrayTest.java └── tree ├── AVLTreeTest.java ├── BSTTreeTest.java └── HuffmanTreeTest.java /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: humbertodias 4 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build, Test and Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | tags: 8 | - "v*" 9 | pull_request: 10 | branches: 11 | - main 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout code 19 | uses: actions/checkout@v2 20 | 21 | - name: Set up JDK 8 for x64 22 | uses: actions/setup-java@v3 23 | with: 24 | java-version: '8' 25 | distribution: 'temurin' 26 | architecture: x64 27 | 28 | - name: Build 29 | run: mvn package 30 | 31 | - name: Archive Folder 32 | uses: actions/upload-artifact@v4 33 | with: 34 | name: artifact 35 | path: ${{github.workspace}}/target/*.jar 36 | 37 | publish-release: 38 | needs: build 39 | runs-on: ubuntu-latest 40 | 41 | steps: 42 | - name: Download Artifact 43 | uses: actions/download-artifact@v4 44 | with: 45 | name: artifact 46 | path: ${{github.workspace}} 47 | 48 | - name: Create Release 49 | id: create_release 50 | uses: softprops/action-gh-release@v1 51 | if: startsWith(github.ref, 'refs/tags/') 52 | with: 53 | files: ${{ github.workspace }}/*.jar 54 | token: ${{ secrets.GITHUB_TOKEN }} 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml.tag 3 | pom.xml.releaseBackup 4 | pom.xml.versionsBackup 5 | pom.xml.next 6 | release.properties 7 | dependency-reduced-pom.xml 8 | buildNumber.properties 9 | .mvn/timing.properties 10 | /nbproject/ 11 | 12 | 13 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 14 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 15 | 16 | # User-specific stuff 17 | .idea/**/workspace.xml 18 | .idea/**/tasks.xml 19 | .idea/dictionaries 20 | 21 | # Sensitive or high-churn files 22 | .idea/**/dataSources/ 23 | .idea/**/dataSources.ids 24 | .idea/**/dataSources.local.xml 25 | .idea/**/sqlDataSources.xml 26 | .idea/**/dynamic.xml 27 | .idea/**/uiDesigner.xml 28 | 29 | # Gradle 30 | .idea/**/gradle.xml 31 | .idea/**/libraries 32 | 33 | # CMake 34 | cmake-build-debug/ 35 | cmake-build-release/ 36 | 37 | # Mongo Explorer plugin 38 | .idea/**/mongoSettings.xml 39 | 40 | # File-based project format 41 | *.iws 42 | 43 | # IntelliJ 44 | out/ 45 | 46 | # mpeltonen/sbt-idea plugin 47 | .idea_modules/ 48 | 49 | # JIRA plugin 50 | atlassian-ide-plugin.xml 51 | 52 | # Cursive Clojure plugin 53 | .idea/replstate.xml 54 | 55 | # Crashlytics plugin (for Android Studio and IntelliJ) 56 | com_crashlytics_export_strings.xml 57 | crashlytics.properties 58 | crashlytics-build.properties 59 | fabric.properties 60 | 61 | # Editor-based Rest Client 62 | .idea/httpRequests 63 | .idea 64 | *.iml 65 | 66 | .vscode -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build, Test](https://github.com/humbertodias/java-data-structures-algorithms/actions/workflows/build.yml/badge.svg)](https://github.com/humbertodias/java-data-structures-algorithms/actions/workflows/build.yml) 2 | 3 | # Java Data Structure Algorithms 4 | 5 | Data Structure Algorithms using Java 6 | 7 | ## Prerequisites 8 | 9 | 1. Git 2.6+ 10 | 2. Maven 3+ 11 | 3. Java 8+ 12 | 13 | ## Sorting 14 | 15 | * [Bubble](src/main/java/dsa/sort/BubbleSort.java), [Insertion](src/main/java/dsa/sort/InsertionSort.java), [Selection](src/main/java/dsa/sort/SelectionSort.java), [Merge](src/main/java/dsa/sort/MergeSort.java) 16 | 17 | ![Preview](doc/bubble-sort.gif) 18 | ![Preview](doc/insertion-sort.gif) 19 | ![Preview](doc/selection-sort.gif) 20 | ![Preview](doc/merge-sort.gif) 21 | 22 | * [Shell](src/main/java/dsa/sort/ShellSort.java), [Heap](src/main/java/dsa/sort/HeapSort.java), [Quick](src/main/java/dsa/sort/QuickSort.java), [Radix](src/main/java/dsa/sort/RadixSort.java) 23 | 24 | ![Preview](doc/shell-sort.gif) 25 | ![Preview](doc/heap-sort.gif) 26 | ![Preview](doc/quick-sort.gif) 27 | 28 | ## Searching 29 | 30 | * [Binary](src/main/java/dsa/search/BinarySearch.java), [Sequential](src/main/java/dsa/search/SequentialSearch.java) 31 | 32 | ![Preview](doc/binary-and-linear-search.gif) 33 | 34 | ## Data Structure 35 | 36 | 1. Stack 37 | 38 | ![Preview](doc/stack.jpg) 39 | 40 | [StackArray](src/main/java/dsa/stack/StackArray.java), 41 | [StackLinked](src/main/java/dsa/stack/StackLinkedList.java) 42 | 43 | 2. Queue 44 | 45 | * [Array](src/main/java/dsa/queue/QueueArray.java) or [Linked](src/main/java/dsa/queue/QueueLinkedList.java) 46 | 47 | ![Preview](doc/queue.jpg) 48 | 49 | * [Minimum](src/main/java/dsa/queue/priority/MinPQ.java) / [Maximum](src/main/java/dsa/queue/priority/MaxPQ.java) Priority Queue 50 | 51 | ![Preview](doc/priorityqueue.png) 52 | 53 | 3. LinkedList 54 | 55 | * [Singly](src/main/java/dsa/list/SinglyLinkedList.java) 56 | 57 | ![Preview](doc/linked_list.jpg) 58 | 59 | * [Doubly](src/main/java/dsa/list/DoublyLinkedList.java) 60 | 61 | ![Preview](doc/doubly_linked_list.jpg) 62 | 63 | * [Circular](src/main/java/dsa/list/CircularLinkedList.java) 64 | 65 | ![Preview](doc/singly_circular_linked_list.jpg) 66 | 67 | 4. Tree 68 | 69 | * [BinaryTree](src/main/java/dsa/tree/bst/BinarySearchTree.java) 70 | 71 | ![Preview](doc/binary_tree.jpg) 72 | 73 | * [AVLTree](src/main/java/dsa/tree/avl/AVLTree.java) 74 | 75 | ![Preview](doc/avl.gif) 76 | 77 | * [HuffmanTree](src/main/java/dsa/tree/huffman/HuffmanTree.java) 78 | 79 | ![Preview](doc/huffman.png) 80 | 81 | 5. Graph 82 | 83 | * [Vertex](src/main/java/dsa/graph/Graph.java) or [Adjacent Matrix](src/main/java/dsa/graph/GraphMatrix.java) 84 | 85 | ![Preview](doc/graph_adjacent_matrix.png) 86 | 87 | * [Dijkstra](src/main/java/dsa/ai/graph/path/Dijkstra.java) 88 | 89 | ![Preview](doc/dijkstra.gif) 90 | 91 | * [BellmanFord](src/main/java/dsa/ai/graph/path/BellmanFord.java) 92 | 93 | ![Preview](doc/bellman_ford.gif) 94 | 95 | * [Mini Max](src/main/java/dsa/ai/graph/minimax/Minimax.java) 96 | 97 | ![Preview](doc/mini-max.gif) 98 | 99 | * [AStar](src/main/java/dsa/ai/graph/path/astar/AStar.java) 100 | 101 | ![Preview](doc/a-star.gif) 102 | 103 | 104 | ## How to Play 105 | 106 | Clone 107 | 108 | ```shell 109 | git clone https://github.com/humbertodias/java-data-structures-algorithms.git 110 | ``` 111 | 112 | Inside the folder 113 | 114 | ```shell 115 | cd java-data-structures-algorithms 116 | ``` 117 | 118 | Run 119 | 120 | ```shell 121 | mvn test 122 | ``` 123 | ``` 124 | ------------------------------------------------------- 125 | T E S T S 126 | ------------------------------------------------------- 127 | Running dsa.graph.astar.AStarTest 128 | Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.102 sec 129 | Running dsa.graph.test.BFSTest 130 | Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec 131 | Running dsa.graph.test.DFSTest 132 | Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec 133 | Running dsa.graph.test.DijkstraTest 134 | Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec 135 | Running dsa.list.test.DoublyLinkedListTest 136 | Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.006 sec 137 | Running dsa.list.test.SinglyLinkedListTest 138 | Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec 139 | Running dsa.queue.test.MaxPQTest 140 | Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.015 sec 141 | Running dsa.queue.test.MinPQTest 142 | Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.008 sec 143 | Running dsa.queue.test.QueueArrayTest 144 | Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.011 sec 145 | Running dsa.stack.test.StackArrayTest 146 | Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 sec 147 | Running dsa.tree.test.BSTTreeTest 148 | Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.013 sec 149 | Running dsa.tree.test.HuffmanTreeTest 150 | Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.016 sec 151 | 152 | Results : 153 | 154 | Tests run: 26, Failures: 0, Errors: 0, Skipped: 0 155 | 156 | [INFO] ------------------------------------------------------------------------ 157 | [INFO] BUILD SUCCESS 158 | [INFO] ------------------------------------------------------------------------ 159 | [INFO] Total time: 2.069 s 160 | [INFO] Finished at: 2016-06-11T18:38:32-03:00 161 | [INFO] Final Memory: 9M/245M 162 | [INFO] ------------------------------------------------------------------------ 163 | ``` 164 | 165 | ## References 166 | 167 | 1. [A* Search Algorithm](https://en.wikipedia.org/wiki/A*_search_algorithm) 168 | 169 | 2. [Dijkstra](http://www.vogella.com/tutorials/JavaAlgorithmsDijkstra/article.html) 170 | 171 | 3. [BellmanFord](http://www.geekviewpoint.com/java/graph/bellman_ford_shortest_path) 172 | 173 | 4. [Huffman](https://rosettacode.org/wiki/Huffman_coding#Java) 174 | 175 | 5. [List](http://java2novice.com/data-structures-in-java/linked-list/doubly-linked-list/) 176 | 177 | 6. [Stack](http://eddmann.com/posts/implementing-a-stack-in-java-using-arrays-and-linked-lists/) 178 | 179 | 7. [Sorting](http://www.sorting-algorithms.com/) 180 | 181 | 8. [Sorting Steps](https://www.bluffton.edu/~nesterd/java/SortingDemo.html) 182 | 183 | 9. [Radix Sort](https://en.wikipedia.org/wiki/Radix_sort) 184 | 185 | 10. [Mini Max](http://www.brian-borowski.com/software/connectfour/) -------------------------------------------------------------------------------- /doc/a-star.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/a-star.gif -------------------------------------------------------------------------------- /doc/avl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/avl.gif -------------------------------------------------------------------------------- /doc/bellman_ford.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/bellman_ford.gif -------------------------------------------------------------------------------- /doc/binary-and-linear-search.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/binary-and-linear-search.gif -------------------------------------------------------------------------------- /doc/binary_tree.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/binary_tree.jpg -------------------------------------------------------------------------------- /doc/bubble-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/bubble-sort.gif -------------------------------------------------------------------------------- /doc/dijkstra.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/dijkstra.gif -------------------------------------------------------------------------------- /doc/doubly_linked_list.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/doubly_linked_list.jpg -------------------------------------------------------------------------------- /doc/graph.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/graph.jpg -------------------------------------------------------------------------------- /doc/graph_adjacent_matrix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/graph_adjacent_matrix.png -------------------------------------------------------------------------------- /doc/heap-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/heap-sort.gif -------------------------------------------------------------------------------- /doc/huffman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/huffman.png -------------------------------------------------------------------------------- /doc/insertion-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/insertion-sort.gif -------------------------------------------------------------------------------- /doc/linked_list.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/linked_list.jpg -------------------------------------------------------------------------------- /doc/merge-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/merge-sort.gif -------------------------------------------------------------------------------- /doc/mini-max.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/mini-max.gif -------------------------------------------------------------------------------- /doc/priorityqueue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/priorityqueue.png -------------------------------------------------------------------------------- /doc/queue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/queue.jpg -------------------------------------------------------------------------------- /doc/quick-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/quick-sort.gif -------------------------------------------------------------------------------- /doc/selection-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/selection-sort.gif -------------------------------------------------------------------------------- /doc/shell-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/shell-sort.gif -------------------------------------------------------------------------------- /doc/singly_circular_linked_list.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/singly_circular_linked_list.jpg -------------------------------------------------------------------------------- /doc/stack.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humbertodias/java-data-structures-algorithms/4b83cd2c8967cc13c9ff0329433373d02d345096/doc/stack.jpg -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | edu.cse 5 | dsa 6 | 1.0 7 | jar 8 | 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | junit 16 | junit 17 | 4.13.2 18 | test 19 | 20 | 21 | org.hamcrest 22 | hamcrest-core 23 | 3.0 24 | test 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/main/java/dsa/ai/graph/minimax/Board.java: -------------------------------------------------------------------------------- 1 | 2 | package dsa.ai.graph.minimax; 3 | 4 | import java.io.PrintStream; 5 | 6 | /** 7 | * File: Board.java 8 | * Author: Brian Borowski 9 | * Date created: April 9, 2012 10 | * Date last modified: August 6, 2014 11 | */ 12 | public class Board { 13 | public static final char MARK_RED = 'X', MARK_BLACK = 'O', UNMARKED = ' ', 14 | MARK_PINK = 'P', MARK_GRAY = 'G'; 15 | public static final String RED = "Red", BLACK = "Black"; 16 | public static final int ROWS = 6, COLUMNS = 7; 17 | public static final int[] INCREMENT = {0, 1, 4, 32, 128, 512}; 18 | 19 | private final char[][] board; 20 | private final int[][] moveNumbers; 21 | private final int[] firstAvailableRow; 22 | private final Cell[] winningCells; 23 | private boolean winnerFound, redWinFound, blackWinFound; 24 | private int moveNumber; 25 | 26 | public Board() { 27 | board = new char[ROWS][COLUMNS]; 28 | moveNumbers = new int[ROWS][COLUMNS]; 29 | firstAvailableRow = new int[COLUMNS]; 30 | winningCells = new Cell[4]; 31 | reset(); 32 | } 33 | 34 | public void reset() { 35 | for (int row = 0; row < ROWS; row++) { 36 | for (int col = 0; col < COLUMNS; col++) { 37 | board[row][col] = UNMARKED; 38 | moveNumbers[row][col] = 0; 39 | } 40 | } 41 | for (int col = 0; col < COLUMNS; col++) { 42 | firstAvailableRow[col] = ROWS - 1; 43 | } 44 | for (int i = 0; i < 4; i++) { 45 | winningCells[i] = new Cell(0, 0); 46 | } 47 | winnerFound = false; 48 | moveNumber = 1; 49 | } 50 | 51 | public boolean isColumnAvailable(int column) { 52 | return firstAvailableRow[column] != -1; 53 | } 54 | 55 | public int getFirstAvailableRow(int column) { 56 | return firstAvailableRow[column]; 57 | } 58 | 59 | public char get(int row, int column) { 60 | return board[row][column]; 61 | } 62 | 63 | public char[][] getGrid() { 64 | char[][] grid = new char[ROWS][COLUMNS]; 65 | for (int row = 0; row < ROWS; row++) { 66 | for (int col = 0; col < COLUMNS; col++) { 67 | grid[row][col] = board[row][col]; 68 | } 69 | } 70 | return grid; 71 | } 72 | 73 | public void display(PrintStream out) { 74 | for (int row = 0; row < ROWS; row++) { 75 | for (int col = 0; col < COLUMNS; col++) { 76 | out.print("|" + board[row][col]); 77 | } 78 | out.println("|"); 79 | } 80 | out.println("---------------"); 81 | } 82 | 83 | public int mark(int col, char mark) throws IllegalArgumentException { 84 | int row = firstAvailableRow[col]; 85 | if (row < 0) { 86 | throw new IllegalArgumentException( 87 | "Column " + (col + 1) + " is already full."); 88 | } 89 | board[row][col] = mark; 90 | --firstAvailableRow[col]; 91 | return row; 92 | } 93 | 94 | public void set(int col, char mark) throws IllegalArgumentException { 95 | int row = mark(col, mark); 96 | moveNumbers[row][col] = moveNumber++; 97 | } 98 | 99 | public void unset(int col) throws IllegalArgumentException { 100 | int row = firstAvailableRow[col]; 101 | if (row >= ROWS) { 102 | throw new IllegalArgumentException( 103 | "Column " + (col + 1) + " is already empty."); 104 | } 105 | row = ++firstAvailableRow[col]; 106 | board[row][col] = UNMARKED; 107 | } 108 | 109 | public static String getColorOfPlayer(char player) 110 | throws IllegalArgumentException { 111 | 112 | if (player == MARK_RED) { 113 | return RED; 114 | } else if (player == MARK_BLACK) { 115 | return BLACK; 116 | } else { 117 | throw new IllegalArgumentException( 118 | "Unknown player " + player + " received."); 119 | } 120 | } 121 | 122 | public Cell[] getWinningCells() { 123 | return winnerFound ? winningCells : null; 124 | } 125 | 126 | public int[][] getMoveNumbers() { 127 | return moveNumbers; 128 | } 129 | 130 | public char getWinner() { 131 | winnerFound = false; 132 | // Check rows 133 | for (int row = 0; row < ROWS; row++) { 134 | for (int col = 3; col < COLUMNS; col++) { 135 | int redCount = 0, blackCount = 0; 136 | for (int val = 0; val < 4; val++) { 137 | winningCells[val].row = row; 138 | winningCells[val].column = col - val; 139 | char mark = board[row][col - val]; 140 | if (mark == MARK_RED) { 141 | redCount++; 142 | } else if (mark == MARK_BLACK) { 143 | blackCount++; 144 | } 145 | } 146 | if (redCount == 4) { 147 | winnerFound = true; 148 | return MARK_RED; 149 | } else if (blackCount == 4) { 150 | winnerFound = true; 151 | return MARK_BLACK; 152 | } 153 | } 154 | } 155 | // Check columns 156 | for (int col = 0; col < COLUMNS; col++) { 157 | for (int row = 3; row < ROWS; row++) { 158 | int redCount = 0, blackCount = 0; 159 | for (int val = 0; val < 4; val++) { 160 | winningCells[val].row = row - val; 161 | winningCells[val].column = col; 162 | char mark = board[row - val][col]; 163 | if (mark == MARK_RED) { 164 | redCount++; 165 | } else if (mark == MARK_BLACK) { 166 | blackCount++; 167 | } 168 | } 169 | if (redCount == 4) { 170 | winnerFound = true; 171 | return MARK_RED; 172 | } else if (blackCount == 4) { 173 | winnerFound = true; 174 | return MARK_BLACK; 175 | } 176 | } 177 | } 178 | // Check major diagonals 179 | for (int row = ROWS - 4; row >= 0; row--) { 180 | for (int col = COLUMNS - 4; col >= 0; col--) { 181 | int redCount = 0, blackCount = 0; 182 | for (int val = 3; val >= 0; val--) { 183 | winningCells[val].row = row + val; 184 | winningCells[val].column = col + val; 185 | char mark = board[row + val][col + val]; 186 | if (mark == MARK_RED) { 187 | redCount++; 188 | } else if (mark == MARK_BLACK) { 189 | blackCount++; 190 | } 191 | } 192 | if (redCount == 4) { 193 | winnerFound = true; 194 | return MARK_RED; 195 | } else if (blackCount == 4) { 196 | winnerFound = true; 197 | return MARK_BLACK; 198 | } 199 | } 200 | } 201 | // Check minor diagonals 202 | for (int row = ROWS - 4; row >= 0; row--) { 203 | for (int col = COLUMNS - 4; col >= 0; col--) { 204 | int redCount = 0, blackCount = 0; 205 | for (int val = 3; val >= 0; val--) { 206 | winningCells[val].row = row + val; 207 | winningCells[val].column = col - val + 3; 208 | char mark = board[row + val][col - val + 3]; 209 | if (mark == MARK_RED) { 210 | redCount++; 211 | } else if (mark == MARK_BLACK) { 212 | blackCount++; 213 | } 214 | } 215 | if (redCount == 4) { 216 | winnerFound = true; 217 | return MARK_RED; 218 | } else if (blackCount == 4) { 219 | winnerFound = true; 220 | return MARK_BLACK; 221 | } 222 | } 223 | } 224 | return UNMARKED; 225 | } 226 | 227 | private int getScoreIncrement(int redCount, int blackCount, char player) { 228 | if (redCount == blackCount) { 229 | if (player == Board.MARK_RED) { 230 | return -1; 231 | } 232 | return 1; 233 | } else if (redCount < blackCount) { 234 | if (player == Board.MARK_RED) { 235 | return INCREMENT[blackCount] - INCREMENT[redCount]; 236 | } 237 | return INCREMENT[blackCount + 1] - INCREMENT[redCount]; 238 | } else { 239 | if (player == Board.MARK_RED) { 240 | return -INCREMENT[redCount + 1] + INCREMENT[blackCount]; 241 | } 242 | return -INCREMENT[redCount] + INCREMENT[blackCount]; 243 | } 244 | } 245 | 246 | public boolean redWinFound() { 247 | return redWinFound; 248 | } 249 | 250 | public boolean blackWinFound() { 251 | return blackWinFound; 252 | } 253 | 254 | public int getHeuristicScore(char player, int col, int depth, int maxDepth) { 255 | int score = 0, 256 | row = firstAvailableRow[col] + 1, 257 | redCount, blackCount; 258 | redWinFound = blackWinFound = false; 259 | 260 | /////////////////////////////////////////////////////////////////////// 261 | // Check row 262 | /////////////////////////////////////////////////////////////////////// 263 | redCount = blackCount = 0; 264 | char[] boardRow = board[row]; 265 | int cStart = col - 3, 266 | colStart = cStart >= 0 ? cStart : 0, 267 | colEnd = COLUMNS - 3 - (colStart - cStart); 268 | for (int c = colStart; c < colEnd; c++) { 269 | redCount = blackCount = 0; 270 | for (int val = 0; val < 4; val++) { 271 | char mark = boardRow[c + val]; 272 | if (mark == MARK_RED) { 273 | redCount++; 274 | } else if (mark == MARK_BLACK) { 275 | blackCount++; 276 | } 277 | } 278 | if (redCount == 4) { 279 | redWinFound = true; 280 | if (depth <= 2) { 281 | return Integer.MIN_VALUE + 1; 282 | } 283 | } else if (blackCount == 4) { 284 | blackWinFound = true; 285 | if (depth <= 2) { 286 | return Integer.MAX_VALUE - 1; 287 | } 288 | } 289 | score += getScoreIncrement(redCount, blackCount, player); 290 | } 291 | 292 | /////////////////////////////////////////////////////////////////////// 293 | // Check column 294 | /////////////////////////////////////////////////////////////////////// 295 | redCount = blackCount = 0; 296 | int rowEnd = Math.min(ROWS, row + 4); 297 | for (int r = row; r < rowEnd; r++) { 298 | char mark = board[r][col]; 299 | if (mark == MARK_RED) { 300 | redCount++; 301 | } else if (mark == MARK_BLACK) { 302 | blackCount++; 303 | } 304 | } 305 | if (redCount == 4) { 306 | redWinFound = true; 307 | if (depth <= 2) { 308 | return Integer.MIN_VALUE + 1; 309 | } 310 | } else if (blackCount == 4) { 311 | blackWinFound = true; 312 | if (depth <= 2) { 313 | return Integer.MAX_VALUE - 1; 314 | } 315 | } 316 | score += getScoreIncrement(redCount, blackCount, player); 317 | 318 | /////////////////////////////////////////////////////////////////////// 319 | // Check major diagonal 320 | /////////////////////////////////////////////////////////////////////// 321 | int minValue = Math.min(row, col), 322 | rowStart = row - minValue; 323 | colStart = col - minValue; 324 | for (int r = rowStart, c = colStart; r <= ROWS - 4 && c <= COLUMNS - 4; r++, c++) { 325 | redCount = blackCount = 0; 326 | for (int val = 0; val < 4; val++) { 327 | char mark = board[r + val][c + val]; 328 | if (mark == MARK_RED) { 329 | redCount++; 330 | } else if (mark == MARK_BLACK) { 331 | blackCount++; 332 | } 333 | } 334 | if (redCount == 4) { 335 | redWinFound = true; 336 | if (depth <= 2) { 337 | return Integer.MIN_VALUE + 1; 338 | } 339 | } else if (blackCount == 4) { 340 | blackWinFound = true; 341 | if (depth <= 2) { 342 | return Integer.MAX_VALUE - 1; 343 | } 344 | } 345 | score += getScoreIncrement(redCount, blackCount, player); 346 | } 347 | 348 | /////////////////////////////////////////////////////////////////////// 349 | // Check minor diagonal 350 | /////////////////////////////////////////////////////////////////////// 351 | minValue = Math.min(ROWS - 1 - row, col); 352 | rowStart = row + minValue; 353 | colStart = col - minValue; 354 | for (int r = rowStart, c = colStart; r >= 3 && c <= COLUMNS - 4; r--, c++) { 355 | redCount = blackCount = 0; 356 | for (int val = 0; val < 4; val++) { 357 | char mark = board[r - val][c + val]; 358 | if (mark == MARK_RED) { 359 | redCount++; 360 | } else if (mark == MARK_BLACK) { 361 | blackCount++; 362 | } 363 | } 364 | if (redCount == 4) { 365 | redWinFound = true; 366 | if (depth <= 2) { 367 | return Integer.MIN_VALUE + 1; 368 | } 369 | } else if (blackCount == 4) { 370 | blackWinFound = true; 371 | if (depth <= 2) { 372 | return Integer.MAX_VALUE - 1; 373 | } 374 | } 375 | score += getScoreIncrement(redCount, blackCount, player); 376 | } 377 | return score; 378 | } 379 | 380 | public boolean isFull() { 381 | for (int row = 0; row < ROWS; row++) { 382 | for (int col = 0; col < COLUMNS; col++) { 383 | if (board[row][col] == Board.UNMARKED) { 384 | return false; 385 | } 386 | } 387 | } 388 | return true; 389 | } 390 | } -------------------------------------------------------------------------------- /src/main/java/dsa/ai/graph/minimax/Cell.java: -------------------------------------------------------------------------------- 1 | package dsa.ai.graph.minimax; 2 | 3 | public class Cell { 4 | public int row, column; 5 | 6 | public Cell(int row, int column) { 7 | this.row = row; 8 | this.column = column; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/dsa/ai/graph/minimax/Minimax.java: -------------------------------------------------------------------------------- 1 | 2 | package dsa.ai.graph.minimax; 3 | 4 | 5 | public class Minimax { 6 | 7 | private final Board board; 8 | private int column, boardsAnalyzed; 9 | private final int maxDepth; 10 | private boolean redWinFound, blackWinFound; 11 | 12 | public Minimax(Board board, int maxDepth) { 13 | this.board = board; 14 | this.boardsAnalyzed = 0; 15 | this.maxDepth = maxDepth; 16 | } 17 | 18 | public int getBoardsAnalyzed() { 19 | return boardsAnalyzed; 20 | } 21 | 22 | public int alphaBeta(char player) { 23 | redWinFound = blackWinFound = false; 24 | if (player == Board.MARK_BLACK) { 25 | evaluateBlackMove(0, 1, -1, Integer.MIN_VALUE + 1, 26 | Integer.MAX_VALUE - 1); 27 | if (blackWinFound) { 28 | return column; 29 | } 30 | redWinFound = blackWinFound = false; 31 | evaluateRedMove(0, 1, -1, Integer.MIN_VALUE + 1, 32 | Integer.MAX_VALUE - 1); 33 | if (redWinFound) { 34 | return column; 35 | } 36 | evaluateBlackMove(0, maxDepth, -1, Integer.MIN_VALUE + 1, 37 | Integer.MAX_VALUE - 1); 38 | } else { 39 | evaluateRedMove(0, 1, -1, Integer.MIN_VALUE + 1, 40 | Integer.MAX_VALUE - 1); 41 | if (redWinFound) { 42 | return column; 43 | } 44 | redWinFound = blackWinFound = false; 45 | evaluateBlackMove(0, 1, -1, Integer.MIN_VALUE + 1, 46 | Integer.MAX_VALUE - 1); 47 | if (blackWinFound) { 48 | return column; 49 | } 50 | evaluateRedMove(0, maxDepth, -1, Integer.MIN_VALUE + 1, 51 | Integer.MAX_VALUE - 1); 52 | } 53 | return column; 54 | } 55 | 56 | private int evaluateRedMove(int depth, int maxDepth, int col, int alpha, int beta) { 57 | boardsAnalyzed++; 58 | int min = Integer.MAX_VALUE, score = 0; 59 | if (col != -1) { 60 | score = board.getHeuristicScore(Board.MARK_BLACK, col, depth, maxDepth); 61 | if (board.blackWinFound()) { 62 | blackWinFound = true; 63 | return score; 64 | } 65 | } 66 | if (depth == maxDepth) { 67 | return score; 68 | } 69 | for (int c = 0; c < Board.COLUMNS; c++) { 70 | if (board.isColumnAvailable(c)) { 71 | board.mark(c, Board.MARK_RED); 72 | int value = evaluateBlackMove(depth + 1, maxDepth, c, alpha, beta); 73 | board.unset(c); 74 | if (value < min) { 75 | min = value; 76 | if (depth == 0) { 77 | column = c; 78 | } 79 | } 80 | if (value < beta) { 81 | beta = value; 82 | } 83 | if (alpha >= beta) { 84 | return beta; 85 | } 86 | } 87 | } 88 | 89 | if (min == Integer.MAX_VALUE) { 90 | return 0; 91 | } 92 | return min; 93 | } 94 | 95 | private int evaluateBlackMove(int depth, int maxDepth, int col, int alpha, int beta) { 96 | boardsAnalyzed++; 97 | int max = Integer.MIN_VALUE, score = 0; 98 | if (col != -1) { 99 | score = board.getHeuristicScore(Board.MARK_RED, col, depth, maxDepth); 100 | if (board.redWinFound()) { 101 | redWinFound = true; 102 | return score; 103 | } 104 | } 105 | if (depth == maxDepth) { 106 | return score; 107 | } 108 | for (int c = 0; c < Board.COLUMNS; c++) { 109 | if (board.isColumnAvailable(c)) { 110 | board.mark(c, Board.MARK_BLACK); 111 | int value = evaluateRedMove(depth + 1, maxDepth, c, alpha, beta); 112 | board.unset(c); 113 | if (value > max) { 114 | max = value; 115 | if (depth == 0) { 116 | column = c; 117 | } 118 | } 119 | if (value > alpha) { 120 | alpha = value; 121 | } 122 | if (alpha >= beta) { 123 | return alpha; 124 | } 125 | } 126 | } 127 | if (max == Integer.MIN_VALUE) { 128 | return 0; 129 | } 130 | return max; 131 | } 132 | 133 | 134 | } -------------------------------------------------------------------------------- /src/main/java/dsa/ai/graph/path/BellmanFord.java: -------------------------------------------------------------------------------- 1 | package dsa.ai.graph.path; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | public class BellmanFord { 8 | 9 | public Integer[][] singleSourceShortestPath(Integer[][] weight, 10 | int source) throws Exception { 11 | 12 | //auxiliary constants 13 | final int SIZE = weight.length; 14 | final int EVE = -1;//to indicate no predecessor 15 | final int INFINITY = Integer.MAX_VALUE; 16 | 17 | //declare and initialize pred to EVE and minDist to INFINITY 18 | Integer[] pred = new Integer[SIZE]; 19 | Integer[] minDist = new Integer[SIZE]; 20 | Arrays.fill(pred, EVE); 21 | Arrays.fill(minDist, INFINITY); 22 | 23 | //set minDist[source] = 0 because source is 0 distance from itself. 24 | minDist[source] = 0; 25 | 26 | //relax the edge set V-1 times to find all shortest paths 27 | for (int i = 1; i < minDist.length - 1; i++) { 28 | for (int v = 0; v < SIZE; v++) { 29 | for (int x : adjacency(weight, v)) { 30 | if (minDist[x] > minDist[v] + weight[v][x]) { 31 | minDist[x] = minDist[v] + weight[v][x]; 32 | pred[x] = v; 33 | } 34 | } 35 | } 36 | } 37 | 38 | //detect cycles if any 39 | for (int v = 0; v < SIZE; v++) { 40 | for (int x : adjacency(weight, v)) { 41 | if (minDist[x] > minDist[v] + weight[v][x]) { 42 | throw new Exception("Negative cycle found"); 43 | } 44 | } 45 | } 46 | 47 | Integer[][] result = {pred, minDist}; 48 | return result; 49 | } 50 | 51 | /** 52 | * **************************************************************** 53 | * Retrieve all the neighbors of vertex v. 54 | * *************************************************************** 55 | */ 56 | private List adjacency(Integer[][] G, int v) { 57 | List result = new ArrayList<>(); 58 | for (int x = 0; x < G.length; x++) { 59 | if (G[v][x] != null) { 60 | result.add(x); 61 | } 62 | } 63 | return result; 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /src/main/java/dsa/ai/graph/path/Dijkstra.java: -------------------------------------------------------------------------------- 1 | package dsa.ai.graph.path; 2 | 3 | import dsa.graph.Edge; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Collections; 7 | import java.util.HashMap; 8 | import java.util.HashSet; 9 | import java.util.LinkedList; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.Set; 13 | 14 | import dsa.graph.*; 15 | 16 | /** 17 | * http://www.vogella.com/tutorials/JavaAlgorithmsDijkstra/article.html 18 | */ 19 | public class Dijkstra { 20 | 21 | private final List nodes; 22 | private final List edges; 23 | private Set settledNodes; 24 | private Set unSettledNodes; 25 | private Map predecessors; 26 | private Map distance; 27 | 28 | public Dijkstra(Graph graph) { 29 | // create a copy of the array so that we can operate on this array 30 | this.nodes = new ArrayList<>(graph.getVertexes()); 31 | this.edges = new ArrayList<>(graph.getEdges()); 32 | } 33 | 34 | public void execute(Vertex source) { 35 | settledNodes = new HashSet<>(); 36 | unSettledNodes = new HashSet<>(); 37 | distance = new HashMap<>(); 38 | predecessors = new HashMap<>(); 39 | distance.put(source, 0); 40 | unSettledNodes.add(source); 41 | while (unSettledNodes.size() > 0) { 42 | Vertex node = getMinimum(unSettledNodes); 43 | settledNodes.add(node); 44 | unSettledNodes.remove(node); 45 | findMinimalDistances(node); 46 | } 47 | } 48 | 49 | private void findMinimalDistances(Vertex node) { 50 | List adjacentNodes = getNeighbors(node); 51 | for (Vertex target : adjacentNodes) { 52 | if (getShortestDistance(target) > getShortestDistance(node) 53 | + getDistance(node, target)) { 54 | distance.put(target, getShortestDistance(node) 55 | + getDistance(node, target)); 56 | predecessors.put(target, node); 57 | unSettledNodes.add(target); 58 | } 59 | } 60 | 61 | } 62 | 63 | private int getDistance(Vertex node, Vertex target) { 64 | for (Edge edge : edges) { 65 | if (edge.getSource().equals(node) 66 | && edge.getDestination().equals(target)) { 67 | return edge.getWeight(); 68 | } 69 | } 70 | throw new RuntimeException("Should not happen"); 71 | } 72 | 73 | private List getNeighbors(Vertex node) { 74 | List neighbors = new ArrayList<>(); 75 | for (Edge edge : edges) { 76 | if (edge.getSource().equals(node) 77 | && !isSettled(edge.getDestination())) { 78 | neighbors.add(edge.getDestination()); 79 | } 80 | } 81 | return neighbors; 82 | } 83 | 84 | private Vertex getMinimum(Set vertexes) { 85 | Vertex minimum = null; 86 | for (Vertex vertex : vertexes) { 87 | if (minimum == null) { 88 | minimum = vertex; 89 | } else if (getShortestDistance(vertex) < getShortestDistance(minimum)) { 90 | minimum = vertex; 91 | } 92 | } 93 | return minimum; 94 | } 95 | 96 | private boolean isSettled(Vertex vertex) { 97 | return settledNodes.contains(vertex); 98 | } 99 | 100 | private int getShortestDistance(Vertex destination) { 101 | Integer d = distance.get(destination); 102 | if (d == null) { 103 | return Integer.MAX_VALUE; 104 | } else { 105 | return d; 106 | } 107 | } 108 | 109 | /** 110 | * This method returns the path from the source to the selected target and 111 | * NULL if no path exists 112 | */ 113 | public LinkedList getPath(Vertex target) { 114 | LinkedList path = new LinkedList<>(); 115 | Vertex step = target; 116 | // check if a path exists 117 | if (predecessors.get(step) == null) { 118 | return null; 119 | } 120 | path.add(step); 121 | while (predecessors.get(step) != null) { 122 | step = predecessors.get(step); 123 | path.add(step); 124 | } 125 | // Put it into the correct order 126 | Collections.reverse(path); 127 | return path; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/dsa/ai/graph/path/astar/AStar.java: -------------------------------------------------------------------------------- 1 | package dsa.ai.graph.path.astar; 2 | 3 | import java.util.Comparator; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.PriorityQueue; 10 | import java.util.Set; 11 | 12 | /** 13 | * Helper class containing pathfinding algorithms. 14 | * 15 | */ 16 | public class AStar { 17 | 18 | /** 19 | * A Star pathfinding. Note that the heuristic has to be monotonic: 20 | * {@code h(x) <= d(x, y) + h(y)}. 21 | * 22 | * @param 23 | * @param start Starting node 24 | * @param goal Goal node 25 | * @return Shortest path from start to goal, or null if none found 26 | */ 27 | public static > List doAStar(T start, T goal) { 28 | Set closed = new HashSet<>(); 29 | Map fromMap = new HashMap<>(); 30 | List route = new LinkedList<>(); 31 | Map gScore = new HashMap<>(); 32 | final Map fScore = new HashMap<>(); 33 | PriorityQueue open = new PriorityQueue<>(11, new Comparator() { 34 | 35 | @Override 36 | public int compare(T nodeA, T nodeB) { 37 | return Double.compare(fScore.get(nodeA), fScore.get(nodeB)); 38 | } 39 | }); 40 | 41 | gScore.put(start, 0.0); 42 | fScore.put(start, start.getHeuristic(goal)); 43 | open.offer(start); 44 | 45 | while (!open.isEmpty()) { 46 | T current = open.poll(); 47 | if (current.equals(goal)) { 48 | while (current != null) { 49 | route.add(0, current); 50 | current = fromMap.get(current); 51 | } 52 | 53 | return route; 54 | } 55 | 56 | closed.add(current); 57 | 58 | for (T neighbour : current.getNeighbours()) { 59 | if (closed.contains(neighbour)) { 60 | continue; 61 | } 62 | 63 | double tentG = gScore.get(current) 64 | + current.getTraversalCost(neighbour); 65 | 66 | boolean contains = open.contains(neighbour); 67 | if (!contains || tentG < gScore.get(neighbour)) { 68 | gScore.put(neighbour, tentG); 69 | fScore.put(neighbour, tentG + neighbour.getHeuristic(goal)); 70 | 71 | if (contains) { 72 | open.remove(neighbour); 73 | } 74 | 75 | open.offer(neighbour); 76 | fromMap.put(neighbour, current); 77 | } 78 | } 79 | } 80 | 81 | return null; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/dsa/ai/graph/path/astar/Grid2d.java: -------------------------------------------------------------------------------- 1 | package dsa.ai.graph.path.astar; 2 | 3 | import java.util.HashSet; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | /** 8 | * Creates nodes and neighbours from a 2d grid. Each point in the map has an 9 | * integer value that specifies the cost of crossing that point. If this value 10 | * is negative, the point is unreachable. 11 | * 12 | * If diagonal movement is allowed, the Chebyshev distance is used, else 13 | * Manhattan distance is used. 14 | * 15 | * 16 | */ 17 | public class Grid2d { 18 | 19 | private final double[][] map; 20 | private final boolean allowDiagonal; 21 | 22 | /** 23 | * A node in a 2d map. This is simply the coordinates of the point. 24 | * 25 | */ 26 | public class MapNode implements Node { 27 | 28 | private final int x, y; 29 | 30 | public MapNode(int x, int y) { 31 | this.x = x; 32 | this.y = y; 33 | } 34 | 35 | @Override 36 | public double getHeuristic(MapNode goal) { 37 | if (allowDiagonal) { 38 | return Math.max(Math.abs(x - goal.x), Math.abs(y - goal.y)); 39 | } else { 40 | return Math.abs(x - goal.x) + Math.abs(y - goal.y); 41 | } 42 | } 43 | 44 | @Override 45 | public double getTraversalCost(MapNode neighbour) { 46 | return 1 + map[neighbour.y][neighbour.x]; 47 | } 48 | 49 | @Override 50 | public Set getNeighbours() { 51 | Set neighbours = new HashSet<>(); 52 | 53 | for (int i = x - 1; i <= x + 1; i++) { 54 | for (int j = y - 1; j <= y + 1; j++) { 55 | if ((i == x && j == y) || i < 0 || j < 0 || j >= map.length 56 | || i >= map[j].length) { 57 | continue; 58 | } 59 | 60 | if (!allowDiagonal 61 | && ((i < x && j < y) || (i > x && j > y))) { 62 | continue; 63 | } 64 | 65 | if (map[j][i] < 0) { 66 | continue; 67 | } 68 | 69 | // TODO: create cache instead of recreation 70 | neighbours.add(new MapNode(i, j)); 71 | } 72 | } 73 | 74 | return neighbours; 75 | } 76 | 77 | @Override 78 | public String toString() { 79 | return "(" + x + ", " + y + ")"; 80 | } 81 | 82 | @Override 83 | public int hashCode() { 84 | final int prime = 31; 85 | int result = 1; 86 | result = prime * result + getOuterType().hashCode(); 87 | result = prime * result + x; 88 | result = prime * result + y; 89 | return result; 90 | } 91 | 92 | @Override 93 | public boolean equals(Object obj) { 94 | if (this == obj) { 95 | return true; 96 | } 97 | if (obj == null) { 98 | return false; 99 | } 100 | if (getClass() != obj.getClass()) { 101 | return false; 102 | } 103 | MapNode other = (MapNode) obj; 104 | if (!getOuterType().equals(other.getOuterType())) { 105 | return false; 106 | } 107 | if (x != other.x) { 108 | return false; 109 | } 110 | return y == other.y; 111 | } 112 | 113 | private Grid2d getOuterType() { 114 | return Grid2d.this; 115 | } 116 | 117 | } 118 | 119 | public Grid2d(double[][] map, boolean allowDiagonal) { 120 | this.map = map; 121 | this.allowDiagonal = allowDiagonal; 122 | } 123 | 124 | public List findPath(int xStart, int yStart, int xGoal, int yGoal) { 125 | return AStar.doAStar(new MapNode(xStart, yStart), new MapNode( 126 | xGoal, yGoal)); 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/dsa/ai/graph/path/astar/Node.java: -------------------------------------------------------------------------------- 1 | package dsa.ai.graph.path.astar; 2 | 3 | import java.util.Set; 4 | 5 | /** 6 | * A node in a graph, useful for pathfinding. 7 | * 8 | * @param Actual type of the node 9 | */ 10 | public interface Node { 11 | 12 | /** 13 | * The heuristic cost to move from the current node to the goal. In most 14 | * cases this is the Manhattan distance or Chebyshev distance. 15 | * 16 | * @param goal 17 | * @return 18 | */ 19 | double getHeuristic(T goal); 20 | 21 | /** 22 | * The cost of moving from the current node to the neighbour. In most cases 23 | * this is just the distance between the nodes, but additional terrain cost 24 | * can be added as well (for example climbing a mountain is more expensive 25 | * than walking on a road). 26 | * 27 | * @param neighbour Neighbour of current node 28 | * @return Traversal cost 29 | */ 30 | double getTraversalCost(T neighbour); 31 | 32 | /** 33 | * Gets the set of neighbouring nodes. 34 | * 35 | * @return Neighbouring nodes 36 | */ 37 | Set getNeighbours(); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/dsa/graph/Edge.java: -------------------------------------------------------------------------------- 1 | package dsa.graph; 2 | 3 | public class Edge { 4 | 5 | private final String id; 6 | private final Vertex source; 7 | private final Vertex destination; 8 | private final int weight; 9 | 10 | public Edge(String id, Vertex source, Vertex destination, int weight) { 11 | this.id = id; 12 | this.source = source; 13 | this.destination = destination; 14 | this.weight = weight; 15 | } 16 | 17 | public String getId() { 18 | return id; 19 | } 20 | 21 | public Vertex getDestination() { 22 | return destination; 23 | } 24 | 25 | public Vertex getSource() { 26 | return source; 27 | } 28 | 29 | public int getWeight() { 30 | return weight; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return source + " " + destination; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/dsa/graph/Graph.java: -------------------------------------------------------------------------------- 1 | package dsa.graph; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Graph { 7 | 8 | private final List vertexes; 9 | private final List edges; 10 | 11 | public Graph() { 12 | this.vertexes = new ArrayList<>(); 13 | this.edges = new ArrayList<>(); 14 | } 15 | 16 | public Graph(List vertexes, List edges) { 17 | this.vertexes = vertexes; 18 | this.edges = edges; 19 | } 20 | 21 | public List getVertexes() { 22 | return vertexes; 23 | } 24 | 25 | public List getEdges() { 26 | return edges; 27 | } 28 | 29 | public void addVertex(Vertex v) { 30 | this.vertexes.add(v); 31 | } 32 | 33 | public void addEdge(Edge e) { 34 | this.edges.add(e); 35 | } 36 | 37 | private int[][] cleanMatrix() { 38 | int n = this.getVertexes().size(); 39 | int mat[][] = new int[n][n]; 40 | int i, j; 41 | for (i = 0; i < n; i++) { 42 | for (j = 0; j < n; j++) { 43 | mat[i][j] = 0; 44 | } 45 | } 46 | return mat; 47 | } 48 | 49 | public int[] V() { 50 | int[] vs = new int[vertexes.size()]; 51 | 52 | for (int i = 0; i < vertexes.size(); i++) { 53 | vs[i] = Integer.parseInt(vertexes.get(i).getId()); 54 | } 55 | 56 | return vs; 57 | } 58 | 59 | public int[][] adj() { 60 | int[][] mat = cleanMatrix(); 61 | 62 | int source, dest; 63 | for (Edge edge : edges) { 64 | source = Integer.parseInt(edge.getSource().getId()); 65 | dest = Integer.parseInt(edge.getDestination().getId()); 66 | mat[source][dest] = edge.getWeight(); 67 | } 68 | 69 | return mat; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/dsa/graph/GraphMatrix.java: -------------------------------------------------------------------------------- 1 | package dsa.graph; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * 7 | * Data structure used to represent a graph 8 | */ 9 | public class GraphMatrix { 10 | 11 | int[][] adjMatrix; 12 | int rootNode = 0; 13 | int NNodes; 14 | 15 | boolean[] visited; 16 | 17 | /** 18 | * Construct a graph of N nodes 19 | * 20 | * @param N 21 | */ 22 | public GraphMatrix(int N) { 23 | NNodes = N; 24 | adjMatrix = new int[N][N]; 25 | visited = new boolean[N]; 26 | } 27 | 28 | public GraphMatrix(int[][] mat) { 29 | int i, j; 30 | 31 | NNodes = mat.length; 32 | 33 | adjMatrix = new int[NNodes][NNodes]; 34 | visited = new boolean[NNodes]; 35 | 36 | for (i = 0; i < NNodes; i++) { 37 | for (j = 0; j < NNodes; j++) { 38 | adjMatrix[i][j] = mat[i][j]; 39 | } 40 | } 41 | } 42 | 43 | /** 44 | * BFS uses Queue data structure 45 | * 46 | * @return 47 | */ 48 | public List bfs() { 49 | 50 | List walk = new ArrayList<>(); 51 | 52 | Queue q = new LinkedList<>(); 53 | 54 | q.add(rootNode); 55 | visited[rootNode] = true; 56 | 57 | walk.add(rootNode); 58 | 59 | while (!q.isEmpty()) { 60 | int n, child; 61 | n = q.peek(); 62 | 63 | child = getUnvisitedChildNode(n); 64 | 65 | if (child != -1) { 66 | visited[child] = true; 67 | 68 | walk.add(child); 69 | 70 | q.add(child); 71 | } else { 72 | q.remove(); 73 | } 74 | } 75 | 76 | clearVisited(); //Clear visited property of nodes 77 | 78 | return walk; 79 | } 80 | 81 | /** 82 | * DFS uses Stack data structure 83 | * 84 | * @return 85 | */ 86 | public List dfs() { 87 | 88 | List walk = new ArrayList<>(); 89 | Stack s = new Stack<>(); 90 | 91 | s.push(rootNode); 92 | visited[rootNode] = true; 93 | 94 | walk.add(rootNode); 95 | 96 | while (!s.isEmpty()) { 97 | int n, child; 98 | 99 | n = s.peek(); 100 | 101 | child = getUnvisitedChildNode(n); 102 | 103 | if (child != -1) { 104 | visited[child] = true; 105 | 106 | walk.add(child); 107 | 108 | s.push(child); 109 | } else { 110 | s.pop(); 111 | } 112 | } 113 | 114 | clearVisited(); //Clear visited property of nodes 115 | 116 | return walk; 117 | } 118 | 119 | public int getUnvisitedChildNode(int n) { 120 | for (int j = 0; j < NNodes; j++) { 121 | if (adjMatrix[n][j] > 0) { 122 | if (!visited[j]) { 123 | return j; 124 | } 125 | } 126 | } 127 | 128 | return -1; 129 | } 130 | 131 | public void clearVisited() { 132 | for (int i = 0; i < visited.length; i++) { 133 | visited[i] = false; 134 | } 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/dsa/graph/Vertex.java: -------------------------------------------------------------------------------- 1 | package dsa.graph; 2 | 3 | public class Vertex { 4 | 5 | final private String id; 6 | final private String name; 7 | 8 | public Vertex(String id, String name) { 9 | this.id = id; 10 | this.name = name; 11 | } 12 | 13 | public String getId() { 14 | return id; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | @Override 22 | public int hashCode() { 23 | final int prime = 31; 24 | int result = 1; 25 | result = prime * result + ((id == null) ? 0 : id.hashCode()); 26 | return result; 27 | } 28 | 29 | @Override 30 | public boolean equals(Object obj) { 31 | if (this == obj) { 32 | return true; 33 | } 34 | if (obj == null) { 35 | return false; 36 | } 37 | if (getClass() != obj.getClass()) { 38 | return false; 39 | } 40 | Vertex other = (Vertex) obj; 41 | if (id == null) { 42 | if (other.id != null) { 43 | return false; 44 | } 45 | } else if (!id.equals(other.id)) { 46 | return false; 47 | } 48 | return true; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return name; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/dsa/list/CircularLinkedList.java: -------------------------------------------------------------------------------- 1 | package dsa.list; 2 | 3 | /** 4 | * 5 | */ 6 | public class CircularLinkedList { 7 | 8 | private int size = 0; 9 | private Node head = null; 10 | private Node tail = null; 11 | 12 | /** 13 | * add a new node at the start of the linked list 14 | * 15 | * @param data 16 | * 17 | */ 18 | public void addNodeAtStart(Object data) { 19 | Node n = new Node(data); 20 | if (size == 0) { 21 | head = n; 22 | tail = n; 23 | n.next = head; 24 | } else { 25 | Node temp = head; 26 | n.next = temp; 27 | head = n; 28 | tail.next = head; 29 | } 30 | size++; 31 | } 32 | 33 | public void addNodeAtEnd(Object data) { 34 | if (size == 0) { 35 | addNodeAtStart(data); 36 | } else { 37 | Node n = new Node(data); 38 | tail.next = n; 39 | tail = n; 40 | tail.next = head; 41 | size++; 42 | } 43 | } 44 | 45 | public void deleteNodeFromStart() { 46 | if (size == 0) { 47 | throw new RuntimeException("List is Empty"); 48 | } else { 49 | head = head.next; 50 | tail.next = head; 51 | size--; 52 | } 53 | } 54 | 55 | public Object elementAt(int index) { 56 | if (index > size) { 57 | return -1; 58 | } 59 | Node n = head; 60 | while (index - 1 != 0) { 61 | n = n.next; 62 | index--; 63 | } 64 | return n.data; 65 | } 66 | 67 | /** 68 | * print the linked list 69 | */ 70 | public void print() { 71 | System.out.print("Circular Linked List:"); 72 | Node temp = head; 73 | if (size <= 0) { 74 | System.out.print("List is empty"); 75 | } else { 76 | do { 77 | System.out.print(" " + temp.data); 78 | temp = temp.next; 79 | } while (temp != head); 80 | } 81 | System.out.println(); 82 | } 83 | 84 | /** 85 | * get Size 86 | * 87 | * @return 88 | */ 89 | public int size() { 90 | return size; 91 | } 92 | 93 | private class Node { 94 | 95 | Object data; 96 | Node next; 97 | 98 | public Node(Object data) { 99 | this.data = data; 100 | } 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/dsa/list/DoublyLinkedList.java: -------------------------------------------------------------------------------- 1 | package dsa.list; 2 | 3 | 4 | import java.util.NoSuchElementException; 5 | 6 | /** 7 | * http://java2novice.com/data-structures-in-java/linked-list/doubly-linked-list/ 8 | * @param 9 | */ 10 | public class DoublyLinkedList implements LinkedList{ 11 | 12 | private Node head; 13 | private Node tail; 14 | private int size; 15 | 16 | public DoublyLinkedList() { 17 | size = 0; 18 | } 19 | /** 20 | * this class keeps track of each element information 21 | * @author java2novice 22 | * 23 | */ 24 | private class Node { 25 | E element; 26 | Node next; 27 | Node prev; 28 | 29 | public Node(E element, Node next, Node prev) { 30 | this.element = element; 31 | this.next = next; 32 | this.prev = prev; 33 | } 34 | } 35 | /** 36 | * returns the size of the linked list 37 | * @return 38 | */ 39 | @Override 40 | public int size() { return size; } 41 | 42 | /** 43 | * return whether the list is empty or not 44 | * @return 45 | */ 46 | @Override 47 | public boolean isEmpty() { return size == 0; } 48 | 49 | /** 50 | * adds element at the starting of the linked list 51 | * @param element 52 | * @return 53 | */ 54 | public DoublyLinkedList addFirst(E element) { 55 | Node tmp = new Node(element, head, null); 56 | if(head != null ) {head.prev = tmp;} 57 | head = tmp; 58 | if(tail == null) { tail = tmp;} 59 | size++; 60 | return this; 61 | } 62 | 63 | @Override 64 | public DoublyLinkedList add(E element){ 65 | return addFirst(element); 66 | } 67 | 68 | /** 69 | * adds element at the end of the linked list 70 | * @param element 71 | */ 72 | public void addLast(E element) { 73 | 74 | Node tmp = new Node(element, null, tail); 75 | if(tail != null) {tail.next = tmp;} 76 | tail = tmp; 77 | if(head == null) { head = tmp;} 78 | size++; 79 | } 80 | 81 | /** 82 | * this method walks forward through the linked list 83 | */ 84 | public void iterateForward(){ 85 | 86 | Node tmp = head; 87 | while(tmp != null){ 88 | System.out.println(tmp.element); 89 | tmp = tmp.next; 90 | } 91 | } 92 | 93 | /** 94 | * this method walks backward through the linked list 95 | */ 96 | public void iterateBackward(){ 97 | 98 | Node tmp = tail; 99 | while(tmp != null){ 100 | System.out.println(tmp.element); 101 | tmp = tmp.prev; 102 | } 103 | } 104 | 105 | @Override 106 | public E remove(){ 107 | return this.removeFirst(); 108 | } 109 | 110 | /** 111 | * this method removes element from the start of the linked list 112 | * @return 113 | */ 114 | public E removeFirst() { 115 | if (size == 0) throw new NoSuchElementException(); 116 | Node tmp = head; 117 | head = head.next; 118 | head.prev = null; 119 | size--; 120 | return tmp.element; 121 | } 122 | 123 | /** 124 | * this method removes element from the end of the linked list 125 | * @return 126 | */ 127 | public E removeLast() { 128 | if (size == 0) throw new NoSuchElementException(); 129 | Node tmp = tail; 130 | tail = tail.prev; 131 | tail.next = null; 132 | size--; 133 | return tmp.element; 134 | } 135 | 136 | } -------------------------------------------------------------------------------- /src/main/java/dsa/list/LinkedList.java: -------------------------------------------------------------------------------- 1 | package dsa.list; 2 | 3 | /** 4 | * 5 | */ 6 | interface LinkedList { 7 | LinkedList add(T item); 8 | T remove(); 9 | boolean isEmpty(); 10 | int size(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/dsa/list/SinglyLinkedList.java: -------------------------------------------------------------------------------- 1 | package dsa.list; 2 | 3 | /** 4 | * http://java2novice.com/data-structures-in-java/linked-list/singly-linked-list/ 5 | * @param 6 | */ 7 | public class SinglyLinkedList implements LinkedList { 8 | 9 | private Node head; 10 | private Node tail; 11 | private int total = 0; 12 | 13 | /** 14 | * 15 | * @param element 16 | * @return 17 | */ 18 | @Override 19 | public SinglyLinkedList add(T element) { 20 | 21 | Node nd = new Node<>(); 22 | nd.setValue(element); 23 | 24 | /** 25 | * check if the list is empty 26 | */ 27 | if (head == null) { 28 | //since there is only one element, both head and 29 | //tail points to the same object. 30 | head = nd; 31 | tail = nd; 32 | } else { 33 | //set current tail next link to new node 34 | tail.setNextRef(nd); 35 | //set tail as newly created node 36 | tail = nd; 37 | } 38 | total++; 39 | 40 | return this; 41 | } 42 | 43 | public T remove(){ 44 | return deleteFront(); 45 | } 46 | 47 | public T deleteFront() { 48 | 49 | if (head == null) { 50 | throw new RuntimeException("Underflow..."); 51 | } 52 | Node tmp = head; 53 | 54 | head = tmp.getNextRef(); 55 | if (head == null) { 56 | tail = null; 57 | } 58 | 59 | total--; 60 | 61 | return tmp.getValue(); 62 | } 63 | 64 | @Override 65 | public int size(){ 66 | return total; 67 | } 68 | 69 | @Override 70 | public boolean isEmpty(){ 71 | return total == 0; 72 | } 73 | 74 | private class Node implements Comparable { 75 | 76 | private T value; 77 | private Node nextRef; 78 | 79 | public T getValue() { 80 | return value; 81 | } 82 | 83 | public void setValue(T value) { 84 | this.value = value; 85 | } 86 | 87 | public Node getNextRef() { 88 | return nextRef; 89 | } 90 | 91 | public void setNextRef(Node ref) { 92 | this.nextRef = ref; 93 | } 94 | 95 | @Override 96 | public int compareTo(T arg) { 97 | if (arg == this.value) { 98 | return 0; 99 | } else { 100 | return 1; 101 | } 102 | } 103 | 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/dsa/queue/Queue.java: -------------------------------------------------------------------------------- 1 | package dsa.queue; 2 | 3 | /** 4 | * http://eddmann.com/posts/implementing-a-queue-in-java-using-arrays-and-linked-lists/ 5 | * @param 6 | */ 7 | interface Queue { 8 | Queue enqueue(T ele); 9 | T dequeue(); 10 | int size(); 11 | } -------------------------------------------------------------------------------- /src/main/java/dsa/queue/QueueArray.java: -------------------------------------------------------------------------------- 1 | package dsa.queue; 2 | 3 | public class QueueArray implements Queue { 4 | 5 | private T[] arr; 6 | 7 | private int total, first, next; 8 | 9 | public QueueArray() 10 | { 11 | arr = (T[]) new Object[2]; 12 | } 13 | 14 | private void resize(int capacity) 15 | { 16 | T[] tmp = (T[]) new Object[capacity]; 17 | 18 | for (int i = 0; i < total; i++) 19 | tmp[i] = arr[(first + i) % arr.length]; 20 | 21 | arr = tmp; 22 | first = 0; 23 | next = total; 24 | } 25 | 26 | @Override 27 | public QueueArray enqueue(T ele) 28 | { 29 | if (arr.length == total) resize(arr.length * 2); 30 | arr[next++] = ele; 31 | if (next == arr.length) next = 0; 32 | total++; 33 | return this; 34 | } 35 | 36 | @Override 37 | public T dequeue() 38 | { 39 | if (total == 0) throw new java.util.NoSuchElementException(); 40 | T ele = arr[first]; 41 | arr[first] = null; 42 | if (++first == arr.length) first = 0; 43 | if (--total > 0 && total == arr.length / 4) resize(arr.length / 2); 44 | return ele; 45 | } 46 | 47 | @Override 48 | public int size(){ 49 | return total; 50 | } 51 | 52 | @Override 53 | public String toString() 54 | { 55 | return java.util.Arrays.toString(arr); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /src/main/java/dsa/queue/QueueLinkedList.java: -------------------------------------------------------------------------------- 1 | package dsa.queue; 2 | 3 | 4 | public class QueueLinkedList implements Queue { 5 | 6 | private int total; 7 | 8 | private Node first, last; 9 | 10 | private class Node { 11 | private T ele; 12 | private Node next; 13 | } 14 | 15 | @Override 16 | public QueueLinkedList enqueue(T ele) 17 | { 18 | Node current = last; 19 | last = new Node(); 20 | last.ele = ele; 21 | 22 | if (total++ == 0) first = last; 23 | else current.next = last; 24 | 25 | return this; 26 | } 27 | 28 | public T dequeue() 29 | { 30 | if (total == 0) throw new java.util.NoSuchElementException(); 31 | T ele = first.ele; 32 | first = first.next; 33 | if (--total == 0) last = null; 34 | return ele; 35 | } 36 | 37 | @Override 38 | public int size(){ 39 | return total; 40 | } 41 | 42 | 43 | @Override 44 | public String toString() 45 | { 46 | StringBuilder sb = new StringBuilder(); 47 | Node tmp = first; 48 | while (tmp != null) { 49 | sb.append(tmp.ele).append(", "); 50 | tmp = tmp.next; 51 | } 52 | return sb.toString(); 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/main/java/dsa/queue/priority/MaxPQ.java: -------------------------------------------------------------------------------- 1 | package dsa.queue.priority; 2 | 3 | import java.util.NoSuchElementException; 4 | 5 | /** 6 | * Implements a Priority Queue ordered that iterates over the largest 7 | * key. 8 | * 9 | *
Lecture: APIs and Elementary Implementations (Week 4)
10 | * 11 | *

12 | * Keep the entries ordered in an resizing array. 13 | *

14 | * 15 | *

16 | * This colecttion uses Binary heap algorithm.

17 | * 18 | * @see UnorderedMaxPQ.java 19 | * @param parameterized type for key. 20 | */ 21 | public class MaxPQ> { 22 | 23 | private Key[] pq; 24 | private int N; 25 | 26 | public MaxPQ() { 27 | this(1); 28 | } 29 | 30 | @SuppressWarnings("unchecked") 31 | public MaxPQ(int capacity) { 32 | pq = (Key[]) new Comparable[capacity + 1]; 33 | } 34 | 35 | public boolean isEmpty() { 36 | return N == 0; 37 | } 38 | 39 | public void insert(Key x) { 40 | if (N == pq.length - 1) { 41 | resize(2 * pq.length); 42 | } 43 | 44 | pq[++N] = x; 45 | swim(N); 46 | } 47 | 48 | public Key delMax() { 49 | if (isEmpty()) { 50 | throw new NoSuchElementException(); 51 | } 52 | 53 | Key max = pq[1]; 54 | exch(1, N--); 55 | sink(1); 56 | 57 | pq[N + 1] = null; 58 | 59 | if ((N > 0) && (N == (pq.length - 1) / 4)) { 60 | resize(pq.length / 2); 61 | } 62 | 63 | return max; 64 | } 65 | 66 | //node promoted to level of incompetence (Binary heap); 67 | private void swim(int k) { 68 | while (k > 1 && less(k / 2, k)) { 69 | exch(k, k / 2); 70 | k = k / 2; 71 | } 72 | } 73 | 74 | //better subordinate (child) promoted (Binary heap); 75 | private void sink(int k) { 76 | while (2 * k <= N) { 77 | int j = 2 * k; 78 | 79 | if (j < N && less(j, j + 1)) { 80 | j++; 81 | } 82 | 83 | if (!less(k, j)) { 84 | break; 85 | } 86 | 87 | exch(k, j); 88 | k = j; 89 | } 90 | } 91 | 92 | private boolean less(int i, int j) { 93 | return pq[i].compareTo(pq[j]) < 0; 94 | } 95 | 96 | private void exch(int i, int j) { 97 | Key swap = pq[i]; 98 | pq[i] = pq[j]; 99 | pq[j] = swap; 100 | } 101 | 102 | private void resize(int capacity) { 103 | @SuppressWarnings("unchecked") 104 | Key[] copy = (Key[]) new Comparable[capacity]; 105 | 106 | for (int i = 1; i <= N; i++) { 107 | copy[i] = pq[i]; 108 | } 109 | 110 | pq = copy; 111 | } 112 | 113 | public int size(){ 114 | return this.N; 115 | } 116 | 117 | } -------------------------------------------------------------------------------- /src/main/java/dsa/queue/priority/MinPQ.java: -------------------------------------------------------------------------------- 1 | package dsa.queue.priority; 2 | 3 | import java.util.NoSuchElementException; 4 | 5 | /** 6 | * Implements a Priority Queue ordered that iterates over the smallest 7 | * key. 8 | * 9 | *
Lecture: APIs and Elementary Implementations (Week 4)
10 | * 11 | *

12 | * Keep the entries ordered in an resizing array. 13 | *

14 | * 15 | *

16 | * This colecttion uses Binary heap algorithm.

17 | * 18 | * @param parameterized type for key. 19 | */ 20 | public class MinPQ> { 21 | 22 | private Key[] pq; 23 | private int N; 24 | 25 | public MinPQ() { 26 | this(1); 27 | } 28 | 29 | @SuppressWarnings("unchecked") 30 | public MinPQ(int capacity) { 31 | pq = (Key[]) new Comparable[capacity + 1]; 32 | } 33 | 34 | public boolean isEmpty() { 35 | return N == 0; 36 | } 37 | 38 | public void insert(Key x) { 39 | if (N == pq.length - 1) { 40 | resize(2 * pq.length); 41 | } 42 | 43 | pq[++N] = x; 44 | swim(N); 45 | } 46 | 47 | public Key delMin() { 48 | if (isEmpty()) { 49 | throw new NoSuchElementException(); 50 | } 51 | 52 | exch(1, N); 53 | Key min = pq[N--]; 54 | sink(1); 55 | pq[N + 1] = null; 56 | 57 | if ((N > 0) && (N == (pq.length - 1) / 4)) { 58 | resize(pq.length / 2); 59 | } 60 | 61 | return min; 62 | } 63 | 64 | private void swim(int k) { 65 | while (k > 1 && less(k, k / 2)) { 66 | exch(k / 2, k); 67 | k = k / 2; 68 | } 69 | } 70 | 71 | private void sink(int k) { 72 | while (2 * k <= N) { 73 | int j = 2 * k; 74 | 75 | if (j < N && less(j + 1, j)) { 76 | j++; 77 | } 78 | 79 | if (!less(j, k)) { 80 | break; 81 | } 82 | 83 | exch(k, j); 84 | k = j; 85 | } 86 | } 87 | 88 | private boolean less(int i, int j) { 89 | return pq[i].compareTo(pq[j]) < 0; 90 | } 91 | 92 | private void exch(int i, int j) { 93 | Key swap = pq[i]; 94 | pq[i] = pq[j]; 95 | pq[j] = swap; 96 | } 97 | 98 | private void resize(int capacity) { 99 | @SuppressWarnings("unchecked") 100 | Key[] copy = (Key[]) new Comparable[capacity]; 101 | 102 | for (int i = 1; i <= N; i++) { 103 | copy[i] = pq[i]; 104 | } 105 | 106 | pq = copy; 107 | } 108 | 109 | public int size() { 110 | return this.N; 111 | } 112 | 113 | } -------------------------------------------------------------------------------- /src/main/java/dsa/search/BinarySearch.java: -------------------------------------------------------------------------------- 1 | package dsa.search; 2 | 3 | public class BinarySearch { 4 | 5 | public static boolean contains(Comparable[] a, Comparable b) { 6 | if (a.length == 0) { 7 | return false; 8 | } 9 | int low = 0; 10 | int high = a.length - 1; 11 | 12 | while (low <= high) { 13 | int middle = (low + high) / 2; 14 | // if (b > a[middle]) { 15 | if (b.compareTo(a[middle]) >= 1) { 16 | low = middle + 1; 17 | // } else if (b < a[middle]) { 18 | } else if (b.compareTo( a[middle] ) <= -1 ) { 19 | high = middle - 1; 20 | } else { // The element has been found 21 | return true; 22 | } 23 | } 24 | return false; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/dsa/search/SequentialSearch.java: -------------------------------------------------------------------------------- 1 | package dsa.search; 2 | 3 | import java.util.Objects; 4 | 5 | public class SequentialSearch { 6 | 7 | public static boolean contains(Comparable[] a, Comparable b) { 8 | for (Comparable i : a) { 9 | if (Objects.equals(i, b)) { 10 | return true; 11 | } 12 | } 13 | return false; 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/java/dsa/sort/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | public class BubbleSort { 4 | 5 | /** 6 | * In bubble sort, we basically traverse the array from first to 7 | * array_length - 1 position and compare the element with the next one. 8 | * Element is swapped with the next element if the next element is greater. 9 | * 10 | * Bubble sort steps are as follows. 11 | * 12 | * 1. Compare array[0] & array[1] 2. If array[0] > array [1] swap it. 3. 13 | * Compare array[1] & array[2] 4. If array[1] > array[2] swap it. ... 5. 14 | * Compare array[n-1] & array[n] 6. if [n-1] > array[n] then swap it. 15 | * 16 | * After this step we will have largest element at the last index. 17 | * 18 | * Repeat the same steps for array[1] to array[n-1] * 19 | * @param intArray 20 | */ 21 | public void sort(Integer[] intArray) { 22 | 23 | int n = intArray.length; 24 | int temp; 25 | 26 | for (int i = 0; i < n; i++) { 27 | for (int j = 1; j < (n - i); j++) { 28 | 29 | if (intArray[j - 1] > intArray[j]) { 30 | //swap the elements! 31 | temp = intArray[j - 1]; 32 | intArray[j - 1] = intArray[j]; 33 | intArray[j] = temp; 34 | } 35 | 36 | } 37 | } 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/dsa/sort/HeapSort.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | public class HeapSort { 4 | 5 | private static int N; 6 | 7 | /* Sort Function */ 8 | public static void sort(Integer arr[]) { 9 | heapify(arr); 10 | for (int i = N; i > 0; i--) { 11 | swap(arr, 0, i); 12 | N = N - 1; 13 | maxheap(arr, 0); 14 | } 15 | } 16 | 17 | /* Function to build a heap */ 18 | public static void heapify(Integer arr[]) { 19 | N = arr.length - 1; 20 | for (int i = N / 2; i >= 0; i--) { 21 | maxheap(arr, i); 22 | } 23 | } 24 | 25 | /* Function to swap largest element in heap */ 26 | public static void maxheap(Integer arr[], Integer i) { 27 | int left = 2 * i; 28 | int right = 2 * i + 1; 29 | int max = i; 30 | if (left <= N && arr[left] > arr[i]) { 31 | max = left; 32 | } 33 | if (right <= N && arr[right] > arr[max]) { 34 | max = right; 35 | } 36 | 37 | if (max != i) { 38 | swap(arr, i, max); 39 | maxheap(arr, max); 40 | } 41 | } 42 | 43 | /* Function to swap two numbers in an array */ 44 | public static void swap(Integer arr[], Integer i, Integer j) { 45 | int tmp = arr[i]; 46 | arr[i] = arr[j]; 47 | arr[j] = tmp; 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/main/java/dsa/sort/InsertionSort.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | public class InsertionSort { 4 | 5 | void sort(Integer[] arr) { 6 | int i, j, newValue; 7 | for (i = 1; i < arr.length; i++) { 8 | newValue = arr[i]; 9 | j = i; 10 | while (j > 0 && arr[j - 1] > newValue) { 11 | arr[j] = arr[j - 1]; 12 | j--; 13 | } 14 | arr[j] = newValue; 15 | } 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /src/main/java/dsa/sort/MergeSort.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | public class MergeSort { 4 | 5 | public void sort(Comparable[] a) { 6 | Comparable[] tmp = new Comparable[a.length]; 7 | sort(a, tmp, 0, a.length - 1); 8 | } 9 | 10 | private void sort(Comparable[] a, Comparable[] tmp, int left, int right) { 11 | if (left < right) { 12 | int center = (left + right) / 2; 13 | sort(a, tmp, left, center); 14 | sort(a, tmp, center + 1, right); 15 | merge(a, tmp, left, center + 1, right); 16 | } 17 | } 18 | 19 | private void merge(Comparable[] a, Comparable[] tmp, int left, int right, int rightEnd) { 20 | int leftEnd = right - 1; 21 | int k = left; 22 | int num = rightEnd - left + 1; 23 | 24 | while (left <= leftEnd && right <= rightEnd) { 25 | if (a[left].compareTo(a[right]) <= 0) { 26 | tmp[k++] = a[left++]; 27 | } else { 28 | tmp[k++] = a[right++]; 29 | } 30 | } 31 | 32 | while (left <= leftEnd) // Copy rest of first half 33 | { 34 | tmp[k++] = a[left++]; 35 | } 36 | 37 | while (right <= rightEnd) // Copy rest of right half 38 | { 39 | tmp[k++] = a[right++]; 40 | } 41 | 42 | // Copy tmp back 43 | for (int i = 0; i < num; i++, rightEnd--) { 44 | a[rightEnd] = tmp[rightEnd]; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/dsa/sort/QuickSort.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | public class QuickSort { 4 | 5 | private Integer array[]; 6 | private int length; 7 | 8 | public void sort(Integer[] inputArr) { 9 | 10 | if (inputArr == null || inputArr.length == 0) { 11 | return; 12 | } 13 | this.array = inputArr; 14 | length = inputArr.length; 15 | quickSort(0, length - 1); 16 | } 17 | 18 | private void quickSort(int lowerIndex, int higherIndex) { 19 | 20 | int i = lowerIndex; 21 | int j = higherIndex; 22 | // calculate pivot number, I am taking pivot as middle index number 23 | int pivot = array[lowerIndex + (higherIndex - lowerIndex) / 2]; 24 | // Divide into two arrays 25 | while (i <= j) { 26 | /** 27 | * In each iteration, we will identify a number from left side which 28 | * is greater then the pivot value, and also we will identify a 29 | * number from right side which is less then the pivot value. Once 30 | * the search is done, then we exchange both numbers. 31 | */ 32 | while (array[i] < pivot) { 33 | i++; 34 | } 35 | while (array[j] > pivot) { 36 | j--; 37 | } 38 | if (i <= j) { 39 | exchangeNumbers(i, j); 40 | //move index to next position on both sides 41 | i++; 42 | j--; 43 | } 44 | } 45 | // call quickSort() method recursively 46 | if (lowerIndex < j) { 47 | quickSort(lowerIndex, j); 48 | } 49 | if (i < higherIndex) { 50 | quickSort(i, higherIndex); 51 | } 52 | } 53 | 54 | private void exchangeNumbers(int i, int j) { 55 | int temp = array[i]; 56 | array[i] = array[j]; 57 | array[j] = temp; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/dsa/sort/RadixSort.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | public class RadixSort { 4 | 5 | private static final int BITS_PER_BYTE = 8; 6 | 7 | /** 8 | * Rearranges the array of W-character strings in ascending order. 9 | * 10 | * @param a the array to be sorted 11 | * @param W the number of characters per string 12 | */ 13 | public void sort(String[] a, int W) { 14 | int N = a.length; 15 | int R = 256; // extend ASCII alphabet size 16 | String[] aux = new String[N]; 17 | 18 | for (int d = W - 1; d >= 0; d--) { 19 | // sort by key-indexed counting on dth character 20 | 21 | // compute frequency counts 22 | int[] count = new int[R + 1]; 23 | for (int i = 0; i < N; i++) { 24 | count[a[i].charAt(d) + 1]++; 25 | } 26 | 27 | // compute cumulates 28 | for (int r = 0; r < R; r++) { 29 | count[r + 1] += count[r]; 30 | } 31 | 32 | // move data 33 | for (int i = 0; i < N; i++) { 34 | aux[count[a[i].charAt(d)]++] = a[i]; 35 | } 36 | 37 | // copy back 38 | for (int i = 0; i < N; i++) { 39 | a[i] = aux[i]; 40 | } 41 | } 42 | } 43 | 44 | /** 45 | * Rearranges the array of 32-bit integers in ascending order. This is about 46 | * 2-3x faster than Arrays.sort(). 47 | * 48 | * @param a the array to be sorted 49 | */ 50 | public void sort(Integer[] a) { 51 | int BITS = 32; // each int is 32 bits 52 | int W = BITS / BITS_PER_BYTE; // each int is 4 bytes 53 | int R = 1 << BITS_PER_BYTE; // each bytes is between 0 and 255 54 | int MASK = R - 1; // 0xFF 55 | 56 | int N = a.length; 57 | int[] aux = new int[N]; 58 | 59 | for (int d = 0; d < W; d++) { 60 | 61 | // compute frequency counts 62 | int[] count = new int[R + 1]; 63 | for (int i = 0; i < N; i++) { 64 | int c = (a[i] >> BITS_PER_BYTE * d) & MASK; 65 | count[c + 1]++; 66 | } 67 | 68 | // compute cumulates 69 | for (int r = 0; r < R; r++) { 70 | count[r + 1] += count[r]; 71 | } 72 | 73 | // for most significant byte, 0x80-0xFF comes before 0x00-0x7F 74 | if (d == W - 1) { 75 | int shift1 = count[R] - count[R / 2]; 76 | int shift2 = count[R / 2]; 77 | for (int r = 0; r < R / 2; r++) { 78 | count[r] += shift1; 79 | } 80 | for (int r = R / 2; r < R; r++) { 81 | count[r] -= shift2; 82 | } 83 | } 84 | 85 | // move data 86 | for (int i = 0; i < N; i++) { 87 | int c = (a[i] >> BITS_PER_BYTE * d) & MASK; 88 | aux[count[c]++] = a[i]; 89 | } 90 | 91 | // copy back 92 | for (int i = 0; i < N; i++) { 93 | a[i] = aux[i]; 94 | } 95 | } 96 | } 97 | 98 | } -------------------------------------------------------------------------------- /src/main/java/dsa/sort/SelectionSort.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | public class SelectionSort { 4 | 5 | public void sort(Integer[] arr) { 6 | 7 | for (int i = 0; i < arr.length - 1; i++) { 8 | int index = i; 9 | for (int j = i + 1; j < arr.length; j++) { 10 | if (arr[j] < arr[index]) { 11 | index = j; 12 | } 13 | } 14 | 15 | int smallerNumber = arr[index]; 16 | arr[index] = arr[i]; 17 | arr[i] = smallerNumber; 18 | } 19 | 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/dsa/sort/ShellSort.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | public class ShellSort { 4 | 5 | public void sort(Integer[] nums) { 6 | int h = 1; 7 | int n = nums.length; 8 | while (h < n) { 9 | h = h * 3 + 1; 10 | } 11 | h = h / 3; 12 | int c, j; 13 | while (h > 0) { 14 | for (int i = h; i < n; i++) { 15 | c = nums[i]; 16 | j = i; 17 | while (j >= h && nums[j - h] > c) { 18 | nums[j] = nums[j - h]; 19 | j = j - h; 20 | } 21 | nums[j] = c; 22 | } 23 | h = h / 2; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/dsa/stack/Stack.java: -------------------------------------------------------------------------------- 1 | package dsa.stack; 2 | 3 | /** 4 | * http://eddmann.com/posts/implementing-a-stack-in-java-using-arrays-and-linked-lists/ 5 | * @param 6 | */ 7 | interface Stack { 8 | Stack push(T ele); 9 | T pop(); 10 | int size(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/dsa/stack/StackArray.java: -------------------------------------------------------------------------------- 1 | package dsa.stack; 2 | 3 | public class StackArray implements Stack { 4 | 5 | private T[] arr; 6 | 7 | private int total; 8 | 9 | public StackArray() 10 | { 11 | arr = (T[]) new Object[2]; 12 | } 13 | 14 | private void resize(int capacity) 15 | { 16 | T[] tmp = (T[]) new Object[capacity]; 17 | System.arraycopy(arr, 0, tmp, 0, total); 18 | arr = tmp; 19 | } 20 | 21 | @Override 22 | public StackArray push(T ele) 23 | { 24 | if (arr.length == total) resize(arr.length * 2); 25 | arr[total++] = ele; 26 | return this; 27 | } 28 | 29 | @Override 30 | public T pop() 31 | { 32 | if (total == 0) throw new java.util.NoSuchElementException(); 33 | T ele = arr[--total]; 34 | arr[total] = null; 35 | if (total > 0 && total == arr.length / 4) resize(arr.length / 2); 36 | return ele; 37 | } 38 | 39 | @Override 40 | public int size(){ 41 | return total; 42 | } 43 | 44 | @Override 45 | public String toString() 46 | { 47 | return java.util.Arrays.toString(arr); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/main/java/dsa/stack/StackLinkedList.java: -------------------------------------------------------------------------------- 1 | package dsa.stack; 2 | 3 | public class StackLinkedList implements Stack { 4 | 5 | private int total; 6 | 7 | private Node first; 8 | 9 | private class Node { 10 | private T ele; 11 | private Node next; 12 | } 13 | 14 | public StackLinkedList push(T ele) 15 | { 16 | Node current = first; 17 | first = new Node(); 18 | first.ele = ele; 19 | first.next = current; 20 | total++; 21 | return this; 22 | } 23 | 24 | @Override 25 | public T pop() 26 | { 27 | if (first == null) new java.util.NoSuchElementException(); 28 | T ele = first.ele; 29 | first = first.next; 30 | total--; 31 | return ele; 32 | } 33 | 34 | @Override 35 | public int size(){ 36 | return total; 37 | } 38 | 39 | @Override 40 | public String toString() 41 | { 42 | StringBuilder sb = new StringBuilder(); 43 | Node tmp = first; 44 | while (tmp != null) { 45 | sb.append(tmp.ele).append(", "); 46 | tmp = tmp.next; 47 | } 48 | return sb.toString(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/dsa/tree/avl/AVLTree.java: -------------------------------------------------------------------------------- 1 | package dsa.tree.avl; 2 | 3 | import java.io.PrintStream; 4 | 5 | public class AVLTree { 6 | 7 | private Node root; 8 | 9 | private class Node { 10 | private int key; 11 | private int balance; 12 | private Node left, right, parent; 13 | 14 | Node(int k, Node p) { 15 | key = k; 16 | parent = p; 17 | } 18 | } 19 | 20 | public boolean insert(int key) { 21 | if (root == null) 22 | root = new Node(key, null); 23 | else { 24 | Node n = root; 25 | Node parent; 26 | while (true) { 27 | if (n.key == key) 28 | return false; 29 | 30 | parent = n; 31 | 32 | boolean goLeft = n.key > key; 33 | n = goLeft ? n.left : n.right; 34 | 35 | if (n == null) { 36 | if (goLeft) { 37 | parent.left = new Node(key, parent); 38 | } else { 39 | parent.right = new Node(key, parent); 40 | } 41 | rebalance(parent); 42 | break; 43 | } 44 | } 45 | } 46 | return true; 47 | } 48 | 49 | public void delete(int delKey) { 50 | if (root == null) 51 | return; 52 | Node n = root; 53 | Node parent = root; 54 | Node delNode = null; 55 | Node child = root; 56 | 57 | while (child != null) { 58 | parent = n; 59 | n = child; 60 | child = delKey >= n.key ? n.right : n.left; 61 | if (delKey == n.key) 62 | delNode = n; 63 | } 64 | 65 | if (delNode != null) { 66 | delNode.key = n.key; 67 | 68 | child = n.left != null ? n.left : n.right; 69 | 70 | if (root.key == delKey) { 71 | root = child; 72 | } else { 73 | if (parent.left == n) { 74 | parent.left = child; 75 | } else { 76 | parent.right = child; 77 | } 78 | rebalance(parent); 79 | } 80 | } 81 | } 82 | 83 | private void rebalance(Node n) { 84 | setBalance(n); 85 | 86 | if (n.balance == -2) { 87 | if (height(n.left.left) >= height(n.left.right)) 88 | n = rotateRight(n); 89 | else 90 | n = rotateLeftThenRight(n); 91 | 92 | } else if (n.balance == 2) { 93 | if (height(n.right.right) >= height(n.right.left)) 94 | n = rotateLeft(n); 95 | else 96 | n = rotateRightThenLeft(n); 97 | } 98 | 99 | if (n.parent != null) { 100 | rebalance(n.parent); 101 | } else { 102 | root = n; 103 | } 104 | } 105 | 106 | private Node rotateLeft(Node a) { 107 | 108 | Node b = a.right; 109 | b.parent = a.parent; 110 | 111 | a.right = b.left; 112 | 113 | if (a.right != null) 114 | a.right.parent = a; 115 | 116 | b.left = a; 117 | a.parent = b; 118 | 119 | if (b.parent != null) { 120 | if (b.parent.right == a) { 121 | b.parent.right = b; 122 | } else { 123 | b.parent.left = b; 124 | } 125 | } 126 | 127 | setBalance(a, b); 128 | 129 | return b; 130 | } 131 | 132 | private Node rotateRight(Node a) { 133 | 134 | Node b = a.left; 135 | b.parent = a.parent; 136 | 137 | a.left = b.right; 138 | 139 | if (a.left != null) 140 | a.left.parent = a; 141 | 142 | b.right = a; 143 | a.parent = b; 144 | 145 | if (b.parent != null) { 146 | if (b.parent.right == a) { 147 | b.parent.right = b; 148 | } else { 149 | b.parent.left = b; 150 | } 151 | } 152 | 153 | setBalance(a, b); 154 | 155 | return b; 156 | } 157 | 158 | private Node rotateLeftThenRight(Node n) { 159 | n.left = rotateLeft(n.left); 160 | return rotateRight(n); 161 | } 162 | 163 | private Node rotateRightThenLeft(Node n) { 164 | n.right = rotateRight(n.right); 165 | return rotateLeft(n); 166 | } 167 | 168 | private int height(Node n) { 169 | if (n == null) 170 | return -1; 171 | return 1 + Math.max(height(n.left), height(n.right)); 172 | } 173 | 174 | private void setBalance(Node... nodes) { 175 | for (Node n : nodes) 176 | n.balance = height(n.right) - height(n.left); 177 | } 178 | 179 | public void printBalance(PrintStream out) { 180 | printBalance(root, out); 181 | } 182 | 183 | private void printBalance(Node n, PrintStream out) { 184 | if (n != null) { 185 | printBalance(n.left, out); 186 | out.printf("%s ", n.balance); 187 | printBalance(n.right, out); 188 | } 189 | } 190 | 191 | 192 | } 193 | -------------------------------------------------------------------------------- /src/main/java/dsa/tree/bst/BSTNode.java: -------------------------------------------------------------------------------- 1 | package dsa.tree.bst; 2 | 3 | public class BSTNode { 4 | 5 | BSTNode left, right; 6 | int data; 7 | 8 | /* Constructor */ 9 | public BSTNode() { 10 | left = null; 11 | right = null; 12 | data = 0; 13 | } 14 | 15 | /* Constructor */ 16 | public BSTNode(int n) { 17 | left = null; 18 | right = null; 19 | data = n; 20 | } 21 | 22 | /* Function to set left node */ 23 | public void setLeft(BSTNode n) { 24 | left = n; 25 | } 26 | 27 | /* Function to set right node */ 28 | public void setRight(BSTNode n) { 29 | right = n; 30 | } 31 | 32 | /* Function to get left node */ 33 | public BSTNode getLeft() { 34 | return left; 35 | } 36 | 37 | /* Function to get right node */ 38 | public BSTNode getRight() { 39 | return right; 40 | } 41 | 42 | /* Function to set data to node */ 43 | public void setData(int d) { 44 | data = d; 45 | } 46 | 47 | /* Function to get data from node */ 48 | public int getData() { 49 | return data; 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return String.valueOf(data); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/dsa/tree/bst/BinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package dsa.tree.bst; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Class BST 8 | **/ 9 | public class BinarySearchTree { 10 | 11 | private BSTNode root; 12 | 13 | /** 14 | * Constructor 15 | **/ 16 | public BinarySearchTree() { 17 | root = null; 18 | } 19 | 20 | /* Function to check if tree is empty */ 21 | public boolean isEmpty() { 22 | return root == null; 23 | } 24 | 25 | /* Functions to insert data */ 26 | public void insert(int data) { 27 | root = insert(root, data); 28 | } 29 | 30 | /* Function to insert data recursively */ 31 | private BSTNode insert(BSTNode node, int data) { 32 | if (node == null) { 33 | node = new BSTNode(data); 34 | } else if (data <= node.getData()) { 35 | node.left = insert(node.left, data); 36 | } else { 37 | node.right = insert(node.right, data); 38 | } 39 | return node; 40 | } 41 | 42 | /* Functions to delete data */ 43 | public void delete(int k) { 44 | if (isEmpty()) { 45 | System.out.println("Tree Empty"); 46 | } else if (search(k) == false) { 47 | System.out.println("Sorry " + k + " is not present"); 48 | } else { 49 | root = delete(root, k); 50 | System.out.println(k + " deleted from the tree"); 51 | } 52 | } 53 | 54 | private BSTNode delete(BSTNode root, int k) { 55 | BSTNode p, p2, n; 56 | if (root.getData() == k) { 57 | BSTNode lt, rt; 58 | lt = root.getLeft(); 59 | rt = root.getRight(); 60 | if (lt == null && rt == null) { 61 | return null; 62 | } else if (lt == null) { 63 | p = rt; 64 | return p; 65 | } else if (rt == null) { 66 | p = lt; 67 | return p; 68 | } else { 69 | p2 = rt; 70 | p = rt; 71 | while (p.getLeft() != null) { 72 | p = p.getLeft(); 73 | } 74 | p.setLeft(lt); 75 | return p2; 76 | } 77 | } 78 | if (k < root.getData()) { 79 | n = delete(root.getLeft(), k); 80 | root.setLeft(n); 81 | } else { 82 | n = delete(root.getRight(), k); 83 | root.setRight(n); 84 | } 85 | return root; 86 | } 87 | 88 | /* Functions to count number of nodes */ 89 | public int countNodes() { 90 | return countNodes(root); 91 | } 92 | 93 | /* Function to count number of nodes recursively */ 94 | private int countNodes(BSTNode r) { 95 | if (r == null) { 96 | return 0; 97 | } else { 98 | int l = 1; 99 | l += countNodes(r.getLeft()); 100 | l += countNodes(r.getRight()); 101 | return l; 102 | } 103 | } 104 | 105 | /* Functions to search for an element */ 106 | public boolean search(int val) { 107 | return search(root, val); 108 | } 109 | 110 | /* Function to search for an element recursively */ 111 | private boolean search(BSTNode r, int val) { 112 | boolean found = false; 113 | while ((r != null) && !found) { 114 | int rval = r.getData(); 115 | if (val < rval) { 116 | r = r.getLeft(); 117 | } else if (val > rval) { 118 | r = r.getRight(); 119 | } else { 120 | found = true; 121 | break; 122 | } 123 | found = search(r, val); 124 | } 125 | return found; 126 | } 127 | 128 | /* Function for inorder traversal */ 129 | public List inorder() { 130 | List walk = new ArrayList<>(); 131 | inorder(root, walk); 132 | return walk; 133 | } 134 | 135 | private void inorder(BSTNode r, List walk) { 136 | if (r != null) { 137 | inorder(r.getLeft(), walk); 138 | // System.out.print(r.getData() + " "); 139 | walk.add(r); 140 | inorder(r.getRight(), walk); 141 | } 142 | } 143 | 144 | /* Function for preorder traversal */ 145 | public List preorder() { 146 | List walk = new ArrayList<>(); 147 | preorder(root, walk); 148 | return walk; 149 | } 150 | 151 | private void preorder(BSTNode r, List walk) { 152 | if (r != null) { 153 | // System.out.print(r.getData() + " "); 154 | walk.add(r); 155 | preorder(r.getLeft(), walk); 156 | preorder(r.getRight(), walk); 157 | } 158 | } 159 | 160 | /* Function for postorder traversal */ 161 | public List postorder() { 162 | List walk = new ArrayList<>(); 163 | 164 | postorder(root, walk); 165 | return walk; 166 | } 167 | 168 | private void postorder(BSTNode r, List walk) { 169 | if (r != null) { 170 | postorder(r.getLeft(), walk); 171 | postorder(r.getRight(), walk); 172 | // System.out.print(r.getData() + " "); 173 | walk.add(r); 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/main/java/dsa/tree/huffman/BitStream.java: -------------------------------------------------------------------------------- 1 | package dsa.tree.huffman; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * BitStream class for reading and writing variable lengths of bits to a byte 7 | * array 8 | */ 9 | public class BitStream { 10 | 11 | private final int DEFAULT_SIZE = 256; 12 | 13 | // byte array for actual BitStream 14 | private byte[] bank; 15 | 16 | // boolean array representation of a single byte 17 | private boolean[] bits = new boolean[8]; 18 | 19 | // current position in bit array 20 | private int bitPosition; 21 | 22 | // current position in byte array 23 | private int bytePosition; 24 | 25 | // are we at the end of the bank 26 | private boolean endOfBank = false; 27 | 28 | // number of leftover bits short of a full byte 29 | private byte padBits; 30 | 31 | private boolean closed = false; 32 | 33 | /** 34 | * Creates a new BitStream of DEFAULT_SIZE 35 | */ 36 | public BitStream() { 37 | bank = new byte[DEFAULT_SIZE]; 38 | } 39 | 40 | /** 41 | * Creates a new BitStream of given size 42 | * 43 | * @param size size of BitStream 44 | */ 45 | public BitStream(int size) { 46 | bank = new byte[size]; 47 | } 48 | 49 | /** 50 | * Creates a new BitStream from a byte array assumes last byte is padBits 51 | * 52 | * @param bank byte array of encoded bits 53 | */ 54 | public BitStream(byte[] bank) { 55 | this.bank = bank; 56 | this.padBits = bank[bank.length - 1]; 57 | pullByte(); 58 | } 59 | 60 | /** 61 | * Get the byte array 62 | * 63 | * @return byte array of BitStream 64 | */ 65 | public byte[] getBank() { 66 | return bank; 67 | } 68 | 69 | /** 70 | * grow byte array by DEFAULT_SIZE 71 | * 72 | * @return byte array grown by DEFAULT_SIZE 73 | */ 74 | private byte[] grow() { 75 | return Arrays.copyOf(bank, bank.length + DEFAULT_SIZE); 76 | } 77 | 78 | /** 79 | * size of array 80 | * 81 | * @return size of array 82 | */ 83 | public int length() { 84 | return bank.length; 85 | } 86 | 87 | /** 88 | * returns EOB() or EndOfBank flag 89 | * 90 | * @return true if end of bank 91 | */ 92 | public boolean EOB() { 93 | return endOfBank; 94 | } 95 | 96 | /** 97 | * add a single bit to the BitStream 98 | * 99 | * @param bit true for 1, false for 0 100 | */ 101 | public void pushBit(boolean bit) { 102 | if (closed) { 103 | return; 104 | } 105 | bits[bitPosition] = bit; 106 | bitPosition++; 107 | if (bitPosition > 7) { 108 | flush(); 109 | } 110 | } 111 | 112 | /** 113 | * flush the full byte to the BitStream 114 | */ 115 | private void flush() { 116 | int makeByte = 0; 117 | for (int i = 0; i < 8; i++) { 118 | // push 1's to the correct bit position 119 | if (bits[i]) { 120 | makeByte |= 1 << 7 - i; 121 | } 122 | } 123 | bank[bytePosition] = (byte) (makeByte & 0xff); 124 | bytePosition++; 125 | if (bytePosition >= bank.length) { 126 | bank = grow(); 127 | } 128 | bitPosition = 0; 129 | clearBits(); 130 | } 131 | 132 | /** 133 | * set all bits in the current bit[] array to 0 134 | */ 135 | private void clearBits() { 136 | for (int i = 0; i < bits.length; i++) { 137 | bits[i] = false; 138 | } 139 | } 140 | 141 | /** 142 | * Push bits to BitStream length will be based on highest one-bit in integer 143 | * 144 | * @param inBits integer value to push 145 | */ 146 | public void pushBits(int inBits) { 147 | int len = 31 - Integer.numberOfLeadingZeros(inBits); 148 | while (len >= 0) { 149 | pushBit((inBits & (1 << len)) == 1 << len); 150 | len--; 151 | } 152 | } 153 | 154 | /** 155 | * Push bits to BitStream pushes a set length of bits, padding with zeroes 156 | * if necessary if value length is greater than length, will push entire 157 | * value 158 | * 159 | * @param value integer value to push 160 | * @param length number of bits to push 161 | */ 162 | public void pushBits(int value, int length) { 163 | for (int i = length - 1; i >= 0; i--) { 164 | pushBit((value >> i & 1) == 1); 165 | } 166 | } 167 | 168 | /** 169 | * Push bits to BitStream pushes a String representation of a binary number 170 | * 171 | * @param bitString 172 | */ 173 | public void pushBits(String bitString) { 174 | for (int i = 0; i < bitString.length(); i++) { 175 | pushBit(bitString.charAt(i) == '1'); 176 | } 177 | } 178 | 179 | /** 180 | * pull a byte of the current byte position in the array 181 | */ 182 | private void pullByte() { 183 | clearBits(); 184 | byte current = bank[bytePosition]; 185 | for (int i = 7, j = 0; i >= 0; i--, j++) { 186 | int flagBit = 1 << i; 187 | if ((current & flagBit) == flagBit) { 188 | bits[j] = true; 189 | } 190 | } 191 | bytePosition++; 192 | if (bytePosition > bank.length - 1) { 193 | endOfBank = true; 194 | } 195 | bitPosition = 0; 196 | } 197 | 198 | /** 199 | * Returns a single bit at bitPosition 200 | * 201 | * @return bit boolean true for 1, false for 0 202 | */ 203 | public boolean readBit() { 204 | boolean bit = bits[bitPosition]; 205 | bitPosition++; 206 | if (bytePosition == bank.length - 1 && bitPosition > 7 - padBits) { 207 | endOfBank = true; 208 | } 209 | if (bitPosition > 7) { 210 | pullByte(); 211 | } 212 | return bit; 213 | } 214 | 215 | /** 216 | * read length number of bits from the stream 217 | * 218 | * @param length 219 | * @return integer 220 | */ 221 | public int readBits(int length) { 222 | int retval = 0; 223 | for (int i = length - 1; i >= 0; i--) { 224 | retval |= ((readBit()) ? 1 : 0) << i; 225 | } 226 | return retval; 227 | } 228 | 229 | /** 230 | * close stream for writing operations. will pull the first byte for reading 231 | * operations. 232 | */ 233 | public void close() { 234 | if (closed) { 235 | return; 236 | } 237 | closed = true; 238 | padBits = (byte) ((-(bitPosition) + 8) % 8); 239 | if (padBits > 0) { 240 | flush(); 241 | } 242 | bank[bytePosition] = padBits; 243 | bank = Arrays.copyOfRange(bank, 0, bytePosition + 1); 244 | bitPosition = 0; 245 | bytePosition = 0; 246 | pullByte(); 247 | } 248 | 249 | @Override 250 | public String toString() { 251 | if (bitPosition != 0) { 252 | flush(); 253 | } 254 | String retval = ""; 255 | for (int i = 0; i < bank.length; i++) { 256 | if (i % 24 == 0) { 257 | retval += "\n"; 258 | } 259 | retval += Integer.toHexString((int) (bank[i] & 0xff)) + " "; 260 | } 261 | return retval; 262 | } 263 | 264 | @Override 265 | public int hashCode() { 266 | int hash = 5; 267 | hash = 37 * hash + Arrays.hashCode(this.bank); 268 | return hash; 269 | } 270 | 271 | @Override 272 | public boolean equals(Object obj) { 273 | if (this == obj) { 274 | return true; 275 | } 276 | if (obj == null) { 277 | return false; 278 | } 279 | if (getClass() != obj.getClass()) { 280 | return false; 281 | } 282 | final BitStream other = (BitStream) obj; 283 | if (!Arrays.equals(this.bank, other.bank)) { 284 | return false; 285 | } 286 | return true; 287 | } 288 | 289 | 290 | 291 | 292 | } 293 | -------------------------------------------------------------------------------- /src/main/java/dsa/tree/huffman/HuffmanTree.java: -------------------------------------------------------------------------------- 1 | package dsa.tree.huffman; 2 | 3 | /* 4 | * Huffman Tree class 5 | */ 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.nio.file.Files; 10 | import java.util.Arrays; 11 | import java.util.PriorityQueue; 12 | 13 | public class HuffmanTree { 14 | 15 | // the Tree of Trees 16 | private Tree htree; 17 | 18 | // the bit codes and lengths 19 | private int[] huffmanCodes = new int[256]; 20 | private int[] huffmanLengths = new int[256]; 21 | 22 | public static int[] getFrequencies(String input) { 23 | int[] freq = new int[256]; 24 | for (int i = 0; i < input.length(); i++) { 25 | int value = (int) input.charAt(i); 26 | freq[value]++; 27 | } 28 | return freq; 29 | } 30 | 31 | /** 32 | * Create Huffman Tree for encoding and populates the code/length arrays 33 | * based on a 256 element array of frequency counts 34 | * 35 | * @param frequencies integer array of frequency counts 36 | */ 37 | public HuffmanTree(int[] frequencies) { 38 | this.htree = getHuffmanTree(frequencies); 39 | getCodes(); 40 | } 41 | 42 | /** 43 | * Create Huffman Tree for decoding from a BitStream of the encoded tree 44 | * frequencies have been discarded 45 | * 46 | * @param bs BitStream of encoded tree 47 | */ 48 | public HuffmanTree(BitStream bs) { 49 | this.htree = getHuffmanTree(bs); 50 | getCodes(); 51 | } 52 | 53 | /** 54 | * get Tree 55 | * 56 | * @return Tree Huffman Tree 57 | */ 58 | public Tree getTree() { 59 | return htree; 60 | } 61 | 62 | public BitStream getEncodedTree() { 63 | return htree.encodedTree(); 64 | } 65 | 66 | /** 67 | * Encode a string to a huffman-encoded BitStream 68 | * 69 | * @param input String to encode 70 | * @return output BitStream encoded stream 71 | */ 72 | public BitStream encode(String input) { 73 | BitStream output = new BitStream(); 74 | for (int i = 0; i < input.length(); i++) { 75 | output.pushBits(huffmanCodes[(int) input.charAt(i)], huffmanLengths[(int) input.charAt(i)]); 76 | } 77 | output.close(); 78 | return output; 79 | } 80 | 81 | /** 82 | * Encode a byte array to a huffman-encoded BitStream 83 | * 84 | * @param input byte[] array to encode 85 | * @return output BitStream encoded stream 86 | */ 87 | public BitStream encode(byte[] input) { 88 | BitStream output = new BitStream(); 89 | for (int i = 0; i < input.length; i++) { 90 | output.pushBits(huffmanCodes[input[i]], huffmanLengths[input[i]]); 91 | } 92 | output.close(); 93 | return output; 94 | } 95 | 96 | /** 97 | * Decode a huffman-encoded BitStream to String 98 | * 99 | * @param input BitStream of encoded data 100 | * @return output decoded String 101 | */ 102 | public String decode(BitStream input) { 103 | StringBuilder output = new StringBuilder(); 104 | while (!input.EOB()) { 105 | output.append((char) htree.getCode(input)); 106 | } 107 | return output.toString(); 108 | } 109 | 110 | /** 111 | * 112 | * @param input 113 | * @param filePath 114 | * @return 115 | * @throws IOException 116 | */ 117 | public File saveToFile(BitStream input, String filePath) throws IOException { 118 | File file = new File(filePath); 119 | try (FileOutputStream fos = new FileOutputStream(filePath)) { 120 | fos.write(input.getBank()); 121 | } 122 | return file; 123 | } 124 | 125 | /** 126 | * 127 | * @param file 128 | * @return 129 | * @throws IOException 130 | */ 131 | public BitStream readFromFile(File file) throws IOException { 132 | byte[] array = Files.readAllBytes(file.toPath()); 133 | return new BitStream(array); 134 | } 135 | 136 | 137 | /** 138 | * 139 | * @param filePath 140 | * @return 141 | * @throws IOException 142 | */ 143 | public BitStream readFromFile(String filePath) throws IOException { 144 | return readFromFile( new File(filePath ) ); 145 | } 146 | 147 | /** 148 | * Decode a huffman-encoded BitStream to byte array 149 | * 150 | * @param input BitStream of encoded data 151 | * @return output byte array 152 | */ 153 | public byte[] decodeBytes(BitStream input) { 154 | byte[] output = new byte[input.length() * 4]; 155 | int counter = 0; 156 | while (!input.EOB()) { 157 | output[counter] = (byte) (htree.getCode(input) & 0xff); 158 | counter++; 159 | } 160 | return Arrays.copyOfRange(output, 0, counter + 1); 161 | } 162 | 163 | /** 164 | * Build Tree from frequency array Stores them in a Priority Queue pulls out 165 | * two smallest and adds them together creates a new subtree 166 | * 167 | * @param frequencies integer array of frequencies 168 | * @return Tree huffman tree 169 | */ 170 | private Tree getHuffmanTree(int[] frequencies) { 171 | PriorityQueue heap = new PriorityQueue<>(); 172 | for (int i = 0; i < frequencies.length; i++) { 173 | if (frequencies[i] > 0) { 174 | // add all frequencies > 0 as new subtree with no children 175 | heap.add(new Tree(i, frequencies[i])); 176 | } 177 | } 178 | 179 | while (heap.size() > 1) { 180 | Tree t1 = heap.remove(); 181 | Tree t2 = heap.remove(); 182 | heap.add(new Tree(t1, t2)); 183 | } 184 | 185 | return heap.remove(); 186 | } 187 | 188 | /** 189 | * Re-build tree from BitStream frequencies were not stored but are now 190 | * unimportant 191 | * 192 | * @param bs BitStream of encoded tree 1 bit + literal byte or 0 193 | * @return Tree Huffman Tree 194 | */ 195 | private Tree getHuffmanTree(BitStream bs) { 196 | if (bs.readBit()) { 197 | return new Tree(bs.readBits(8), 0); 198 | } else { 199 | Tree left = getHuffmanTree(bs); 200 | Tree right = getHuffmanTree(bs); 201 | return new Tree(left, right); 202 | } 203 | 204 | } 205 | 206 | /** 207 | * Build huffman codes based on current tree 208 | */ 209 | private void getCodes() { 210 | if (htree.root == null) { 211 | return; 212 | } 213 | getCodes(htree.root); 214 | } 215 | 216 | /** 217 | * recursive helper class 218 | */ 219 | private void getCodes(Node root) { 220 | if (!htree.isLeaf(root)) { 221 | root.left.huffmanCode = root.huffmanCode << 1; 222 | root.left.huffmanLen = root.huffmanLen + 1; 223 | getCodes(root.left); 224 | 225 | root.right.huffmanCode = root.huffmanCode << 1 ^ 1; 226 | root.right.huffmanLen = root.huffmanLen + 1; 227 | getCodes(root.right); 228 | } else { 229 | huffmanCodes[root.index] = root.huffmanCode; 230 | huffmanLengths[root.index] = root.huffmanLen; 231 | } 232 | } 233 | 234 | /** 235 | * Show all non-zero codes 236 | * 237 | * @return 238 | */ 239 | public String displayCodes() { 240 | StringBuilder out = new StringBuilder(); 241 | for (int i = 0; i < 256; i++) { 242 | if (huffmanLengths[i] > 0) { 243 | out.append(i).append(" : ").append(toBinaryString(huffmanCodes[i], huffmanLengths[i])).append(System.lineSeparator()); 244 | } 245 | } 246 | return out.toString(); 247 | } 248 | 249 | /** 250 | * Binary String method with padding/truncating to specified length 251 | * 252 | * @param value integer value to convert 253 | * @param length integer length to convert, adding zeroes at the front if 254 | * necessary 255 | * @return retval String binary representation of value at specified length 256 | */ 257 | public static String toBinaryString(int value, int length) { 258 | String retval = ""; 259 | for (int i = length - 1; i >= 0; i--) { 260 | retval += ((value >> i & 1) == 1) ? "1" : "0"; 261 | } 262 | return retval; 263 | } 264 | 265 | /** 266 | * Tree class 267 | */ 268 | class Tree implements Comparable { 269 | 270 | Node root; 271 | 272 | /** 273 | * Create tree with childless leaf node 274 | * 275 | * @param index integer of character/byte value 276 | * @param frequency count of occuring frequency 277 | */ 278 | public Tree(int index, int frequency) { 279 | root = new Node(index, frequency); 280 | } 281 | 282 | /** 283 | * Create subtree with null node as root and total of two subtree 284 | * frequencies 285 | * 286 | * @param tree1 left subtree 287 | * @param tree2 right subtree 288 | */ 289 | public Tree(Tree tree1, Tree tree2) { 290 | root = new Node(); 291 | root.left = tree1.root; 292 | root.right = tree2.root; 293 | root.frequency = tree1.root.frequency + tree2.root.frequency; 294 | } 295 | 296 | /** 297 | * Encode Huffman Tree to BitStream if leaf node pushes 1 + literal byte 298 | * otherwise 0 299 | * 300 | * @return bs BitStream with encoded tree 301 | */ 302 | public BitStream encodedTree() { 303 | BitStream bs = new BitStream(); 304 | encodedTree(root, bs); 305 | bs.close(); 306 | //System.out.println(bs); 307 | return bs; 308 | } 309 | 310 | /** 311 | * recursive helper method 312 | */ 313 | private void encodedTree(Node node, BitStream bs) { 314 | if (isLeaf(node)) { 315 | bs.pushBit(true); 316 | bs.pushBits(node.index, 8); 317 | } else { 318 | bs.pushBit(false); 319 | encodedTree(node.left, bs); 320 | encodedTree(node.right, bs); 321 | } 322 | } 323 | 324 | /** 325 | * Get individual huffman code from current spot in tree recurses until 326 | * leaf node found 327 | */ 328 | public int getCode(BitStream bs) { 329 | Node current = root; 330 | boolean bit; 331 | while (!isLeaf(current)) { 332 | bit = bs.readBit(); 333 | if (bit) { 334 | current = current.right; 335 | } else { 336 | current = current.left; 337 | } 338 | 339 | } 340 | return current.index; 341 | } 342 | 343 | /** 344 | * is node a leaf node (childless) 345 | * 346 | * @param n Node to test 347 | * @return true if node has no children 348 | */ 349 | public boolean isLeaf(Node n) { 350 | return n.left == null; 351 | } 352 | 353 | @Override 354 | public int compareTo(Tree t) { 355 | return root.frequency - t.root.frequency; 356 | } 357 | } 358 | 359 | /** 360 | * Node Class 361 | * 362 | */ 363 | class Node { 364 | // actual ascii character value 365 | 366 | int index; 367 | 368 | // count 369 | int frequency; 370 | 371 | // integer value of huffman code 372 | int huffmanCode; 373 | 374 | // legth of huffman code in bits 375 | int huffmanLen; 376 | 377 | // left child 378 | Node left; 379 | 380 | //right child 381 | Node right; 382 | 383 | /** 384 | * Create blank Node 385 | */ 386 | public Node() { 387 | 388 | } 389 | 390 | /** 391 | * create Node based on index value and frequency count 392 | */ 393 | public Node(int index, int frequency) { 394 | this.index = index; 395 | this.frequency = frequency; 396 | } 397 | 398 | @Override 399 | public String toString() { 400 | return this.index + " : " + this.frequency; 401 | } 402 | 403 | } 404 | } 405 | -------------------------------------------------------------------------------- /src/test/java/AllTests.java: -------------------------------------------------------------------------------- 1 | 2 | import dsa.ai.graph.astar.AStarTest; 3 | import dsa.graph.BFSTest; 4 | import dsa.graph.DFSTest; 5 | import dsa.ai.graph.DijkstraTest; 6 | import dsa.list.DoublyLinkedListTest; 7 | import dsa.list.SinglyLinkedListTest; 8 | import dsa.queue.QueueArrayTest; 9 | import dsa.sort.AllSortTest; 10 | import dsa.stack.StackArrayTest; 11 | import dsa.tree.BSTTreeTest; 12 | import dsa.tree.HuffmanTreeTest; 13 | import org.junit.runner.RunWith; 14 | import org.junit.runners.Suite; 15 | import org.junit.runners.Suite.SuiteClasses; 16 | 17 | @RunWith(Suite.class) 18 | @SuiteClasses({BFSTest.class, DFSTest.class, DijkstraTest.class, DoublyLinkedListTest.class, SinglyLinkedListTest.class, QueueArrayTest.class, StackArrayTest.class, AStarTest.class, BSTTreeTest.class, HuffmanTreeTest.class, AllSortTest.class}) 19 | public class AllTests { 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/dsa/ai/graph/BellmanFordTest.java: -------------------------------------------------------------------------------- 1 | package dsa.ai.graph; 2 | 3 | import dsa.ai.graph.path.BellmanFord; 4 | import org.junit.Test; 5 | import static org.junit.Assert.*; 6 | 7 | public class BellmanFordTest { 8 | 9 | public BellmanFordTest() { 10 | } 11 | 12 | @Test 13 | public void testBellmanFordWithPositiveEdges() throws Exception { 14 | Integer[][] weight = { 15 | {null, 10, null, null, 3}, 16 | {null, null, 2, null, 1}, 17 | {null, null, null, 7, null}, 18 | {null, null, 9, null, null}, 19 | {null, 4, 8, 2, null} 20 | }; 21 | int source = 0; 22 | BellmanFord instance = new BellmanFord(); 23 | Integer[][] expResult = {{-1, 4, 1, 4, 0}, {0, 7, 9, 5, 3}}; 24 | Integer[][] result = instance.singleSourceShortestPath(weight, source); 25 | assertArrayEquals(expResult, result); 26 | } 27 | 28 | @Test 29 | public void testBellmanFordWithNegativeEdges() throws Exception { 30 | Integer[][] weight = { 31 | {null, -1, 4, null, null}, 32 | {null, null, 3, 2, 2}, 33 | {null, null, null, null, null}, 34 | {null, 1, 5, null, null}, 35 | {null, null, null, -3, null} 36 | }; 37 | int source = 0; 38 | BellmanFord instance = new BellmanFord(); 39 | Integer[][] expResult = {{-1, 0, 1, 4, 1}, {0, -1, 2, -2, 1}}; 40 | Integer[][] result = instance.singleSourceShortestPath(weight, source); 41 | assertArrayEquals(expResult, result); 42 | } 43 | 44 | @Test 45 | public void testBellmanFordWithNegativeCycle() { 46 | Integer[][] weight = { 47 | {null, -1, 4, null, null}, 48 | {null, null, 3, 2, 2}, 49 | {null, -6, null, null, null}, 50 | {null, 1, 5, null, null}, 51 | {null, null, null, -3, null} 52 | }; 53 | int source = 0; 54 | BellmanFord instance = new BellmanFord(); 55 | try { 56 | instance.singleSourceShortestPath(weight, source); 57 | fail("Should have thrown an exception: Negative weight cycle"); 58 | } catch (Exception ex) { 59 | assertTrue(true); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/test/java/dsa/ai/graph/DijkstraTest.java: -------------------------------------------------------------------------------- 1 | package dsa.ai.graph; 2 | 3 | import dsa.ai.graph.path.Dijkstra; 4 | import dsa.graph.Edge; 5 | import dsa.graph.Graph; 6 | import dsa.graph.Vertex; 7 | import java.util.ArrayList; 8 | import java.util.LinkedList; 9 | import java.util.List; 10 | import static org.junit.Assert.assertNotNull; 11 | import static org.junit.Assert.assertTrue; 12 | import org.junit.Test; 13 | 14 | /** 15 | * 16 | * @author humbertodias 17 | */ 18 | public class DijkstraTest { 19 | 20 | private List nodes; 21 | private List edges; 22 | 23 | @Test 24 | public void testExcute() { 25 | nodes = new ArrayList<>(); 26 | edges = new ArrayList<>(); 27 | for (int i = 0; i < 11; i++) { 28 | Vertex location = new Vertex("Node_" + i, "Node_" + i); 29 | nodes.add(location); 30 | } 31 | 32 | addLane("Edge_0", 0, 1, 85); 33 | addLane("Edge_1", 0, 2, 217); 34 | addLane("Edge_2", 0, 4, 173); 35 | addLane("Edge_3", 2, 6, 186); 36 | addLane("Edge_4", 2, 7, 103); 37 | addLane("Edge_5", 3, 7, 183); 38 | addLane("Edge_6", 5, 8, 250); 39 | addLane("Edge_7", 8, 9, 84); 40 | addLane("Edge_8", 7, 9, 167); 41 | addLane("Edge_9", 4, 9, 502); 42 | addLane("Edge_10", 9, 10, 40); 43 | addLane("Edge_11", 1, 10, 600); 44 | 45 | // Lets check from location Loc_1 to Loc_10 46 | Graph graph = new Graph(nodes, edges); 47 | Dijkstra dijkstra = new Dijkstra(graph); 48 | dijkstra.execute(nodes.get(0)); 49 | LinkedList path = dijkstra.getPath(nodes.get(10)); 50 | 51 | assertNotNull(path); 52 | assertTrue(path.size() > 0); 53 | } 54 | 55 | private void addLane(String laneId, int sourceLocNo, int destLocNo, 56 | int duration) { 57 | Edge lane = new Edge(laneId, nodes.get(sourceLocNo), nodes.get(destLocNo), duration); 58 | edges.add(lane); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/dsa/ai/graph/astar/AStarTest.java: -------------------------------------------------------------------------------- 1 | package dsa.ai.graph.astar; 2 | 3 | import dsa.ai.graph.path.astar.Grid2d; 4 | import dsa.ai.graph.path.astar.Grid2d.MapNode; 5 | import java.util.List; 6 | import org.junit.After; 7 | import org.junit.AfterClass; 8 | import org.junit.Before; 9 | import org.junit.BeforeClass; 10 | import org.junit.Test; 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * https://gist.github.com/benruijl/3385624 15 | */ 16 | public class AStarTest { 17 | 18 | public AStarTest() { 19 | } 20 | 21 | @BeforeClass 22 | public static void setUpClass() { 23 | } 24 | 25 | @AfterClass 26 | public static void tearDownClass() { 27 | } 28 | 29 | @Before 30 | public void setUp() { 31 | } 32 | 33 | @After 34 | public void tearDown() { 35 | } 36 | 37 | // 38 | @Test 39 | public void findPath() { 40 | 41 | double[][] map = {{0, 1, 2}, {3, 3, 2}, {0, -1, 0}}; 42 | Grid2d map2d = new Grid2d(map, false); 43 | List path = map2d.findPath(0, 0, 2, 2); 44 | String found = "[(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)]"; 45 | assertEquals(path.toString(), found); 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/dsa/ai/graph/minimax/MiniMaxTest.java: -------------------------------------------------------------------------------- 1 | package dsa.ai.graph.minimax; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.PrintStream; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.*; 9 | 10 | public class MiniMaxTest { 11 | 12 | @Test 13 | public void minimax() { 14 | 15 | // This section is for testing purposes only, in cases where the 16 | // computer makes a seemingly bad choice. 17 | Board board = new Board(); 18 | board.set(0, Board.MARK_RED); 19 | board.set(0, Board.MARK_RED); 20 | 21 | board.set(1, Board.MARK_BLACK); 22 | board.set(1, Board.MARK_RED); 23 | board.set(1, Board.MARK_BLACK); 24 | board.set(1, Board.MARK_BLACK); 25 | board.set(1, Board.MARK_RED); 26 | board.set(1, Board.MARK_RED); 27 | 28 | board.set(2, Board.MARK_RED); 29 | board.set(2, Board.MARK_RED); 30 | board.set(2, Board.MARK_RED); 31 | board.set(2, Board.MARK_BLACK); 32 | board.set(2, Board.MARK_RED); 33 | 34 | board.set(3, Board.MARK_RED); 35 | board.set(3, Board.MARK_BLACK); 36 | board.set(3, Board.MARK_RED); 37 | board.set(3, Board.MARK_BLACK); 38 | board.set(3, Board.MARK_BLACK); 39 | board.set(3, Board.MARK_BLACK); 40 | 41 | board.set(4, Board.MARK_BLACK); 42 | board.set(4, Board.MARK_RED); 43 | board.set(4, Board.MARK_BLACK); 44 | board.set(4, Board.MARK_RED); 45 | 46 | board.set(6, Board.MARK_BLACK); 47 | board.set(6, Board.MARK_BLACK); 48 | board.set(6, Board.MARK_BLACK); 49 | board.set(6, Board.MARK_RED); 50 | board.set(6, Board.MARK_BLACK); 51 | 52 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 53 | PrintStream out = new PrintStream(baos); 54 | 55 | board.display(out); 56 | 57 | String board1 = "| |X| |O| | | |\n" 58 | + "| |X|X|O| | |O|\n" 59 | + "| |O|O|O|X| |X|\n" 60 | + "| |O|X|X|O| |O|\n" 61 | + "|X|X|X|O|X| |O|\n" 62 | + "|X|O|X|X|O| |O|\n" 63 | + "---------------"; 64 | 65 | assertEquals(board1.trim(), baos.toString().trim()); 66 | 67 | Minimax minimax = new Minimax(board, 8); 68 | char mark = Board.MARK_RED; 69 | int col = minimax.alphaBeta(mark); 70 | // System.out.println("Place in column: " + col); 71 | assertEquals(2, col); 72 | 73 | // System.out.println("Boards analyzed: " + minimax.getBoardsAnalyzed()); 74 | 75 | assertEquals(2494, minimax.getBoardsAnalyzed()); 76 | board.set(col, mark); 77 | board.display(out); 78 | 79 | /* 80 | String board2 = "| |X|X|O| | | |\n" 81 | + "| |X|X|O| | |O|\n" 82 | + "| |O|O|O|X| |X|\n" 83 | + "| |O|X|X|O| |O|\n" 84 | + "|X|X|X|O|X| |O|\n" 85 | + "|X|O|X|X|O| |O|\n" 86 | + "---------------"; 87 | 88 | assertEquals(board2.trim(), baos.toString().trim()); 89 | */ 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/test/java/dsa/graph/BFSTest.java: -------------------------------------------------------------------------------- 1 | package dsa.graph; 2 | 3 | import org.junit.*; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | /** 11 | * 12 | * @author humbertodias 13 | */ 14 | public class BFSTest { 15 | 16 | GraphMatrix graphMatrix; 17 | 18 | public BFSTest() { 19 | } 20 | 21 | @BeforeClass 22 | public static void setUpClass() { 23 | } 24 | 25 | @AfterClass 26 | public static void tearDownClass() { 27 | } 28 | 29 | @Before 30 | public void setUp() { 31 | // 0 1 2 3 4 5 6 7 8 32 | // =================================================== 33 | int [][] conn = { { 0, 1, 0, 1, 0, 0, 0, 0, 1 }, // 0 34 | { 1, 0, 0, 0, 0, 0, 0, 1, 0 }, // 1 35 | { 0, 0, 0, 1, 0, 1, 0, 1, 0 }, // 2 36 | { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, // 3 37 | { 0, 0, 0, 1, 0, 0, 0, 0, 1 }, // 4 38 | { 0, 0, 1, 0, 0, 0, 1, 0, 0 }, // 5 39 | { 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 6 40 | { 0, 1, 1, 0, 0, 0, 0, 0, 0 }, // 7 41 | { 1, 0, 0, 0, 1, 0, 0, 0, 0 } }; 42 | 43 | graphMatrix = new GraphMatrix(conn); 44 | } 45 | 46 | @After 47 | public void tearDown() { 48 | } 49 | 50 | @Test 51 | public void bfs() { 52 | Integer[] walk = {0, 1, 3, 8, 7, 2, 4, 5, 6}; 53 | List bfs = Arrays.asList(walk); 54 | assertEquals(bfs, graphMatrix.bfs() ); 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/dsa/graph/DFSTest.java: -------------------------------------------------------------------------------- 1 | package dsa.graph; 2 | 3 | import org.junit.*; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | public class DFSTest { 11 | 12 | private GraphMatrix graphMatrix; 13 | 14 | public DFSTest() { 15 | } 16 | 17 | @BeforeClass 18 | public static void setUpClass() { 19 | } 20 | 21 | @AfterClass 22 | public static void tearDownClass() { 23 | } 24 | 25 | @Before 26 | public void setUp() { 27 | // 0 1 2 3 4 5 6 7 8 28 | // =================================================== 29 | int [][] conn = { { 0, 1, 0, 1, 0, 0, 0, 0, 1 }, // 0 30 | { 1, 0, 0, 0, 0, 0, 0, 1, 0 }, // 1 31 | { 0, 0, 0, 1, 0, 1, 0, 1, 0 }, // 2 32 | { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, // 3 33 | { 0, 0, 0, 1, 0, 0, 0, 0, 1 }, // 4 34 | { 0, 0, 1, 0, 0, 0, 1, 0, 0 }, // 5 35 | { 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 6 36 | { 0, 1, 1, 0, 0, 0, 0, 0, 0 }, // 7 37 | { 1, 0, 0, 0, 1, 0, 0, 0, 0 } }; 38 | 39 | graphMatrix = new GraphMatrix(conn); 40 | } 41 | 42 | @After 43 | public void tearDown() { 44 | } 45 | 46 | @Test 47 | public void dfs() { 48 | Integer[] walk = {0, 1, 7, 2, 3, 4, 8, 5, 6}; 49 | List dfs = Arrays.asList(walk); 50 | assertEquals(dfs, graphMatrix.dfs() ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/dsa/list/CircularLinkedListTest.java: -------------------------------------------------------------------------------- 1 | package dsa.list; 2 | 3 | import org.junit.*; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class CircularLinkedListTest { 8 | 9 | CircularLinkedList list = new CircularLinkedList(); 10 | int MAX = 10; 11 | 12 | public CircularLinkedListTest() { 13 | } 14 | 15 | @BeforeClass 16 | public static void setUpClass() { 17 | } 18 | 19 | @AfterClass 20 | public static void tearDownClass() { 21 | } 22 | 23 | @Before 24 | public void setUp() { 25 | 26 | for (int i = 0; i < MAX; i++) { 27 | list.addNodeAtEnd(Math.random()); 28 | } 29 | 30 | } 31 | 32 | @After 33 | public void tearDown() { 34 | } 35 | 36 | @Test 37 | public void size() { 38 | assertEquals(list.size(), MAX); 39 | } 40 | 41 | @Test 42 | public void remove() { 43 | list.deleteNodeFromStart(); 44 | assertEquals(list.size(), MAX - 1); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/dsa/list/DoublyLinkedListTest.java: -------------------------------------------------------------------------------- 1 | package dsa.list; 2 | 3 | import org.junit.*; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * 9 | */ 10 | public class DoublyLinkedListTest { 11 | 12 | DoublyLinkedList list = new DoublyLinkedList(); 13 | int MAX = 10; 14 | 15 | public DoublyLinkedListTest() { 16 | } 17 | 18 | @BeforeClass 19 | public static void setUpClass() { 20 | } 21 | 22 | @AfterClass 23 | public static void tearDownClass() { 24 | } 25 | 26 | @Before 27 | public void setUp() { 28 | 29 | for (int i = 0; i < MAX; i++) { 30 | list.addFirst(Math.random()); 31 | } 32 | 33 | } 34 | 35 | @After 36 | public void tearDown() { 37 | } 38 | 39 | @Test 40 | public void size() { 41 | assertEquals(list.size(), MAX); 42 | } 43 | 44 | @Test 45 | public void remove(){ 46 | list.removeFirst(); 47 | assertEquals(list.size(), MAX-1); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/dsa/list/SinglyLinkedListTest.java: -------------------------------------------------------------------------------- 1 | package dsa.list; 2 | 3 | import org.junit.*; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * 9 | */ 10 | public class SinglyLinkedListTest { 11 | 12 | SinglyLinkedList list = new SinglyLinkedList(); 13 | int MAX = 10; 14 | 15 | public SinglyLinkedListTest() { 16 | } 17 | 18 | @BeforeClass 19 | public static void setUpClass() { 20 | } 21 | 22 | @AfterClass 23 | public static void tearDownClass() { 24 | } 25 | 26 | @Before 27 | public void setUp() { 28 | 29 | for (int i = 0; i < MAX; i++) { 30 | list.add(Math.random()); 31 | } 32 | 33 | } 34 | 35 | @After 36 | public void tearDown() { 37 | } 38 | 39 | @Test 40 | public void size() { 41 | assertEquals(list.size(), MAX); 42 | } 43 | 44 | @Test 45 | public void remove() { 46 | list.deleteFront(); 47 | assertEquals(list.size(), MAX - 1); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/dsa/queue/MaxPQTest.java: -------------------------------------------------------------------------------- 1 | package dsa.queue; 2 | 3 | import dsa.queue.priority.MaxPQ; 4 | import org.junit.After; 5 | import org.junit.AfterClass; 6 | import org.junit.Before; 7 | import org.junit.BeforeClass; 8 | import org.junit.Test; 9 | import static org.junit.Assert.*; 10 | 11 | public class MaxPQTest { 12 | 13 | MaxPQ queue = new MaxPQ(); 14 | 15 | @BeforeClass 16 | public static void setUpClass() { 17 | 18 | } 19 | 20 | @AfterClass 21 | public static void tearDownClass() { 22 | } 23 | 24 | @Before 25 | public void setUp() { 26 | 27 | queue.insert(1); 28 | queue.insert(2); 29 | queue.insert(3); 30 | queue.insert(4); 31 | 32 | } 33 | 34 | @After 35 | public void tearDown() { 36 | } 37 | 38 | @Test 39 | public void size() { 40 | assertEquals(queue.size(), 4); 41 | } 42 | 43 | @Test 44 | public void insert() { 45 | queue.insert(5); 46 | assertEquals(queue.size(), 5); 47 | } 48 | 49 | @Test 50 | public void dequeue() { 51 | Object last = queue.delMax(); 52 | assertEquals(last, 4); 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/test/java/dsa/queue/MinPQTest.java: -------------------------------------------------------------------------------- 1 | package dsa.queue; 2 | 3 | import dsa.queue.priority.MinPQ; 4 | import org.junit.After; 5 | import org.junit.AfterClass; 6 | import org.junit.Before; 7 | import org.junit.BeforeClass; 8 | import org.junit.Test; 9 | import static org.junit.Assert.*; 10 | 11 | public class MinPQTest { 12 | 13 | MinPQ queue = new MinPQ(); 14 | 15 | @BeforeClass 16 | public static void setUpClass() { 17 | 18 | } 19 | 20 | @AfterClass 21 | public static void tearDownClass() { 22 | } 23 | 24 | @Before 25 | public void setUp() { 26 | 27 | queue.insert(4); 28 | queue.insert(3); 29 | queue.insert(2); 30 | queue.insert(1); 31 | 32 | } 33 | 34 | @After 35 | public void tearDown() { 36 | } 37 | 38 | @Test 39 | public void size() { 40 | assertEquals(queue.size(), 4); 41 | } 42 | 43 | @Test 44 | public void insert() { 45 | queue.insert(5); 46 | assertEquals(queue.size(), 5); 47 | } 48 | 49 | @Test 50 | public void dequeue() { 51 | Object last = queue.delMin(); 52 | assertEquals(last, 1); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/dsa/queue/QueueArrayTest.java: -------------------------------------------------------------------------------- 1 | package dsa.queue; 2 | 3 | import org.junit.*; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class QueueArrayTest { 8 | 9 | QueueArray queue = new QueueArray(); 10 | 11 | @BeforeClass 12 | public static void setUpClass() { 13 | 14 | } 15 | 16 | @AfterClass 17 | public static void tearDownClass() { 18 | } 19 | 20 | @Before 21 | public void setUp() { 22 | 23 | queue.enqueue(1); 24 | queue.enqueue(2); 25 | queue.enqueue(3); 26 | queue.enqueue(4); 27 | 28 | } 29 | 30 | @After 31 | public void tearDown() { 32 | } 33 | 34 | @Test 35 | public void size() { 36 | assertEquals(queue.size(), 4); 37 | } 38 | 39 | @Test 40 | public void enqueue() { 41 | queue.enqueue(5); 42 | assertEquals(queue.size(), 5); 43 | } 44 | 45 | @Test 46 | public void dequeue() { 47 | Object last = queue.dequeue(); 48 | assertEquals(last, 1); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/dsa/search/BinarySearchTest.java: -------------------------------------------------------------------------------- 1 | package dsa.search; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class BinarySearchTest { 9 | 10 | @Test 11 | public void testContains() { 12 | Integer[] a = {1, 2, 3, 4, 5, 7, 17, 19}; 13 | assertTrue(BinarySearch.contains(a, 17)); 14 | assertTrue(BinarySearch.contains(a, 1)); 15 | assertTrue(BinarySearch.contains(a, 2)); 16 | assertTrue(BinarySearch.contains(a, 3)); 17 | assertTrue(BinarySearch.contains(a, 4)); 18 | assertFalse(BinarySearch.contains(a, 10)); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /src/test/java/dsa/search/SequentialSearchTest.java: -------------------------------------------------------------------------------- 1 | package dsa.search; 2 | 3 | import static org.junit.Assert.assertFalse; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import org.junit.Test; 7 | 8 | public class SequentialSearchTest { 9 | 10 | @Test 11 | public void testContains() { 12 | Integer[] a = {1, 2, 3, 4, 5, 19, 17, 7}; 13 | assertTrue(SequentialSearch.contains(a, 17)); 14 | assertTrue(SequentialSearch.contains(a, 1)); 15 | assertTrue(SequentialSearch.contains(a, 2)); 16 | assertTrue(SequentialSearch.contains(a, 3)); 17 | assertTrue(SequentialSearch.contains(a, 4)); 18 | assertFalse(SequentialSearch.contains(a, 10)); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/dsa/sort/AllSortTest.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.junit.runners.Suite; 5 | 6 | @RunWith(Suite.class) 7 | @Suite.SuiteClasses({BubbleSortTest.class, SelectionSortTest.class, InsertionSortTest.class, MergeSortTest.class, ShellSortTest.class, HeapSortTest.class, QuickSortTest.class, RadixSortTest.class}) 8 | public class AllSortTest { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/test/java/dsa/sort/BubbleSortTest.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | import java.util.Arrays; 4 | import org.junit.Assert; 5 | 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import static org.junit.Assert.assertArrayEquals; 10 | 11 | public class BubbleSortTest { 12 | 13 | BubbleSort sorter = new BubbleSort(); 14 | Integer[] input = {24, 2, 45, 20, 56, 75, 2, 56, 99, 53, 12}; 15 | 16 | @Before 17 | public void setUp() { 18 | } 19 | 20 | @Test 21 | public void sort() { 22 | Integer[] expected = input.clone(); 23 | Arrays.sort(expected); 24 | Integer[] sorted = input.clone(); 25 | sorter.sort(sorted); 26 | assertArrayEquals(expected, sorted); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/dsa/sort/HeapSortTest.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | import java.util.Arrays; 4 | import org.junit.Assert; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.assertArrayEquals; 9 | 10 | public class HeapSortTest { 11 | 12 | QuickSort sorter = new QuickSort(); 13 | Integer[] input = {24, 2, 45, 20, 56, 75, 2, 56, 99, 53, 12}; 14 | 15 | @Before 16 | public void setUp() { 17 | } 18 | 19 | @Test 20 | public void sort() { 21 | Integer[] expected = input.clone(); 22 | Arrays.sort(expected); 23 | Integer[] sorted = input.clone(); 24 | sorter.sort(sorted); 25 | assertArrayEquals(expected, sorted); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/dsa/sort/InsertionSortTest.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | import java.util.Arrays; 4 | import org.junit.Assert; 5 | 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import static org.junit.Assert.assertArrayEquals; 10 | 11 | public class InsertionSortTest { 12 | 13 | InsertionSort sorter = new InsertionSort(); 14 | Integer[] input = {24, 2, 45, 20, 56, 75, 2, 56, 99, 53, 12}; 15 | 16 | @Before 17 | public void setUp() { 18 | } 19 | 20 | @Test 21 | public void sort() { 22 | Integer[] expected = input.clone(); 23 | Arrays.sort(expected); 24 | Integer[] sorted = input.clone(); 25 | sorter.sort(sorted); 26 | assertArrayEquals(expected, sorted); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/dsa/sort/MergeSortTest.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | 4 | import java.util.Arrays; 5 | import org.junit.Assert; 6 | 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | import static org.junit.Assert.assertArrayEquals; 11 | 12 | 13 | public class MergeSortTest { 14 | 15 | MergeSort sorter = new MergeSort(); 16 | Integer[] input = {24, 2, 45, 20, 56, 75, 2, 56, 99, 53, 12}; 17 | 18 | @Before 19 | public void setUp() { 20 | } 21 | 22 | @Test 23 | public void sort() { 24 | Integer[] expected = input.clone(); 25 | Arrays.sort(expected); 26 | Integer[] sorted = input.clone(); 27 | sorter.sort(sorted); 28 | assertArrayEquals(expected, sorted); 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/dsa/sort/QuickSortTest.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | import java.util.Arrays; 4 | import org.junit.Assert; 5 | 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import static org.junit.Assert.assertArrayEquals; 10 | 11 | public class QuickSortTest { 12 | 13 | QuickSort sorter = new QuickSort(); 14 | Integer[] input = {24, 2, 45, 20, 56, 75, 2, 56, 99, 53, 12}; 15 | 16 | @Before 17 | public void setUp() { 18 | } 19 | 20 | @Test 21 | public void sort() { 22 | Integer[] expected = input.clone(); 23 | Arrays.sort(expected); 24 | Integer[] sorted = input.clone(); 25 | sorter.sort(sorted); 26 | assertArrayEquals(expected, sorted); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/dsa/sort/RadixSortTest.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | import java.util.Arrays; 4 | import org.junit.Assert; 5 | 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import static org.junit.Assert.assertArrayEquals; 10 | 11 | public class RadixSortTest { 12 | 13 | RadixSort sorter = new RadixSort(); 14 | Integer[] input = {24, 2, 45, 20, 56, 75, 2, 56, 99, 53, 12}; 15 | 16 | @Before 17 | public void setUp() { 18 | } 19 | 20 | @Test 21 | public void sort() { 22 | Integer[] expected = input.clone(); 23 | Arrays.sort(expected); 24 | Integer[] sorted = input.clone(); 25 | sorter.sort(sorted); 26 | assertArrayEquals(expected, sorted); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/dsa/sort/SelectionSortTest.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | import java.util.Arrays; 4 | import org.junit.Assert; 5 | 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import static org.junit.Assert.assertArrayEquals; 10 | 11 | public class SelectionSortTest { 12 | 13 | SelectionSort sorter = new SelectionSort(); 14 | Integer[] input = {24, 2, 45, 20, 56, 75, 2, 56, 99, 53, 12}; 15 | 16 | @Before 17 | public void setUp() { 18 | } 19 | 20 | @Test 21 | public void sort() { 22 | Integer[] expected = input.clone(); 23 | Arrays.sort(expected); 24 | Integer[] sorted = input.clone(); 25 | sorter.sort(sorted); 26 | assertArrayEquals(expected, sorted); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/dsa/sort/ShellSortTest.java: -------------------------------------------------------------------------------- 1 | package dsa.sort; 2 | 3 | import java.util.Arrays; 4 | import org.junit.Assert; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.assertArrayEquals; 9 | 10 | public class ShellSortTest { 11 | 12 | ShellSort sorter = new ShellSort(); 13 | Integer[] input = {24, 2, 45, 20, 56, 75, 2, 56, 99, 53, 12}; 14 | 15 | @Before 16 | public void setUp() { 17 | } 18 | 19 | @Test 20 | public void sort() { 21 | Integer[] expected = input.clone(); 22 | Arrays.sort(expected); 23 | Integer[] sorted = input.clone(); 24 | sorter.sort(sorted); 25 | assertArrayEquals(expected, sorted); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/dsa/stack/StackArrayTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package dsa.stack; 7 | 8 | import org.junit.*; 9 | 10 | import static org.junit.Assert.assertEquals; 11 | 12 | 13 | public class StackArrayTest { 14 | 15 | StackArray stack = new StackArray(); 16 | 17 | public StackArrayTest() { 18 | } 19 | 20 | @BeforeClass 21 | public static void setUpClass() { 22 | 23 | } 24 | 25 | @AfterClass 26 | public static void tearDownClass() { 27 | } 28 | 29 | @Before 30 | public void setUp() { 31 | 32 | stack.push(1); 33 | stack.push(2); 34 | stack.push(3); 35 | stack.push(4); 36 | 37 | } 38 | 39 | @After 40 | public void tearDown() { 41 | } 42 | 43 | @Test 44 | public void size() { 45 | assertEquals(stack.size(), 4); 46 | } 47 | 48 | @Test 49 | public void push() { 50 | stack.push(5); 51 | assertEquals(stack.size(), 5); 52 | } 53 | 54 | @Test 55 | public void pop() { 56 | stack.push(6); 57 | Object last = stack.pop(); 58 | assertEquals(last, 6); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/dsa/tree/AVLTreeTest.java: -------------------------------------------------------------------------------- 1 | package dsa.tree; 2 | 3 | import dsa.tree.avl.AVLTree; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.PrintStream; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class AVLTreeTest { 12 | 13 | AVLTree tree = new AVLTree(); 14 | 15 | @Before 16 | public void setUp() { 17 | for (int i = 1; i < 10; i++) { 18 | tree.insert(i); 19 | } 20 | 21 | } 22 | 23 | @Test 24 | public void insert() { 25 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 26 | PrintStream out = new PrintStream(baos); 27 | tree.printBalance(out); 28 | String expected = "0 0 0 1 0 1 0 0 0 "; 29 | assertEquals(expected, baos.toString()); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/dsa/tree/BSTTreeTest.java: -------------------------------------------------------------------------------- 1 | package dsa.tree; 2 | 3 | import dsa.tree.bst.BinarySearchTree; 4 | import org.junit.After; 5 | import org.junit.AfterClass; 6 | import org.junit.Before; 7 | import org.junit.BeforeClass; 8 | import org.junit.Test; 9 | import static org.junit.Assert.*; 10 | 11 | public class BSTTreeTest { 12 | 13 | BinarySearchTree t = new BinarySearchTree(); 14 | 15 | public BSTTreeTest() { 16 | } 17 | 18 | @BeforeClass 19 | public static void setUpClass() { 20 | 21 | } 22 | 23 | @AfterClass 24 | public static void tearDownClass() { 25 | } 26 | 27 | @Before 28 | public void setUp() { 29 | t.insert(1); 30 | t.insert(2); 31 | t.insert(3); 32 | t.insert(4); 33 | } 34 | 35 | @After 36 | public void tearDown() { 37 | } 38 | 39 | @Test 40 | public void size() { 41 | assertEquals(t.countNodes(), 4); 42 | } 43 | 44 | @Test 45 | public void preorder() { 46 | assertEquals(t.preorder().toString(), "[1, 2, 3, 4]"); 47 | } 48 | 49 | @Test 50 | public void postorder() { 51 | assertEquals(t.postorder().toString(), "[4, 3, 2, 1]"); 52 | } 53 | 54 | @Test 55 | public void inorder() { 56 | assertEquals(t.inorder().toString(), "[1, 2, 3, 4]"); 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /src/test/java/dsa/tree/HuffmanTreeTest.java: -------------------------------------------------------------------------------- 1 | package dsa.tree; 2 | 3 | import dsa.tree.huffman.BitStream; 4 | import dsa.tree.huffman.HuffmanTree; 5 | import java.io.FileNotFoundException; 6 | import java.io.IOException; 7 | import java.util.Arrays; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | public class HuffmanTreeTest { 14 | 15 | String testString = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " 16 | + "ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " 17 | + "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in " 18 | + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat " 19 | + "non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; 20 | 21 | int[] frequencies; 22 | HuffmanTree ht; 23 | BitStream encoded; 24 | 25 | @Before 26 | public void setup() { 27 | // get frequency array 28 | frequencies = HuffmanTree.getFrequencies(testString); 29 | 30 | // create huffman tree from frequencies 31 | ht = new HuffmanTree(frequencies); 32 | 33 | encoded = ht.encode(testString); 34 | 35 | } 36 | 37 | @Test 38 | public void textLength() { 39 | assertEquals(445, testString.length()); 40 | } 41 | 42 | @Test 43 | public void frequencyArray() { 44 | String sfrequencies = "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 3, 16, 18, 37, 3, 3, 1, 42, 0, 0, 21, 17, 24, 29, 11, 5, 22, 18, 32, 28, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"; 45 | assertEquals(sfrequencies, Arrays.toString(frequencies)); 46 | } 47 | 48 | @Test 49 | public void displayCodes() { 50 | String codes = "32 : 110\n" 51 | + "44 : 0101111\n" 52 | + "46 : 000000\n" 53 | + "68 : 000011010\n" 54 | + "69 : 000011011\n" 55 | + "76 : 00001000\n" 56 | + "85 : 00001001\n" 57 | + "97 : 1000\n" 58 | + "98 : 0101100\n" 59 | + "99 : 10110\n" 60 | + "100 : 11101\n" 61 | + "101 : 1111\n" 62 | + "102 : 0101101\n" 63 | + "103 : 0101110\n" 64 | + "104 : 00001100\n" 65 | + "105 : 001\n" 66 | + "108 : 0001\n" 67 | + "109 : 10111\n" 68 | + "110 : 0110\n" 69 | + "111 : 1001\n" 70 | + "112 : 01010\n" 71 | + "113 : 000001\n" 72 | + "114 : 0100\n" 73 | + "115 : 11100\n" 74 | + "116 : 1010\n" 75 | + "117 : 0111\n" 76 | + "118 : 0000111\n" 77 | + "120 : 0000101\n"; 78 | assertEquals(codes, ht.displayCodes()); 79 | } 80 | 81 | @Test 82 | public void encodeDecode() throws FileNotFoundException, IOException { 83 | 84 | // get BitStream of tree 85 | BitStream bs = ht.getEncodedTree(); 86 | 87 | String bbs = bs.toString(); 88 | assertEquals("\n2 5d 71 14 ca ad e0 b4 28 94 5b b5 b2 d2 5c 97 2 c5 66 59 e5 8b 75 d4 \n58 6d eb a2 c7 6d 48 b 9d 92 ca 1 ", bbs); 89 | 90 | int treelen = bs.getBank().length; 91 | assertEquals(36, treelen); 92 | 93 | // encode string to bitstream 94 | BitStream os = ht.encode(testString); 95 | 96 | String oos = "\n8 94 fb e2 ae 3d f7 64 65 37 d 68 bf d2 fd 69 6e 7d ab e9 d3 47 4a 8f \n" 97 | + "2c 59 76 f1 34 bf 73 fb bb 3b cb f2 f3 dd 5f 75 4a 62 d6 3d 3d 76 ac f5 \n" 98 | + "86 16 4a 7e fa dd 91 94 fd 78 5c d1 a0 48 2f 0 60 9a de c6 fa 3b ae 58 \n" 99 | + "df 7 f6 31 75 f8 17 3c cd 3c a4 7e ef b e9 63 51 46 5b 38 8c 5e d3 86 \n" 100 | + "16 4a 1e 66 3c 39 eb 40 90 5c ab 78 5d f1 ad 37 bc f6 75 a5 b9 e0 bc 50 \n" 101 | + "18 34 e7 9a 1e bf 14 74 fd d9 19 4c 5b 27 a9 3c 33 db be 86 b1 6c 1e 45 \n" 102 | + "d5 51 5f 83 f8 9a df ce 7e b1 11 7b ee c8 ca 7e f7 cb 5d 71 8a cc e2 31 \n" 103 | + "95 8 62 9d 0 c1 b0 b6 f5 57 ba 6e 16 ad 36 b4 7d a2 b5 9d 47 b1 51 59 \n" 104 | + "a5 b2 92 4f 7d a9 7e e3 b5 62 da ce 2a 8c b 9d 2b 56 9b 18 dd fe 7a 3b \n" 105 | + "56 bc 88 9a d0 c6 f8 f7 7f 2b c 2c 94 7b 80 1 "; 106 | assertEquals(oos, os.toString()); 107 | 108 | int datalen = os.getBank().length; 109 | assertEquals(232, datalen); 110 | 111 | int compressedLength = (datalen + treelen); 112 | assertEquals(268, compressedLength); 113 | 114 | int orig = testString.length(); 115 | int compressedPercent = (int) (((float) (orig - treelen - datalen) / orig) * 100); 116 | assertEquals(39, compressedPercent); 117 | 118 | // re-create huffman tree from encoded bitstream 119 | HuffmanTree dt = new HuffmanTree(bs); 120 | 121 | String codes = "32 : 110\n" 122 | + "44 : 0101111\n" 123 | + "46 : 000000\n" 124 | + "68 : 000011010\n" 125 | + "69 : 000011011\n" 126 | + "76 : 00001000\n" 127 | + "85 : 00001001\n" 128 | + "97 : 1000\n" 129 | + "98 : 0101100\n" 130 | + "99 : 10110\n" 131 | + "100 : 11101\n" 132 | + "101 : 1111\n" 133 | + "102 : 0101101\n" 134 | + "103 : 0101110\n" 135 | + "104 : 00001100\n" 136 | + "105 : 001\n" 137 | + "108 : 0001\n" 138 | + "109 : 10111\n" 139 | + "110 : 0110\n" 140 | + "111 : 1001\n" 141 | + "112 : 01010\n" 142 | + "113 : 000001\n" 143 | + "114 : 0100\n" 144 | + "115 : 11100\n" 145 | + "116 : 1010\n" 146 | + "117 : 0111\n" 147 | + "118 : 0000111\n" 148 | + "120 : 0000101\n"; 149 | 150 | assertEquals(codes, dt.displayCodes()); 151 | 152 | // decode back to string 153 | String output = dt.decode(os); 154 | assertEquals(testString, output); 155 | } 156 | 157 | @Test 158 | public void decode() { 159 | String decoded = ht.decode(encoded); 160 | assertEquals(testString, decoded); 161 | } 162 | 163 | @Test 164 | public void encode() { 165 | assertEquals(encoded, ht.encode(testString)); 166 | } 167 | 168 | } --------------------------------------------------------------------------------