├── .DS_Store
├── .github
├── CODEOWNERS
└── workflows
│ ├── codeql-analysis.yml
│ └── go.yml
├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── adjaceny-list-graph
├── adjacency-list-graph.go
└── adjacency-list-graph_test.go
├── allpairs
├── allpairs.go
└── allpairs_test.go
├── bst
├── binarySearchTree.go
└── binarySearchTree_test.go
├── btree
├── btree.go
└── btree_test.go
├── bubblesort
├── bubblesort.go
└── bubblesort_test.go
├── convexHull
├── convexHull.go
└── convexHull_test.go
├── doc
├── gopher.jpg
└── logo.png
├── graph
├── graph.go
└── graph_test.go
├── heapsort
├── heapsort.go
└── heapsort_test.go
├── insertsort
├── insertsort.go
└── insertsort_test.go
├── knuthMorrisPratt
├── knuthMorrisPratt.go
└── knuthMorrisPratt_test.go
├── kruskal
├── dsu.go
├── dsu_test.go
├── kruskal.go
└── kruskal_test.go
├── linked-list
├── linked-list.go
└── linked-list_test.go
├── ludecomposition
├── ludecomposition.go
└── ludecomposition_test.go
├── mergesort
├── mergesort.go
└── mergesort_test.go
├── qsort
├── qsort.go
└── qsort_test.go
├── queuestack
├── queue.go
├── queue_test.go
├── stack.go
└── stack_test.go
├── rabinkarp
├── rabinkarp.go
└── rabinkarp_test.go
├── rbtree
├── rbtree.go
└── rbtree_test.go
└── stack
├── stack.go
└── stack_test.go
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ch3ck/algo/5aae7fab9e3d6ebca20ee30441c232f43815b89b/.DS_Store
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # CODE OWNERS
2 |
3 | * @ch3ck
4 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # ******** NOTE ********
2 | # We have attempted to detect the languages in your repository. Please check
3 | # the `language` matrix defined below to confirm you have the correct set of
4 | # supported CodeQL languages.
5 | #
6 | name: "CodeQL"
7 |
8 | on:
9 | push:
10 | branches: [ master ]
11 | pull_request:
12 | # The branches below must be a subset of the branches above
13 | branches: [ master ]
14 | schedule:
15 | - cron: '35 22 * * 3'
16 |
17 | jobs:
18 | analyze:
19 | name: Analyze
20 | runs-on: ubuntu-latest
21 | permissions:
22 | actions: read
23 | contents: read
24 | security-events: write
25 |
26 | strategy:
27 | fail-fast: false
28 | matrix:
29 | language: [ 'go' ]
30 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
31 | # Learn more about CodeQL language support at https://git.io/codeql-language-support
32 |
33 | steps:
34 | - name: Checkout repository
35 | uses: actions/checkout@v2
36 |
37 | # Initializes the CodeQL tools for scanning.
38 | - name: Initialize CodeQL
39 | uses: github/codeql-action/init@v1
40 | with:
41 | languages: ${{ matrix.language }}
42 | # If you wish to specify custom queries, you can do so here or in a config file.
43 | # By default, queries listed here will override any specified in a config file.
44 | # Prefix the list here with "+" to use these queries and those in the config file.
45 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
46 |
47 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
48 | # If this step fails, then you should remove it and run the build manually (see below)
49 | - name: Autobuild
50 | uses: github/codeql-action/autobuild@v1
51 |
52 | # ℹ️ Command-line programs to run using the OS shell.
53 | # 📚 https://git.io/JvXDl
54 |
55 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
56 | # and modify them (or add more) to build your code if your project
57 | # uses a compiled language
58 |
59 | #- run: |
60 | # make bootstrap
61 | # make release
62 |
63 | - name: Perform CodeQL Analysis
64 | uses: github/codeql-action/analyze@v1
65 |
--------------------------------------------------------------------------------
/.github/workflows/go.yml:
--------------------------------------------------------------------------------
1 | name: Go
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 |
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v2
15 |
16 | - name: Set up Go
17 | uses: actions/setup-go@v2
18 | with:
19 | go-version: 1.17
20 |
21 | - name: Build
22 | run: go build -v ./...
23 |
24 | - name: Test
25 | run: go test -v ./...
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files, Static and Dynamic libs (Shared Objects)
2 | *.o
3 | *.a
4 | *.so
5 |
6 | # Folders
7 | _obj
8 | _test
9 |
10 | # Architecture specific extensions/prefixes
11 | *.[568vq]
12 | [568vq].out
13 |
14 | *.cgo1.go
15 | *.cgo2.c
16 | _cgo_defun.c
17 | _cgo_gotypes.go
18 | _cgo_export.*
19 |
20 | _testmain.go
21 |
22 | *.exe
23 | *.test
24 | *.prof
25 | .idea
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 |
3 | before_install:
4 | - go get -u github.com/golang/lint/golint
5 | - golint ./...
6 | # - go vet ./...
7 | - diff -u <(echo-n) <(gofmt -s -d .)
8 |
9 | install:
10 | - go get -u -v $((go list -f '{{join .TestImports "\n"}}' ./... && go list -f '{{join .Imports "\n"}}' ./...) | sort | uniq | grep -v AlGo)
11 |
12 | script:
13 | - go test ./...
14 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Algo
2 |
3 | Want to hack on Algo? Awesome! We have a contributor's guide that explains
4 | how to add new features to this repository.
5 |
6 | 
7 |
8 | This page contains information about reporting issues as well as some tips and
9 | guidelines useful to experienced open source contributors. Finally, make sure
10 | you read through before you start participating.
11 |
12 |
13 | ## Topics
14 |
15 | * [Data Structures](#)
16 | * [Algorithms](#)
17 |
18 | We have different Data structures and algorithms in mind which we created in the
19 | issues.
20 |
21 | Create a new 'package' for each new Data structure or Algorithm with it's unit test
22 | integrated in the /test directory. This test should easily be called and tested
23 | from the main package
24 |
25 |
26 | ### Conventions
27 |
28 | Fork the repository and make changes on your fork in a feature branch:
29 |
30 | - If it's a bug fix branch, name it XXXX-something where XXXX is the number of
31 | the issue.
32 | - If it's a feature branch, create an enhancement issue to announce
33 | your intentions, and name it XXXX-something where XXXX is the number of the
34 | issue.
35 |
36 | Submit unit tests for your changes. Go has a great test framework built in; use
37 | it! Take a look at existing tests for inspiration. Run the test on your branch before
38 | submitting a pull request.
39 |
40 | Update the documentation when creating or modifying features. Test your
41 | documentation changes for clarity, concision, and correctness, as well as a
42 | clean documentation build.
43 |
44 | Write clean code. Universally formatted code promotes ease of writing, reading,
45 | and maintenance. Always run `gofmt -s -w file.go` on each changed file before
46 | committing your changes. Most editors have plug-ins that do this automatically.
47 |
48 | Pull request descriptions should be as clear as possible and include a reference
49 | to all the issues that they address.
50 |
51 | Commit messages must start with a capitalized and short summary (max. 50 chars)
52 | written in the imperative, followed by an optional, more detailed explanatory
53 | text which is separated from the summary by an empty line.
54 |
55 | Code review comments may be added to your pull request. Discuss, then make the
56 | suggested modifications and push additional commits to your feature branch. Post
57 | a comment after pushing. New commits show up in the pull request automatically,
58 | but the reviewers are notified only when you comment.
59 |
60 | Pull requests must be cleanly rebased on top of master without multiple branches
61 | mixed into the PR.
62 |
63 | **Git tip**: If your PR no longer merges cleanly, use `rebase master` in your
64 | feature branch to update your pull request rather than `merge master`.
65 |
66 |
67 | Include an issue reference like `Closes #XXXX` or `Fixes #XXXX` in commits that
68 | close an issue. Including references automatically closes the issue on a merge.
69 |
70 | Please do not add yourself to the `AUTHORS` file, as it is regenerated regularly
71 | from the Git history.
72 |
73 | Please see the [Coding Style](#coding-style) for further guidelines.
74 |
75 |
76 | ## Sign your work
77 |
78 | The sign-off is a simple line at the end of the explanation for the patch. Your
79 | signature certifies that you wrote the patch or otherwise have the right to pass
80 | it on as an open-source patch. The rules are pretty simple: if you can certify
81 | the below (from [developercertificate.org](http://developercertificate.org/)).
82 |
83 |
84 |
85 | ## Communication guidelines
86 |
87 | We want to keep things awesome, growing and collaborative. We need
88 | your help to keep it that way. To help with this we've come up with some general
89 | guidelines for the community as a whole:
90 |
91 | * Be nice: Be courteous, respectful and polite to fellow community members:
92 | no regional, racial, gender, or other abuse will be tolerated. We like
93 | nice people way better than mean ones!
94 |
95 | * Encourage diversity and participation: Make everyone in our community feel
96 | welcome, regardless of their background and the extent of their
97 | contributions, and do everything possible to encourage participation in
98 | our community.
99 |
100 | * Keep it legal: Basically, don't get us in trouble. Share only content that
101 | you own, do not share private or sensitive information, and don't break
102 | the law.
103 |
104 | * Stay on topic: Make sure that you are posting to the correct channel and
105 | avoid off-topic discussions. Remember when you update an issue or respond
106 | to an email you are potentially sending to a large number of people. Please
107 | consider this before you update. Also remember that nobody likes spam.
108 |
109 |
110 | ## Coding Style
111 |
112 | Unless explicitly stated, we follow all coding guidelines from the Go
113 | community. While some of these standards may seem arbitrary, they somehow seem
114 | to result in a solid, consistent codebase.
115 |
116 | It is possible that the code base does not currently comply with these
117 | guidelines. We are not looking for a massive PR that fixes this, since that
118 | goes against the spirit of the guidelines. All new contributions should make a
119 | best effort to clean up and make the code base better than they left it.
120 | Obviously, apply your best judgement. Remember, the goal here is to make the
121 | code base easier for humans to navigate and understand. Always keep that in
122 | mind when nudging others to comply.
123 |
124 | The rules:
125 |
126 | 1. All code should be formatted with `gofmt -s`.
127 | 2. Comment the code. Tell us the why, the history and the context.
128 | 3. Document _all_ declarations and methods, even private ones. Declare
129 | expectations, caveats and anything else that may be important. If a type
130 | gets exported, having the comments already there will ensure it's ready.
131 |
132 |
133 | ## Questions
134 |
135 | If you have any further questions please feel free to reach out to [Nyah Check](nyah@ch3ck.me)
136 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Nyah Check
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AlGo [](https://goreportcard.com/report/github.com/Ch3ck/Algo) [](https://travis-ci.org/Ch3ck/AlGo) [](https://github.com/Ch3ck/AlGo/issues) [](https://github.com/Ch3ck/AlGo/stargazers)
2 | AlGo was created by, and is maintained by [Nyah Check](https://github.com/Ch3ck), and it's the Golang implementation of the Data Structures and Algorithms as referred in CLRS.
3 |
4 | Feel free to check out the [license](LICENSE), and make contributions by pull requests.
5 |
6 | ## Contributing
7 |
8 | Star and Fork this repo; then follow the instructions in [Contributing.md](CONTRIBUTING.md)
9 |
10 | ## Talking to other Devs and Contributors
11 |
12 |
13 |
14 |
15 |
16 | Internet Relay Chat (IRC) |
17 |
18 |
19 | IRC is a direct line to our most Algo contributors; we have
20 | both the #ublab group on
21 | irc.freenode.net.
22 | IRC is a rich chat protocol but it can overwhelm new users. You can search
23 | our chat archives.
24 |
25 | |
26 | Twitter |
27 |
28 | You can follow Algo Maintainer
29 | to get updates; You can also tweet us questions or just
30 | share blogs or stories.
31 | |
32 |
33 |
34 |
35 | ## License
36 |
37 | [](https://raw.githubusercontent.com/Ch3ck/AlGo/master/LICENSE)
38 |
39 | 
40 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Use this section to tell people about which versions of your project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | 5.1.x | :white_check_mark: |
11 | | 5.0.x | :x: |
12 | | 4.0.x | :white_check_mark: |
13 | | < 4.0 | :x: |
14 |
15 | ## Reporting a Vulnerability
16 |
17 | Use this section to tell people how to report a vulnerability.
18 |
19 | Tell them where to go, how often they can expect to get an update on a
20 | reported vulnerability, what to expect if the vulnerability is accepted or
21 | declined, etc.
22 |
--------------------------------------------------------------------------------
/adjaceny-list-graph/adjacency-list-graph.go:
--------------------------------------------------------------------------------
1 | // SUMMARY
2 | //
3 | // This module implements a graph data structure using the adjacency
4 | // list implementation as defined by Goodrich, Tamassia & Goldwasser (2014)
5 | // in [1]. This implementation however makes some changes; most notably
6 | // is the use of a map data structure for the `primary structure` that holds
7 | // the vertices as compared to the array based data structure the authors suggested.
8 | // The Graph Abstract Data Type implemented is the same as the the one proposed
9 | // by the authors.
10 | //
11 | // As suggested by the authors, each vertex in the graph uses an will have
12 | // both outgoing and incoming list of edges, since the graph is directed.
13 | //
14 | //
15 | // REFERENCE
16 | //
17 | // [1] Goodrich, M. T., Tamassia, R., & Goldwasser, M. H. (2014).
18 | // Data structures and algorithms in Java. John Wiley & Sons.
19 |
20 | package adjaceny_list_graph
21 |
22 | import (
23 | "github.com/Ch3ck/AlGo/queuestack"
24 | )
25 |
26 | // A vertex (or node) in the graph.
27 | // Each vertex has the following attributes:
28 | //
29 | // id (int): a number to help access the node in O(1) time
30 | // item (interface): the item stored in the vertex
31 | // outgoingEdges (list.List): a list of the vertices, that along
32 | // with the current vertex form an outgoing edge.
33 | // incomingEdges (list.List): a list of the vertices, that along
34 | // with the current vertex form an outgoing edge.
35 | type vertex struct {
36 | id int
37 | item interface{}
38 | outgoingEdges []*edge
39 | incomingEdges []*edge
40 | }
41 |
42 | // An edge in the directed graph.
43 | // Each edge is represented as a 2-tuple struct that has the following attributes
44 | //
45 | // weight (interface): a value denoted the weight of an edge (when dealing with weighted graphs).
46 | // It is set to nil for unweighted graphs.
47 | // fromVertex (vertex): the vertex this edge starts from. The outgoing vertex.
48 | // toVertex (vertex): the vertex this edge is incident on. The incoming vertex.
49 | type edge struct {
50 | id int
51 | weight interface{}
52 | fromVertex *vertex
53 | toVertex *vertex
54 | }
55 |
56 | func NewEdge() *edge {
57 | return &edge{
58 | 0,
59 | "sugar",
60 | new(vertex),
61 | new(vertex),
62 | }
63 | }
64 |
65 | // The Directed Adjacency List Graph.
66 | //
67 | // ATTRIBUTES
68 | //
69 | // primaryStructure (map[int]vertex): holds the vertices in the graph. A map is used
70 | // because it provides O(1) access to a node.
71 | // numVertices (int): The total number of vertices in the graph.
72 | // numEdges (int): The total number of edges in the graph.
73 | type DirectedAdjacencyListGraph struct {
74 | primaryStructure map[int]*vertex
75 | numVertices int
76 | numEdges int
77 | }
78 |
79 | func NewDALGraph() *DirectedAdjacencyListGraph {
80 | return &DirectedAdjacencyListGraph{
81 | make(map[int]*vertex),
82 | 0,
83 | 0,
84 | }
85 | }
86 |
87 | // NumVertices returns the total number of vertices currently in the graph.
88 | func (dalg *DirectedAdjacencyListGraph) NumVertices() int {
89 | return dalg.numVertices
90 | }
91 |
92 | // NumEdges returns the total number of edges currently in the graph.
93 | func (dalg *DirectedAdjacencyListGraph) NumEdges() int {
94 | return dalg.numEdges
95 | }
96 |
97 | // Edges returns a list of all the edges in the graph.
98 | func (dalg *DirectedAdjacencyListGraph) Edges() []*edge {
99 | var edges = make([]*edge, dalg.numEdges)
100 | for _, v := range dalg.primaryStructure {
101 | edges = append(edges, v.outgoingEdges...)
102 | }
103 |
104 | return edges
105 | }
106 |
107 | // Edges returns a list of all the edges in the graph
108 | func (dalg *DirectedAdjacencyListGraph) Vertices() []*vertex {
109 | var vertices = make([]*vertex, dalg.numVertices)
110 | for _, v := range dalg.primaryStructure {
111 | vertices = append(vertices, v)
112 | }
113 |
114 | return vertices
115 | }
116 |
117 | // GetEdge returns the `edge` that start from `fromVertex` and ends at `toVertex`
118 | // if one exists; otherwise return null.
119 | //
120 | // ARGUMENTS
121 | //
122 | // fromVertex (vertex): the vertex this edge starts from. The outgoing vertex.
123 | // toVertex (vertex): the vertex this edge is incident on. The incoming vertex.
124 | func (dalg *DirectedAdjacencyListGraph) GetEdge(fromVertexID, toVertexID int) *edge {
125 | fromVertex := dalg.primaryStructure[fromVertexID]
126 | toVertex := dalg.primaryStructure[toVertexID]
127 | if fromVertex != nil && toVertex != nil {
128 | for _, e := range fromVertex.outgoingEdges {
129 | if e.toVertex == toVertex {
130 | return e
131 | }
132 | }
133 | }
134 |
135 | return nil
136 | }
137 |
138 | // OutDegree returns the number of outgoing edges from vertex with the specified ID.
139 | //
140 | // ARGUMENTS
141 | //
142 | // id (int): ID of the vertex of interest
143 | func (dalg *DirectedAdjacencyListGraph) OutDegree(id int) int {
144 | if dalg.primaryStructure[id] != nil {
145 | return len(dalg.primaryStructure[id].outgoingEdges)
146 | }
147 |
148 | return -1
149 | }
150 |
151 | // InDegree returns the number of outgoing edges from vertex with the specified ID.
152 | //
153 | // ARGUMENTS
154 | //
155 | // id (int): ID of the vertex of interest
156 | func (dalg *DirectedAdjacencyListGraph) InDegree(id int) int {
157 | if dalg.primaryStructure[id] != nil {
158 | return len(dalg.primaryStructure[id].incomingEdges)
159 | }
160 |
161 | return -1
162 | }
163 |
164 | // OutgoingEdges Returns a list of all outgoing edges from vertex with the specified ID.
165 | //
166 | // ARGUMENTS
167 | //
168 | // id (int): ID of the vertex of interest
169 | func (dalg *DirectedAdjacencyListGraph) OutgoingEdges(id int) []*edge {
170 | if dalg.primaryStructure[id] != nil {
171 | return dalg.primaryStructure[id].outgoingEdges
172 | }
173 |
174 | return nil
175 | }
176 |
177 | // IncomingEdges Returns a list of all outgoing edges from vertex with the specified ID.
178 | //
179 | // ARGUMENTS
180 | //
181 | // id (int): ID of the vertex of interest
182 | func (dalg *DirectedAdjacencyListGraph) IncomingEdges(id int) []*edge {
183 | if dalg.primaryStructure[id] != nil {
184 | return dalg.primaryStructure[id].outgoingEdges
185 | }
186 |
187 | return nil
188 | }
189 |
190 | // InsertVertex Creates and returns a new Vertex storing element `item`.
191 | //
192 | // ARGUMENTS
193 | // item (interface): the item the vertex will hold.
194 | func (dalg *DirectedAdjacencyListGraph) InsertVertex(item interface{}) *vertex {
195 | if item != nil {
196 | v := &vertex{
197 | dalg.numVertices,
198 | item,
199 | make([]*edge, 0),
200 | make([]*edge, 0),
201 | }
202 | dalg.primaryStructure[dalg.numVertices] = v
203 | dalg.numVertices++
204 |
205 | return v
206 | }
207 |
208 | return nil
209 | }
210 |
211 | // InsertEdge Creates and returns a new Edge from vertex `fromVertex` to vertex `toVertex`,
212 | // storing element x; an error occurs if there already exists an edge from `fromVertex` to `toVertex`
213 | //
214 | // ARGUMENTS
215 | //
216 | // fromVertex (vertex): the vertex this edge starts from. The outgoing vertex.
217 | // toVertex (vertex): the vertex this edge is incident on. The incoming vertex.
218 | // item (interface): the item the edge will hold (in the case of a weighted graph).
219 | func (dalg *DirectedAdjacencyListGraph) InsertEdge(fromVertexID, toVertexID int, item interface{}) interface{} {
220 | if dalg.GetEdge(fromVertexID, toVertexID) == nil {
221 | fromVertex := dalg.primaryStructure[fromVertexID]
222 | toVertex := dalg.primaryStructure[toVertexID]
223 | if fromVertex != nil && toVertex != nil {
224 | e := &edge{
225 | dalg.numEdges,
226 | item,
227 | fromVertex,
228 | toVertex,
229 | }
230 |
231 | fromVertex.outgoingEdges = append(fromVertex.outgoingEdges, e)
232 | toVertex.incomingEdges = append(toVertex.incomingEdges, e)
233 |
234 | dalg.numEdges++
235 |
236 | return e
237 | }
238 | }
239 |
240 | return nil
241 | }
242 |
243 | // RemoveVertex Removes vertex with the specified ID and all its incident edges from the graph.
244 | //
245 | // ARGUMENTS
246 | //
247 | // id (int): ID of the vertex of interest
248 | func (dalg *DirectedAdjacencyListGraph) RemoveVertex(id int) bool {
249 | if dalg.primaryStructure[id] != nil {
250 | delete(dalg.primaryStructure, id)
251 | dalg.numVertices--
252 |
253 | return true
254 | }
255 |
256 | return false
257 | }
258 |
259 | // RemoveEdge removes edge e from the graph.
260 | //
261 | // ARGUMENTS
262 | //
263 | // e (edge): the edge to be removed
264 | func (dalg *DirectedAdjacencyListGraph) RemoveEdge(e *edge) bool {
265 | if e != nil && e.id >= 0 && e.id < len(e.fromVertex.outgoingEdges) {
266 |
267 | e.fromVertex.outgoingEdges[e.id] = e.fromVertex.outgoingEdges[len(e.fromVertex.outgoingEdges)-1]
268 | e.fromVertex.outgoingEdges = e.fromVertex.outgoingEdges[:len(e.fromVertex.outgoingEdges)-1]
269 |
270 | e.toVertex.incomingEdges[e.id] = e.toVertex.incomingEdges[len(e.toVertex.incomingEdges)-1]
271 | e.toVertex.incomingEdges = e.toVertex.incomingEdges[:len(e.toVertex.incomingEdges)-1]
272 |
273 | dalg.numEdges--
274 |
275 | return true
276 | }
277 |
278 | return false
279 | }
280 |
281 | // Performs a Generic Breadth-First Search on the graph. All is does is
282 | // return a list of the IDs of the nodes in the order they were visited.
283 | //
284 | // Example: [4, 2, 0, 3, 1]
285 | func (dalg *DirectedAdjacencyListGraph) BFS() []int {
286 | var l []int
287 | visitedTable := make(map[int]bool, dalg.numVertices)
288 | for key := range dalg.primaryStructure {
289 | visitedTable[key] = false
290 | }
291 |
292 | for key, vertex := range dalg.primaryStructure {
293 | if !visitedTable[key] {
294 | l = bfs(vertex, visitedTable)
295 | }
296 | }
297 |
298 | return l
299 | }
300 |
301 | func bfs(v *vertex, visitedTable map[int]bool) []int {
302 | l := make([]int, 0)
303 | queue := queuestack.NewQueue()
304 | queue.Enqueue(v)
305 | visitedTable[v.id] = true
306 |
307 | l = append(l, v.id)
308 |
309 | for !queue.Empty() {
310 | if node, err := queue.Dequeue(); err == nil {
311 | for _, ed := range node.(*vertex).outgoingEdges {
312 | if !visitedTable[ed.toVertex.id] {
313 | visitedTable[ed.toVertex.id] = true
314 | queue.Enqueue(ed.toVertex)
315 |
316 | l = append(l, ed.toVertex.id)
317 | }
318 | }
319 | }
320 | }
321 |
322 | return l
323 | }
324 |
--------------------------------------------------------------------------------
/adjaceny-list-graph/adjacency-list-graph_test.go:
--------------------------------------------------------------------------------
1 | package adjaceny_list_graph
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | // Setup
8 | var dalg = NewDALGraph()
9 |
10 | func TestDirectedAdjacencyListGraph_NumEdges(t *testing.T) {
11 | if dalg.numEdges != 0 {
12 | t.Errorf("Incorrect, got: %d, expected: %d.", dalg.numEdges, 0)
13 | }
14 | }
15 |
16 | func TestDirectedAdjacencyListGraph_NumVertices(t *testing.T) {
17 | if dalg.numVertices != 0 {
18 | t.Errorf("Incorrect, got: %d, expected: %d.", dalg.numVertices, 0)
19 | }
20 | }
21 |
22 | func TestDirectedAdjacencyListGraph_InsertVertex(t *testing.T) {
23 | v := dalg.InsertVertex("thor")
24 | if v.item != "thor" {
25 | t.Errorf("Incorrect, got: %d, expected: %s.", v.item, "thor")
26 | }
27 |
28 | v = dalg.InsertVertex("loki")
29 | if v.item != "loki" {
30 | t.Errorf("Incorrect, got: %d, expected: %s.", v.item, "loki")
31 | }
32 |
33 | v = dalg.InsertVertex(nil)
34 | if v != nil {
35 | t.Errorf("Incorrect, got: %d, expected: %v.", v, nil)
36 | }
37 |
38 | if dalg.numVertices != 2 {
39 | t.Errorf("Incorrect, got: %d, expected: %v.", dalg.numVertices, 1)
40 | }
41 | }
42 |
43 | func TestDirectedAdjacencyListGraph_InsertEdge(t *testing.T) {
44 | e := dalg.InsertEdge(0, 1, "brother")
45 | if e.(*edge).weight != "brother" {
46 | t.Errorf("Incorrect, got: %d, expected: %v.", e.(edge).weight, "brother")
47 | }
48 |
49 | if dalg.numEdges != 1 {
50 | t.Errorf("Incorrect, got: %d, expected: %v.", dalg.numEdges, 1)
51 | }
52 |
53 | if dalg.primaryStructure[0].outgoingEdges[0].weight != "brother" ||
54 | dalg.primaryStructure[1].incomingEdges[0].weight != "brother" {
55 |
56 | t.Error("edge between vertex 0 and 1 broken")
57 | }
58 |
59 | e = dalg.InsertEdge(1, 4, "brother")
60 | if e != nil {
61 | t.Error("Incorrect, should be nil")
62 | }
63 |
64 | e = dalg.InsertEdge(0, 1, "brother")
65 | if e != nil {
66 | t.Error("Incorrect, should be nil. Edge already exist")
67 | }
68 | }
69 |
70 | func TestDirectedAdjacencyListGraph_GetEdge(t *testing.T) {
71 | e := dalg.GetEdge(0, 1)
72 | if e == nil {
73 | t.Error("Incorrect. Edge actually exist")
74 | }
75 |
76 | if e.weight != "brother" {
77 | t.Errorf("Incorrect, got: %d, expected: %v.", e.weight, "brother")
78 | }
79 |
80 | e = dalg.GetEdge(1, 4)
81 | if e != nil {
82 | t.Error("Incorrect. Edge DOES NOT actually exist. e should be nil")
83 | }
84 | }
85 |
86 | func TestDirectedAdjacencyListGraph_RemoveEdge(t *testing.T) {
87 | e := dalg.GetEdge(0, 1)
88 | if e == nil {
89 | t.Error("Incorrect. Edge actually exist")
90 | }
91 |
92 | dalg.RemoveEdge(e)
93 |
94 | e = dalg.GetEdge(0, 1)
95 | if e != nil {
96 | t.Error("Incorrect. Edge does not exist. Should be nil")
97 | }
98 |
99 | if dalg.numEdges != 0 {
100 | t.Errorf("Incorrect, got: %d, expected: %v.", dalg.numEdges, 0)
101 | }
102 |
103 | e = dalg.GetEdge(1, 4)
104 | if e != nil {
105 | t.Error("Incorrect. Edge DOES NOT actually exist. e should be nil")
106 | }
107 |
108 | if dalg.RemoveEdge(e) {
109 | t.Error("Incorrect. Edge DOES NOT actually exist.")
110 | }
111 |
112 | if dalg.RemoveEdge(NewEdge()) {
113 | t.Error("Incorrect. Edge DOES NOT actually exist.")
114 | }
115 | }
116 |
117 | func TestDirectedAdjacencyListGraph_RemoveVertex(t *testing.T) {
118 | dalg.RemoveVertex(0)
119 | if dalg.numVertices != 1 {
120 | t.Errorf("Incorrect, got: %d, expected: %v.", dalg.numVertices, 1)
121 | }
122 |
123 | if dalg.RemoveVertex(0) {
124 | t.Error("Incorrect. Vertex DOES NOT actually exist.")
125 | }
126 | }
127 |
128 | func TestIntegration(t *testing.T) {
129 | // Create a new graph
130 | g := NewDALGraph()
131 |
132 | // Insert all the vertices
133 | v1 := g.InsertVertex(1)
134 | v2 := g.InsertVertex(2)
135 | v3 := g.InsertVertex(3)
136 | v4 := g.InsertVertex(4)
137 | v5 := g.InsertVertex(5)
138 |
139 | // Insert all the edges
140 | e12 := g.InsertEdge(v1.id, v2.id, "12")
141 | g.InsertEdge(v1.id, v4.id, "14")
142 | g.InsertEdge(v3.id, v1.id, "31")
143 | e34 := g.InsertEdge(v3.id, v4.id, "34")
144 | g.InsertEdge(v4.id, v5.id, "45")
145 | g.InsertEdge(v5.id, v3.id, "53")
146 |
147 | e912 := g.InsertEdge(9, 12, "912")
148 | if e912 != nil {
149 | t.Errorf("Incorrect, cannot insert such edge")
150 | }
151 |
152 | // Checking for the number of edges and vertices
153 | if g.NumVertices() != 5 {
154 | t.Errorf("Incorrect, got: %d, expected: %v.", g.NumVertices(), 5)
155 | }
156 | if g.NumEdges() != 6 {
157 | t.Errorf("Incorrect, got: %d, expected: %v.", g.NumEdges(), 6)
158 | }
159 |
160 | // Testing GetEdge()
161 | e := g.GetEdge(v1.id, v2.id)
162 | if e.id != e12.(*edge).id {
163 | t.Errorf("Incorrect, got: %d, expected: %v.", e.id, e12.(*edge).id)
164 | }
165 | if e.weight != e12.(*edge).weight {
166 | t.Errorf("Incorrect, got: %d, expected: %v.", e.weight, e12.(*edge).weight)
167 | }
168 |
169 | e = g.GetEdge(v3.id, v4.id)
170 | if e.id != e34.(*edge).id {
171 | t.Errorf("Incorrect, got: %d, expected: %v.", e.id, e34.(*edge).id)
172 | }
173 | if e.weight != e34.(*edge).weight {
174 | t.Errorf("Incorrect, got: %d, expected: %v.", e.weight, e34.(*edge).weight)
175 | }
176 |
177 | e = g.GetEdge(5, 3)
178 | if e != nil {
179 | t.Error("Incorrect. That edge is invalid")
180 | }
181 |
182 | // Testing OutDegree
183 | if g.OutDegree(v1.id) != 2 {
184 | t.Errorf("Incorrect, got: %d, expected: %v.", g.OutDegree(v1.id), 2)
185 | }
186 | if g.OutDegree(v3.id) != 2 {
187 | t.Errorf("Incorrect, got: %d, expected: %v.", g.OutDegree(v3.id), 2)
188 | }
189 | if g.OutDegree(v5.id) != 1 {
190 | t.Errorf("Incorrect, got: %d, expected: %v.", g.OutDegree(v5.id), 1)
191 | }
192 | if g.OutDegree(9) != -1 {
193 | t.Errorf("Incorrect, got: %d, expected: %v.", g.OutDegree(9), -1)
194 | }
195 |
196 | // Testing InDegree
197 | if g.InDegree(v4.id) != 2 {
198 | t.Errorf("Incorrect, got: %d, expected: %v.", g.InDegree(v4.id), 2)
199 | }
200 | if g.InDegree(v3.id) != 1 {
201 | t.Errorf("Incorrect, got: %d, expected: %v.", g.InDegree(v3.id), 1)
202 | }
203 | if g.InDegree(v2.id) != 1 {
204 | t.Errorf("Incorrect, got: %d, expected: %v.", g.InDegree(v2.id), 1)
205 | }
206 | if g.InDegree(9) != -1 {
207 | t.Errorf("Incorrect, got: %d, expected: %v.", g.InDegree(9), -1)
208 | }
209 |
210 | // Testing Breadth-First Search
211 | t.Log(g.BFS())
212 | }
213 |
--------------------------------------------------------------------------------
/allpairs/allpairs.go:
--------------------------------------------------------------------------------
1 | // This package provide a algorithm for distance of all pairs problems
2 | // It solves this problem with Floyd-Warshall algorithm in O(N^3)
3 | package allpairs
4 |
5 | // Max Integer
6 | const INF = int(^uint(0) >> 2)
7 |
8 | // Type for edge data - endpoints u, v and length
9 | type Edge struct {
10 | u, v, length int
11 | }
12 |
13 | type Edges []Edge
14 |
15 | func (edges Edges) Swap(i, j int) {
16 | edges[i], edges[j] = edges[j], edges[i]
17 | }
18 |
19 | func (edges Edges) Len() int {
20 | return len(edges)
21 | }
22 |
23 | func (edges Edges) Less(i, j int) bool {
24 | return edges[i].length < edges[j].length
25 | }
26 |
27 | // Computes the distance of all pairs
28 | func allPairsDistance(n int, edges []Edge) [][]int {
29 | distance := make([][]int, n)
30 | for i := range distance {
31 | distance[i] = make([]int, n)
32 | }
33 |
34 | for i := 0; i < n; i++ {
35 | for j := 0; j < n; j++ {
36 | distance[i][j] = INF
37 | }
38 | }
39 |
40 | for _, edge := range edges {
41 | if distance[edge.u][edge.v] > edge.length {
42 | distance[edge.u][edge.v] = edge.length
43 | }
44 | }
45 |
46 | for i := 0; i < n; i++ {
47 | distance[i][i] = 0
48 | }
49 |
50 | for k := 0; k < n; k++ {
51 | for i := 0; i < n; i++ {
52 | for j := 0; j < n; j++ {
53 | if distance[i][j] > distance[i][k]+distance[k][j] {
54 | distance[i][j] = distance[i][k] + distance[k][j]
55 | }
56 | }
57 | }
58 | }
59 |
60 | return distance
61 | }
62 |
--------------------------------------------------------------------------------
/allpairs/allpairs_test.go:
--------------------------------------------------------------------------------
1 | package allpairs
2 |
3 | import "testing"
4 |
5 | // Tests the Floyd Warshall all pairs algorithm
6 | func TestAllPairs(t *testing.T) {
7 | edges := []Edge{{4, 5, 10}}
8 |
9 | for i := 0; i < 3; i++ {
10 | for j := i + 1; j < 3; j++ {
11 | edges = append(edges, Edge{i, j, j - i})
12 | }
13 | }
14 |
15 | // For the given test the answer has cost 13 and is unique
16 |
17 | distance := allPairsDistance(6, edges)
18 |
19 | if len(distance) != 6 {
20 | t.Error("Returned array of distance have wrong size")
21 | }
22 |
23 | if distance[4][5] != 10 {
24 | t.Error("Distance from 4 to 5 is wrong")
25 | }
26 |
27 | if distance[1][5] != INF {
28 | t.Error("Distance from 1 to 5 is wrong")
29 | }
30 |
31 | if distance[1][2] != 1 {
32 | t.Error("Distance from 1 to 2 is wrong")
33 | }
34 |
35 | if distance[3][3] != 0 {
36 | t.Error("Distance from 3 to 3 is wrong")
37 | }
38 |
39 | if distance[3][5] != INF {
40 | t.Error("Distance from 3 to 4 is wrong")
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/bst/binarySearchTree.go:
--------------------------------------------------------------------------------
1 | package bst
2 |
3 | import (
4 | "fmt" //importing required packages
5 | )
6 |
7 | type Node struct { //Node represents node of a Binary Search Tree
8 | value int
9 | left *Node
10 | right *Node
11 | }
12 |
13 | func Insert(root *Node, key int) *Node { //The following function inserts elements into Binary Search Tree
14 | if root == nil {
15 | root = &Node{key, nil, nil} //root node is created with left and right child as nil
16 | } else if key < root.value {
17 | root.left = Insert(root.left, key) //Using recursion to maintain the tree as BST
18 | } else if key > root.value {
19 | root.right = Insert(root.right, key)
20 | }
21 | return root
22 | }
23 |
24 | func Search(root *Node, key int) *Node { //The following function searches a given key in a BST
25 | if root == nil {
26 | return root
27 | }
28 |
29 | if root.value == key { //If the key is not found a nil pointer is returned
30 | return root
31 | }
32 | if root.value < key {
33 | return Search(root.right, key)
34 | }
35 | return Search(root.left, key)
36 |
37 | }
38 | func Minval(root *Node) *Node { //The following function is used in Delete function to find the inorder successor
39 | var current *Node
40 | current = root
41 | for current.left != nil {
42 | current = current.left
43 | }
44 | return current
45 | }
46 | func Delete(root *Node, key int) *Node { //The following function deletes the key in BST and returns the new root
47 | if root == nil {
48 | //base case
49 | return root
50 | }
51 | if key < root.value { //If the key to be deleted is smaller than the root's key,the key lies in the left subtree
52 | root.left = Delete(root.left, key)
53 | } else if key > root.value { //If the key to be deleted is greater than the root's key,the key lies in the right subtree
54 | root.right = Delete(root.right, key)
55 | } else { //node with only one child
56 | if root.left == nil {
57 | var temp *Node = root.right
58 | return temp
59 | } else if root.right == nil {
60 | var temp *Node = root.left
61 | return temp
62 | } //node with two children
63 | var temp *Node
64 | temp = Minval(root.right) //Get inorder successor
65 | root.value = temp.value //Get the inorder successor's value
66 | root.right = Delete(root.right, temp.value) //Delete the inorder successor
67 | }
68 | return root
69 | }
70 | func PreorderTraverse(root *Node) { //The following function does preorder traversal of BST,i.e,Root,left,Right nodes.
71 | if root == nil {
72 | return
73 | }
74 | fmt.Println(root.value)
75 | PreorderTraverse(root.left)
76 | PreorderTraverse(root.right)
77 | }
78 |
79 | func InorderTraverse(root *Node) { //The following function does inorder traversal of BST,i.e,Left,Root,Right nodes.
80 | if root == nil {
81 | return
82 | }
83 | InorderTraverse(root.left)
84 | fmt.Println(root.value)
85 | InorderTraverse(root.right)
86 | }
87 |
88 | func PostorderTraverse(root *Node) { //The following function does postorder traversal of BST,i.e,Left,Right,Root nodes.
89 | if root == nil {
90 | return
91 | }
92 | PostorderTraverse(root.left)
93 | PostorderTraverse(root.right)
94 | fmt.Println(root.value)
95 | }
96 | func IdenticalTrees(a *Node, b *Node) bool { //The following function checks whether two trees are indentical or not
97 | if a == nil && b == nil {
98 | return true
99 | }
100 | if a != nil && b != nil {
101 | return (a.value == b.value && IdenticalTrees(a.left, b.left) && IdenticalTrees(a.right, b.right))
102 | }
103 | return false
104 | }
105 |
--------------------------------------------------------------------------------
/bst/binarySearchTree_test.go:
--------------------------------------------------------------------------------
1 | package bst
2 |
3 | import "testing"
4 |
5 | func TestDelete(t *testing.T) {
6 | var testNode *Node
7 | testNode = Insert(testNode, 12)
8 | Insert(testNode, 1)
9 | Insert(testNode, 3)
10 | Insert(testNode, 25)
11 |
12 | var expectedNode *Node
13 | expectedNode = Insert(expectedNode, 12)
14 | Insert(expectedNode, 1)
15 | Insert(expectedNode, 3)
16 | Delete(testNode, 25)
17 |
18 | if testNode == nil {
19 | t.Error("Binary tree cannot be empty for deletion")
20 | }
21 |
22 | if IdenticalTrees(testNode, expectedNode) == false {
23 | t.Error("Deletion has not taken place")
24 | }
25 |
26 | }
27 | func TestSearch(t *testing.T) {
28 | var testNode *Node
29 | testNode = Insert(testNode, 12)
30 | Insert(testNode, 1)
31 | Insert(testNode, 3)
32 | Insert(testNode, 25)
33 | if Search(testNode, 3) == nil {
34 | t.Error("This is incorrect since the number is present in BST")
35 | }
36 | }
37 |
38 | func TestInsert(t *testing.T) {
39 | var testNode *Node
40 | testNode = Insert(testNode, 12)
41 | Insert(testNode, 1)
42 | Insert(testNode, 3)
43 | Insert(testNode, 25)
44 |
45 | if testNode == nil {
46 | t.Error("The elements haven't been inserted into the bst")
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/btree/btree.go:
--------------------------------------------------------------------------------
1 | package btree
2 |
3 | //Index interface of data container of Node
4 | type Index interface {
5 | LessThan(Index) bool
6 | EqualsTo(Index) bool
7 | }
8 |
9 | //Node Tree element struct
10 | type Node struct {
11 | Data Index
12 | Score int
13 | Edges [2]*Node
14 | }
15 |
16 | // Public
17 |
18 | // Insert a node into the AVL tree.
19 | func Insert(tree **Node, data Index) {
20 | *tree, _ = insertInRightOf(*tree, data)
21 | }
22 |
23 | // Remove a single item from an AVL tree.
24 | func Remove(tree **Node, data Index) {
25 | *tree, _ = removeFromRightOf(*tree, data)
26 | }
27 |
28 | // Private
29 |
30 | func opp(d int) int {
31 | return 1 - d
32 | }
33 |
34 | //singleRotation
35 | func singleRotation(parent *Node, direction int) (b *Node) {
36 | b = parent.Edges[opp(direction)]
37 | parent.Edges[opp(direction)] = b.Edges[direction]
38 | b.Edges[direction] = parent
39 | return
40 | }
41 |
42 | //doubleRotation
43 | func doubleRotation(parent *Node, d int) (b *Node) {
44 | b = parent.Edges[opp(d)].Edges[d]
45 | parent.Edges[opp(d)].Edges[d] = b.Edges[opp(d)]
46 | b.Edges[opp(d)] = parent.Edges[opp(d)]
47 | parent.Edges[opp(d)] = b
48 |
49 | b = parent.Edges[opp(d)]
50 | parent.Edges[opp(d)] = b.Edges[d]
51 | b.Edges[d] = parent
52 | return
53 | }
54 |
55 | func adjust(parent *Node, dir, bal int) {
56 | n := parent.Edges[dir]
57 | nn := n.Edges[opp(dir)]
58 | switch nn.Score {
59 | case 0:
60 | parent.Score = 0
61 | n.Score = 0
62 | case bal:
63 | parent.Score = bal
64 | n.Score = 0
65 | default:
66 | parent.Score = 0
67 | n.Score = bal
68 | }
69 | nn.Score = 0
70 | }
71 |
72 | func insertScoreBalance(node *Node, dir int) *Node {
73 | n := node.Edges[dir]
74 | bal := 2*dir - 1
75 | if n.Score == bal {
76 | node.Score = 0
77 | n.Score = 0
78 | return singleRotation(node, opp(dir))
79 | }
80 | adjust(node, dir, bal)
81 | return doubleRotation(node, opp(dir))
82 | }
83 |
84 | //insertInRightOf
85 | func insertInRightOf(node *Node, data Index) (*Node, bool) {
86 | if node == nil {
87 | return &Node{Data: data}, false
88 | }
89 | dir := 0
90 | if node.Data.LessThan(data) {
91 | dir = 1
92 | }
93 | var done bool
94 | node.Edges[dir], done = insertInRightOf(node.Edges[dir], data)
95 | if done {
96 | return node, true
97 | }
98 | node.Score += 2*dir - 1
99 | switch node.Score {
100 | case 0:
101 | return node, true
102 | case 1, -1:
103 | return node, false
104 | }
105 | return insertScoreBalance(node, dir), true
106 | }
107 |
108 | //removeScoreBalance
109 | func removeScoreBalance(root *Node, dir int) (*Node, bool) {
110 | n := root.Edges[opp(dir)]
111 | bal := 2*dir - 1
112 | switch n.Score {
113 | case -bal:
114 | root.Score = 0
115 | n.Score = 0
116 | return singleRotation(root, dir), false
117 | case bal:
118 | adjust(root, opp(dir), -bal)
119 | return doubleRotation(root, dir), false
120 | }
121 | root.Score = -bal
122 | n.Score = bal
123 | return singleRotation(root, dir), true
124 | }
125 |
126 | //removeFromRightOf
127 | func removeFromRightOf(node *Node, data Index) (*Node, bool) {
128 | if node == nil {
129 | return nil, false
130 | }
131 | if node.Data.EqualsTo(data) {
132 | switch {
133 | case node.Edges[0] == nil:
134 | return node.Edges[1], false
135 | case node.Edges[1] == nil:
136 | return node.Edges[0], false
137 | }
138 | heir := node.Edges[0]
139 | for heir.Edges[1] != nil {
140 | heir = heir.Edges[1]
141 | }
142 | node.Data = heir.Data
143 | data = heir.Data
144 | }
145 | dir := 0
146 | if node.Data.LessThan(data) {
147 | dir = 1
148 | }
149 | var done bool
150 | node.Edges[dir], done = removeFromRightOf(node.Edges[dir], data)
151 | if done {
152 | return node, true
153 | }
154 | node.Score += 1 - 2*dir
155 | switch node.Score {
156 | case 1, -1:
157 | return node, true
158 | case 0:
159 | return node, false
160 | }
161 | return removeScoreBalance(node, dir)
162 | }
163 |
--------------------------------------------------------------------------------
/btree/btree_test.go:
--------------------------------------------------------------------------------
1 | package btree
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "testing"
7 | )
8 |
9 | type integerIndex int
10 |
11 | func (ii integerIndex) LessThan(ii2 Index) bool {
12 | return ii < ii2.(integerIndex)
13 | }
14 | func (ii integerIndex) EqualsTo(ii2 Index) bool {
15 | return ii == ii2.(integerIndex)
16 | }
17 |
18 | //TestBtree
19 | func TestBtree(t *testing.T) {
20 | var tree *Node
21 | fmt.Println("Empty Tree:")
22 | balancedTreeJson, _ := json.MarshalIndent(tree, "", "--")
23 |
24 | fmt.Println("\nInsert Tree:")
25 | Insert(&tree, integerIndex(4))
26 | if tree.Score != 4 {
27 | t.Fatalf("Score should be 4, got %v", tree.Score)
28 | }
29 | Insert(&tree, integerIndex(3))
30 | Insert(&tree, integerIndex(8))
31 | if tree.Score != 4 {
32 | t.Fatalf("Score should be 4, got %v", tree.Score)
33 | }
34 | Insert(&tree, integerIndex(6))
35 | Insert(&tree, integerIndex(7))
36 | Insert(&tree, integerIndex(9))
37 | if tree.Score != 6 {
38 | t.Fatalf("Score should be 6, got %v", tree.Score)
39 | }
40 | balancedTreeJson, _ = json.MarshalIndent(tree, "", "--")
41 | fmt.Println(string(balancedTreeJson))
42 |
43 | fmt.Println("\nRemove Tree:")
44 | Remove(&tree, integerIndex(4))
45 | Remove(&tree, integerIndex(6))
46 | balancedTreeJson, _ = json.MarshalIndent(tree, "", "--")
47 | fmt.Println(string(balancedTreeJson))
48 | }
49 |
--------------------------------------------------------------------------------
/bubblesort/bubblesort.go:
--------------------------------------------------------------------------------
1 | // Package bubblesort provides implementation for bubble sort algorithm
2 | package bubblesort
3 |
4 | // Swap function changes two integers
5 | func Swap(lhs *int, rhs *int) {
6 | tmp := *lhs
7 | *lhs = *rhs
8 | *rhs = tmp
9 | }
10 |
11 | // Bubblesort function receives an array and return the sorted array
12 | // O(N^2)
13 | func bubbleSort(A []int) []int {
14 | N := len(A)
15 | result := make([]int, len(A))
16 | i := 0
17 | j := 0
18 | for i = 0; i < N; i++ {
19 | result[i] = A[i]
20 | }
21 |
22 | for i = 0; i < N-1; i++ {
23 | for j = 0; j < N-1; j++ {
24 | if result[j] > result[j+1] {
25 | Swap(&result[j], &result[j+1])
26 | }
27 | }
28 | }
29 | return result
30 | }
31 |
--------------------------------------------------------------------------------
/bubblesort/bubblesort_test.go:
--------------------------------------------------------------------------------
1 | package bubblesort
2 |
3 |
4 | import (
5 | "math/rand"
6 | "reflect"
7 | "sort"
8 | "testing"
9 | "time"
10 | )
11 |
12 | // TestBubbleSort inspired in mergesort_test
13 | func TestBubbleSort(t *testing.T) {
14 | empty := []int{}
15 | resultEmpty := bubbleSort(empty)
16 |
17 | if !reflect.DeepEqual(empty, resultEmpty) {
18 | t.Error("ERROR!", "Expected:", empty, "Result:", resultEmpty)
19 | return
20 | }
21 |
22 | unitary := []int{42}
23 | resultUnitary := bubbleSort(unitary)
24 |
25 | if !reflect.DeepEqual(unitary, resultUnitary) {
26 | t.Error("ERROR!", "Expected:", unitary, "Result:", resultUnitary)
27 | return
28 | }
29 |
30 | rand.Seed(int64(time.Now().Nanosecond()))
31 | for test := 0; test < 10; test++ {
32 | array := make([]int, 100)
33 | for i := 0; i < 100; i++ {
34 | array[i] = rand.Int()
35 | }
36 |
37 | expected := make([]int, 100)
38 | copy(expected, array)
39 | sort.Ints(expected)
40 |
41 | result := bubbleSort(array)
42 |
43 | if !reflect.DeepEqual(result, expected) {
44 | t.Error("ERROR!", "Expected:", expected, "Result:", result)
45 | return
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/convexHull/convexHull.go:
--------------------------------------------------------------------------------
1 | // Package convexHull provides an algotithm for finding a convex hull from a
2 | // set of point. Implemented algorithm:
3 | // https://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain
4 | package convexHull
5 |
6 | import "sort"
7 |
8 | // Point is a struct that holds the X Y cooridinates
9 | // of a specific point in the Ecliden plane or space.
10 | type Point struct {
11 | X, Y int
12 | }
13 |
14 | // Points is a slice built up of Point structs.
15 | type Points []Point
16 |
17 | func (points Points) Swap(i, j int) {
18 | points[i], points[j] = points[j], points[i]
19 | }
20 |
21 | func (points Points) Len() int {
22 | return len(points)
23 | }
24 |
25 | // lets sort our Points by x and, if equal, by y
26 | func (points Points) Less(i, j int) bool {
27 | if points[i].X == points[j].X {
28 | return points[i].Y < points[j].Y
29 | }
30 | return points[i].X < points[j].X
31 | }
32 |
33 | // returns the modulo (and sign) of the cross product between vetors OA and OB
34 | func crossProduct(O, A, B Point) int {
35 | return (A.X-O.X)*(B.Y-O.Y) - (A.Y-O.Y)*(B.X-O.X)
36 | }
37 |
38 | // findConvexHull returns a slice of Point with a convex hull
39 | // it is counterclockwise and starts and ends at the same point
40 | // i.e. the same point is repeated at the beginning and at the end
41 | func findConvexHull(points Points) Points {
42 | n := len(points) // number of points to find convex hull
43 | var result Points // final result
44 | count := 0 // size of our convex hull (number of points added)
45 |
46 | // lets sort our points by x and if equal by y
47 | sort.Sort(points)
48 |
49 | if n == 0 {
50 | return result
51 | }
52 |
53 | // add the first element:
54 | result = append(result, points[0])
55 | count++
56 |
57 | // find the lower hull
58 | for i := 1; i < n; i++ {
59 | // remove points which are not part of the lower hull
60 | for count > 1 && crossProduct(result[count-2], result[count-1], points[i]) < 0 {
61 | count--
62 | result = result[:count]
63 | }
64 |
65 | // add a new better point than the removed ones
66 | result = append(result, points[i])
67 | count++
68 | }
69 |
70 | count0 := count // our base counter for the upper hull
71 |
72 | // find the upper hull
73 | for i := n - 2; i >= 0; i-- {
74 | // remove points which are not part of the upper hull
75 | for count-count0 > 0 && crossProduct(result[count-2], result[count-1], points[i]) < 0 {
76 | count--
77 | result = result[:count]
78 | }
79 |
80 | // add a new better point than the removed ones
81 | result = append(result, points[i])
82 | count++
83 | }
84 |
85 | return result
86 | }
87 |
--------------------------------------------------------------------------------
/convexHull/convexHull_test.go:
--------------------------------------------------------------------------------
1 | package convexHull
2 |
3 | import "testing"
4 |
5 | func TestConvexHull(t *testing.T) {
6 | var points = Points{{0, 3}, {2, 2}, {1, 1}, {2, 1},
7 | {3, 0}, {0, 0}, {3, 3}}
8 | var expected = Points{{0, 0}, {3, 0}, {3, 3}, {0, 3}, {0, 0}}
9 | var result = findConvexHull(points)
10 |
11 | if result == nil {
12 | t.Error("returned convex hull is nil")
13 | return
14 | }
15 |
16 | if len(result) != len(expected) {
17 | t.Error("returned convex hull has a different size")
18 | return
19 | }
20 |
21 | for i := range result {
22 | if result[i] != expected[i] {
23 | t.Error("returned convex hull is wrong")
24 | return
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/doc/gopher.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ch3ck/algo/5aae7fab9e3d6ebca20ee30441c232f43815b89b/doc/gopher.jpg
--------------------------------------------------------------------------------
/doc/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ch3ck/algo/5aae7fab9e3d6ebca20ee30441c232f43815b89b/doc/logo.png
--------------------------------------------------------------------------------
/graph/graph.go:
--------------------------------------------------------------------------------
1 | package graph
2 |
3 | import "fmt"
4 |
5 | // Node
6 | type ID string
7 |
8 | type Node interface {
9 | Id() ID
10 | Edges() []ID
11 | }
12 |
13 | type node struct {
14 | id ID
15 | edges []ID
16 | }
17 |
18 | func (n node) Id() ID {
19 | return n.id
20 | }
21 |
22 | func (n node) Edges() []ID {
23 | return n.edges
24 | }
25 |
26 | // Graph
27 | type Graph interface {
28 | AddNode(id ID, edges []ID) Node
29 | BreadthFirstTraversal(start ID, visitor NodeVisitorFunc) error
30 | DepthFirstTraversal(start ID, visitor NodeVisitorFunc) error
31 | }
32 |
33 | // returning an error terminates the traversal
34 | type NodeVisitorFunc func(n Node, depth int) error
35 |
36 | type graph struct {
37 | nodes map[ID]*node
38 | }
39 |
40 | func NewDirectedGraph() Graph {
41 | return &graph{
42 | nodes: map[ID]*node{},
43 | }
44 | }
45 |
46 | func (g graph) AddNode(id ID, edges []ID) Node {
47 | node := &node{
48 | id: id,
49 | edges: edges,
50 | }
51 | g.nodes[id] = node
52 | return node
53 | }
54 |
55 | // Visits each node in breadth-first order. if the visitor function returns an error
56 | // traversal is terminated and the error returned by this function.
57 | func (g graph) BreadthFirstTraversal(start ID, visitor NodeVisitorFunc) error {
58 | toVisitIds := []ID{}
59 | visitedIds := map[ID]interface{}{}
60 |
61 | depth := 0
62 | toVisitIds = append(toVisitIds, start)
63 |
64 | for len(toVisitIds) != 0 {
65 | currId := toVisitIds[0]
66 | visitedIds[currId] = nil
67 |
68 | if node := g.nodes[currId]; node != nil {
69 | if err := visitor(node, depth); err != nil {
70 | return err
71 | }
72 | for _, id := range node.edges {
73 | if _, ok := visitedIds[id]; !ok {
74 | toVisitIds = append(toVisitIds, id)
75 | }
76 | }
77 | } else {
78 | return fmt.Errorf("inconsistent graph, missing node with id %s", currId)
79 | }
80 |
81 | toVisitIds = toVisitIds[1:]
82 | }
83 |
84 | return nil
85 | }
86 |
87 | // Visits each node in depth-first order. if the visitor function returns an error
88 | // traversal is terminated and the error returned by this function.
89 | func (g graph) DepthFirstTraversal(start ID, visitor NodeVisitorFunc) error {
90 | visitedIds := map[ID]interface{}{}
91 |
92 | return g.depthFirstTraversal(start, 0, visitedIds, visitor)
93 | }
94 |
95 | func (g graph) depthFirstTraversal(currId ID, depth int, visitedIds map[ID]interface{}, visitor NodeVisitorFunc) error {
96 | curr := g.nodes[currId]
97 | if curr == nil {
98 | return fmt.Errorf("inconsistent graph or start, missing node with id %s", currId)
99 | }
100 |
101 | if err := visitor(curr, depth); err != nil {
102 | return err
103 | }
104 | visitedIds[currId] = nil
105 |
106 | for _, id := range curr.edges {
107 | if _, found := visitedIds[id]; !found {
108 | if err := g.depthFirstTraversal(id, depth+1, visitedIds, visitor); err != nil {
109 | return err
110 | }
111 | }
112 | }
113 | return nil
114 | }
115 |
--------------------------------------------------------------------------------
/graph/graph_test.go:
--------------------------------------------------------------------------------
1 | package graph_test
2 |
3 | import (
4 | "fmt"
5 | "github.com/Ch3ck/AlGo/graph"
6 | "github.com/stretchr/testify/assert"
7 | "testing"
8 | )
9 |
10 | func TestBreadthFirstTraversal(t *testing.T) {
11 | t.Run("directed graph breadth first traversal", func(t *testing.T) {
12 | // create data
13 | g := graph.NewDirectedGraph()
14 | g.AddNode("0", []graph.ID{"1a", "1b", "1c"})
15 | g.AddNode("1a", []graph.ID{"2a1"})
16 | g.AddNode("1b", []graph.ID{"2b1", "2b2"})
17 | g.AddNode("1c", []graph.ID{"2c1"})
18 | g.AddNode("2a1", []graph.ID{"3a1"})
19 | g.AddNode("2b1", []graph.ID{"0"})
20 | g.AddNode("2b2", []graph.ID{"1a"})
21 | g.AddNode("2c1", []graph.ID{"2c1"})
22 | g.AddNode("3a1", []graph.ID{})
23 |
24 | fmt.Printf("input: %+v\n", g)
25 |
26 | expected := []graph.ID{"0", "1a", "1b", "1c", "2a1", "2b1", "2b2", "2c1", "3a1"}
27 | actual := []graph.ID{}
28 | err := g.BreadthFirstTraversal("0", func(n graph.Node, depth int) error {
29 | actual = append(actual, n.Id())
30 | return nil
31 | })
32 |
33 | assert.NoError(t, err, "traversal error")
34 | assert.Equal(t, expected, actual, "traversal order failed")
35 | })
36 | }
37 |
38 | func TestDepthFirstTraversal(t *testing.T) {
39 | t.Run("directed graph depth first traversal", func(t *testing.T) {
40 | // create data
41 | g := graph.NewDirectedGraph()
42 | g.AddNode("0", []graph.ID{"1a", "1b", "1c"})
43 | g.AddNode("1a", []graph.ID{"2a1"})
44 | g.AddNode("1b", []graph.ID{"2b1", "2b2"})
45 | g.AddNode("1c", []graph.ID{"2c1"})
46 | g.AddNode("2a1", []graph.ID{"3a1"})
47 | g.AddNode("2b1", []graph.ID{"0", "1c"})
48 | g.AddNode("2b2", []graph.ID{"1a"})
49 | g.AddNode("2c1", []graph.ID{"2c1"})
50 | g.AddNode("3a1", []graph.ID{})
51 |
52 | fmt.Printf("input: %+v\n", g)
53 |
54 | expected := []graph.ID{"0", "1a", "2a1", "3a1", "1b", "2b1", "1c", "2c1", "2b2"}
55 | actual := []graph.ID{}
56 | err := g.DepthFirstTraversal("0", func(n graph.Node, depth int) error {
57 | actual = append(actual, n.Id())
58 | return nil
59 | })
60 |
61 | assert.NoError(t, err, "traversal error")
62 | assert.Equal(t, expected, actual, "traversal order failed")
63 | })
64 | }
65 |
--------------------------------------------------------------------------------
/heapsort/heapsort.go:
--------------------------------------------------------------------------------
1 | package heapsort
2 |
3 | /*import "os"
4 | import "strconv"
5 | import "fmt"*/
6 |
7 | //Heapsort for integers in Golang
8 | //based on Professor Mark Allen Weiss' solution in C
9 | //http://users.cs.fiu.edu/~weiss/
10 |
11 | func Swap(lhs *int, rhs *int) {
12 | tmp := *lhs
13 | *lhs = *rhs
14 | *rhs = tmp
15 | }
16 |
17 | func LeftChild(in int) (out int) {
18 | out = 2*in + 1
19 | return
20 | }
21 |
22 | func PercDown(A []int, i int, N int) {
23 | var Child int
24 | var Tmp int
25 |
26 | for Tmp = A[i]; LeftChild(i) < N; i = Child {
27 | Child = LeftChild(i)
28 | if Child != N-1 && A[Child+1] > A[Child] {
29 | Child++
30 | }
31 | if Tmp < A[Child] {
32 | A[i] = A[Child]
33 | } else {
34 | break
35 | }
36 | }
37 | A[i] = Tmp
38 | }
39 |
40 | func Heapsort(A []int, N int) ([]int, int) {
41 | i := N
42 | for i = N / 2; i >= 0; i-- { //Build Heap
43 | PercDown(A, i, N)
44 | }
45 |
46 | for i = N - 1; i > 0; i-- {
47 | Swap(&A[0], &A[i]) //DeleteMax
48 | PercDown(A, 0, i)
49 | }
50 | return A, 1
51 | }
52 |
--------------------------------------------------------------------------------
/heapsort/heapsort_test.go:
--------------------------------------------------------------------------------
1 | package heapsort_test
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 |
7 | "github.com/Ch3ck/AlGo/heapsort"
8 | )
9 |
10 | func TestHeapsort(t *testing.T) {
11 | var data = []int{3, 1, 4, 1, 5, 9, 2, 6} //create data
12 | fmt.Println("input: ", data)
13 | var expected = []int{1, 1, 2, 3, 4, 5, 6, 9}
14 | var result, flag = heapsort.Heapsort(data, len(data))
15 |
16 | if flag != 1 {
17 | fmt.Print("Something went wrong")
18 | return
19 | }
20 |
21 | //check if result is null
22 | if result == nil {
23 | t.Error("returned value is nil")
24 | return
25 | }
26 |
27 | //result is not null, we perform checks
28 | if len(result) != len(expected) {
29 | t.Error("sorted data has different length from input data")
30 | return
31 | } else { //lengths are okay, we compare output values with expected values
32 | for i := range result {
33 | if result[i] != expected[i] {
34 | t.Error("failed at sorting")
35 | } else {
36 | fmt.Println("expect: ", expected)
37 | fmt.Println("output: ", result)
38 | fmt.Println("success")
39 | return
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/insertsort/insertsort.go:
--------------------------------------------------------------------------------
1 | package insertsort
2 |
3 | // Swap is a helper function used to swich the places of
4 | // two items in an array.
5 | func Swap(arraysrt []int, i, j int) {
6 | tmp := arraysrt[j]
7 | arraysrt[j] = arraysrt[i]
8 | arraysrt[i] = tmp
9 | }
10 |
11 | // InsertSort is an implementation of the insert sort
12 | // algorithm.
13 | func InsertSort(array []int) []int {
14 | for i := 1; i < len(array); i++ {
15 | for j := i; j > 0 && array[j] < array[j-1]; j-- {
16 | Swap(array, j, j-1)
17 | }
18 | }
19 | return array
20 | }
21 |
--------------------------------------------------------------------------------
/insertsort/insertsort_test.go:
--------------------------------------------------------------------------------
1 | package insertsort
2 |
3 | import (
4 | "reflect"
5 | "testing"
6 | )
7 |
8 | /* Test pair for InsertSort() algorithm */
9 | type testpair struct {
10 | unsortedSlice []int
11 | sortedSlice []int
12 | }
13 |
14 | /* Test instance of testpair the unsorted and sorted slices */
15 | var tests = []testpair{
16 | {[]int{3, 2, 1, 5, 6, 3, 7, 8, 9}, []int{1, 2, 3, 3, 5, 6, 7, 8, 9}},
17 | {[]int{1, 4, 2, 3}, []int{1, 2, 3, 4}},
18 | {[]int{4, 5, 2, 7, 6, 8, 7}, []int{2, 4, 5, 6, 7, 7, 8}},
19 | }
20 |
21 | /* Test case to test the InsertSort function */
22 | func TestInsertSort(t *testing.T) {
23 | for _, pair := range tests {
24 | sorted := InsertSort(pair.unsortedSlice)
25 |
26 | if !reflect.DeepEqual(sorted, pair.sortedSlice) {
27 | t.Error(
28 | "For", pair.unsortedSlice,
29 | "expected", pair.sortedSlice,
30 | "got", sorted,
31 | )
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/knuthMorrisPratt/knuthMorrisPratt.go:
--------------------------------------------------------------------------------
1 | // Package knuthMorrisPratt provides a simple Match function to find occurrences
2 | // of a pattern in a block of text
3 | package knuthMorrisPratt
4 |
5 | // Match uses the Knuth-Morris-Pratt algorithm to find occurrences of `pattern` in `text`
6 | // and returns the list of indexes where the matches are in `text`
7 | func Match(text, pattern string) (result []int) {
8 | n := len(text)
9 | m := len(pattern)
10 |
11 | if n == 0 || m == 0 {
12 | return
13 | }
14 |
15 | pi := prefix(pattern)
16 | q := 0
17 |
18 | for i := 0; i < n; i++ {
19 | for q > 0 && pattern[q] != text[i] {
20 | q = pi[q-1]
21 | }
22 | if pattern[q] == text[i] {
23 | q++
24 | }
25 | if q == m {
26 | result = append(result, i-m+1)
27 | q = pi[q-1]
28 | }
29 | }
30 |
31 | return
32 | }
33 |
34 | // prefix function, pi, encapsulates knowledege about how a pattern matches againsts
35 | // shifts of itself.
36 | func prefix(pattern string) []int {
37 | m := len(pattern)
38 | if m == 0 {
39 | return []int{}
40 | }
41 |
42 | pi := make([]int, m)
43 | pi[0] = 0
44 | k := 0
45 | for q := 1; q < m; q++ {
46 | for k > 0 && pattern[k] != pattern[q] {
47 | k = pi[k-1]
48 | }
49 | if pattern[k] == pattern[q] {
50 | k++
51 | }
52 | pi[q] = k
53 | }
54 |
55 | return pi
56 | }
57 |
--------------------------------------------------------------------------------
/knuthMorrisPratt/knuthMorrisPratt_test.go:
--------------------------------------------------------------------------------
1 | package knuthMorrisPratt
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestMatchBlankPattern(t *testing.T) {
10 | result := Match("text", "")
11 | assert.Empty(t, result)
12 | }
13 |
14 | func TestMatchBlankText(t *testing.T) {
15 | result := Match("", "pattern")
16 | assert.Empty(t, result)
17 | }
18 |
19 | func TestMatchBlank(t *testing.T) {
20 | result := Match("", "")
21 | assert.Empty(t, result)
22 | }
23 |
24 | func TestMatchSimple(t *testing.T) {
25 | result := Match("abc", "b")
26 | assert.Equal(t, 1, len(result))
27 | assert.Contains(t, result, 1)
28 | }
29 |
30 | func TestMatchMultiple(t *testing.T) {
31 | result := Match("abcb", "b")
32 | assert.Equal(t, 2, len(result))
33 | assert.Contains(t, result, 1, 3)
34 | }
35 |
36 | func TestMatchLongPattern(t *testing.T) {
37 | result := Match("abcb", "cb")
38 | assert.Equal(t, 1, len(result))
39 | assert.Contains(t, result, 2)
40 | }
41 |
42 | func TestMatchLongPatternMultiple(t *testing.T) {
43 | result := Match("acbcacb", "cb")
44 | assert.Equal(t, 2, len(result))
45 | assert.Contains(t, result, 1, 5)
46 | }
47 |
48 | func TestMatchComplex(t *testing.T) {
49 | result := Match("acbcabcababcbabcaacb", "abcababcbabca")
50 | assert.Equal(t, 1, len(result))
51 | assert.Contains(t, result, 4)
52 | }
53 |
54 | func TestMatchNoMatch(t *testing.T) {
55 | result := Match("acbcacb", "xyz")
56 | assert.Empty(t, result)
57 | }
58 |
59 | func TestPrefixBlank(t *testing.T) {
60 | result := prefix("")
61 | assert.Empty(t, result)
62 | }
63 |
64 | func TestPrefixSimple(t *testing.T) {
65 | result := prefix("ab")
66 | assert.Equal(t, []int{0, 0}, result)
67 | }
68 |
69 | func TestPrefixLong(t *testing.T) {
70 | result := prefix("abcdefghij")
71 | assert.Equal(t, []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, result)
72 | }
73 |
74 | func TestPrefixSimpleRepeat(t *testing.T) {
75 | result := prefix("aba")
76 | assert.Equal(t, []int{0, 0, 1}, result)
77 | }
78 | func TestPrefixSimpleRepeatSame(t *testing.T) {
79 | result := prefix("aaa")
80 | assert.Equal(t, []int{0, 1, 2}, result)
81 | }
82 |
83 | func TestPrefixComplexRepeat(t *testing.T) {
84 | result := prefix("abcababcbabca")
85 | assert.Equal(t, []int{0, 0, 0, 1, 2, 1, 2, 3, 0, 1, 2, 3, 4}, result)
86 | }
87 |
--------------------------------------------------------------------------------
/kruskal/dsu.go:
--------------------------------------------------------------------------------
1 | package kruskal
2 |
3 | // Type holding parent pointer and rank for a DSU node
4 | type Node struct {
5 | parent *Node
6 | rank int
7 | }
8 |
9 | // Recursive implementation of find with path compression
10 | func Find(node *Node) *Node {
11 | // If a node is root of it's component then it has it's parent pointer set to nil
12 | if node.parent == nil {
13 | return node
14 | } else {
15 | node.parent = Find(node.parent)
16 | return node.parent
17 | }
18 | }
19 |
20 | // Implementation of union with ranks, returns a node being the root of the new component
21 | func Union(a, b *Node) *Node {
22 | a = Find(a)
23 | b = Find(b)
24 |
25 | if a == b {
26 | return a
27 | }
28 |
29 | // Swap nodes if needed so that b has higher rank
30 | if a.rank < b.rank {
31 | a, b = b, a
32 | }
33 |
34 | b.parent = a
35 | if a.rank == b.rank {
36 | a.rank++
37 | }
38 |
39 | return a
40 | }
41 |
--------------------------------------------------------------------------------
/kruskal/dsu_test.go:
--------------------------------------------------------------------------------
1 | package kruskal
2 |
3 | import "testing"
4 |
5 | // Tests the DSU implementation
6 | func TestDsu(t *testing.T) {
7 | // Creates 5 one-element sets
8 | nodes := make([]Node, 5)
9 |
10 | // Performs find on an one-element set
11 | if Find(&nodes[0]) != &nodes[0] {
12 | t.Error("Find on an newly created element should return itself")
13 | }
14 |
15 | Union(&nodes[0], &nodes[1])
16 | Union(&nodes[2], &nodes[3])
17 |
18 | if Find(&nodes[0]) != Find(&nodes[1]) {
19 | t.Error("Nodes after union should have equal representatives")
20 | }
21 |
22 | // Unions nodes 0, 1, 2, 3 into one set
23 | Union(&nodes[0], &nodes[3])
24 | Union(&nodes[1], &nodes[3])
25 |
26 | if Find(&nodes[0]) == Find(&nodes[4]) {
27 | t.Error("Nodes in different sets should have different representatives")
28 | }
29 |
30 | if Find(&nodes[0]) != Find(&nodes[2]) {
31 | t.Error("Nodes in the same set should have equal representatives")
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/kruskal/kruskal.go:
--------------------------------------------------------------------------------
1 | // Package provides an implementation of the Kruskal's minimum spanning forest algorithm
2 | // together with an implementation of disjoint set data structure
3 | package kruskal
4 |
5 | import "sort"
6 |
7 | // Type for edge data - endpoints u, v and length
8 | type Edge struct {
9 | u, v, length int
10 | }
11 |
12 | // Type required for calling the sort.Sort method
13 | type Edges []Edge
14 |
15 | func (edges Edges) Swap(i, j int) {
16 | edges[i], edges[j] = edges[j], edges[i]
17 | }
18 |
19 | func (edges Edges) Len() int {
20 | return len(edges)
21 | }
22 |
23 | func (edges Edges) Less(i, j int) bool {
24 | return edges[i].length < edges[j].length
25 | }
26 |
27 | // Computes the minimum spanning forest in a graph with vertices numbered from 0 to n-1
28 | // and a given set of edges.
29 | // Returns the subset of edges forming the minimum spanning forest.
30 | func MinimumSpanningForest(n int, edges []Edge) []Edge {
31 | forestEdges := make([]Edge, 0)
32 |
33 | // Disjoint set union that holds the division of the graph into connected components
34 | nodes := make([]Node, n)
35 |
36 | // Sort edges increasingly by length using the Less() function
37 | sort.Sort(Edges(edges))
38 |
39 | for _, edge := range edges {
40 | uNode := &nodes[edge.u]
41 | vNode := &nodes[edge.v]
42 |
43 | // If an edge connects two different components, add it to the forest
44 | if Find(uNode) != Find(vNode) {
45 | Union(uNode, vNode)
46 | forestEdges = append(forestEdges, edge)
47 | }
48 | }
49 |
50 | return forestEdges
51 | }
52 |
--------------------------------------------------------------------------------
/kruskal/kruskal_test.go:
--------------------------------------------------------------------------------
1 | package kruskal
2 |
3 | import "testing"
4 |
5 | // Tests the kruskal's algorithm
6 | func TestKruskal(t *testing.T) {
7 | edges := []Edge{{4, 5, 10}}
8 |
9 | for i := 0; i < 4; i++ {
10 | for j := i + 1; j < 4; j++ {
11 | edges = append(edges, Edge{i, j, j - i})
12 | }
13 | }
14 |
15 | // For the given test the answer has cost 13 and is unique
16 | forestEdges := MinimumSpanningForest(6, edges)
17 |
18 | if len(forestEdges) != 4 {
19 | t.Error("Returned set of edges has invalid size")
20 | }
21 |
22 | forestEdgesSet := make(map[Edge]bool)
23 | for _, edge := range forestEdges {
24 | forestEdgesSet[edge] = true
25 | }
26 |
27 | answer := []Edge{{4, 5, 10}}
28 |
29 | for i := 0; i < 3; i++ {
30 | answer = append(answer, Edge{i, i + 1, 1})
31 | }
32 |
33 | // Checking that each edge from the answer appears amongst the edges returned
34 | // by the algorithm
35 | for _, edge := range answer {
36 | if _, ok := forestEdgesSet[edge]; !ok {
37 | t.Error("Returned set of edges is not a minimum spanning forest")
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/linked-list/linked-list.go:
--------------------------------------------------------------------------------
1 | // Copyright 2009 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // Package list implements a doubly linked list.
6 | //
7 | // To iterate over a list (where l is a *List):
8 | // for e := l.Front(); e != nil; e = e.Next() {
9 | // // do something with e.Value
10 | // }
11 | //
12 | package list
13 |
14 | // Element is an element of a linked list.
15 | type Element struct {
16 | // Next and previous pointers in the doubly-linked list of elements.
17 | // To simplify the implementation, internally a list l is implemented
18 | // as a ring, such that &l.root is both the next element of the last
19 | // list element (l.Back()) and the previous element of the first list
20 | // element (l.Front()).
21 | next, prev *Element
22 |
23 | // The list to which this element belongs.
24 | list *List
25 |
26 | // The value stored with this element.
27 | Value interface{}
28 | }
29 |
30 | // Next returns the next list element or nil.
31 | func (e *Element) Next() *Element {
32 | if p := e.next; e.list != nil && p != &e.list.root {
33 | return p
34 | }
35 | return nil
36 | }
37 |
38 | // Prev returns the previous list element or nil.
39 | func (e *Element) Prev() *Element {
40 | if p := e.prev; e.list != nil && p != &e.list.root {
41 | return p
42 | }
43 | return nil
44 | }
45 |
46 | // List represents a doubly linked list.
47 | // The zero value for List is an empty list ready to use.
48 | type List struct {
49 | root Element // sentinel list element, only &root, root.prev, and root.next are used
50 | len int // current list length excluding (this) sentinel element
51 | }
52 |
53 | // Init initializes or clears list l.
54 | func (l *List) Init() *List {
55 | l.root.next = &l.root
56 | l.root.prev = &l.root
57 | l.len = 0
58 | return l
59 | }
60 |
61 | // New returns an initialized list.
62 | func New() *List { return new(List).Init() }
63 |
64 | // Len returns the number of elements of list l.
65 | // The complexity is O(1).
66 | func (l *List) Len() int { return l.len }
67 |
68 | // Front returns the first element of list l or nil.
69 | func (l *List) Front() *Element {
70 | if l.len == 0 {
71 | return nil
72 | }
73 | return l.root.next
74 | }
75 |
76 | // Back returns the last element of list l or nil.
77 | func (l *List) Back() *Element {
78 | if l.len == 0 {
79 | return nil
80 | }
81 | return l.root.prev
82 | }
83 |
84 | // lazyInit lazily initializes a zero List value.
85 | func (l *List) lazyInit() {
86 | if l.root.next == nil {
87 | l.Init()
88 | }
89 | }
90 |
91 | // insert inserts e after at, increments l.len, and returns e.
92 | func (l *List) insert(e, at *Element) *Element {
93 | n := at.next
94 | at.next = e
95 | e.prev = at
96 | e.next = n
97 | n.prev = e
98 | e.list = l
99 | l.len++
100 | return e
101 | }
102 |
103 | // insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
104 | func (l *List) insertValue(v interface{}, at *Element) *Element {
105 | return l.insert(&Element{Value: v}, at)
106 | }
107 |
108 | // remove removes e from its list, decrements l.len, and returns e.
109 | func (l *List) remove(e *Element) *Element {
110 | e.prev.next = e.next
111 | e.next.prev = e.prev
112 | e.next = nil // avoid memory leaks
113 | e.prev = nil // avoid memory leaks
114 | e.list = nil
115 | l.len--
116 | return e
117 | }
118 |
119 | // Remove removes e from l if e is an element of list l.
120 | // It returns the element value e.Value.
121 | func (l *List) Remove(e *Element) interface{} {
122 | if e.list == l {
123 | // if e.list == l, l must have been initialized when e was inserted
124 | // in l or l == nil (e is a zero Element) and l.remove will crash
125 | l.remove(e)
126 | }
127 | return e.Value
128 | }
129 |
130 | // PushFront inserts a new element e with value v at the front of list l and returns e.
131 | func (l *List) PushFront(v interface{}) *Element {
132 | l.lazyInit()
133 | return l.insertValue(v, &l.root)
134 | }
135 |
136 | // PushBack inserts a new element e with value v at the back of list l and returns e.
137 | func (l *List) PushBack(v interface{}) *Element {
138 | l.lazyInit()
139 | return l.insertValue(v, l.root.prev)
140 | }
141 |
142 | // InsertBefore inserts a new element e with value v immediately before mark and returns e.
143 | // If mark is not an element of l, the list is not modified.
144 | func (l *List) InsertBefore(v interface{}, mark *Element) *Element {
145 | if mark.list != l {
146 | return nil
147 | }
148 | // see comment in List.Remove about initialization of l
149 | return l.insertValue(v, mark.prev)
150 | }
151 |
152 | // InsertAfter inserts a new element e with value v immediately after mark and returns e.
153 | // If mark is not an element of l, the list is not modified.
154 | func (l *List) InsertAfter(v interface{}, mark *Element) *Element {
155 | if mark.list != l {
156 | return nil
157 | }
158 | // see comment in List.Remove about initialization of l
159 | return l.insertValue(v, mark)
160 | }
161 |
162 | // MoveToFront moves element e to the front of list l.
163 | // If e is not an element of l, the list is not modified.
164 | func (l *List) MoveToFront(e *Element) {
165 | if e.list != l || l.root.next == e {
166 | return
167 | }
168 | // see comment in List.Remove about initialization of l
169 | l.insert(l.remove(e), &l.root)
170 | }
171 |
172 | // MoveToBack moves element e to the back of list l.
173 | // If e is not an element of l, the list is not modified.
174 | func (l *List) MoveToBack(e *Element) {
175 | if e.list != l || l.root.prev == e {
176 | return
177 | }
178 | // see comment in List.Remove about initialization of l
179 | l.insert(l.remove(e), l.root.prev)
180 | }
181 |
182 | // MoveBefore moves element e to its new position before mark.
183 | // If e or mark is not an element of l, or e == mark, the list is not modified.
184 | func (l *List) MoveBefore(e, mark *Element) {
185 | if e.list != l || e == mark || mark.list != l {
186 | return
187 | }
188 | l.insert(l.remove(e), mark.prev)
189 | }
190 |
191 | // MoveAfter moves element e to its new position after mark.
192 | // If e or mark is not an element of l, or e == mark, the list is not modified.
193 | func (l *List) MoveAfter(e, mark *Element) {
194 | if e.list != l || e == mark || mark.list != l {
195 | return
196 | }
197 | l.insert(l.remove(e), mark)
198 | }
199 |
200 | // PushBackList inserts a copy of an other list at the back of list l.
201 | // The lists l and other may be the same.
202 | func (l *List) PushBackList(other *List) {
203 | l.lazyInit()
204 | for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
205 | l.insertValue(e.Value, l.root.prev)
206 | }
207 | }
208 |
209 | // PushFrontList inserts a copy of an other list at the front of list l.
210 | // The lists l and other may be the same.
211 | func (l *List) PushFrontList(other *List) {
212 | l.lazyInit()
213 | for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
214 | l.insertValue(e.Value, &l.root)
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/linked-list/linked-list_test.go:
--------------------------------------------------------------------------------
1 | package list_test
2 |
3 | import (
4 | "container/list"
5 | "fmt"
6 | "testing"
7 | )
8 |
9 | //create three lists globally
10 | var l = list.New()
11 | var a = list.New()
12 | var b = list.New()
13 |
14 | //method to print list head to tail
15 | func printHeadToTail(l *list.List) {
16 | fmt.Printf("list: ")
17 | for e := l.Front(); e != nil; e = e.Next() {
18 | fmt.Printf("%v ", e.Value)
19 | }
20 | fmt.Println()
21 | }
22 |
23 | //method to print list tail to head
24 | func printTailToHead(l *list.List) {
25 | fmt.Printf("list (reversed): ")
26 | for e := l.Back(); e != nil; e = e.Prev() {
27 | fmt.Printf("%v ", e.Value)
28 | }
29 | fmt.Println()
30 | }
31 |
32 | func TestLinkedListMethods(t *testing.T) {
33 |
34 | //fmt.Println(reflect.TypeOf(l))
35 |
36 | //list l = [3,4,5]
37 | e3 := l.PushBack(3)
38 | l.PushBack(4)
39 | e5 := l.PushBack(5)
40 |
41 | fmt.Println("List l:")
42 | printHeadToTail(l)
43 |
44 | fmt.Println("\nInsertBefore(2, element3):")
45 | //pass 2, and 6 to list using
46 | //InsertBefore and InsertAfter methods
47 | l.InsertBefore(2, e3) //[(2),3,4,5]
48 | printHeadToTail(l)
49 |
50 | fmt.Println("\nInsertAfter(6, element5):")
51 | l.InsertAfter(6, e5) //[(2),3,4,5,(6)]
52 | printHeadToTail(l)
53 |
54 | //list a = [0,1]
55 | a.PushBack(0)
56 | a.PushBack(1)
57 |
58 | fmt.Println("\nList a:")
59 | printHeadToTail(a)
60 |
61 | //list b = [7,8]
62 | b.PushBack(7)
63 | b.PushBack(8)
64 |
65 | fmt.Println("\nList b:")
66 | printHeadToTail(b)
67 |
68 | fmt.Println("\nPushFrontList(a):")
69 | //append list a to the head (front) of the list
70 | //using PushFrontList
71 | l.PushFrontList(a) //([0,1],2,3,4,5)
72 | printHeadToTail(l)
73 |
74 | fmt.Println("\nPushBackList(b):")
75 | //append list b to the tail (back) of the list
76 | //using PushBackList
77 | l.PushBackList(b) //([0,1],2,3,4,5,6,[7,8])
78 | printHeadToTail(l)
79 |
80 | //print list length (0,1,2,3,4,5,6,7,8) => 9 elements
81 | fmt.Println("\nLinked list length:", l.Len())
82 |
83 | fmt.Println("\nPrint list in reverse:")
84 | //print out elements (tail to head)
85 | printTailToHead(l)
86 |
87 | eMinus1 := l.PushBack(-1)
88 | e9 := l.PushFront(9)
89 |
90 | fmt.Println("\nPushBack(-1) and PushFront(9):")
91 | printHeadToTail(l)
92 |
93 | l.MoveToFront(eMinus1)
94 | l.MoveToBack(e9)
95 |
96 | fmt.Println("\nMoveToFront(-1) and MoveToBack(9):")
97 | printHeadToTail(l)
98 |
99 | fmt.Println("\nRemove(Front()):")
100 | e := l.Front() //-1
101 | l.Remove(e)
102 | printHeadToTail(l)
103 |
104 | fmt.Println("\nMoveBefore(Front(), Back())")
105 | e = l.Front() //0
106 | f := l.Back()
107 | l.MoveBefore(e, f)
108 | printHeadToTail(l)
109 |
110 | fmt.Println("\nMoveAfter(Front(), Back())")
111 | l.MoveAfter(e, f)
112 | printHeadToTail(l)
113 | }
114 |
--------------------------------------------------------------------------------
/ludecomposition/ludecomposition.go:
--------------------------------------------------------------------------------
1 | // Package provides an algorithm for constructing the LU decomposition
2 | // (with pivoting) of a given matrix.
3 | package ludecomposition
4 |
5 | import (
6 | "errors"
7 | "math"
8 | )
9 |
10 | // Applies pivoting to the input. If the given matrix is invertible,
11 | // after pivotization there are no zeros on the main diagonal.
12 | // Returns the permutation that was applied on the rows of the matrix.
13 | func pivotize(matrix [][]float64) (perm []int) {
14 | n := len(matrix)
15 | perm = make([]int, n)
16 |
17 | // Initialize perm to identity permutation
18 | for i := range perm {
19 | perm[i] = i
20 | }
21 |
22 | for i := range matrix {
23 | max := matrix[i][i]
24 | pos := i
25 |
26 | // Extract maximum from the values in matrix[i:n-1][i]
27 | for j := i; j < n; j++ {
28 | if matrix[j][i] > max {
29 | max = matrix[j][i]
30 | pos = j
31 | }
32 | }
33 |
34 | // Swap rows bringing the maximum value to the main diagonal
35 | if pos != i {
36 | perm[i], perm[pos] = perm[pos], perm[i]
37 | matrix[i], matrix[pos] = matrix[pos], matrix[i]
38 | }
39 | }
40 |
41 | return perm
42 | }
43 |
44 | // Returns an n x n identity matrix.
45 | func identityMatrix(n int) (matrix [][]float64) {
46 | matrix = make([][]float64, n)
47 |
48 | for i := range matrix {
49 | matrix[i] = make([]float64, n)
50 |
51 | for j := range matrix[i] {
52 | matrix[i][j] = 0.0
53 | }
54 |
55 | matrix[i][i] = 1.0
56 | }
57 |
58 | return
59 | }
60 |
61 | // Implementation of the LU decomposition algorithm.
62 | // Returns L, U and perm, where L and U form the decomposition,
63 | // and perm is the row permutation applied during pivoting.
64 | // The L matrix has only ones on it's main diagonal, which makes the returned solution
65 | // uniquely defined.
66 | // Raises an error if the input matrix is non-invertible.
67 | func FindLuDecomposition(matrix [][]float64) ([][]float64, [][]float64, []int, error) {
68 | var EPSILON float64 = 1e-9
69 |
70 | n := len(matrix)
71 |
72 | l := identityMatrix(n)
73 | u := make([][]float64, n)
74 |
75 | // Initialize u as a deep copy of the input matrix
76 | for i := range u {
77 | u[i] = make([]float64, n)
78 | copy(u[i], matrix[i])
79 | }
80 |
81 | perm := pivotize(u)
82 |
83 | for i := range u {
84 | // If after pivotization there are values equal to zero on the main diagonal
85 | // it means that the input matrix is singular, and thus there is no solution
86 | if math.Abs(u[i][i]) < EPSILON {
87 | return nil, nil, nil, errors.New("matrix is singular")
88 | }
89 | }
90 |
91 | for i := range u {
92 | for j := i + 1; j < n; j++ {
93 | ratio := u[j][i] / u[i][i]
94 |
95 | // Zero out u[j][i] by subtracting from the j'th row the i'th row
96 | // multiplied by a suitable coefficient
97 | for k := 0; k < n; k++ {
98 | u[j][k] -= ratio * u[i][k]
99 | }
100 |
101 | // Permorm an analogous column-wise operation
102 | // in order to keep the L*U product constant
103 | for k := 0; k < n; k++ {
104 | l[k][i] += ratio * l[k][j]
105 | }
106 | }
107 | }
108 |
109 | return l, u, perm, nil
110 | }
111 |
--------------------------------------------------------------------------------
/ludecomposition/ludecomposition_test.go:
--------------------------------------------------------------------------------
1 | package ludecomposition
2 |
3 | import (
4 | "math"
5 | "reflect"
6 | "testing"
7 | )
8 |
9 | // Holds input and output for a testcase
10 | type testdata struct {
11 | matrix [][]float64
12 | l [][]float64
13 | u [][]float64
14 | perm []int
15 | }
16 |
17 | var tests = []testdata{
18 | {[][]float64{{4.0, 3.0}, {6.0, 3.0}},
19 | [][]float64{{1.0, 0.0}, {2.0 / 3.0, 1.0}},
20 | [][]float64{{6.0, 3.0}, {0.0, 1.0}},
21 | []int{1, 0}},
22 | {[][]float64{{3.0, 6.0}, {-3.0, -5.0}},
23 | [][]float64{{1.0, 0.0}, {-1.0, 1.0}},
24 | [][]float64{{3.0, 6.0}, {0.0, 1.0}},
25 | []int{0, 1}},
26 | {[][]float64{{1.0, 2.0, 1.0}, {3.0, 3.0, 1.0}, {0.0, 9.0, 1.0}},
27 | [][]float64{{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0 / 9.0, 1.0 / 9.0, 1.0}},
28 | [][]float64{{3.0, 3.0, 1.0}, {0.0, 9.0, 1.0}, {0.0, 0.0, 5.0 / 9.0}},
29 | []int{1, 2, 0}},
30 | }
31 |
32 | // Compares two matrices for equality, considering floating point values
33 | // with absolute difference less than 1e-9 as equal.
34 | func areEqual(a, b [][]float64) bool {
35 | var EPSILON float64 = 1e-9
36 |
37 | if len(a) != len(b) {
38 | return false
39 | }
40 |
41 | for i := range a {
42 | if len(a[i]) != len(b[i]) {
43 | return false
44 | }
45 |
46 | for j := range a[i] {
47 | if math.Abs(a[i][j]-b[i][j]) > EPSILON {
48 | return false
49 | }
50 | }
51 | }
52 |
53 | return true
54 | }
55 |
56 | // Tests the algorithm for LU decomposition. Note that, assuming L has only ones on
57 | // its main diagonal, the solution is unique.
58 | func TestLuDecomposition(t *testing.T) {
59 | for _, test := range tests {
60 | l, u, perm, err := FindLuDecomposition(test.matrix)
61 |
62 | if err != nil {
63 | t.Error("Error occurred:", err)
64 | }
65 |
66 | if !areEqual(l, test.l) {
67 | t.Error(
68 | "For input", test.matrix,
69 | "expected L", test.l,
70 | "got", l,
71 | )
72 | }
73 |
74 | if !areEqual(u, test.u) {
75 | t.Error(
76 | "For input", test.matrix,
77 | "expected U", test.u,
78 | "got", u,
79 | )
80 | }
81 |
82 | if !reflect.DeepEqual(perm, test.perm) {
83 | t.Error(
84 | "For input", test.matrix,
85 | "expected permutation", test.perm,
86 | "got", perm,
87 | )
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/mergesort/mergesort.go:
--------------------------------------------------------------------------------
1 | // Package mergesort provides an implementation for merge sort sorting algorithm
2 | package mergesort
3 |
4 | // MergeSort receives a slice and returns a new sorted slice
5 | func MergeSort(array []int) []int {
6 | if len(array) <= 1 {
7 | result := make([]int, len(array))
8 | copy(result, array)
9 | return result
10 | }
11 |
12 | mid := len(array) / 2
13 | leftArray := MergeSort(array[:mid])
14 | rightArray := MergeSort(array[mid:])
15 |
16 | result := make([]int, len(array))
17 |
18 | arrayIndex := 0
19 | leftIndex := 0
20 | rightIndex := 0
21 | for leftIndex < len(leftArray) && rightIndex < len(rightArray) {
22 | if leftArray[leftIndex] <= rightArray[rightIndex] {
23 | result[arrayIndex] = leftArray[leftIndex]
24 | leftIndex++
25 | } else {
26 | result[arrayIndex] = rightArray[rightIndex]
27 | rightIndex++
28 | }
29 | arrayIndex++
30 | }
31 |
32 | for leftIndex < len(leftArray) {
33 | result[arrayIndex] = leftArray[leftIndex]
34 | leftIndex++
35 | arrayIndex++
36 | }
37 |
38 | for rightIndex < len(rightArray) {
39 | result[arrayIndex] = rightArray[rightIndex]
40 | rightIndex++
41 | arrayIndex++
42 | }
43 |
44 | return result
45 | }
46 |
--------------------------------------------------------------------------------
/mergesort/mergesort_test.go:
--------------------------------------------------------------------------------
1 | package mergesort
2 |
3 | import (
4 | "math/rand"
5 | "reflect"
6 | "sort"
7 | "testing"
8 | "time"
9 | )
10 |
11 | func TestMergeSort(t *testing.T) {
12 | empty := []int{}
13 | resultEmpty := MergeSort(empty)
14 |
15 | if !reflect.DeepEqual(empty, resultEmpty) {
16 | t.Error("ERROR!", "Expected:", empty, "Result:", resultEmpty)
17 | return
18 | }
19 |
20 | unitary := []int{1921}
21 | resultUnitary := MergeSort(unitary)
22 |
23 | if !reflect.DeepEqual(unitary, resultUnitary) {
24 | t.Error("ERROR!", "Expected:", unitary, "Result:", resultUnitary)
25 | return
26 | }
27 |
28 | rand.Seed(int64(time.Now().Nanosecond()))
29 | for test := 0; test < 10; test++ {
30 | array := make([]int, 100)
31 | for i := 0; i < 100; i++ {
32 | array[i] = rand.Int()
33 | }
34 |
35 | expected := make([]int, 100)
36 | copy(expected, array)
37 | sort.Ints(expected)
38 |
39 | result := MergeSort(array)
40 |
41 | if !reflect.DeepEqual(result, expected) {
42 | t.Error("ERROR!", "Expected:", expected, "Result:", result)
43 | return
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/qsort/qsort.go:
--------------------------------------------------------------------------------
1 | /*Package qsort -- Quick Sort Algorithm Data structure implementation: */
2 | /* This Algorithm takes an slice of integers and */
3 | /* sort using the qsort() algorithm below */
4 | /* Author: Alangi Derick (@d3r1ck)*/
5 | package qsort
6 |
7 | import "math/rand"
8 |
9 | /*Qsort (As GoLang standard, the function in a package should */
10 | /* start with Upper case letter) */
11 | func Qsort(slice []int) []int {
12 |
13 | /* Check if the slice has just a single cell */
14 | /* If it does have just a single cell, return */
15 | /* the slice. */
16 | if len(slice) < 2 {
17 | return slice
18 | }
19 |
20 | left, right := 0, len(slice)-1
21 |
22 | /* Pick a pivot in the slice */
23 | pivotIndex := rand.Int() % len(slice)
24 |
25 | /* Move pivot to the right of slice */
26 | slice[pivotIndex], slice[right] = slice[right], slice[pivotIndex]
27 |
28 | /* Move elements smaller than pivot to the left */
29 | for i := range slice {
30 | if slice[i] < slice[right] {
31 | slice[i], slice[left] = slice[left], slice[i]
32 | left++
33 | }
34 |
35 | }
36 |
37 | /* Place the pivot after the last smaller element */
38 | slice[left], slice[right] = slice[right], slice[left]
39 |
40 | /* Do a recursive call to the Qsort function */
41 | /* with new values to sort entire slice */
42 | Qsort(slice[:left])
43 | Qsort(slice[left+1:])
44 |
45 | return slice
46 | }
47 |
--------------------------------------------------------------------------------
/qsort/qsort_test.go:
--------------------------------------------------------------------------------
1 | /* Testing the Qsort() function in the qsort package */
2 | /* Author: Alangi Derick (@d3r1ck), Date: 10/10/2016 */
3 |
4 | package qsort
5 |
6 | import (
7 | "reflect"
8 | "testing"
9 | )
10 |
11 | /* Test pair for Qsort() algorithm */
12 | type testpair struct {
13 | unsortedSlice []int
14 | sortedSlice []int
15 | }
16 |
17 | /* Test instance of testpair the unsorted and sorted slices */
18 | var tests = []testpair{
19 | {
20 | unsortedSlice: []int{3, 2, 1, 5, 6, 3, 7, 8, 9},
21 | sortedSlice: []int{1, 2, 3, 3, 5, 6, 7, 8, 9},
22 | },
23 | {
24 | unsortedSlice: []int{1, 4, 2, 3},
25 | sortedSlice: []int{1, 2, 3, 4}},
26 | }
27 |
28 | /* Test case to test the Qsort function */
29 | func TestQsort(t *testing.T) {
30 | for _, pair := range tests {
31 | sorted := Qsort(pair.unsortedSlice)
32 |
33 | if !reflect.DeepEqual(sorted, pair.sortedSlice) {
34 | t.Error(
35 | "For", pair.unsortedSlice,
36 | "expected", pair.sortedSlice,
37 | "got", sorted,
38 | )
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/queuestack/queue.go:
--------------------------------------------------------------------------------
1 | package queuestack
2 |
3 | import "errors"
4 |
5 | // Queue represents a collection data structure with FIFO (First In First Out) semantics).
6 | type Queue interface {
7 | Enqueue(value interface{})
8 | Dequeue() (interface{}, error)
9 | Peek() (interface{}, error)
10 | Empty() bool
11 | }
12 |
13 | type queue struct {
14 | data []interface{}
15 | size int
16 | }
17 |
18 | func (q *queue) Enqueue(value interface{}) {
19 | q.data = append(q.data, value)
20 | q.size++
21 | }
22 |
23 | func (q *queue) Dequeue() (interface{}, error) {
24 | if q.size > 0 {
25 | value := q.data[0]
26 | q.size--
27 | q.data = q.data[1:]
28 |
29 | return value, nil
30 | }
31 |
32 | return nil, errors.New("no such element")
33 | }
34 |
35 | func (q *queue) Peek() (interface{}, error) {
36 | if q.size > 0 {
37 | value := q.data[0]
38 | return value, nil
39 | }
40 |
41 | return nil, errors.New("no such element")
42 | }
43 |
44 | func (q *queue) Empty() bool {
45 | return q.size == 0
46 | }
47 |
48 | // NewQueue returns an empty queue.
49 | func NewQueue() Queue {
50 | return &queue{}
51 | }
52 |
--------------------------------------------------------------------------------
/queuestack/queue_test.go:
--------------------------------------------------------------------------------
1 | package queuestack
2 |
3 | import "testing"
4 |
5 | func TestQueueIsInitiallyEmpty(t *testing.T) {
6 | q := NewQueue()
7 |
8 | if !q.Empty() {
9 | t.Error("newly created queue should contain no elements!")
10 | }
11 | }
12 |
13 | func TestQueueIsNonEmptyAfterEnqueue(t *testing.T) {
14 | q := NewQueue()
15 |
16 | q.Enqueue(1)
17 |
18 | if q.Empty() {
19 | t.Error("queue should not be empty after enqueue-ing any elements!")
20 | }
21 | }
22 |
23 | func TestQueueIsEmptyAfterEnqueueAndDequeue(t *testing.T) {
24 | q := NewQueue()
25 |
26 | q.Enqueue(1)
27 | v, err := q.Dequeue()
28 |
29 | if !q.Empty() {
30 | t.Error("queue should be empty after enqueue-ing and dequeue-ing an element!")
31 | }
32 |
33 | if err != nil {
34 | t.Error("there should not have been anything erroneous occurring after enqueueing and dequeueing an element!")
35 | }
36 |
37 | if v != 1 {
38 | t.Error("value dequeued should be the same as what was enqueued got:", v, "want:", 1)
39 | }
40 | }
41 |
42 | func TestDequeueingAnEmptyQueueErrors(t *testing.T) {
43 | q := NewQueue()
44 |
45 | _, err := q.Dequeue()
46 |
47 | if err == nil {
48 | t.Error("queue should have errored when it was dequeued while empty!")
49 | }
50 | }
51 |
52 | func TestPeekingAnEmptyQueueErrors(t *testing.T) {
53 | q := NewQueue()
54 |
55 | _, err := q.Peek()
56 |
57 | if err == nil {
58 | t.Error("queue should have errored when it was dequeued while empty!")
59 | }
60 | }
61 |
62 | func TestPeekReturnsHeadOfQueue(t *testing.T) {
63 | q := NewQueue()
64 |
65 | q.Enqueue(1)
66 | q.Enqueue(2)
67 |
68 | v, err := q.Peek()
69 |
70 | if err != nil {
71 | t.Error("there should have been nothing erroneous that occurred.")
72 | }
73 |
74 | if v != 1 {
75 | t.Error("queue should have returned the first value in line!")
76 | }
77 | }
78 |
79 | func TestQueueIsFIFOCompliant(t *testing.T) {
80 | q := NewQueue()
81 |
82 | values := []interface{}{0, 1, 2, 3}
83 |
84 | for _, v := range values {
85 | q.Enqueue(v)
86 | }
87 |
88 | for _, v := range values {
89 | dequeued, err := q.Dequeue()
90 |
91 | if err != nil {
92 | t.Fatal("encountered unexpected error:", err)
93 | }
94 |
95 | if v != dequeued {
96 | t.Error("queue is not FIFO compliant")
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/queuestack/stack.go:
--------------------------------------------------------------------------------
1 | package queuestack
2 |
3 | import "errors"
4 |
5 | // Stack represents a collection data structure with LIFO (Last In First Out) semantics).
6 | type Stack interface {
7 | Push(value interface{})
8 | Pop() (interface{}, error)
9 | Peek() (interface{}, error)
10 | Empty() bool
11 | }
12 |
13 | type stack struct {
14 | data []interface{}
15 | size int
16 | }
17 |
18 | func (s *stack) Push(value interface{}) {
19 | s.data = append(s.data, value)
20 | s.size++
21 | }
22 |
23 | func (s *stack) Pop() (interface{}, error) {
24 | if s.size > 0 {
25 | value := s.data[s.size-1]
26 | s.size--
27 | s.data = s.data[:s.size]
28 | return value, nil
29 | }
30 |
31 | return nil, errors.New("no such element")
32 | }
33 |
34 | func (s *stack) Peek() (interface{}, error) {
35 | if s.size > 0 {
36 | value := s.data[s.size-1]
37 | return value, nil
38 | }
39 |
40 | return nil, errors.New("no such element")
41 | }
42 |
43 | func (s *stack) Empty() bool {
44 | return s.size == 0
45 | }
46 |
47 | // NewStack returns an empty stack.
48 | func NewStack() Stack {
49 | return &stack{}
50 | }
51 |
--------------------------------------------------------------------------------
/queuestack/stack_test.go:
--------------------------------------------------------------------------------
1 | package queuestack
2 |
3 | import "testing"
4 |
5 | func TestStackIsInitiallyEmpty(t *testing.T) {
6 | s := NewStack()
7 |
8 | if !s.Empty() {
9 | t.Error("newly created stack should contain no elements!")
10 | }
11 | }
12 |
13 | func TestStackIsNonEmptyAfterPush(t *testing.T) {
14 | s := NewStack()
15 |
16 | s.Push(1)
17 |
18 | if s.Empty() {
19 | t.Error("stack should not be empty after pushing any elements!")
20 | }
21 | }
22 |
23 | func TestStackIsEmptyAfterPushAndPop(t *testing.T) {
24 | s := NewStack()
25 |
26 | s.Push(1)
27 | v, err := s.Pop()
28 |
29 | if !s.Empty() {
30 | t.Error("stack should be empty after pushing and popping an element!")
31 | }
32 |
33 | if err != nil {
34 | t.Error("there should not have been anything erroneous occurring after pushing and popping an element:", err)
35 | }
36 |
37 | if v != 1 {
38 | t.Error("value popped should be the same as what was pushed! got:", v, "want:", 1)
39 | }
40 | }
41 |
42 | func TestPoppingAnEmptyStackErrors(t *testing.T) {
43 | s := NewStack()
44 |
45 | _, err := s.Pop()
46 |
47 | if err == nil {
48 | t.Error("stack should have errored when it was popped while empty!")
49 | }
50 | }
51 |
52 | func TestPeekingAnEmptyStackErrors(t *testing.T) {
53 | s := NewStack()
54 |
55 | _, err := s.Peek()
56 |
57 | if err == nil {
58 | t.Error("stack should have errored when it was peeked while empty!")
59 | }
60 | }
61 |
62 | func TestPeekReturnsTopOfStack(t *testing.T) {
63 | s := NewStack()
64 |
65 | s.Push(1)
66 | s.Push(2)
67 |
68 | v, err := s.Peek()
69 |
70 | if err != nil {
71 | t.Error("there should have been nothing erroneous that occurred:", err)
72 | }
73 |
74 | if v != 2 {
75 | t.Error("stack should have returned the top value on the stack! got:", v, "want:", 2)
76 | }
77 | }
78 |
79 | func TestStackIsLIFOCompliant(t *testing.T) {
80 | s := NewStack()
81 |
82 | values := []interface{}{0, 1, 2, 3}
83 |
84 | for _, v := range values {
85 | s.Push(v)
86 | }
87 |
88 | offset := len(values) - 1
89 | for !s.Empty() {
90 | val, err := s.Pop()
91 |
92 | if err != nil {
93 | t.Fatal("encountered unexpected error:", err)
94 | }
95 |
96 | if val != values[offset] {
97 | t.Error("stack is not LIFO compliant")
98 | }
99 |
100 | offset--
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/rabinkarp/rabinkarp.go:
--------------------------------------------------------------------------------
1 | package rabinkarp
2 |
3 | const base = 2048
4 |
5 | // Search searches given patterns in txt and returns the matched ones. Returns
6 | // empty string slice if there is no match.
7 | func Search(txt string, patterns []string) []string {
8 | in := Indices(txt, patterns)
9 | matches := make([]string, len(in))
10 | i := 0
11 | for j, p := range patterns {
12 | if _, ok := in[j]; ok {
13 | matches[i] = p
14 | i++
15 | }
16 | }
17 |
18 | return matches
19 | }
20 |
21 | // Indices returns the Indices of the first occurrence of each pattern in txt.
22 | func Indices(txt string, patterns []string) map[int]int {
23 | n, m := len(txt), MinLen(patterns)
24 | matches := make(map[int]int)
25 |
26 | if n < m || len(patterns) == 0 {
27 | return matches
28 | }
29 |
30 | var mult uint32 = 1 // mult = base^(m-1)
31 | for i := 0; i < m-1; i++ {
32 | mult = (mult * base)
33 | }
34 |
35 | hp := HashPatterns(patterns, m)
36 | h := Hash(txt[:m])
37 | for i := 0; i < n-m+1 && len(hp) > 0; i++ {
38 | if i > 0 {
39 | h = h - mult*uint32(txt[i-1])
40 | h = h*base + uint32(txt[i+m-1])
41 | }
42 |
43 | if mps, ok := hp[h]; ok {
44 | for _, pi := range mps {
45 | pat := patterns[pi]
46 | e := i + len(pat)
47 | if _, ok := matches[pi]; !ok && e <= n && pat == txt[i:e] {
48 | matches[pi] = i
49 | }
50 | }
51 | }
52 | }
53 | return matches
54 | }
55 |
56 | // Hash converts a string into a uint32 hash.
57 | func Hash(s string) uint32 {
58 | var h uint32
59 | for i := 0; i < len(s); i++ {
60 | h = (h*base + uint32(s[i]))
61 | }
62 | return h
63 | }
64 |
65 | // HashPatterns takes a slice of patterns and creates a map of
66 | // patterns to their hashed value.
67 | func HashPatterns(patterns []string, l int) map[uint32][]int {
68 | m := make(map[uint32][]int)
69 | for i, t := range patterns {
70 | h := Hash(t[:l])
71 | if _, ok := m[h]; ok {
72 | m[h] = append(m[h], i)
73 | } else {
74 | m[h] = []int{i}
75 | }
76 | }
77 |
78 | return m
79 | }
80 |
81 | // MinLen returns the patterns of the smallest length.
82 | func MinLen(patterns []string) int {
83 | if len(patterns) == 0 {
84 | return 0
85 | }
86 |
87 | m := len(patterns[0])
88 | for i := range patterns {
89 | if m > len(patterns[i]) {
90 | m = len(patterns[i])
91 | }
92 | }
93 |
94 | return m
95 | }
96 |
--------------------------------------------------------------------------------
/rabinkarp/rabinkarp_test.go:
--------------------------------------------------------------------------------
1 | package rabinkarp
2 |
3 | import (
4 | "reflect"
5 | "sort"
6 | "testing"
7 | )
8 |
9 | // Struct for test data
10 | var SearchTests = []struct {
11 | txt string
12 | patterns []string
13 | expected []string
14 | }{
15 | {"walter h white", []string{"white", "pinkman", "walter"}, []string{"walter", "white"}},
16 | {"damon salvatore", []string{"damon", "stephen", "salvatore"}, []string{"damon", "salvatore"}},
17 | }
18 |
19 | // run testcase
20 | func TestSearch(t *testing.T) {
21 | for _, ct := range SearchTests {
22 | found := Search(ct.txt, ct.patterns)
23 | if !eq(found, ct.expected) {
24 | t.Error("Broken test .....",
25 | ct.txt, ct.patterns, found, ct.expected)
26 | }
27 | }
28 | }
29 |
30 | // sort string for comparison
31 | func eq(f, s []string) bool {
32 | fx := make([]string, len(f))
33 | sx := make([]string, len(s))
34 | copy(fx, f)
35 | copy(sx, s)
36 |
37 | sort.Strings(fx)
38 | sort.Strings(sx)
39 | return reflect.DeepEqual(fx, sx)
40 | }
41 |
--------------------------------------------------------------------------------
/rbtree/rbtree.go:
--------------------------------------------------------------------------------
1 | package rbtree
2 |
3 | import "fmt"
4 |
5 | // color of node
6 | const (
7 | RED = 0
8 | BLACK = 1
9 | )
10 |
11 | type keytype interface {
12 | LessThan(interface{}) bool
13 | }
14 |
15 | type valuetype interface{}
16 |
17 | type node struct {
18 | left, right, parent *node
19 | color int
20 | Key keytype
21 | Value valuetype
22 | }
23 |
24 | // Tree is a struct of red-black tree
25 | type Tree struct {
26 | root *node
27 | size int
28 | }
29 |
30 | // NewTree returns a new rbtree
31 | func NewTree() *Tree {
32 | return &Tree{}
33 | }
34 |
35 | // Find finds the node and return its value
36 | func (t *Tree) Find(key keytype) interface{} {
37 | n := t.findnode(key)
38 | if n != nil {
39 | return n.Value
40 | }
41 | return nil
42 | }
43 |
44 | // FindIt finds the node and return it as a iterator
45 | func (t *Tree) FindIt(key keytype) *node {
46 | return t.findnode(key)
47 | }
48 |
49 | // Empty checks whether the rbtree is empty
50 | func (t *Tree) Empty() bool {
51 | if t.root == nil {
52 | return true
53 | }
54 | return false
55 | }
56 |
57 | // Iterator creates the rbtree's iterator that points to the minmum node
58 | func (t *Tree) Iterator() *node {
59 | return minimum(t.root)
60 | }
61 |
62 | // Size returns the size of the rbtree
63 | func (t *Tree) Size() int {
64 | return t.size
65 | }
66 |
67 | // Clear destroys the rbtree
68 | func (t *Tree) Clear() {
69 | t.root = nil
70 | t.size = 0
71 | }
72 |
73 | // Insert inserts the key-value pair into the rbtree
74 | func (t *Tree) Insert(key keytype, value valuetype) {
75 | x := t.root
76 | var y *node
77 |
78 | for x != nil {
79 | y = x
80 | if key.LessThan(x.Key) {
81 | x = x.left
82 | } else {
83 | x = x.right
84 | }
85 | }
86 |
87 | z := &node{parent: y, color: RED, Key: key, Value: value}
88 | t.size++
89 |
90 | if y == nil {
91 | z.color = BLACK
92 | t.root = z
93 | return
94 | } else if z.Key.LessThan(y.Key) {
95 | y.left = z
96 | } else {
97 | y.right = z
98 | }
99 | t.rbInsertFixup(z)
100 |
101 | }
102 |
103 | // Delete deletes the node by key
104 | func (t *Tree) Delete(key keytype) {
105 | z := t.findnode(key)
106 | if z == nil {
107 | return
108 | }
109 |
110 | var x, y, parent *node
111 | y = z
112 | yOriginalColor := y.color
113 | parent = z.parent
114 | if z.left == nil {
115 | x = z.right
116 | t.transplant(z, z.right)
117 | } else if z.right == nil {
118 | x = z.left
119 | t.transplant(z, z.left)
120 | } else {
121 | y = minimum(z.right)
122 | yOriginalColor = y.color
123 | x = y.right
124 |
125 | if y.parent == z {
126 | if x == nil {
127 | parent = y
128 | } else {
129 | x.parent = y
130 | }
131 | } else {
132 | t.transplant(y, y.right)
133 | y.right = z.right
134 | y.right.parent = y
135 | }
136 | t.transplant(z, y)
137 | y.left = z.left
138 | y.left.parent = y
139 | y.color = z.color
140 | }
141 |
142 | if yOriginalColor == BLACK {
143 | t.rbDeleteFixup(x, parent)
144 | }
145 | t.size--
146 | }
147 |
148 | func (t *Tree) rbInsertFixup(z *node) {
149 | var y *node
150 | for z.parent != nil && z.parent.color == RED {
151 | if z.parent == z.parent.parent.left {
152 | y = z.parent.parent.right
153 | if y != nil && y.color == RED {
154 | z.parent.color = BLACK
155 | y.color = BLACK
156 | z.parent.parent.color = RED
157 | z = z.parent.parent
158 | } else {
159 | if z == z.parent.right {
160 | z = z.parent
161 | t.leftRotate(z)
162 | }
163 | z.parent.color = BLACK
164 | z.parent.parent.color = RED
165 | t.rightRotate(z.parent.parent)
166 | }
167 | } else {
168 | y = z.parent.parent.left
169 | if y != nil && y.color == RED {
170 | z.parent.color = BLACK
171 | y.color = BLACK
172 | z.parent.parent.color = RED
173 | z = z.parent.parent
174 | } else {
175 | if z == z.parent.left {
176 | z = z.parent
177 | t.rightRotate(z)
178 | }
179 | z.parent.color = BLACK
180 | z.parent.parent.color = RED
181 | t.leftRotate(z.parent.parent)
182 | }
183 | }
184 | }
185 | t.root.color = BLACK
186 | }
187 |
188 | func (t *Tree) rbDeleteFixup(x, parent *node) {
189 | var w *node
190 |
191 | for x != t.root && getColor(x) == BLACK {
192 | if x != nil {
193 | parent = x.parent
194 | }
195 | if x == parent.left {
196 | w = parent.right
197 | if w.color == RED {
198 | w.color = BLACK
199 | parent.color = RED
200 | t.leftRotate(parent)
201 | w = parent.right
202 | }
203 | if getColor(w.left) == BLACK && getColor(w.right) == BLACK {
204 | w.color = RED
205 | x = parent
206 | } else {
207 | if getColor(w.right) == BLACK {
208 | if w.left != nil {
209 | w.left.color = BLACK
210 | }
211 | w.color = RED
212 | t.rightRotate(w)
213 | w = parent.right
214 | }
215 | w.color = parent.color
216 | parent.color = BLACK
217 | if w.right != nil {
218 | w.right.color = BLACK
219 | }
220 | t.leftRotate(parent)
221 | x = t.root
222 | }
223 | } else {
224 | w = parent.left
225 | if w.color == RED {
226 | w.color = BLACK
227 | parent.color = RED
228 | t.rightRotate(parent)
229 | w = parent.left
230 | }
231 | if getColor(w.left) == BLACK && getColor(w.right) == BLACK {
232 | w.color = RED
233 | x = parent
234 | } else {
235 | if getColor(w.left) == BLACK {
236 | if w.right != nil {
237 | w.right.color = BLACK
238 | }
239 | w.color = RED
240 | t.leftRotate(w)
241 | w = parent.left
242 | }
243 | w.color = parent.color
244 | parent.color = BLACK
245 | if w.left != nil {
246 | w.left.color = BLACK
247 | }
248 | t.rightRotate(parent)
249 | x = t.root
250 | }
251 | }
252 | }
253 | if x != nil {
254 | x.color = BLACK
255 | }
256 | }
257 |
258 | func (t *Tree) leftRotate(x *node) {
259 | y := x.right
260 | x.right = y.left
261 | if y.left != nil {
262 | y.left.parent = x
263 | }
264 | y.parent = x.parent
265 | if x.parent == nil {
266 | t.root = y
267 | } else if x == x.parent.left {
268 | x.parent.left = y
269 | } else {
270 | x.parent.right = y
271 | }
272 | y.left = x
273 | x.parent = y
274 | }
275 |
276 | func (t *Tree) rightRotate(x *node) {
277 | y := x.left
278 | x.left = y.right
279 | if y.right != nil {
280 | y.right.parent = x
281 | }
282 | y.parent = x.parent
283 | if x.parent == nil {
284 | t.root = y
285 | } else if x == x.parent.left {
286 | x.parent.left = y
287 | } else {
288 | x.parent.right = y
289 | }
290 | y.right = x
291 | x.parent = y
292 | }
293 |
294 | // Preorder prints the tree in pre order
295 | func (t *Tree) Preorder() {
296 | fmt.Println("preorder begin!")
297 | if t.root != nil {
298 | t.root.preorder()
299 | }
300 | fmt.Println("preorder end!")
301 | }
302 |
303 | // findnode finds the node by key and return it,if not exists return nil
304 | func (t *Tree) findnode(key keytype) *node {
305 | x := t.root
306 | for x != nil {
307 | if key.LessThan(x.Key) {
308 | x = x.left
309 | } else {
310 | if key == x.Key {
311 | return x
312 | }
313 | x = x.right
314 | }
315 | }
316 | return nil
317 | }
318 |
319 | // transplant transplants the subtree u and v
320 | func (t *Tree) transplant(u, v *node) {
321 | if u.parent == nil {
322 | t.root = v
323 | } else if u == u.parent.left {
324 | u.parent.left = v
325 | } else {
326 | u.parent.right = v
327 | }
328 | if v == nil {
329 | return
330 | }
331 | v.parent = u.parent
332 | }
333 |
334 | // Next returns the node's successor as an iterator
335 | func (n *node) Next() *node {
336 | return successor(n)
337 | }
338 |
339 | func (n *node) preorder() {
340 | fmt.Printf("(%v %v)", n.Key, n.Value)
341 | if n.parent == nil {
342 | fmt.Printf("nil")
343 | } else {
344 | fmt.Printf("whose parent is %v", n.parent.Key)
345 | }
346 | if n.color == RED {
347 | fmt.Println(" and color RED")
348 | } else {
349 | fmt.Println(" and color BLACK")
350 | }
351 | if n.left != nil {
352 | fmt.Printf("%v's left child is ", n.Key)
353 | n.left.preorder()
354 | }
355 | if n.right != nil {
356 | fmt.Printf("%v's right child is ", n.Key)
357 | n.right.preorder()
358 | }
359 | }
360 |
361 | // successor returns the successor of the node
362 | func successor(x *node) *node {
363 | if x.right != nil {
364 | return minimum(x.right)
365 | }
366 | y := x.parent
367 | for y != nil && x == y.right {
368 | x = y
369 | y = x.parent
370 | }
371 | return y
372 | }
373 |
374 | // getColor gets color of the node
375 | func getColor(n *node) int {
376 | if n == nil {
377 | return BLACK
378 | }
379 | return n.color
380 | }
381 |
382 | // minimum finds the minimum node of subtree n.
383 | func minimum(n *node) *node {
384 | for n.left != nil {
385 | n = n.left
386 | }
387 | return n
388 | }
389 |
390 | // maximum finds the maximum node of subtree n.
391 | func maximum(n *node) *node {
392 | for n.right != nil {
393 | n = n.right
394 | }
395 | return n
396 | }
397 |
--------------------------------------------------------------------------------
/rbtree/rbtree_test.go:
--------------------------------------------------------------------------------
1 | package rbtree
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | type key int
8 |
9 | func (n key) LessThan(b interface{}) bool {
10 | value, _ := b.(key)
11 | return n < value
12 | }
13 |
14 | func TestPreorder(t *testing.T) {
15 | tree := NewTree()
16 |
17 | tree.Insert(key(1), "123")
18 | tree.Insert(key(3), "234")
19 | tree.Insert(key(4), "dfa3")
20 | tree.Insert(key(6), "sd4")
21 | tree.Insert(key(5), "jcd4")
22 | tree.Insert(key(2), "bcd4")
23 | if tree.Size() != 6 {
24 | t.Error("Error size")
25 | }
26 | tree.Preorder()
27 | }
28 |
29 | func TestFind(t *testing.T) {
30 |
31 | tree := NewTree()
32 |
33 | tree.Insert(key(1), "123")
34 | tree.Insert(key(3), "234")
35 | tree.Insert(key(4), "dfa3")
36 | tree.Insert(key(6), "sd4")
37 | tree.Insert(key(5), "jcd4")
38 | tree.Insert(key(2), "bcd4")
39 |
40 | n := tree.FindIt(key(4))
41 | if n.Value != "dfa3" {
42 | t.Error("Error value")
43 | }
44 | n.Value = "bdsf"
45 | if n.Value != "bdsf" {
46 | t.Error("Error value modify")
47 | }
48 | value := tree.Find(key(5)).(string)
49 | if value != "jcd4" {
50 | t.Error("Error value after modifyed other node")
51 | }
52 | }
53 | func TestIterator(t *testing.T) {
54 | tree := NewTree()
55 |
56 | tree.Insert(key(1), "123")
57 | tree.Insert(key(3), "234")
58 | tree.Insert(key(4), "dfa3")
59 | tree.Insert(key(6), "sd4")
60 | tree.Insert(key(5), "jcd4")
61 | tree.Insert(key(2), "bcd4")
62 |
63 | it := tree.Iterator()
64 |
65 | for it != nil {
66 | it = it.Next()
67 | }
68 |
69 | }
70 |
71 | func TestDelete(t *testing.T) {
72 | tree := NewTree()
73 |
74 | tree.Insert(key(1), "123")
75 | tree.Insert(key(3), "234")
76 | tree.Insert(key(4), "dfa3")
77 | tree.Insert(key(6), "sd4")
78 | tree.Insert(key(5), "jcd4")
79 | tree.Insert(key(2), "bcd4")
80 | for i := 1; i <= 6; i++ {
81 | tree.Delete(key(i))
82 | if tree.Size() != 6-i {
83 | t.Error("Delete Error")
84 | }
85 | }
86 | tree.Insert(key(1), "bcd4")
87 | tree.Clear()
88 | tree.Preorder()
89 | if tree.Find(key(1)) != nil {
90 | t.Error("Can't clear")
91 | }
92 | }
93 |
94 | func TestDelete2(t *testing.T) {
95 | tree := NewTree()
96 | tree.Insert(key(4), "1qa")
97 | tree.Insert(key(2), "2ws")
98 | tree.Insert(key(3), "3ed")
99 | tree.Insert(key(1), "4rf")
100 | tree.Insert(key(8), "5tg")
101 | tree.Insert(key(5), "6yh")
102 | tree.Insert(key(7), "7uj")
103 | tree.Insert(key(9), "8ik")
104 | tree.Delete(key(1))
105 | tree.Delete(key(2))
106 | }
107 |
--------------------------------------------------------------------------------
/stack/stack.go:
--------------------------------------------------------------------------------
1 | package stack
2 |
3 | // Element is an element of a stack
4 | type Element struct {
5 | // The value stored with this element
6 | Value interface{}
7 | }
8 |
9 | // Stack represents a stack
10 | type Stack struct {
11 | items []Element // items of your stack
12 | length int // current stack length
13 | }
14 |
15 | // Init initializes or clears the stack s
16 | func (s *Stack) Init() *Stack {
17 | s.items = nil
18 | s.length = 0
19 | return s
20 | }
21 |
22 | // New returns an initialized stack
23 | func New() *Stack {
24 | return new(Stack).Init()
25 | }
26 |
27 | // Len (Length) returns the number of elements of the stack s.
28 | // The complexity is O(1)
29 | func (s *Stack) Len() int {
30 | return s.length
31 | }
32 |
33 | // IsEmpty returns true if the stack s is empty
34 | func (s *Stack) IsEmpty() bool {
35 | return s.length == 0
36 | }
37 |
38 | // Push inserts an item into the stack
39 | func (s *Stack) Push(v interface{}) {
40 | s.items = append(s.items[:s.length], Element{Value: v})
41 | s.length++
42 | }
43 |
44 | // Pop removes an item from the stack
45 | func (s *Stack) Pop() interface{} {
46 | if s.length == 0 {
47 | return nil
48 | }
49 | ToRemove := s.items[s.length-1]
50 | s.items = s.items[:(s.length - 1)]
51 | s.length--
52 | return ToRemove.Value
53 | }
54 |
55 | // Peek shows you the last element of the stack
56 | func (s *Stack) Peek() interface{} {
57 | if s.length == 0 {
58 | return nil
59 | }
60 | return s.items[s.length-1].Value
61 | }
62 |
--------------------------------------------------------------------------------
/stack/stack_test.go:
--------------------------------------------------------------------------------
1 | package stack
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestStack(t *testing.T) {
8 | var data = []int{0, 1, 2, 3, 4}
9 | s := new(Stack)
10 |
11 | for i := 0; i < len(data); i++ {
12 | s.Push(data[i])
13 | }
14 |
15 | N := s.Len()
16 | if N != 5 {
17 | t.Error("stack length should be 5")
18 | }
19 |
20 | for i := 0; i < N; i++ {
21 | s.Pop()
22 | }
23 |
24 | if !s.IsEmpty() {
25 | t.Error("stack should be empty")
26 | }
27 |
28 | for i := 0; i < len(data)-1; i++ {
29 | s.Push(data[i])
30 | }
31 |
32 | if s.IsEmpty() {
33 | t.Error("stack should not be empty")
34 | }
35 |
36 | if s.Peek() != 3 {
37 | t.Error("peek should return 3")
38 | }
39 |
40 | s.Init()
41 |
42 | if !s.IsEmpty() {
43 | t.Error("stack should be empty")
44 | }
45 | }
46 |
--------------------------------------------------------------------------------