Compare commits
25 Commits
master
...
siriak-pat
Author | SHA1 | Date | |
---|---|---|---|
|
42454b8f19 | ||
|
82ec2a3334 | ||
|
b57b421676 | ||
|
d882e9e171 | ||
|
7c09263a51 | ||
|
80266354ba | ||
|
35813dad0d | ||
|
86281de95a | ||
|
4f8e68f9a7 | ||
|
0fd704cf4c | ||
|
b424c32171 | ||
|
5a006eee0a | ||
|
95254039dd | ||
|
5396003da5 | ||
|
1cd6b522e6 | ||
|
91ec6f20f9 | ||
|
5ac57b61e4 | ||
|
db3dfc7006 | ||
|
3ab3863692 | ||
|
b2ada76765 | ||
|
b2531054b6 | ||
|
3dc5378417 | ||
|
96b66c7759 | ||
|
ee33e3c3a2 | ||
|
53544c2810 |
136
.clang-format
136
.clang-format
@ -1,136 +0,0 @@
|
||||
---
|
||||
Language: Java
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlignConsecutiveMacros: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: false
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 300
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertNewlineAtEOF: true
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: Inner
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
...
|
@ -1,25 +0,0 @@
|
||||
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.238.0/containers/java/.devcontainer/base.Dockerfile
|
||||
|
||||
# [Choice] Java version (use -bullseye variants on local arm64/Apple Silicon): 11, 17, 11-bullseye, 17-bullseye, 11-buster, 17-buster
|
||||
ARG VARIANT="21-bullseye"
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/java:1.1.0-${VARIANT}
|
||||
|
||||
# [Option] Install Maven
|
||||
ARG INSTALL_MAVEN="false"
|
||||
ARG MAVEN_VERSION=""
|
||||
# [Option] Install Gradle
|
||||
ARG INSTALL_GRADLE="false"
|
||||
ARG GRADLE_VERSION=""
|
||||
RUN if [ "${INSTALL_MAVEN}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install maven \"${MAVEN_VERSION}\""; fi \
|
||||
&& if [ "${INSTALL_GRADLE}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install gradle \"${GRADLE_VERSION}\""; fi
|
||||
|
||||
# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
|
||||
ARG NODE_VERSION="none"
|
||||
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
|
||||
|
||||
# [Optional] Uncomment this section to install additional OS packages.
|
||||
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
||||
|
||||
# [Optional] Uncomment this line to install global node packages.
|
||||
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
|
@ -1,47 +0,0 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.238.0/containers/java
|
||||
{
|
||||
"name": "Java",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
"args": {
|
||||
// Update the VARIANT arg to pick a Java version: 11, 17
|
||||
// Append -bullseye or -buster to pin to an OS version.
|
||||
// Use the -bullseye variants on local arm64/Apple Silicon.
|
||||
"VARIANT": "21-bullseye",
|
||||
// Options
|
||||
"INSTALL_MAVEN": "true",
|
||||
"INSTALL_GRADLE": "true",
|
||||
"NODE_VERSION": "lts/*"
|
||||
}
|
||||
},
|
||||
|
||||
// Configure tool-specific properties.
|
||||
"customizations": {
|
||||
// Configure properties specific to VS Code.
|
||||
"vscode": {
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {
|
||||
},
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"vscjava.vscode-java-pack",
|
||||
"GitHub.copilot",
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
"postCreateCommand": "java -version",
|
||||
|
||||
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "vscode",
|
||||
"features": {
|
||||
"git": "os-provided",
|
||||
"github-cli": "latest"
|
||||
}
|
||||
}
|
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -1 +1 @@
|
||||
* @yanglbme @vil02 @BamaCharanChhandogi @alxkm @siriak
|
||||
* @siriak
|
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ""
|
||||
labels: ""
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Device Specification**
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
45
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
45
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -1,45 +0,0 @@
|
||||
name: "Bug report"
|
||||
description: "Create a report to help us improve"
|
||||
title: "[BUG] <title>"
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: "Description"
|
||||
description: "A clear and concise description of what the bug is."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: "Steps to reproduce"
|
||||
description: "Steps to reproduce the behavior (if applicable)"
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: exceptedbhv
|
||||
attributes:
|
||||
label: "Excepted behavior"
|
||||
description: "A clear and concise description of what you expected to happen."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: "Screenshots"
|
||||
description: "If applicable, add screenshots to help explain your problem."
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: "Additional context"
|
||||
description: "Is there anything else we should know about this bug report?"
|
||||
validations:
|
||||
required: false
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,5 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Discord community
|
||||
url: https://the-algorithms.com/discord/
|
||||
about: Have any questions or found any bugs? Please contact us via Discord
|
19
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
19
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ""
|
||||
labels: ""
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
34
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
34
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@ -1,34 +0,0 @@
|
||||
name: "Feature Request"
|
||||
description: "Suggest an idea for this project"
|
||||
title: "[FEATURE REQUEST] <title>"
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: What would you like to Propose?
|
||||
description: Provide a clear and concise explanation of your Proposal.
|
||||
validations:
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
For new implementations, please specify the name and problem statement for the algorithm.
|
||||
For algorithm enhancements, specify what needs to be changed and why. For example:
|
||||
- Adding tests.
|
||||
- Optimizing logic.
|
||||
- Refactoring the file and folders for better structure.
|
||||
- type: textarea
|
||||
id: needdetails
|
||||
attributes:
|
||||
label: "Issue details"
|
||||
description: "Write down all the issue/algorithm details description mentioned above."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: extrainfo
|
||||
attributes:
|
||||
label: "Additional Information"
|
||||
description: "Add any other information or screenshots about the request here."
|
||||
validations:
|
||||
required: false
|
19
.github/ISSUE_TEMPLATE/other.yml
vendored
19
.github/ISSUE_TEMPLATE/other.yml
vendored
@ -1,19 +0,0 @@
|
||||
name: Other
|
||||
description: Use this for any other issues. Do NOT create blank issues
|
||||
title: "[OTHER]"
|
||||
labels: ["awaiting triage"]
|
||||
body:
|
||||
- type: textarea
|
||||
id: issuedescription
|
||||
attributes:
|
||||
label: What would you like to share?
|
||||
description: Provide a clear and concise explanation of your issue.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: extrainfo
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Is there anything else we should know about this issue?
|
||||
validations:
|
||||
required: false
|
18
.github/dependabot.yml
vendored
18
.github/dependabot.yml
vendored
@ -1,18 +0,0 @@
|
||||
---
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/workflows/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "maven"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
...
|
31
.github/pull_request_template.md
vendored
31
.github/pull_request_template.md
vendored
@ -1,16 +1,23 @@
|
||||
<!--
|
||||
Thank you for your contribution!
|
||||
In order to reduce the number of notifications sent to the maintainers, please:
|
||||
- create your PR as draft, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests,
|
||||
- make sure that all of the CI checks pass,
|
||||
- mark your PR as ready for review, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review
|
||||
-->
|
||||
### **Describe your change:**
|
||||
|
||||
<!-- For completed items, change [ ] to [x] -->
|
||||
- [ ] Add an algorithm?
|
||||
- [ ] Fix a bug or typo in an existing algorithm?
|
||||
- [ ] Documentation change?
|
||||
|
||||
#### References
|
||||
|
||||
<!-- Add any reference to previous pull-request or issue -->
|
||||
|
||||
### **Checklist:**
|
||||
|
||||
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->
|
||||
|
||||
- [ ] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Java/blob/master/CONTRIBUTING.md).
|
||||
- [ ] This pull request is all my own work -- I have not plagiarized it.
|
||||
- [ ] All filenames are in PascalCase.
|
||||
- [ ] This pull request is all my own work -- I have not plagiarized.
|
||||
- [ ] I know that pull requests will not be merged if they fail the automated tests.
|
||||
- [ ] This PR only changes one algorithm file. To ease review, please open separate PRs for separate algorithms.
|
||||
- [ ] All new Java files are placed inside an existing directory.
|
||||
- [ ] All filenames are in all uppercase characters with no spaces or dashes.
|
||||
- [ ] All functions and variable names follow Java naming conventions.
|
||||
- [ ] All new algorithms have a URL in their comments that points to Wikipedia or other similar explanations.
|
||||
- [ ] All new code is formatted with `clang-format -i --style=file path/to/your/file.java`
|
||||
- [ ] All new algorithms have a URL in its comments that points to Wikipedia or other similar explanation.
|
||||
- [ ] If this pull request resolves one or more open issues then the commit message contains `Fixes: #{$ISSUE_NO}`.
|
||||
|
39
.github/workflows/build.yml
vendored
39
.github/workflows/build.yml
vendored
@ -1,37 +1,14 @@
|
||||
name: Build
|
||||
on: [push, pull_request]
|
||||
|
||||
on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 21
|
||||
distribution: 'adopt'
|
||||
- name: Build with Maven
|
||||
run: mvn --batch-mode --update-snapshots verify
|
||||
- name: Upload coverage to codecov (tokenless)
|
||||
if: >-
|
||||
github.event_name == 'pull_request' &&
|
||||
github.event.pull_request.head.repo.full_name != github.repository
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
fail_ci_if_error: true
|
||||
- name: Upload coverage to codecov (with token)
|
||||
if: >
|
||||
github.repository == 'TheAlgorithms/Java' &&
|
||||
(github.event_name != 'pull_request' ||
|
||||
github.event.pull_request.head.repo.full_name == github.repository)
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: true
|
||||
- name: Checkstyle
|
||||
run: mvn checkstyle:check
|
||||
- name: SpotBugs
|
||||
run: mvn spotbugs:check
|
||||
- name: PMD
|
||||
run: mvn pmd:check
|
||||
java-version: 17
|
||||
- run: find . -type f -name "*.java" > sources.txt
|
||||
- run: javac @sources.txt
|
16
.github/workflows/clang-format-lint.yml
vendored
16
.github/workflows/clang-format-lint.yml
vendored
@ -1,16 +0,0 @@
|
||||
name: Clang format linter
|
||||
on:
|
||||
push: {}
|
||||
pull_request: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: DoozyX/clang-format-lint-action@v0.18
|
||||
with:
|
||||
source: './src'
|
||||
extensions: 'java'
|
||||
clangFormatVersion: 16
|
47
.github/workflows/codeql.yml
vendored
47
.github/workflows/codeql.yml
vendored
@ -1,47 +0,0 @@
|
||||
---
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '53 3 * * 0'
|
||||
|
||||
env:
|
||||
LANGUAGE: 'java-kotlin'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 21
|
||||
distribution: 'adopt'
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ env.LANGUAGE }}
|
||||
|
||||
- name: Build
|
||||
run: mvn --batch-mode --update-snapshots verify
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{env.LANGUAGE}}"
|
||||
...
|
18
.github/workflows/prettify.yml
vendored
Normal file
18
.github/workflows/prettify.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
name: Prettify
|
||||
on: push
|
||||
jobs:
|
||||
prettier:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Prettify code
|
||||
uses: creyD/prettier_action@v3.3
|
||||
with:
|
||||
prettier_options: --write **/*.{java,md}
|
||||
commit_message: 'Prettify code'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
10
.github/workflows/stale.yml
vendored
10
.github/workflows/stale.yml
vendored
@ -6,12 +6,12 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
- uses: actions/stale@v4
|
||||
with:
|
||||
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution!'
|
||||
close-issue-message: 'Please reopen this issue once you have made the required changes. If you need help, feel free to ask in our [Discord](https://the-algorithms.com/discord) server or ping one of the maintainers here. Thank you for your contribution!'
|
||||
stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution!'
|
||||
close-pr-message: 'Please reopen this pull request once you have made the required changes. If you need help, feel free to ask in our [Discord](https://the-algorithms.com/discord) server or ping one of the maintainers here. Thank you for your contribution!'
|
||||
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
|
||||
close-issue-message: 'Please reopen this issue once you add more information and updates here. If this is not the case and you need some help, feel free to seek help from our [Gitter](https://gitter.im/TheAlgorithms) or ping one of the reviewers. Thank you for your contributions!'
|
||||
stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
|
||||
close-pr-message: 'Please reopen this pull request once you commit the changes requested or make improvements on the code. If this is not the case and you need some help, feel free to seek help from our [Gitter](https://gitter.im/TheAlgorithms) or ping one of the reviewers. Thank you for your contributions!'
|
||||
exempt-issue-labels: 'dont-close'
|
||||
exempt-pr-labels: 'dont-close'
|
||||
days-before-stale: 30
|
||||
|
45
.github/workflows/update_directory.yml
vendored
45
.github/workflows/update_directory.yml
vendored
@ -1,34 +1,13 @@
|
||||
# This GitHub Action updates the DIRECTORY.md file (if needed) when doing a git push or pull_request
|
||||
# This GitHub Action updates the DIRECTORY.md file (if needed) when doing a git push
|
||||
name: Update Directory
|
||||
permissions:
|
||||
contents: write
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'src/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
logLevel:
|
||||
description: 'Log level'
|
||||
required: true
|
||||
default: 'info'
|
||||
type: choice
|
||||
options:
|
||||
- info
|
||||
- warning
|
||||
- debug
|
||||
on: push
|
||||
jobs:
|
||||
update_directory_md:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Update Directory
|
||||
- uses: actions/setup-python@master
|
||||
- name: update_directory_md
|
||||
shell: python
|
||||
run: |
|
||||
import os
|
||||
@ -53,12 +32,8 @@ jobs:
|
||||
def print_path(old_path: str, new_path: str) -> str:
|
||||
global g_output
|
||||
old_parts = old_path.split(os.sep)
|
||||
mid_diff = False
|
||||
new_parts = new_path.split(os.sep)
|
||||
for i, new_part in enumerate(new_parts):
|
||||
if i + 1 > len(old_parts) or old_parts[i] != new_part or mid_diff:
|
||||
if i + 1 < len(new_parts):
|
||||
mid_diff = True
|
||||
for i, new_part in enumerate(new_path.split(os.sep)):
|
||||
if i + 1 > len(old_parts) or old_parts[i] != new_part:
|
||||
if new_part:
|
||||
g_output.append(f"{md_prefix(i)} {new_part.replace('_', ' ')}")
|
||||
return new_path
|
||||
@ -67,7 +42,7 @@ jobs:
|
||||
def build_directory_md(top_dir: str = ".") -> str:
|
||||
global g_output
|
||||
old_path = ""
|
||||
for filepath in sorted(good_filepaths(top_dir), key=str.lower):
|
||||
for filepath in sorted(good_filepaths(), key=str.lower):
|
||||
filepath, filename = os.path.split(filepath)
|
||||
if filepath != old_path:
|
||||
old_path = print_path(old_path, filepath)
|
||||
@ -84,9 +59,9 @@ jobs:
|
||||
- name: Update DIRECTORY.md
|
||||
run: |
|
||||
cat DIRECTORY.md
|
||||
git config --global user.name "$GITHUB_ACTOR"
|
||||
git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||
git config --global user.name github-actions
|
||||
git config --global user.email '${GITHUB_ACTOR}@users.noreply.github.com'
|
||||
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY
|
||||
git add DIRECTORY.md
|
||||
git commit -am "Update directory" || true
|
||||
git commit -am "updating DIRECTORY.md" || true
|
||||
git push --force origin HEAD:$GITHUB_REF || true
|
||||
|
22
.gitignore
vendored
22
.gitignore
vendored
@ -1,6 +1,6 @@
|
||||
/gradle/wrapper/gradle-wrapper.properties
|
||||
|
||||
##----------Android----------
|
||||
# build
|
||||
*.apk
|
||||
*.ap_
|
||||
*.dex
|
||||
@ -10,35 +10,29 @@ gen/
|
||||
build/
|
||||
out/
|
||||
|
||||
# Ignoring Gradle build artifacts and project files
|
||||
##----------Gradle----------
|
||||
# gradle
|
||||
.gradle/
|
||||
gradle-app.setting
|
||||
!gradle-wrapper.jar
|
||||
build/
|
||||
|
||||
# Ignoring Maven build artifacts and project files
|
||||
##----------Maven----------
|
||||
*.classpath
|
||||
*.project
|
||||
*.settings
|
||||
/target/
|
||||
local.properties
|
||||
|
||||
# Ignoring IntelliJ IDEA project files and configurations
|
||||
##----------IDEA----------
|
||||
##----------idea----------
|
||||
*.iml
|
||||
.idea/
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
# Ignoring Android Studio Navigation editor temporary files
|
||||
# Android Studio Navigation editor temp files
|
||||
.navigation/
|
||||
|
||||
# Ignoring common system and editor-generated files
|
||||
##----------Other----------
|
||||
# osx
|
||||
*~
|
||||
.DS_Store
|
||||
gradle.properties
|
||||
|
||||
.vscode
|
||||
*.log
|
||||
|
||||
*.log
|
7
.gitpod.Dockerfile
vendored
Normal file
7
.gitpod.Dockerfile
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
FROM gitpod/workspace-full
|
||||
|
||||
# Install custom tools, runtimes, etc.
|
||||
# For example "bastet", a command-line tetris clone:
|
||||
# RUN brew install bastet
|
||||
#
|
||||
# More information: https://www.gitpod.io/docs/config-docker/
|
@ -1,22 +0,0 @@
|
||||
FROM gitpod/workspace-java-21:2024-07-14-17-19-51
|
||||
|
||||
ENV LLVM_SCRIPT="tmp_llvm.sh"
|
||||
|
||||
RUN test ! -f "$LLVM_SCRIPT" \
|
||||
&& wget https://apt.llvm.org/llvm.sh -O "$LLVM_SCRIPT" \
|
||||
&& chmod +x "$LLVM_SCRIPT"
|
||||
|
||||
USER root
|
||||
|
||||
RUN ./"$LLVM_SCRIPT" 16 \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
clang-format-16=1:16.0.6~++20231112100510+7cbf1a259152-1~exp1~20231112100554.106 \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN ln -s "$(command -v clang-format-16)" "/usr/bin/clang-format"
|
||||
|
||||
USER gitpod
|
||||
|
||||
RUN rm "$LLVM_SCRIPT"
|
13
.gitpod.yml
13
.gitpod.yml
@ -1,13 +1,6 @@
|
||||
---
|
||||
image:
|
||||
file: .gitpod.dockerfile
|
||||
file: .gitpod.Dockerfile
|
||||
|
||||
tasks:
|
||||
- init: |
|
||||
mvn dependency:resolve
|
||||
mvn compile
|
||||
|
||||
vscode:
|
||||
extensions:
|
||||
- xaver.clang-format
|
||||
|
||||
- init: 'echo "TODO: Replace with init/build command"'
|
||||
command: (e.g. 'npm start', 'yarn watch'...)
|
||||
|
@ -1,31 +1,27 @@
|
||||
## How to contribute?
|
||||
|
||||
NOTE: *We DO NOT add leetcode problems. They are just applications of basic principles that can be found in other algorithms included in the repository.*
|
||||
#### **Did you find a bug?**
|
||||
|
||||
### Did you find a bug?
|
||||
- **Ensure the bug was not already reported** by searching on GitHub under [Project Issues](https://github.com/TheAlgorithms/Java/issues).
|
||||
|
||||
**Ensure the bug was not already reported** by searching on GitHub under [Project Issues](https://github.com/TheAlgorithms/Java/issues).
|
||||
- If it is mentioned in the issues and you want to fix it, [fork](https://github.com/TheAlgorithms/Java/fork) the repository and submit your implementation in a pull request. The project maintainers will evaluate it.
|
||||
- If the bug is **NOT** mentioned in the issues, [open a new issue](https://github.com/TheAlgorithms/Java/issues/new). Be sure to include a **title**, a clear **description** and a **test case** demonstrating the expected behavior that is not occurring.
|
||||
- Please avoid opening issues asking to be "assigned” to a particular algorithm. This merely creates unnecessary noise for maintainers. Instead, please submit your implementation in a pull request and it will be evaluated by project maintainers.
|
||||
|
||||
NOTE: *Please avoid opening issues asking to be "assigned" to a particular algorithm. This merely creates unnecessary noise for maintainers. Instead, please submit your implementation in a pull request and project maintainers will evaluate it.*
|
||||
- If you are unable to find an open issue referring to the same problem, depending on the type of issue follow the appropriate steps:
|
||||
|
||||
#### **Do you want to contribute to the documentation?**
|
||||
|
||||
- Please read the documentation in here [Contributing to the Documentation](https://github.com/TheAlgorithms/Java/blob/master/CONTRIBUTING.md) ,[open a new one issue](https://github.com/TheAlgorithms/Java/issues/new), make changes and then create a pull request, it will be put under review and accepted if it is appropriate.
|
||||
|
||||
### Do you want to contribute to the documentation?
|
||||
- [Fork](https://github.com/TheAlgorithms/Java/fork) the repository and make necessary changes.
|
||||
- Create a pull request.
|
||||
- It will be put under review for approval.
|
||||
- If approved, the requested changes will be merged to the repository.
|
||||
#### **Do you want to add a new feature?**
|
||||
|
||||
### Do you want to add a new feature?
|
||||
- [Open a new one issue](https://github.com/TheAlgorithms/Java/issues/new). Be sure to include a **title and a clear description** and a **test case** demonstrating the new feature that you want to add to the project.
|
||||
|
||||
- [Open a new issue](https://github.com/TheAlgorithms/Java/issues/new).
|
||||
- Be sure to include a **title**, a clear **description** and a **test case** demonstrating the new feature you want to add to the project.
|
||||
#### **Do you want to fix a bug?**
|
||||
|
||||
- [Open a new one issue](https://github.com/TheAlgorithms/Java/issues/new).Be sure to include a **title and a clear description** and a **test case** demonstrating the expected behaviour that is not occurring.
|
||||
|
||||
### Do you have questions about the source code?
|
||||
#### **Do you have questions about the source code?**
|
||||
|
||||
- Ask any question about how to use the repository in the [TheAlgorithms room in GITTER](https://gitter.im/TheAlgorithms/community?source=orgpage#) or [open a new issue](https://github.com/TheAlgorithms/Java/issues/new)
|
||||
- Ask any question about how to use the repository in the [TheAlgorithms room in GITTER](https://gitter.im/TheAlgorithms/community?source=orgpage#) or [open a new one issue](https://github.com/TheAlgorithms/Java/issues/new)
|
||||
|
||||
:+1::tada: That's all you need to know about the process now it's your turn to help us improve the repository, thank you again! :+1::tada:
|
||||
:+1::tada: That's all you need to know about the process now it's your turn to help us improve the repository, thank you again! :+1::tada:
|
||||
|
605
Ciphers/AES.java
Normal file
605
Ciphers/AES.java
Normal file
@ -0,0 +1,605 @@
|
||||
package Ciphers;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* This class is build to demonstrate the application of the AES-algorithm on a single 128-Bit block
|
||||
* of data.
|
||||
*/
|
||||
public class AES {
|
||||
|
||||
/**
|
||||
* Precalculated values for x to the power of 2 in Rijndaels galois field. Used as 'RCON' during
|
||||
* the key expansion.
|
||||
*/
|
||||
private static final int[] RCON = {
|
||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
|
||||
0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
|
||||
0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
|
||||
0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
|
||||
0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
|
||||
0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
|
||||
0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
|
||||
0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
|
||||
0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
|
||||
0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
|
||||
0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
|
||||
0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
|
||||
0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
|
||||
0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
|
||||
0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
|
||||
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d
|
||||
};
|
||||
|
||||
/**
|
||||
* Rijndael S-box Substitution table used for encryption in the subBytes step, as well as the key
|
||||
* expansion.
|
||||
*/
|
||||
private static final int[] SBOX = {
|
||||
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
|
||||
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
|
||||
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
|
||||
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
|
||||
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
|
||||
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
|
||||
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
|
||||
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
|
||||
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
|
||||
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
|
||||
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
|
||||
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
|
||||
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
|
||||
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
|
||||
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
|
||||
};
|
||||
|
||||
/** Inverse Rijndael S-box Substitution table used for decryption in the subBytesDec step. */
|
||||
private static final int[] INVERSE_SBOX = {
|
||||
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
|
||||
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
|
||||
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
|
||||
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
|
||||
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
|
||||
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
|
||||
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
|
||||
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
|
||||
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
|
||||
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
|
||||
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
|
||||
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
|
||||
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
|
||||
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
|
||||
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
|
||||
};
|
||||
|
||||
/**
|
||||
* Precalculated lookup table for galois field multiplication by 2 used in the MixColums step
|
||||
* during encryption.
|
||||
*/
|
||||
private static final int[] MULT2 = {
|
||||
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
|
||||
0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
|
||||
0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
|
||||
0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
|
||||
0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
|
||||
0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
|
||||
0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
|
||||
0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
|
||||
0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
|
||||
0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
|
||||
0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
|
||||
0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
|
||||
0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
|
||||
0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
|
||||
0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
|
||||
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
|
||||
};
|
||||
|
||||
/**
|
||||
* Precalculated lookup table for galois field multiplication by 3 used in the MixColums step
|
||||
* during encryption.
|
||||
*/
|
||||
private static final int[] MULT3 = {
|
||||
0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
|
||||
0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
|
||||
0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
|
||||
0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
|
||||
0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
|
||||
0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
|
||||
0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
|
||||
0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
|
||||
0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
|
||||
0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
|
||||
0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
|
||||
0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
|
||||
0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
|
||||
0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
|
||||
0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
|
||||
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
|
||||
};
|
||||
|
||||
/**
|
||||
* Precalculated lookup table for galois field multiplication by 9 used in the MixColums step
|
||||
* during decryption.
|
||||
*/
|
||||
private static final int[] MULT9 = {
|
||||
0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
|
||||
0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
|
||||
0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
|
||||
0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
|
||||
0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
|
||||
0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
|
||||
0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
|
||||
0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
|
||||
0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
|
||||
0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
|
||||
0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
|
||||
0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
|
||||
0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
|
||||
0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
|
||||
0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
|
||||
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
|
||||
};
|
||||
|
||||
/**
|
||||
* Precalculated lookup table for galois field multiplication by 11 used in the MixColums step
|
||||
* during decryption.
|
||||
*/
|
||||
private static final int[] MULT11 = {
|
||||
0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
|
||||
0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
|
||||
0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
|
||||
0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
|
||||
0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
|
||||
0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
|
||||
0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
|
||||
0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
|
||||
0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
|
||||
0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
|
||||
0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
|
||||
0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
|
||||
0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
|
||||
0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
|
||||
0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
|
||||
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
|
||||
};
|
||||
|
||||
/**
|
||||
* Precalculated lookup table for galois field multiplication by 13 used in the MixColums step
|
||||
* during decryption.
|
||||
*/
|
||||
private static final int[] MULT13 = {
|
||||
0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
|
||||
0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
|
||||
0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
|
||||
0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
|
||||
0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
|
||||
0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
|
||||
0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
|
||||
0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
|
||||
0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
|
||||
0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
|
||||
0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
|
||||
0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
|
||||
0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
|
||||
0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
|
||||
0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
|
||||
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
|
||||
};
|
||||
|
||||
/**
|
||||
* Precalculated lookup table for galois field multiplication by 14 used in the MixColums step
|
||||
* during decryption.
|
||||
*/
|
||||
private static final int[] MULT14 = {
|
||||
0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
|
||||
0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
|
||||
0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
|
||||
0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
|
||||
0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
|
||||
0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
|
||||
0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
|
||||
0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
|
||||
0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
|
||||
0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
|
||||
0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
|
||||
0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
|
||||
0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
|
||||
0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
|
||||
0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
|
||||
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
|
||||
};
|
||||
|
||||
/**
|
||||
* Subroutine of the Rijndael key expansion.
|
||||
*/
|
||||
public static BigInteger scheduleCore(BigInteger t, int rconCounter) {
|
||||
StringBuilder rBytes = new StringBuilder(t.toString(16));
|
||||
|
||||
// Add zero padding
|
||||
while (rBytes.length() < 8) {
|
||||
rBytes.insert(0, "0");
|
||||
}
|
||||
|
||||
// rotate the first 16 bits to the back
|
||||
String rotatingBytes = rBytes.substring(0, 2);
|
||||
String fixedBytes = rBytes.substring(2);
|
||||
|
||||
rBytes = new StringBuilder(fixedBytes + rotatingBytes);
|
||||
|
||||
// apply S-Box to all 8-Bit Substrings
|
||||
for (int i = 0; i < 4; i++) {
|
||||
StringBuilder currentByteBits = new StringBuilder(rBytes.substring(i * 2, (i + 1) * 2));
|
||||
|
||||
int currentByte = Integer.parseInt(currentByteBits.toString(), 16);
|
||||
currentByte = SBOX[currentByte];
|
||||
|
||||
// add the current RCON value to the first byte
|
||||
if (i == 0) {
|
||||
currentByte = currentByte ^ RCON[rconCounter];
|
||||
}
|
||||
|
||||
currentByteBits = new StringBuilder(Integer.toHexString(currentByte));
|
||||
|
||||
// Add zero padding
|
||||
|
||||
while (currentByteBits.length() < 2) {
|
||||
currentByteBits.insert(0, '0');
|
||||
}
|
||||
|
||||
// replace bytes in original string
|
||||
rBytes = new StringBuilder(rBytes.substring(0, i * 2) + currentByteBits + rBytes.substring((i + 1) * 2));
|
||||
}
|
||||
|
||||
// t = new BigInteger(rBytes, 16);
|
||||
// return t;
|
||||
return new BigInteger(rBytes.toString(), 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of 10 + 1 round keys that are calculated by using Rijndael key schedule
|
||||
*
|
||||
* @return array of 10 + 1 round keys
|
||||
*/
|
||||
public static BigInteger[] keyExpansion(BigInteger initialKey) {
|
||||
BigInteger[] roundKeys = {
|
||||
initialKey,
|
||||
new BigInteger("0"),
|
||||
new BigInteger("0"),
|
||||
new BigInteger("0"),
|
||||
new BigInteger("0"),
|
||||
new BigInteger("0"),
|
||||
new BigInteger("0"),
|
||||
new BigInteger("0"),
|
||||
new BigInteger("0"),
|
||||
new BigInteger("0"),
|
||||
new BigInteger("0"),
|
||||
};
|
||||
|
||||
// initialize rcon iteration
|
||||
int rconCounter = 1;
|
||||
|
||||
for (int i = 1; i < 11; i++) {
|
||||
|
||||
// get the previous 32 bits the key
|
||||
BigInteger t = roundKeys[i - 1].remainder(new BigInteger("100000000", 16));
|
||||
|
||||
// split previous key into 8-bit segments
|
||||
BigInteger[] prevKey = {
|
||||
roundKeys[i - 1].remainder(new BigInteger("100000000", 16)),
|
||||
roundKeys[i - 1]
|
||||
.remainder(new BigInteger("10000000000000000", 16))
|
||||
.divide(new BigInteger("100000000", 16)),
|
||||
roundKeys[i - 1]
|
||||
.remainder(new BigInteger("1000000000000000000000000", 16))
|
||||
.divide(new BigInteger("10000000000000000", 16)),
|
||||
roundKeys[i - 1].divide(new BigInteger("1000000000000000000000000", 16)),
|
||||
};
|
||||
|
||||
// run schedule core
|
||||
t = scheduleCore(t, rconCounter);
|
||||
rconCounter += 1;
|
||||
|
||||
// Calculate partial round key
|
||||
BigInteger t0 = t.xor(prevKey[3]);
|
||||
BigInteger t1 = t0.xor(prevKey[2]);
|
||||
BigInteger t2 = t1.xor(prevKey[1]);
|
||||
BigInteger t3 = t2.xor(prevKey[0]);
|
||||
|
||||
// Join round key segments
|
||||
t2 = t2.multiply(new BigInteger("100000000", 16));
|
||||
t1 = t1.multiply(new BigInteger("10000000000000000", 16));
|
||||
t0 = t0.multiply(new BigInteger("1000000000000000000000000", 16));
|
||||
roundKeys[i] = t0.add(t1).add(t2).add(t3);
|
||||
}
|
||||
return roundKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* representation of the input 128-bit block as an array of 8-bit integers.
|
||||
*
|
||||
* @param block of 128-bit integers
|
||||
* @return array of 8-bit integers
|
||||
*/
|
||||
public static int[] splitBlockIntoCells(BigInteger block) {
|
||||
|
||||
int[] cells = new int[16];
|
||||
StringBuilder blockBits = new StringBuilder(block.toString(2));
|
||||
|
||||
// Append leading 0 for full "128-bit" string
|
||||
while (blockBits.length() < 128) {
|
||||
blockBits.insert(0, '0');
|
||||
}
|
||||
|
||||
// split 128 to 8 bit cells
|
||||
for (int i = 0; i < cells.length; i++) {
|
||||
String cellBits = blockBits.substring(8 * i, 8 * (i + 1));
|
||||
cells[i] = Integer.parseInt(cellBits, 2);
|
||||
}
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the 128-bit BigInteger representation of the input of an array of 8-bit integers.
|
||||
*
|
||||
* @param cells that we need to merge
|
||||
* @return block of merged cells
|
||||
*/
|
||||
public static BigInteger mergeCellsIntoBlock(int[] cells) {
|
||||
|
||||
StringBuilder blockBits = new StringBuilder();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
StringBuilder cellBits = new StringBuilder(Integer.toBinaryString(cells[i]));
|
||||
|
||||
// Append leading 0 for full "8-bit" strings
|
||||
while (cellBits.length() < 8) {
|
||||
cellBits.insert(0, '0');
|
||||
}
|
||||
|
||||
blockBits.append(cellBits);
|
||||
}
|
||||
|
||||
return new BigInteger(blockBits.toString(), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ciphertext XOR key
|
||||
*/
|
||||
public static BigInteger addRoundKey(BigInteger ciphertext, BigInteger key) {
|
||||
return ciphertext.xor(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* substitutes 8-Bit long substrings of the input using the S-Box and returns the result.
|
||||
*
|
||||
* @return subtraction Output
|
||||
*/
|
||||
public static BigInteger subBytes(BigInteger ciphertext) {
|
||||
|
||||
int[] cells = splitBlockIntoCells(ciphertext);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
cells[i] = SBOX[cells[i]];
|
||||
}
|
||||
|
||||
return mergeCellsIntoBlock(cells);
|
||||
}
|
||||
|
||||
/**
|
||||
* substitutes 8-Bit long substrings of the input using the inverse S-Box for decryption and
|
||||
* returns the result.
|
||||
*
|
||||
* @return subtraction Output
|
||||
*/
|
||||
public static BigInteger subBytesDec(BigInteger ciphertext) {
|
||||
|
||||
int[] cells = splitBlockIntoCells(ciphertext);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
cells[i] = INVERSE_SBOX[cells[i]];
|
||||
}
|
||||
|
||||
return mergeCellsIntoBlock(cells);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cell permutation step. Shifts cells within the rows of the input and returns the result.
|
||||
*/
|
||||
public static BigInteger shiftRows(BigInteger ciphertext) {
|
||||
int[] cells = splitBlockIntoCells(ciphertext);
|
||||
int[] output = new int[16];
|
||||
|
||||
// do nothing in the first row
|
||||
output[0] = cells[0];
|
||||
output[4] = cells[4];
|
||||
output[8] = cells[8];
|
||||
output[12] = cells[12];
|
||||
|
||||
// shift the second row backwards by one cell
|
||||
output[1] = cells[5];
|
||||
output[5] = cells[9];
|
||||
output[9] = cells[13];
|
||||
output[13] = cells[1];
|
||||
|
||||
// shift the third row backwards by two cell
|
||||
output[2] = cells[10];
|
||||
output[6] = cells[14];
|
||||
output[10] = cells[2];
|
||||
output[14] = cells[6];
|
||||
|
||||
// shift the forth row backwards by tree cell
|
||||
output[3] = cells[15];
|
||||
output[7] = cells[3];
|
||||
output[11] = cells[7];
|
||||
output[15] = cells[11];
|
||||
|
||||
return mergeCellsIntoBlock(output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cell permutation step for decryption . Shifts cells within the rows of the input and returns
|
||||
* the result.
|
||||
*/
|
||||
public static BigInteger shiftRowsDec(BigInteger ciphertext) {
|
||||
int[] cells = splitBlockIntoCells(ciphertext);
|
||||
int[] output = new int[16];
|
||||
|
||||
// do nothing in the first row
|
||||
output[0] = cells[0];
|
||||
output[4] = cells[4];
|
||||
output[8] = cells[8];
|
||||
output[12] = cells[12];
|
||||
|
||||
// shift the second row forwards by one cell
|
||||
output[1] = cells[13];
|
||||
output[5] = cells[1];
|
||||
output[9] = cells[5];
|
||||
output[13] = cells[9];
|
||||
|
||||
// shift the third row forwards by two cell
|
||||
output[2] = cells[10];
|
||||
output[6] = cells[14];
|
||||
output[10] = cells[2];
|
||||
output[14] = cells[6];
|
||||
|
||||
// shift the forth row forwards by tree cell
|
||||
output[3] = cells[7];
|
||||
output[7] = cells[11];
|
||||
output[11] = cells[15];
|
||||
output[15] = cells[3];
|
||||
|
||||
return mergeCellsIntoBlock(output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the Rijndael MixColumns to the input and returns the result.
|
||||
*/
|
||||
public static BigInteger mixColumns(BigInteger ciphertext) {
|
||||
|
||||
int[] cells = splitBlockIntoCells(ciphertext);
|
||||
int[] outputCells = new int[16];
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int[] row = {cells[i * 4], cells[i * 4 + 1], cells[i * 4 + 2], cells[i * 4 + 3]};
|
||||
|
||||
outputCells[i * 4] = MULT2[row[0]] ^ MULT3[row[1]] ^ row[2] ^ row[3];
|
||||
outputCells[i * 4 + 1] = row[0] ^ MULT2[row[1]] ^ MULT3[row[2]] ^ row[3];
|
||||
outputCells[i * 4 + 2] = row[0] ^ row[1] ^ MULT2[row[2]] ^ MULT3[row[3]];
|
||||
outputCells[i * 4 + 3] = MULT3[row[0]] ^ row[1] ^ row[2] ^ MULT2[row[3]];
|
||||
}
|
||||
return mergeCellsIntoBlock(outputCells);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the inverse Rijndael MixColumns for decryption to the input and returns the result.
|
||||
*/
|
||||
public static BigInteger mixColumnsDec(BigInteger ciphertext) {
|
||||
|
||||
int[] cells = splitBlockIntoCells(ciphertext);
|
||||
int[] outputCells = new int[16];
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int[] row = {cells[i * 4], cells[i * 4 + 1], cells[i * 4 + 2], cells[i * 4 + 3]};
|
||||
|
||||
outputCells[i * 4] = MULT14[row[0]] ^ MULT11[row[1]] ^ MULT13[row[2]] ^ MULT9[row[3]];
|
||||
outputCells[i * 4 + 1] = MULT9[row[0]] ^ MULT14[row[1]] ^ MULT11[row[2]] ^ MULT13[row[3]];
|
||||
outputCells[i * 4 + 2] = MULT13[row[0]] ^ MULT9[row[1]] ^ MULT14[row[2]] ^ MULT11[row[3]];
|
||||
outputCells[i * 4 + 3] = MULT11[row[0]] ^ MULT13[row[1]] ^ MULT9[row[2]] ^ MULT14[row[3]];
|
||||
}
|
||||
return mergeCellsIntoBlock(outputCells);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the plaintext with the key and returns the result
|
||||
*
|
||||
* @param plainText which we want to encrypt
|
||||
* @param key the key for encrypt
|
||||
* @return EncryptedText
|
||||
*/
|
||||
public static BigInteger encrypt(BigInteger plainText, BigInteger key) {
|
||||
BigInteger[] roundKeys = keyExpansion(key);
|
||||
|
||||
// Initial round
|
||||
plainText = addRoundKey(plainText, roundKeys[0]);
|
||||
|
||||
// Main rounds
|
||||
for (int i = 1; i < 10; i++) {
|
||||
plainText = subBytes(plainText);
|
||||
plainText = shiftRows(plainText);
|
||||
plainText = mixColumns(plainText);
|
||||
plainText = addRoundKey(plainText, roundKeys[i]);
|
||||
}
|
||||
|
||||
// Final round
|
||||
plainText = subBytes(plainText);
|
||||
plainText = shiftRows(plainText);
|
||||
plainText = addRoundKey(plainText, roundKeys[10]);
|
||||
|
||||
return plainText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the ciphertext with the key and returns the result
|
||||
*
|
||||
* @param cipherText The Encrypted text which we want to decrypt
|
||||
* @return decryptedText
|
||||
*/
|
||||
public static BigInteger decrypt(BigInteger cipherText, BigInteger key) {
|
||||
|
||||
BigInteger[] roundKeys = keyExpansion(key);
|
||||
|
||||
// Invert final round
|
||||
cipherText = addRoundKey(cipherText, roundKeys[10]);
|
||||
cipherText = shiftRowsDec(cipherText);
|
||||
cipherText = subBytesDec(cipherText);
|
||||
|
||||
// Invert main rounds
|
||||
for (int i = 9; i > 0; i--) {
|
||||
cipherText = addRoundKey(cipherText, roundKeys[i]);
|
||||
cipherText = mixColumnsDec(cipherText);
|
||||
cipherText = shiftRowsDec(cipherText);
|
||||
cipherText = subBytesDec(cipherText);
|
||||
}
|
||||
|
||||
// Invert initial round
|
||||
cipherText = addRoundKey(cipherText, roundKeys[0]);
|
||||
|
||||
return cipherText;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try (Scanner input = new Scanner(System.in)) {
|
||||
System.out.println("Enter (e) letter for encrpyt or (d) letter for decrypt :");
|
||||
char choice = input.nextLine().charAt(0);
|
||||
String in;
|
||||
switch (choice) {
|
||||
case 'E', 'e' -> {
|
||||
System.out.println("Choose a plaintext block (128-Bit Integer in base 16):");
|
||||
in = input.nextLine();
|
||||
BigInteger plaintext = new BigInteger(in, 16);
|
||||
System.out.println("Choose a Key (128-Bit Integer in base 16):");
|
||||
in = input.nextLine();
|
||||
BigInteger encryptionKey = new BigInteger(in, 16);
|
||||
System.out.println(
|
||||
"The encrypted message is: \n" + encrypt(plaintext, encryptionKey).toString(16));
|
||||
}
|
||||
case 'D', 'd' -> {
|
||||
System.out.println("Enter your ciphertext block (128-Bit Integer in base 16):");
|
||||
in = input.nextLine();
|
||||
BigInteger ciphertext = new BigInteger(in, 16);
|
||||
System.out.println("Choose a Key (128-Bit Integer in base 16):");
|
||||
in = input.nextLine();
|
||||
BigInteger decryptionKey = new BigInteger(in, 16);
|
||||
System.out.println(
|
||||
"The deciphered message is:\n" + decrypt(ciphertext, decryptionKey).toString(16));
|
||||
}
|
||||
default -> System.out.println("** End **");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
97
Ciphers/AESEncryption.java
Normal file
97
Ciphers/AESEncryption.java
Normal file
@ -0,0 +1,97 @@
|
||||
package Ciphers;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
/**
|
||||
* This example program shows how AES encryption and decryption can be done in Java. Please note
|
||||
* that secret key and encrypted text is unreadable binary and hence in the following program we
|
||||
* display it in hexadecimal format of the underlying bytes.
|
||||
*/
|
||||
public class AESEncryption {
|
||||
|
||||
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
|
||||
/**
|
||||
* 1. Generate a plain text for encryption 2. Get a secret key (printed in hexadecimal form). In
|
||||
* actual use this must by encrypted and kept safe. The same key is required for decryption.
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
String plainText = "Hello World";
|
||||
SecretKey secKey = getSecretEncryptionKey();
|
||||
byte[] cipherText = encryptText(plainText, secKey);
|
||||
String decryptedText = decryptText(cipherText, secKey);
|
||||
|
||||
System.out.println("Original Text:" + plainText);
|
||||
System.out.println("AES Key (Hex Form):" + bytesToHex(secKey.getEncoded()));
|
||||
System.out.println("Encrypted Text (Hex Form):" + bytesToHex(cipherText));
|
||||
System.out.println("Descrypted Text:" + decryptedText);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the AES encryption key. In your actual programs, this should be safely stored.
|
||||
*
|
||||
* @return secKey (Secret key that we encrypt using it)
|
||||
* @throws NoSuchAlgorithmException (from KeyGenrator)
|
||||
*/
|
||||
public static SecretKey getSecretEncryptionKey() throws NoSuchAlgorithmException {
|
||||
KeyGenerator aesKeyGenerator = KeyGenerator.getInstance("AES");
|
||||
aesKeyGenerator.init(128); // The AES key size in number of bits
|
||||
return aesKeyGenerator.generateKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts plainText in AES using the secret key
|
||||
*
|
||||
* @return byteCipherText (The encrypted text)
|
||||
* @throws NoSuchPaddingException (from Cipher)
|
||||
* @throws NoSuchAlgorithmException (from Cipher)
|
||||
* @throws InvalidKeyException (from Cipher)
|
||||
* @throws BadPaddingException (from Cipher)
|
||||
* @throws IllegalBlockSizeException (from Cipher)
|
||||
*/
|
||||
public static byte[] encryptText(String plainText, SecretKey secKey)
|
||||
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
|
||||
IllegalBlockSizeException, BadPaddingException {
|
||||
// AES defaults to AES/ECB/PKCS5Padding in Java 7
|
||||
Cipher aesCipher = Cipher.getInstance("AES");
|
||||
aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
|
||||
return aesCipher.doFinal(plainText.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts encrypted byte array using the key used for encryption.
|
||||
*
|
||||
* @return plainText
|
||||
*/
|
||||
public static String decryptText(byte[] byteCipherText, SecretKey secKey)
|
||||
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
|
||||
IllegalBlockSizeException, BadPaddingException {
|
||||
// AES defaults to AES/ECB/PKCS5Padding in Java 7
|
||||
Cipher aesCipher = Cipher.getInstance("AES");
|
||||
aesCipher.init(Cipher.DECRYPT_MODE, secKey);
|
||||
byte[] bytePlainText = aesCipher.doFinal(byteCipherText);
|
||||
return new String(bytePlainText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a binary byte array into readable hex form Old library is deprecated on OpenJdk 11 and
|
||||
* this is faster regarding other solution is using StringBuilder
|
||||
*
|
||||
* @return hexHash
|
||||
*/
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
char[] hexChars = new char[bytes.length * 2];
|
||||
for (int j = 0; j < bytes.length; j++) {
|
||||
int v = bytes[j] & 0xFF;
|
||||
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
|
||||
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
|
||||
}
|
||||
return new String(hexChars);
|
||||
}
|
||||
}
|
115
Ciphers/Caesar.java
Normal file
115
Ciphers/Caesar.java
Normal file
@ -0,0 +1,115 @@
|
||||
package Ciphers;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* A Java implementation of Caesar Cipher. /It is a type of substitution cipher in which each letter
|
||||
* in the plaintext is replaced by a letter some fixed number of positions down the alphabet. /
|
||||
*
|
||||
* @author FAHRI YARDIMCI
|
||||
* @author khalil2535
|
||||
*/
|
||||
public class Caesar {
|
||||
|
||||
/**
|
||||
* Encrypt text by shifting every Latin char by add number shift for ASCII Example : A + 1 -> B
|
||||
*
|
||||
* @return Encrypted message
|
||||
*/
|
||||
public static String encode(String message, int shift) {
|
||||
StringBuilder encoded = new StringBuilder();
|
||||
|
||||
shift %= 26;
|
||||
|
||||
final int length = message.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
|
||||
// int current = message.charAt(i); //using char to shift characters because ascii
|
||||
// is in-order latin alphabet
|
||||
char current = message.charAt(i); // Java law : char + int = char
|
||||
|
||||
if (IsCapitalLatinLetter(current)) {
|
||||
|
||||
current += shift;
|
||||
encoded.append((char) (current > 'Z' ? current - 26 : current)); // 26 = number of latin letters
|
||||
|
||||
} else if (IsSmallLatinLetter(current)) {
|
||||
|
||||
current += shift;
|
||||
encoded.append((char) (current > 'z' ? current - 26 : current)); // 26 = number of latin letters
|
||||
|
||||
} else {
|
||||
encoded.append(current);
|
||||
}
|
||||
}
|
||||
return encoded.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt message by shifting back every Latin char to previous the ASCII Example : B - 1 -> A
|
||||
*
|
||||
* @return message
|
||||
*/
|
||||
public static String decode(String encryptedMessage, int shift) {
|
||||
StringBuilder decoded = new StringBuilder();
|
||||
|
||||
shift %= 26;
|
||||
|
||||
final int length = encryptedMessage.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
char current = encryptedMessage.charAt(i);
|
||||
if (IsCapitalLatinLetter(current)) {
|
||||
|
||||
current -= shift;
|
||||
decoded.append((char) (current < 'A' ? current + 26 : current)); // 26 = number of latin letters
|
||||
|
||||
} else if (IsSmallLatinLetter(current)) {
|
||||
|
||||
current -= shift;
|
||||
decoded.append((char) (current < 'a' ? current + 26 : current)); // 26 = number of latin letters
|
||||
|
||||
} else {
|
||||
decoded.append(current);
|
||||
}
|
||||
}
|
||||
return decoded.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if character is capital Latin letter or false for others
|
||||
*/
|
||||
private static boolean IsCapitalLatinLetter(char c) {
|
||||
return c >= 'A' && c <= 'Z';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if character is small Latin letter or false for others
|
||||
*/
|
||||
private static boolean IsSmallLatinLetter(char c) {
|
||||
return c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner input = new Scanner(System.in);
|
||||
System.out.println("Please enter the message (Latin Alphabet)");
|
||||
String message = input.nextLine();
|
||||
System.out.println(message);
|
||||
System.out.println("Please enter the shift number");
|
||||
int shift = input.nextInt() % 26;
|
||||
System.out.println("(E)ncode or (D)ecode ?");
|
||||
char choice = input.next().charAt(0);
|
||||
switch (choice) {
|
||||
case 'E':
|
||||
case 'e':
|
||||
System.out.println(
|
||||
"ENCODED MESSAGE IS \n" + encode(message, shift)); // send our function to handle
|
||||
break;
|
||||
case 'D':
|
||||
case 'd':
|
||||
System.out.println("DECODED MESSAGE IS \n" + decode(message, shift));
|
||||
default:
|
||||
System.out.println("default case");
|
||||
}
|
||||
input.close();
|
||||
}
|
||||
}
|
199
Ciphers/ColumnarTranspositionCipher.java
Normal file
199
Ciphers/ColumnarTranspositionCipher.java
Normal file
@ -0,0 +1,199 @@
|
||||
package Ciphers;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Columnar Transposition Cipher Encryption and Decryption.
|
||||
*
|
||||
* @author <a href="https://github.com/freitzzz">freitzzz</a>
|
||||
*/
|
||||
public class ColumnarTranspositionCipher {
|
||||
|
||||
private static String keyword;
|
||||
private static Object[][] table;
|
||||
private static String abecedarium;
|
||||
public static final String ABECEDARIUM =
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFG" + "HIJKLMNOPQRSTUVWXYZ0123456789,.;:-@";
|
||||
private static final String ENCRYPTION_FIELD = "≈";
|
||||
private static final char ENCRYPTION_FIELD_CHAR = '≈';
|
||||
|
||||
/**
|
||||
* Encrypts a certain String with the Columnar Transposition Cipher Rule
|
||||
*
|
||||
* @param word Word being encrypted
|
||||
* @param keyword String with keyword being used
|
||||
* @return a String with the word encrypted by the Columnar Transposition Cipher Rule
|
||||
*/
|
||||
public static String encrpyter(String word, String keyword) {
|
||||
ColumnarTranspositionCipher.keyword = keyword;
|
||||
abecedariumBuilder(500);
|
||||
table = tableBuilder(word);
|
||||
Object[][] sortedTable = sortTable(table);
|
||||
StringBuilder wordEncrypted = new StringBuilder();
|
||||
for (int i = 0; i < sortedTable[i].length; i++) {
|
||||
for (int j = 1; j < sortedTable.length; j++) {
|
||||
wordEncrypted.append(sortedTable[j][i]);
|
||||
}
|
||||
}
|
||||
return wordEncrypted.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a certain String with the Columnar Transposition Cipher Rule
|
||||
*
|
||||
* @param word Word being encrypted
|
||||
* @param keyword String with keyword being used
|
||||
* @param abecedarium String with the abecedarium being used. null for default one
|
||||
* @return a String with the word encrypted by the Columnar Transposition Cipher Rule
|
||||
*/
|
||||
public static String encrpyter(String word, String keyword, String abecedarium) {
|
||||
ColumnarTranspositionCipher.keyword = keyword;
|
||||
ColumnarTranspositionCipher.abecedarium = Objects.requireNonNullElse(abecedarium, ABECEDARIUM);
|
||||
table = tableBuilder(word);
|
||||
Object[][] sortedTable = sortTable(table);
|
||||
StringBuilder wordEncrypted = new StringBuilder();
|
||||
for (int i = 0; i < sortedTable[0].length; i++) {
|
||||
for (int j = 1; j < sortedTable.length; j++) {
|
||||
wordEncrypted.append(sortedTable[j][i]);
|
||||
}
|
||||
}
|
||||
return wordEncrypted.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a certain encrypted String with the Columnar Transposition Cipher Rule
|
||||
*
|
||||
* @return a String decrypted with the word encrypted by the Columnar Transposition Cipher Rule
|
||||
*/
|
||||
public static String decrypter() {
|
||||
StringBuilder wordDecrypted = new StringBuilder();
|
||||
for (int i = 1; i < table.length; i++) {
|
||||
for (Object item : table[i]) {
|
||||
wordDecrypted.append(item);
|
||||
}
|
||||
}
|
||||
return wordDecrypted.toString().replaceAll(ENCRYPTION_FIELD, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a table with the word to be encrypted in rows by the Columnar Transposition Cipher Rule
|
||||
*
|
||||
* @return An Object[][] with the word to be encrypted filled in rows and columns
|
||||
*/
|
||||
private static Object[][] tableBuilder(String word) {
|
||||
Object[][] table = new Object[numberOfRows(word) + 1][keyword.length()];
|
||||
char[] wordInChards = word.toCharArray();
|
||||
// Fils in the respective numbers
|
||||
table[0] = findElements();
|
||||
int charElement = 0;
|
||||
for (int i = 1; i < table.length; i++) {
|
||||
for (int j = 0; j < table[i].length; j++) {
|
||||
if (charElement < wordInChards.length) {
|
||||
table[i][j] = wordInChards[charElement];
|
||||
charElement++;
|
||||
} else {
|
||||
table[i][j] = ENCRYPTION_FIELD_CHAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the number of rows the table should have regarding the Columnar Transposition Cipher
|
||||
* Rule
|
||||
*
|
||||
* @return an int with the number of rows that the table should have in order to respect the
|
||||
* Columnar Transposition Cipher Rule.
|
||||
*/
|
||||
private static int numberOfRows(String word) {
|
||||
if (word.length() / keyword.length() > word.length() / keyword.length()) {
|
||||
return (word.length() / keyword.length()) + 1;
|
||||
} else {
|
||||
return word.length() / keyword.length();
|
||||
}
|
||||
}
|
||||
|
||||
/** @return charValues */
|
||||
private static Object[] findElements() {
|
||||
Object[] charValues = new Object[keyword.length()];
|
||||
for (int i = 0; i < charValues.length; i++) {
|
||||
int charValueIndex = abecedarium.indexOf(keyword.charAt(i));
|
||||
charValues[i] = charValueIndex > -1 ? charValueIndex : null;
|
||||
}
|
||||
return charValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return tableSorted
|
||||
*/
|
||||
private static Object[][] sortTable(Object[][] table) {
|
||||
Object[][] tableSorted = new Object[table.length][table[0].length];
|
||||
for (int i = 0; i < tableSorted.length; i++) {
|
||||
System.arraycopy(table[i], 0, tableSorted[i], 0, tableSorted[i].length);
|
||||
}
|
||||
for (int i = 0; i < tableSorted[0].length; i++) {
|
||||
for (int j = i + 1; j < tableSorted[0].length; j++) {
|
||||
if ((int) tableSorted[0][i] > (int) table[0][j]) {
|
||||
Object[] column = getColumn(tableSorted, tableSorted.length, i);
|
||||
switchColumns(tableSorted, j, i, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tableSorted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return columnArray
|
||||
*/
|
||||
private static Object[] getColumn(Object[][] table, int rows, int column) {
|
||||
Object[] columnArray = new Object[rows];
|
||||
for (int i = 0; i < rows; i++) {
|
||||
columnArray[i] = table[i][column];
|
||||
}
|
||||
return columnArray;
|
||||
}
|
||||
|
||||
private static void switchColumns(
|
||||
Object[][] table, int firstColumnIndex, int secondColumnIndex, Object[] columnToSwitch) {
|
||||
for (int i = 0; i < table.length; i++) {
|
||||
table[i][secondColumnIndex] = table[i][firstColumnIndex];
|
||||
table[i][firstColumnIndex] = columnToSwitch[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an abecedarium with a specified ascii inded
|
||||
*
|
||||
* @param value Number of characters being used based on the ASCII Table
|
||||
*/
|
||||
private static void abecedariumBuilder(int value) {
|
||||
StringBuilder t = new StringBuilder();
|
||||
for (int i = 0; i < value; i++) {
|
||||
t.append((char) i);
|
||||
}
|
||||
abecedarium = t.toString();
|
||||
}
|
||||
|
||||
private static void showTable() {
|
||||
for (Object[] table1 : table) {
|
||||
for (Object item : table1) {
|
||||
System.out.print(item + " ");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String keywordForExample = "asd215";
|
||||
String wordBeingEncrypted = "This is a test of the Columnar Transposition Cipher";
|
||||
System.out.println("### Example of Columnar Transposition Cipher ###\n");
|
||||
System.out.println("Word being encryped ->>> " + wordBeingEncrypted);
|
||||
System.out.println(
|
||||
"Word encrypted ->>> "
|
||||
+ ColumnarTranspositionCipher.encrpyter(wordBeingEncrypted, keywordForExample));
|
||||
System.out.println("Word decryped ->>> " + ColumnarTranspositionCipher.decrypter());
|
||||
System.out.println("\n### Encrypted Table ###");
|
||||
showTable();
|
||||
}
|
||||
}
|
74
Ciphers/RSA.java
Normal file
74
Ciphers/RSA.java
Normal file
@ -0,0 +1,74 @@
|
||||
package Ciphers;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
/** @author Nguyen Duy Tiep on 23-Oct-17. */
|
||||
public final class RSA {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
RSA rsa = new RSA(1024);
|
||||
String text1 = JOptionPane.showInputDialog("Enter a message to encrypt :");
|
||||
|
||||
String ciphertext = rsa.encrypt(text1);
|
||||
JOptionPane.showMessageDialog(null, "Your encrypted message : " + ciphertext);
|
||||
|
||||
JOptionPane.showMessageDialog(null, "Your message after decrypt : " + rsa.decrypt(ciphertext));
|
||||
}
|
||||
|
||||
private BigInteger modulus, privateKey, publicKey;
|
||||
|
||||
public RSA(int bits) {
|
||||
generateKeys(bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return encrypted message
|
||||
*/
|
||||
public synchronized String encrypt(String message) {
|
||||
return (new BigInteger(message.getBytes())).modPow(publicKey, modulus).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return encrypted message as big integer
|
||||
*/
|
||||
public synchronized BigInteger encrypt(BigInteger message) {
|
||||
return message.modPow(publicKey, modulus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return plain message
|
||||
*/
|
||||
public synchronized String decrypt(String encryptedMessage) {
|
||||
return new String((new BigInteger(encryptedMessage)).modPow(privateKey, modulus).toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return plain message as big integer
|
||||
*/
|
||||
public synchronized BigInteger decrypt(BigInteger encryptedMessage) {
|
||||
return encryptedMessage.modPow(privateKey, modulus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new public and private key set.
|
||||
*/
|
||||
public synchronized void generateKeys(int bits) {
|
||||
SecureRandom r = new SecureRandom();
|
||||
BigInteger p = new BigInteger(bits / 2, 100, r);
|
||||
BigInteger q = new BigInteger(bits / 2, 100, r);
|
||||
modulus = p.multiply(q);
|
||||
|
||||
BigInteger m = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));
|
||||
|
||||
publicKey = new BigInteger("3");
|
||||
|
||||
while (m.gcd(publicKey).intValue() > 1) {
|
||||
publicKey = publicKey.add(new BigInteger("2"));
|
||||
}
|
||||
|
||||
privateKey = publicKey.modInverse(m);
|
||||
}
|
||||
}
|
83
Ciphers/SimpleSubstitutionCipher.java
Normal file
83
Ciphers/SimpleSubstitutionCipher.java
Normal file
@ -0,0 +1,83 @@
|
||||
package Ciphers;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The simple substitution cipher is a cipher that has been in use for many hundreds of years (an
|
||||
* excellent history is given in Simon Singhs 'the Code Book'). It basically consists of
|
||||
* substituting every plaintext character for a different ciphertext character. It differs from the
|
||||
* Caesar cipher in that the cipher alphabet is not simply the alphabet shifted, it is completely
|
||||
* jumbled.
|
||||
*
|
||||
* @author Hassan Elseoudy
|
||||
*/
|
||||
public class SimpleSubstitutionCipher {
|
||||
|
||||
/**
|
||||
* Encrypt text by replacing each element with its opposite character.
|
||||
*
|
||||
* @return Encrypted message
|
||||
*/
|
||||
public static String encode(String message, String cipherSmall) {
|
||||
StringBuilder encoded = new StringBuilder();
|
||||
|
||||
// This map is used to encode
|
||||
Map<Character, Character> cipherMap = new HashMap<>();
|
||||
|
||||
char beginSmallLetter = 'a';
|
||||
char beginCapitalLetter = 'A';
|
||||
|
||||
cipherSmall = cipherSmall.toLowerCase();
|
||||
String cipherCapital = cipherSmall.toUpperCase();
|
||||
|
||||
// To handle Small and Capital letters
|
||||
for (int i = 0; i < cipherSmall.length(); i++) {
|
||||
cipherMap.put(beginSmallLetter++, cipherSmall.charAt(i));
|
||||
cipherMap.put(beginCapitalLetter++, cipherCapital.charAt(i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < message.length(); i++) {
|
||||
if (Character.isAlphabetic(message.charAt(i))) encoded.append(cipherMap.get(message.charAt(i)));
|
||||
else encoded.append(message.charAt(i));
|
||||
}
|
||||
|
||||
return encoded.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt message by replacing each element with its opposite character in cipher.
|
||||
*
|
||||
* @return message
|
||||
*/
|
||||
public static String decode(String encryptedMessage, String cipherSmall) {
|
||||
StringBuilder decoded = new StringBuilder();
|
||||
|
||||
Map<Character, Character> cipherMap = new HashMap<>();
|
||||
|
||||
char beginSmallLetter = 'a';
|
||||
char beginCapitalLetter = 'A';
|
||||
|
||||
cipherSmall = cipherSmall.toLowerCase();
|
||||
String cipherCapital = cipherSmall.toUpperCase();
|
||||
|
||||
for (int i = 0; i < cipherSmall.length(); i++) {
|
||||
cipherMap.put(cipherSmall.charAt(i), beginSmallLetter++);
|
||||
cipherMap.put(cipherCapital.charAt(i), beginCapitalLetter++);
|
||||
}
|
||||
|
||||
for (int i = 0; i < encryptedMessage.length(); i++) {
|
||||
if (Character.isAlphabetic(encryptedMessage.charAt(i)))
|
||||
decoded.append(cipherMap.get(encryptedMessage.charAt(i)));
|
||||
else decoded.append(encryptedMessage.charAt(i));
|
||||
}
|
||||
|
||||
return decoded.toString();
|
||||
}
|
||||
|
||||
/** TODO remove main and make JUnit Testing */
|
||||
public static void main(String[] args) {
|
||||
String a = encode("defend the east wall of the castle", "phqgiumeaylnofdxjkrcvstzwb");
|
||||
String b = decode(a, "phqgiumeaylnofdxjkrcvstzwb");
|
||||
System.out.println(b);
|
||||
}
|
||||
}
|
62
Ciphers/Vigenere.java
Normal file
62
Ciphers/Vigenere.java
Normal file
@ -0,0 +1,62 @@
|
||||
package Ciphers;
|
||||
|
||||
/**
|
||||
* A Java implementation of Vigenere Cipher.
|
||||
*
|
||||
* @author straiffix
|
||||
* @author beingmartinbmc
|
||||
*/
|
||||
public class Vigenere {
|
||||
|
||||
public static String encrypt(final String message, final String key) {
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (int i = 0, j = 0; i < message.length(); i++) {
|
||||
char c = message.charAt(i);
|
||||
if (Character.isLetter(c)) {
|
||||
if (Character.isUpperCase(c)) {
|
||||
result.append((char) ((c + key.toUpperCase().charAt(j) - 2 * 'A') % 26 + 'A'));
|
||||
|
||||
} else {
|
||||
result.append((char) ((c + key.toLowerCase().charAt(j) - 2 * 'a') % 26 + 'a'));
|
||||
}
|
||||
} else {
|
||||
result.append(c);
|
||||
}
|
||||
j = ++j % key.length();
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String decrypt(final String message, final String key) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (int i = 0, j = 0; i < message.length(); i++) {
|
||||
|
||||
char c = message.charAt(i);
|
||||
if (Character.isLetter(c)) {
|
||||
if (Character.isUpperCase(c)) {
|
||||
result.append((char) ('Z' - (25 - (c - key.toUpperCase().charAt(j))) % 26));
|
||||
|
||||
} else {
|
||||
result.append((char) ('z' - (25 - (c - key.toLowerCase().charAt(j))) % 26));
|
||||
}
|
||||
} else {
|
||||
result.append(c);
|
||||
}
|
||||
|
||||
j = ++j % key.length();
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String text = "Hello World!";
|
||||
String key = "itsakey";
|
||||
System.out.println(text);
|
||||
String ciphertext = encrypt(text, key);
|
||||
System.out.println(ciphertext);
|
||||
System.out.println(decrypt(ciphertext, key));
|
||||
}
|
||||
}
|
127
Conversions/AnyBaseToAnyBase.java
Normal file
127
Conversions/AnyBaseToAnyBase.java
Normal file
@ -0,0 +1,127 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.InputMismatchException;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Class for converting from "any" base to "any" other base, when "any" means from 2-36. Works by
|
||||
* going from base 1 to decimal to base 2. Includes auxiliary method for determining whether a
|
||||
* number is valid for a given base.
|
||||
*
|
||||
* @author Michael Rolland
|
||||
* @version 2017.10.10
|
||||
*/
|
||||
public class AnyBaseToAnyBase {
|
||||
|
||||
/** Smallest and largest base you want to accept as valid input */
|
||||
static final int MINIMUM_BASE = 2;
|
||||
|
||||
static final int MAXIMUM_BASE = 36;
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner in = new Scanner(System.in);
|
||||
String n;
|
||||
int b1, b2;
|
||||
while (true) {
|
||||
try {
|
||||
System.out.print("Enter number: ");
|
||||
n = in.next();
|
||||
System.out.print(
|
||||
"Enter beginning base (between " + MINIMUM_BASE + " and " + MAXIMUM_BASE + "): ");
|
||||
b1 = in.nextInt();
|
||||
if (b1 > MAXIMUM_BASE || b1 < MINIMUM_BASE) {
|
||||
System.out.println("Invalid base!");
|
||||
continue;
|
||||
}
|
||||
if (!validForBase(n, b1)) {
|
||||
System.out.println("The number is invalid for this base!");
|
||||
continue;
|
||||
}
|
||||
System.out.print(
|
||||
"Enter end base (between " + MINIMUM_BASE + " and " + MAXIMUM_BASE + "): ");
|
||||
b2 = in.nextInt();
|
||||
if (b2 > MAXIMUM_BASE || b2 < MINIMUM_BASE) {
|
||||
System.out.println("Invalid base!");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} catch (InputMismatchException e) {
|
||||
System.out.println("Invalid input.");
|
||||
in.next();
|
||||
}
|
||||
}
|
||||
System.out.println(base2base(n, b1, b2));
|
||||
in.close();
|
||||
}
|
||||
|
||||
/** Checks if a number (as a String) is valid for a given base. */
|
||||
public static boolean validForBase(String n, int base) {
|
||||
char[] validDigits = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
|
||||
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
|
||||
};
|
||||
// digitsForBase contains all the valid digits for the base given
|
||||
char[] digitsForBase = Arrays.copyOfRange(validDigits, 0, base);
|
||||
|
||||
// Convert character array into set for convenience of contains() method
|
||||
HashSet<Character> digitsList = new HashSet<>();
|
||||
for (int i = 0; i < digitsForBase.length; i++) digitsList.add(digitsForBase[i]);
|
||||
|
||||
// Check that every digit in n is within the list of valid digits for that base.
|
||||
for (char c : n.toCharArray()) if (!digitsList.contains(c)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to convert any integer from base b1 to base b2. Works by converting from b1 to decimal,
|
||||
* then decimal to b2.
|
||||
*
|
||||
* @param n The integer to be converted.
|
||||
* @param b1 Beginning base.
|
||||
* @param b2 End base.
|
||||
* @return n in base b2.
|
||||
*/
|
||||
public static String base2base(String n, int b1, int b2) {
|
||||
// Declare variables: decimal value of n,
|
||||
// character of base b1, character of base b2,
|
||||
// and the string that will be returned.
|
||||
int decimalValue = 0, charB2;
|
||||
char charB1;
|
||||
String output = "";
|
||||
// Go through every character of n
|
||||
for (int i = 0; i < n.length(); i++) {
|
||||
// store the character in charB1
|
||||
charB1 = n.charAt(i);
|
||||
// if it is a non-number, convert it to a decimal value >9 and store it in charB2
|
||||
if (charB1 >= 'A' && charB1 <= 'Z') charB2 = 10 + (charB1 - 'A');
|
||||
// Else, store the integer value in charB2
|
||||
else charB2 = charB1 - '0';
|
||||
// Convert the digit to decimal and add it to the
|
||||
// decimalValue of n
|
||||
decimalValue = decimalValue * b1 + charB2;
|
||||
}
|
||||
|
||||
// Converting the decimal value to base b2:
|
||||
// A number is converted from decimal to another base
|
||||
// by continuously dividing by the base and recording
|
||||
// the remainder until the quotient is zero. The number in the
|
||||
// new base is the remainders, with the last remainder
|
||||
// being the left-most digit.
|
||||
if (0 == decimalValue) return "0";
|
||||
// While the quotient is NOT zero:
|
||||
while (decimalValue != 0) {
|
||||
// If the remainder is a digit < 10, simply add it to
|
||||
// the left side of the new number.
|
||||
if (decimalValue % b2 < 10) output = Integer.toString(decimalValue % b2) + output;
|
||||
// If the remainder is >= 10, add a character with the
|
||||
// corresponding value to the new number. (A = 10, B = 11, C = 12, ...)
|
||||
else output = (char) ((decimalValue % b2) + 55) + output;
|
||||
// Divide by the new base again
|
||||
decimalValue /= b2;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
51
Conversions/AnyBaseToDecimal.java
Normal file
51
Conversions/AnyBaseToDecimal.java
Normal file
@ -0,0 +1,51 @@
|
||||
package Conversions;
|
||||
|
||||
/** @author Varun Upadhyay (https://github.com/varunu28) */
|
||||
|
||||
// Driver program
|
||||
public class AnyBaseToDecimal {
|
||||
public static void main(String[] args) {
|
||||
assert convertToDecimal("1010", 2) == Integer.valueOf("1010", 2);
|
||||
assert convertToDecimal("777", 8) == Integer.valueOf("777", 8);
|
||||
assert convertToDecimal("999", 10) == Integer.valueOf("999", 10);
|
||||
assert convertToDecimal("ABCDEF", 16) == Integer.valueOf("ABCDEF", 16);
|
||||
assert convertToDecimal("XYZ", 36) == Integer.valueOf("XYZ", 36);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert any radix to decimal number
|
||||
*
|
||||
* @param s the string to be convert
|
||||
* @param radix the radix
|
||||
* @return decimal of bits
|
||||
* @throws NumberFormatException if {@code bits} or {@code radix} is invalid
|
||||
*/
|
||||
public static int convertToDecimal(String s, int radix) {
|
||||
int num = 0;
|
||||
int pow = 1;
|
||||
|
||||
for (int i = s.length() - 1; i >= 0; i--) {
|
||||
int digit = valOfChar(s.charAt(i));
|
||||
if (digit >= radix) {
|
||||
throw new NumberFormatException("For input string " + s);
|
||||
}
|
||||
num += valOfChar(s.charAt(i)) * pow;
|
||||
pow *= radix;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert character to integer
|
||||
*
|
||||
* @param c the character
|
||||
* @return represented digit of given character
|
||||
* @throws NumberFormatException if {@code ch} is not UpperCase or Digit character.
|
||||
*/
|
||||
public static int valOfChar(char c) {
|
||||
if (!(Character.isUpperCase(c) || Character.isDigit(c))) {
|
||||
throw new NumberFormatException("invalid character :" + c);
|
||||
}
|
||||
return Character.isDigit(c) ? c - '0' : c - 'A' + 10;
|
||||
}
|
||||
}
|
30
Conversions/AnytoAny.java
Normal file
30
Conversions/AnytoAny.java
Normal file
@ -0,0 +1,30 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.Scanner;
|
||||
// given a source number , source base, destination base, this code can give you the destination
|
||||
// number.
|
||||
// sn ,sb,db ---> ()dn . this is what we have to do .
|
||||
|
||||
public class AnytoAny {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner scn = new Scanner(System.in);
|
||||
int sn = scn.nextInt();
|
||||
int sb = scn.nextInt();
|
||||
int db = scn.nextInt();
|
||||
int m = 1, dec = 0, dn = 0;
|
||||
while (sn != 0) {
|
||||
dec = dec + (sn % 10) * m;
|
||||
m *= sb;
|
||||
sn /= 10;
|
||||
}
|
||||
m = 1;
|
||||
while (dec != 0) {
|
||||
dn = dn + (dec % db) * m;
|
||||
m *= 10;
|
||||
dec /= db;
|
||||
}
|
||||
System.out.println(dn);
|
||||
scn.close();
|
||||
}
|
||||
}
|
27
Conversions/BinaryToDecimal.java
Normal file
27
Conversions/BinaryToDecimal.java
Normal file
@ -0,0 +1,27 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/** This class converts a Binary number to a Decimal number */
|
||||
class BinaryToDecimal {
|
||||
|
||||
/**
|
||||
* Main Method
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
int binNum, binCopy, d, s = 0, power = 0;
|
||||
System.out.print("Binary number: ");
|
||||
binNum = sc.nextInt();
|
||||
binCopy = binNum;
|
||||
while (binCopy != 0) {
|
||||
d = binCopy % 10;
|
||||
s += d * (int) Math.pow(2, power++);
|
||||
binCopy /= 10;
|
||||
}
|
||||
System.out.println("Decimal equivalent:" + s);
|
||||
sc.close();
|
||||
}
|
||||
}
|
55
Conversions/BinaryToHexadecimal.java
Normal file
55
Conversions/BinaryToHexadecimal.java
Normal file
@ -0,0 +1,55 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Converts any Binary Number to a Hexadecimal Number
|
||||
*
|
||||
* @author Nishita Aggarwal
|
||||
*/
|
||||
public class BinaryToHexadecimal {
|
||||
|
||||
/**
|
||||
* This method converts a binary number to a hexadecimal number.
|
||||
*
|
||||
* @param binary The binary number
|
||||
* @return The hexadecimal number
|
||||
*/
|
||||
static String binToHex(int binary) {
|
||||
// hm to store hexadecimal codes for binary numbers within the range: 0000 to 1111 i.e. for
|
||||
// decimal numbers 0 to 15
|
||||
HashMap<Integer, String> hm = new HashMap<>();
|
||||
// String to store hexadecimal code
|
||||
String hex = "";
|
||||
int i;
|
||||
for (i = 0; i < 10; i++) {
|
||||
hm.put(i, String.valueOf(i));
|
||||
}
|
||||
for (i = 10; i < 16; i++) hm.put(i, String.valueOf((char) ('A' + i - 10)));
|
||||
int currbit;
|
||||
while (binary != 0) {
|
||||
int code4 = 0; // to store decimal equivalent of number formed by 4 decimal digits
|
||||
for (i = 0; i < 4; i++) {
|
||||
currbit = binary % 10;
|
||||
binary = binary / 10;
|
||||
code4 += currbit * Math.pow(2, i);
|
||||
}
|
||||
hex = hm.get(code4) + hex;
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
System.out.println("Enter binary number:");
|
||||
int binary = sc.nextInt();
|
||||
String hex = binToHex(binary);
|
||||
System.out.println("Hexadecimal Code:" + hex);
|
||||
sc.close();
|
||||
}
|
||||
}
|
47
Conversions/BinaryToOctal.java
Normal file
47
Conversions/BinaryToOctal.java
Normal file
@ -0,0 +1,47 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Converts any Binary number to an Octal Number
|
||||
*
|
||||
* @author Zachary Jones
|
||||
*/
|
||||
public class BinaryToOctal {
|
||||
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
System.out.println("Input the binary number: ");
|
||||
int b = sc.nextInt();
|
||||
System.out.println("Octal equivalent: " + convertBinaryToOctal(b));
|
||||
sc.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a binary number to an octal number.
|
||||
*
|
||||
* @param binary The binary number
|
||||
* @return The octal number
|
||||
*/
|
||||
public static String convertBinaryToOctal(int binary) {
|
||||
String octal = "";
|
||||
int currBit = 0, j = 1;
|
||||
while (binary != 0) {
|
||||
int code3 = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
currBit = binary % 10;
|
||||
binary = binary / 10;
|
||||
code3 += currBit * j;
|
||||
j *= 2;
|
||||
}
|
||||
octal = code3 + octal;
|
||||
j = 1;
|
||||
}
|
||||
return octal;
|
||||
}
|
||||
}
|
61
Conversions/DecimalToAnyBase.java
Normal file
61
Conversions/DecimalToAnyBase.java
Normal file
@ -0,0 +1,61 @@
|
||||
package Conversions;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/** @author Varun Upadhyay (https://github.com/varunu28) */
|
||||
|
||||
// Driver Program
|
||||
public class DecimalToAnyBase {
|
||||
public static void main(String[] args) throws Exception {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
|
||||
System.out.println("Enter the decimal input below: ");
|
||||
int decInput = Integer.parseInt(br.readLine());
|
||||
System.out.println();
|
||||
|
||||
System.out.println("Enter the base below: ");
|
||||
int base = Integer.parseInt(br.readLine());
|
||||
System.out.println();
|
||||
|
||||
System.out.println("Decimal Input" + " is: " + decInput);
|
||||
System.out.println(
|
||||
"Value of " + decInput + " in base " + base + " is: " + convertToAnyBase(decInput, base));
|
||||
|
||||
br.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method produces a String value of any given input decimal in any base
|
||||
*
|
||||
* @param inp Decimal of which we need the value in base in String format
|
||||
* @return string format of the converted value in the given base
|
||||
*/
|
||||
public static String convertToAnyBase(int inp, int base) {
|
||||
ArrayList<Character> charArr = new ArrayList<>();
|
||||
|
||||
while (inp > 0) {
|
||||
charArr.add(reVal(inp % base));
|
||||
inp /= base;
|
||||
}
|
||||
|
||||
StringBuilder str = new StringBuilder(charArr.size());
|
||||
|
||||
for (Character ch : charArr) {
|
||||
str.append(ch);
|
||||
}
|
||||
|
||||
return str.reverse().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method produces character value of the input integer and returns it
|
||||
*
|
||||
* @param num integer of which we need the character value of
|
||||
* @return character value of input integer
|
||||
*/
|
||||
public static char reVal(int num) {
|
||||
if (num >= 0 && num <= 9) return (char) (num + '0');
|
||||
else return (char) (num - 10 + 'A');
|
||||
}
|
||||
}
|
47
Conversions/DecimalToBinary.java
Normal file
47
Conversions/DecimalToBinary.java
Normal file
@ -0,0 +1,47 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/** This class converts a Decimal number to a Binary number */
|
||||
class DecimalToBinary {
|
||||
|
||||
/**
|
||||
* Main Method
|
||||
*
|
||||
* @param args Command Line Arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
conventionalConversion();
|
||||
bitwiseConversion();
|
||||
}
|
||||
|
||||
/** This method converts a decimal number to a binary number using a conventional algorithm. */
|
||||
public static void conventionalConversion() {
|
||||
int n, b = 0, c = 0, d;
|
||||
Scanner input = new Scanner(System.in);
|
||||
System.out.printf("Conventional conversion.%n Enter the decimal number: ");
|
||||
n = input.nextInt();
|
||||
while (n != 0) {
|
||||
d = n % 2;
|
||||
b = b + d * (int) Math.pow(10, c++);
|
||||
n /= 2;
|
||||
} // converting decimal to binary
|
||||
System.out.println("\tBinary number: " + b);
|
||||
input.close();
|
||||
}
|
||||
|
||||
/** This method converts a decimal number to a binary number using a bitwise algorithm */
|
||||
public static void bitwiseConversion() {
|
||||
int n, b = 0, c = 0, d;
|
||||
Scanner input = new Scanner(System.in);
|
||||
System.out.printf("Bitwise conversion.%n Enter the decimal number: ");
|
||||
n = input.nextInt();
|
||||
while (n != 0) {
|
||||
d = (n & 1);
|
||||
b += d * (int) Math.pow(10, c++);
|
||||
n >>= 1;
|
||||
}
|
||||
System.out.println("\tBinary number: " + b);
|
||||
input.close();
|
||||
}
|
||||
}
|
33
Conversions/DecimalToHexaDecimal.java
Normal file
33
Conversions/DecimalToHexaDecimal.java
Normal file
@ -0,0 +1,33 @@
|
||||
package Conversions;
|
||||
|
||||
// hex = [0 - 9] -> [A - F]
|
||||
class DecimalToHexaDecimal {
|
||||
private static final int sizeOfIntInHalfBytes = 8;
|
||||
private static final int numberOfBitsInAHalfByte = 4;
|
||||
private static final int halfByte = 0x0F;
|
||||
private static final char[] hexDigits = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
||||
};
|
||||
|
||||
// Returns the hex value of the dec entered in the parameter.
|
||||
public static String decToHex(int dec) {
|
||||
StringBuilder hexBuilder = new StringBuilder(sizeOfIntInHalfBytes);
|
||||
hexBuilder.setLength(sizeOfIntInHalfBytes);
|
||||
for (int i = sizeOfIntInHalfBytes - 1; i >= 0; --i) {
|
||||
int j = dec & halfByte;
|
||||
hexBuilder.setCharAt(i, hexDigits[j]);
|
||||
dec >>= numberOfBitsInAHalfByte;
|
||||
}
|
||||
return hexBuilder.toString().toLowerCase();
|
||||
}
|
||||
|
||||
// Test above function.
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Test...");
|
||||
int dec = 305445566;
|
||||
String libraryDecToHex = Integer.toHexString(dec);
|
||||
String decToHex = decToHex(dec);
|
||||
System.out.println("Result from the library : " + libraryDecToHex);
|
||||
System.out.println("Result decToHex method : " + decToHex);
|
||||
}
|
||||
}
|
29
Conversions/DecimalToOctal.java
Normal file
29
Conversions/DecimalToOctal.java
Normal file
@ -0,0 +1,29 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/** This class converts Decimal numbers to Octal Numbers */
|
||||
public class DecimalToOctal {
|
||||
/**
|
||||
* Main Method
|
||||
*
|
||||
* @param args Command line Arguments
|
||||
*/
|
||||
|
||||
// enter in a decimal value to get Octal output
|
||||
public static void main(String[] args) {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
int n, k, d, s = 0, c = 0;
|
||||
System.out.print("Decimal number: ");
|
||||
n = sc.nextInt();
|
||||
k = n;
|
||||
while (k != 0) {
|
||||
d = k % 8;
|
||||
s += d * (int) Math.pow(10, c++);
|
||||
k /= 8;
|
||||
}
|
||||
|
||||
System.out.println("Octal equivalent:" + s);
|
||||
sc.close();
|
||||
}
|
||||
}
|
73
Conversions/HexToOct.java
Normal file
73
Conversions/HexToOct.java
Normal file
@ -0,0 +1,73 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Converts any Hexadecimal Number to Octal
|
||||
*
|
||||
* @author Tanmay Joshi
|
||||
*/
|
||||
public class HexToOct {
|
||||
/**
|
||||
* This method converts a Hexadecimal number to a decimal number
|
||||
*
|
||||
* @param s The Hexadecimal Number
|
||||
* @return The Decimal number
|
||||
*/
|
||||
public static int hex2decimal(String s) {
|
||||
String str = "0123456789ABCDEF";
|
||||
s = s.toUpperCase();
|
||||
int val = 0;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char a = s.charAt(i);
|
||||
int n = str.indexOf(a);
|
||||
val = 16 * val + n;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a Decimal number to a octal number
|
||||
*
|
||||
* @param q The Decimal Number
|
||||
* @return The Octal number
|
||||
*/
|
||||
public static int decimal2octal(int q) {
|
||||
int now;
|
||||
int i = 1;
|
||||
int octnum = 0;
|
||||
while (q > 0) {
|
||||
now = q % 8;
|
||||
octnum = (now * (int) (Math.pow(10, i))) + octnum;
|
||||
q /= 8;
|
||||
i++;
|
||||
}
|
||||
octnum /= 10;
|
||||
return octnum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method that gets the hex input from user and converts it into octal.
|
||||
*
|
||||
* @param args arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
String hexadecnum;
|
||||
int decnum, octalnum;
|
||||
Scanner scan = new Scanner(System.in);
|
||||
|
||||
System.out.print("Enter Hexadecimal Number : ");
|
||||
hexadecnum = scan.nextLine();
|
||||
|
||||
// first convert hexadecimal to decimal
|
||||
decnum =
|
||||
hex2decimal(
|
||||
hexadecnum); // Pass the string to the hex2decimal function and get the decimal form in
|
||||
// variable decnum
|
||||
|
||||
// convert decimal to octal
|
||||
octalnum = decimal2octal(decnum);
|
||||
System.out.println("Number in octal: " + octalnum);
|
||||
scan.close();
|
||||
}
|
||||
}
|
35
Conversions/HexaDecimalToBinary.java
Normal file
35
Conversions/HexaDecimalToBinary.java
Normal file
@ -0,0 +1,35 @@
|
||||
package Conversions;
|
||||
|
||||
// Hex [0-9],[A-F] -> Binary [0,1]
|
||||
|
||||
public class HexaDecimalToBinary {
|
||||
|
||||
private final int LONG_BITS = 8;
|
||||
|
||||
public void convert(String numHex) {
|
||||
// String a HexaDecimal:
|
||||
int conHex = Integer.parseInt(numHex, 16);
|
||||
// Hex a Binary:
|
||||
String binary = Integer.toBinaryString(conHex);
|
||||
// Output:
|
||||
System.out.println(numHex + " = " + completeDigits(binary));
|
||||
}
|
||||
|
||||
public String completeDigits(String binNum) {
|
||||
for (int i = binNum.length(); i < LONG_BITS; i++) {
|
||||
binNum = "0" + binNum;
|
||||
}
|
||||
return binNum;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
// Testing Numbers:
|
||||
String[] hexNums = {"1", "A1", "ef", "BA", "AA", "BB", "19", "01", "02", "03", "04"};
|
||||
HexaDecimalToBinary objConvert = new HexaDecimalToBinary();
|
||||
|
||||
for (String num : hexNums) {
|
||||
objConvert.convert(num);
|
||||
}
|
||||
}
|
||||
}
|
39
Conversions/HexaDecimalToDecimal.java
Normal file
39
Conversions/HexaDecimalToDecimal.java
Normal file
@ -0,0 +1,39 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
public class HexaDecimalToDecimal {
|
||||
|
||||
// convert hexadecimal to decimal
|
||||
public static int getHexaToDec(String hex) {
|
||||
String digits = "0123456789ABCDEF";
|
||||
hex = hex.toUpperCase();
|
||||
int val = 0;
|
||||
for (int i = 0; i < hex.length(); i++) {
|
||||
int d = digits.indexOf(hex.charAt(i));
|
||||
val = 16 * val + d;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
// Main method gets the hexadecimal input from user and converts it into Decimal output.
|
||||
|
||||
public static void main(String args[]) {
|
||||
String hexa_Input;
|
||||
int dec_output;
|
||||
Scanner scan = new Scanner(System.in);
|
||||
|
||||
System.out.print("Enter Hexadecimal Number : ");
|
||||
hexa_Input = scan.nextLine();
|
||||
|
||||
// convert hexadecimal to decimal
|
||||
|
||||
dec_output = getHexaToDec(hexa_Input);
|
||||
/*
|
||||
Pass the string to the getHexaToDec function
|
||||
and it returns the decimal form in the variable dec_output.
|
||||
*/
|
||||
System.out.println("Number in Decimal: " + dec_output);
|
||||
scan.close();
|
||||
}
|
||||
}
|
39
Conversions/IntegerToRoman.java
Normal file
39
Conversions/IntegerToRoman.java
Normal file
@ -0,0 +1,39 @@
|
||||
package Conversions;
|
||||
|
||||
/**
|
||||
* Converting Integers into Roman Numerals
|
||||
*
|
||||
* <p>('I', 1); ('IV',4); ('V', 5); ('IV',9); ('X', 10); ('XL',40; ('L', 50); ('XC',90); ('C', 100);
|
||||
* ('D', 500); ('M', 1000);
|
||||
*/
|
||||
public class IntegerToRoman {
|
||||
private static int[] allArabianRomanNumbers =
|
||||
new int[] {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
|
||||
private static String[] allRomanNumbers =
|
||||
new String[] {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
|
||||
|
||||
// Value must be > 0
|
||||
|
||||
public static String integerToRoman(int num) {
|
||||
if (num <= 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (int a = 0; a < allArabianRomanNumbers.length; a++) {
|
||||
int times = num / allArabianRomanNumbers[a];
|
||||
for (int b = 0; b < times; b++) {
|
||||
builder.append(allRomanNumbers[a]);
|
||||
}
|
||||
|
||||
num -= times * allArabianRomanNumbers[a];
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(IntegerToRoman.integerToRoman(2131));
|
||||
}
|
||||
}
|
45
Conversions/OctalToDecimal.java
Normal file
45
Conversions/OctalToDecimal.java
Normal file
@ -0,0 +1,45 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Converts any Octal Number to a Decimal Number
|
||||
*
|
||||
* @author Zachary Jones
|
||||
*/
|
||||
public class OctalToDecimal {
|
||||
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
System.out.print("Octal Input: ");
|
||||
String inputOctal = sc.nextLine();
|
||||
int result = convertOctalToDecimal(inputOctal);
|
||||
if (result != -1) System.out.println("Result convertOctalToDecimal : " + result);
|
||||
sc.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts an octal number to a decimal number.
|
||||
*
|
||||
* @param inputOctal The octal number
|
||||
* @return The decimal number
|
||||
*/
|
||||
public static int convertOctalToDecimal(String inputOctal) {
|
||||
|
||||
try {
|
||||
// Actual conversion of Octal to Decimal:
|
||||
Integer outputDecimal = Integer.parseInt(inputOctal, 8);
|
||||
return outputDecimal;
|
||||
} catch (NumberFormatException ne) {
|
||||
// Printing a warning message if the input is not a valid octal
|
||||
// number:
|
||||
System.out.println("Invalid Input, Expecting octal number 0-7");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
62
Conversions/OctalToHexadecimal.java
Normal file
62
Conversions/OctalToHexadecimal.java
Normal file
@ -0,0 +1,62 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Converts any Octal Number to HexaDecimal
|
||||
*
|
||||
* @author Tanmay Joshi
|
||||
*/
|
||||
public class OctalToHexadecimal {
|
||||
|
||||
/**
|
||||
* This method converts a Octal number to a decimal number
|
||||
*
|
||||
* @param s The Octal Number
|
||||
* @return The Decimal number
|
||||
*/
|
||||
public static int octToDec(String s) {
|
||||
int i = 0;
|
||||
for (int j = 0; j < s.length(); j++) {
|
||||
char num = s.charAt(j);
|
||||
num -= '0';
|
||||
i *= 8;
|
||||
i += num;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a Decimal number to a Hexadecimal number
|
||||
*
|
||||
* @param d The Decimal Number
|
||||
* @return The Hexadecimal number
|
||||
*/
|
||||
public static String decimalToHex(int d) {
|
||||
String digits = "0123456789ABCDEF";
|
||||
if (d <= 0) return "0";
|
||||
String hex = "";
|
||||
while (d > 0) {
|
||||
int digit = d % 16;
|
||||
hex = digits.charAt(digit) + hex;
|
||||
d = d / 16;
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
|
||||
Scanner input = new Scanner(System.in);
|
||||
System.out.print("Enter the Octal number: ");
|
||||
// Take octal number as input from user in a string
|
||||
String oct = input.next();
|
||||
|
||||
// Pass the octal number to function and get converted deciaml form
|
||||
int decimal = octToDec(oct);
|
||||
|
||||
// Pass the decimla number to function and get converted Hex form of the number
|
||||
String hex = decimalToHex(decimal);
|
||||
System.out.println("The Hexadecimal equivalant is: " + hex);
|
||||
input.close();
|
||||
}
|
||||
}
|
165
Conversions/RgbHsvConversion.java
Normal file
165
Conversions/RgbHsvConversion.java
Normal file
@ -0,0 +1,165 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* The RGB color model is an additive color model in which red, green, and blue light are added
|
||||
* together in various ways to reproduce a broad array of colors. The name of the model comes from
|
||||
* the initials of the three additive primary colors, red, green, and blue. Meanwhile, the HSV
|
||||
* representation models how colors appear under light. In it, colors are represented using three
|
||||
* components: hue, saturation and (brightness-)value. This class provides methods for converting
|
||||
* colors from one representation to the other. (description adapted from
|
||||
* https://en.wikipedia.org/wiki/RGB_color_model and https://en.wikipedia.org/wiki/HSL_and_HSV).
|
||||
*/
|
||||
public class RgbHsvConversion {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Expected RGB-values taken from https://www.rapidtables.com/convert/color/hsv-to-rgb.html
|
||||
|
||||
// Test hsvToRgb-method
|
||||
assert Arrays.equals(hsvToRgb(0, 0, 0), new int[] {0, 0, 0});
|
||||
assert Arrays.equals(hsvToRgb(0, 0, 1), new int[] {255, 255, 255});
|
||||
assert Arrays.equals(hsvToRgb(0, 1, 1), new int[] {255, 0, 0});
|
||||
assert Arrays.equals(hsvToRgb(60, 1, 1), new int[] {255, 255, 0});
|
||||
assert Arrays.equals(hsvToRgb(120, 1, 1), new int[] {0, 255, 0});
|
||||
assert Arrays.equals(hsvToRgb(240, 1, 1), new int[] {0, 0, 255});
|
||||
assert Arrays.equals(hsvToRgb(300, 1, 1), new int[] {255, 0, 255});
|
||||
assert Arrays.equals(hsvToRgb(180, 0.5, 0.5), new int[] {64, 128, 128});
|
||||
assert Arrays.equals(hsvToRgb(234, 0.14, 0.88), new int[] {193, 196, 224});
|
||||
assert Arrays.equals(hsvToRgb(330, 0.75, 0.5), new int[] {128, 32, 80});
|
||||
|
||||
// Test rgbToHsv-method
|
||||
// approximate-assertions needed because of small deviations due to converting between
|
||||
// int-values and double-values.
|
||||
assert approximatelyEqualHsv(rgbToHsv(0, 0, 0), new double[] {0, 0, 0});
|
||||
assert approximatelyEqualHsv(rgbToHsv(255, 255, 255), new double[] {0, 0, 1});
|
||||
assert approximatelyEqualHsv(rgbToHsv(255, 0, 0), new double[] {0, 1, 1});
|
||||
assert approximatelyEqualHsv(rgbToHsv(255, 255, 0), new double[] {60, 1, 1});
|
||||
assert approximatelyEqualHsv(rgbToHsv(0, 255, 0), new double[] {120, 1, 1});
|
||||
assert approximatelyEqualHsv(rgbToHsv(0, 0, 255), new double[] {240, 1, 1});
|
||||
assert approximatelyEqualHsv(rgbToHsv(255, 0, 255), new double[] {300, 1, 1});
|
||||
assert approximatelyEqualHsv(rgbToHsv(64, 128, 128), new double[] {180, 0.5, 0.5});
|
||||
assert approximatelyEqualHsv(rgbToHsv(193, 196, 224), new double[] {234, 0.14, 0.88});
|
||||
assert approximatelyEqualHsv(rgbToHsv(128, 32, 80), new double[] {330, 0.75, 0.5});
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversion from the HSV-representation to the RGB-representation.
|
||||
*
|
||||
* @param hue Hue of the color.
|
||||
* @param saturation Saturation of the color.
|
||||
* @param value Brightness-value of the color.
|
||||
* @return The tuple of RGB-components.
|
||||
*/
|
||||
public static int[] hsvToRgb(double hue, double saturation, double value) {
|
||||
if (hue < 0 || hue > 360) {
|
||||
throw new IllegalArgumentException("hue should be between 0 and 360");
|
||||
}
|
||||
|
||||
if (saturation < 0 || saturation > 1) {
|
||||
throw new IllegalArgumentException("saturation should be between 0 and 1");
|
||||
}
|
||||
|
||||
if (value < 0 || value > 1) {
|
||||
throw new IllegalArgumentException("value should be between 0 and 1");
|
||||
}
|
||||
|
||||
double chroma = value * saturation;
|
||||
double hueSection = hue / 60;
|
||||
double secondLargestComponent = chroma * (1 - Math.abs(hueSection % 2 - 1));
|
||||
double matchValue = value - chroma;
|
||||
|
||||
return getRgbBySection(hueSection, chroma, matchValue, secondLargestComponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversion from the RGB-representation to the HSV-representation.
|
||||
*
|
||||
* @param red Red-component of the color.
|
||||
* @param green Green-component of the color.
|
||||
* @param blue Blue-component of the color.
|
||||
* @return The tuple of HSV-components.
|
||||
*/
|
||||
public static double[] rgbToHsv(int red, int green, int blue) {
|
||||
if (red < 0 || red > 255) {
|
||||
throw new IllegalArgumentException("red should be between 0 and 255");
|
||||
}
|
||||
|
||||
if (green < 0 || green > 255) {
|
||||
throw new IllegalArgumentException("green should be between 0 and 255");
|
||||
}
|
||||
|
||||
if (blue < 0 || blue > 255) {
|
||||
throw new IllegalArgumentException("blue should be between 0 and 255");
|
||||
}
|
||||
|
||||
double dRed = (double) red / 255;
|
||||
double dGreen = (double) green / 255;
|
||||
double dBlue = (double) blue / 255;
|
||||
double value = Math.max(Math.max(dRed, dGreen), dBlue);
|
||||
double chroma = value - Math.min(Math.min(dRed, dGreen), dBlue);
|
||||
double saturation = value == 0 ? 0 : chroma / value;
|
||||
double hue;
|
||||
|
||||
if (chroma == 0) {
|
||||
hue = 0;
|
||||
} else if (value == dRed) {
|
||||
hue = 60 * (0 + (dGreen - dBlue) / chroma);
|
||||
} else if (value == dGreen) {
|
||||
hue = 60 * (2 + (dBlue - dRed) / chroma);
|
||||
} else {
|
||||
hue = 60 * (4 + (dRed - dGreen) / chroma);
|
||||
}
|
||||
|
||||
hue = (hue + 360) % 360;
|
||||
|
||||
return new double[] {hue, saturation, value};
|
||||
}
|
||||
|
||||
private static boolean approximatelyEqualHsv(double[] hsv1, double[] hsv2) {
|
||||
boolean bHue = Math.abs(hsv1[0] - hsv2[0]) < 0.2;
|
||||
boolean bSaturation = Math.abs(hsv1[1] - hsv2[1]) < 0.002;
|
||||
boolean bValue = Math.abs(hsv1[2] - hsv2[2]) < 0.002;
|
||||
|
||||
return bHue && bSaturation && bValue;
|
||||
}
|
||||
|
||||
private static int[] getRgbBySection(
|
||||
double hueSection, double chroma, double matchValue, double secondLargestComponent) {
|
||||
int red;
|
||||
int green;
|
||||
int blue;
|
||||
|
||||
if (hueSection >= 0 && hueSection <= 1) {
|
||||
red = convertToInt(chroma + matchValue);
|
||||
green = convertToInt(secondLargestComponent + matchValue);
|
||||
blue = convertToInt(matchValue);
|
||||
} else if (hueSection > 1 && hueSection <= 2) {
|
||||
red = convertToInt(secondLargestComponent + matchValue);
|
||||
green = convertToInt(chroma + matchValue);
|
||||
blue = convertToInt(matchValue);
|
||||
} else if (hueSection > 2 && hueSection <= 3) {
|
||||
red = convertToInt(matchValue);
|
||||
green = convertToInt(chroma + matchValue);
|
||||
blue = convertToInt(secondLargestComponent + matchValue);
|
||||
} else if (hueSection > 3 && hueSection <= 4) {
|
||||
red = convertToInt(matchValue);
|
||||
green = convertToInt(secondLargestComponent + matchValue);
|
||||
blue = convertToInt(chroma + matchValue);
|
||||
} else if (hueSection > 4 && hueSection <= 5) {
|
||||
red = convertToInt(secondLargestComponent + matchValue);
|
||||
green = convertToInt(matchValue);
|
||||
blue = convertToInt(chroma + matchValue);
|
||||
} else {
|
||||
red = convertToInt(chroma + matchValue);
|
||||
green = convertToInt(matchValue);
|
||||
blue = convertToInt(secondLargestComponent + matchValue);
|
||||
}
|
||||
|
||||
return new int[] {red, green, blue};
|
||||
}
|
||||
|
||||
private static int convertToInt(double input) {
|
||||
return (int) Math.round(255 * input);
|
||||
}
|
||||
}
|
66
Conversions/RomanToInteger.java
Normal file
66
Conversions/RomanToInteger.java
Normal file
@ -0,0 +1,66 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class RomanToInteger {
|
||||
|
||||
private static Map<Character, Integer> map =
|
||||
new HashMap<Character, Integer>() {
|
||||
/** */
|
||||
private static final long serialVersionUID = 87605733047260530L;
|
||||
|
||||
{
|
||||
put('I', 1);
|
||||
put('V', 5);
|
||||
put('X', 10);
|
||||
put('L', 50);
|
||||
put('C', 100);
|
||||
put('D', 500);
|
||||
put('M', 1000);
|
||||
}
|
||||
};
|
||||
// Roman Number = Roman Numerals
|
||||
|
||||
/**
|
||||
* This function convert Roman number into Integer
|
||||
*
|
||||
* @param A Roman number string
|
||||
* @return integer
|
||||
*/
|
||||
public static int romanToInt(String A) {
|
||||
|
||||
A = A.toUpperCase();
|
||||
char prev = ' ';
|
||||
|
||||
int sum = 0;
|
||||
|
||||
int newPrev = 0;
|
||||
for (int i = A.length() - 1; i >= 0; i--) {
|
||||
char c = A.charAt(i);
|
||||
|
||||
if (prev != ' ') {
|
||||
// checking current Number greater then previous or not
|
||||
newPrev = map.get(prev) > newPrev ? map.get(prev) : newPrev;
|
||||
}
|
||||
|
||||
int currentNum = map.get(c);
|
||||
|
||||
// if current number greater then prev max previous then add
|
||||
if (currentNum >= newPrev) {
|
||||
sum += currentNum;
|
||||
} else {
|
||||
// subtract upcoming number until upcoming number not greater then prev max
|
||||
sum -= currentNum;
|
||||
}
|
||||
|
||||
prev = c;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int sum = romanToInt("MDCCCIV");
|
||||
System.out.println(sum);
|
||||
}
|
||||
}
|
42
Conversions/TurkishToLatinConversion.java
Normal file
42
Conversions/TurkishToLatinConversion.java
Normal file
@ -0,0 +1,42 @@
|
||||
package Conversions;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Converts turkish character to latin character
|
||||
*
|
||||
* @author Özgün Gökşenli
|
||||
*/
|
||||
public class TurkishToLatinConversion {
|
||||
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
System.out.println("Input the string: ");
|
||||
String b = sc.next();
|
||||
System.out.println("Converted: " + convertTurkishToLatin(b));
|
||||
sc.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a turkish character to latin character.
|
||||
*
|
||||
* @param param String paramter
|
||||
* @return String
|
||||
*/
|
||||
public static String convertTurkishToLatin(String param) {
|
||||
char[] turkishChars =
|
||||
new char[] {0x131, 0x130, 0xFC, 0xDC, 0xF6, 0xD6, 0x15F, 0x15E, 0xE7, 0xC7, 0x11F, 0x11E};
|
||||
char[] latinChars = new char[] {'i', 'I', 'u', 'U', 'o', 'O', 's', 'S', 'c', 'C', 'g', 'G'};
|
||||
for (int i = 0; i < turkishChars.length; i++) {
|
||||
param =
|
||||
param.replaceAll(
|
||||
new String(new char[] {turkishChars[i]}), new String(new char[] {latinChars[i]}));
|
||||
}
|
||||
return param;
|
||||
}
|
||||
}
|
1266
DIRECTORY.md
1266
DIRECTORY.md
File diff suppressed because it is too large
Load Diff
110
DataStructures/Bags/Bag.java
Normal file
110
DataStructures/Bags/Bag.java
Normal file
@ -0,0 +1,110 @@
|
||||
package DataStructures.Bags;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* Collection which does not allow removing elements (only collect and iterate)
|
||||
*
|
||||
* @param <Element> - the generic type of an element in this bag
|
||||
*/
|
||||
public class Bag<Element> implements Iterable<Element> {
|
||||
|
||||
private Node<Element> firstElement; // first element of the bag
|
||||
private int size; // size of bag
|
||||
|
||||
private static class Node<Element> {
|
||||
private Element content;
|
||||
private Node<Element> nextElement;
|
||||
}
|
||||
|
||||
/** Create an empty bag */
|
||||
public Bag() {
|
||||
firstElement = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/** @return true if this bag is empty, false otherwise */
|
||||
public boolean isEmpty() {
|
||||
return firstElement == null;
|
||||
}
|
||||
|
||||
/** @return the number of elements */
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/** @param element - the element to add */
|
||||
public void add(Element element) {
|
||||
Node<Element> oldfirst = firstElement;
|
||||
firstElement = new Node<>();
|
||||
firstElement.content = element;
|
||||
firstElement.nextElement = oldfirst;
|
||||
size++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the bag contains a specific element
|
||||
*
|
||||
* @param element which you want to look for
|
||||
* @return true if bag contains element, otherwise false
|
||||
*/
|
||||
public boolean contains(Element element) {
|
||||
Iterator<Element> iterator = this.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
if (iterator.next().equals(element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @return an iterator that iterates over the elements in this bag in arbitrary order */
|
||||
public Iterator<Element> iterator() {
|
||||
return new ListIterator<>(firstElement);
|
||||
}
|
||||
|
||||
@SuppressWarnings("hiding")
|
||||
private class ListIterator<Element> implements Iterator<Element> {
|
||||
private Node<Element> currentElement;
|
||||
|
||||
public ListIterator(Node<Element> firstElement) {
|
||||
currentElement = firstElement;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return currentElement != null;
|
||||
}
|
||||
|
||||
/** remove is not allowed in a bag */
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Element next() {
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
Element element = currentElement.content;
|
||||
currentElement = currentElement.nextElement;
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
/** main-method for testing */
|
||||
public static void main(String[] args) {
|
||||
Bag<String> bag = new Bag<>();
|
||||
|
||||
bag.add("1");
|
||||
bag.add("1");
|
||||
bag.add("2");
|
||||
|
||||
System.out.println("size of bag = " + bag.size());
|
||||
for (String s : bag) {
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
System.out.println(bag.contains(null));
|
||||
System.out.println(bag.contains("1"));
|
||||
System.out.println(bag.contains("3"));
|
||||
}
|
||||
}
|
130
DataStructures/Buffers/CircularBuffer.java
Normal file
130
DataStructures/Buffers/CircularBuffer.java
Normal file
@ -0,0 +1,130 @@
|
||||
package DataStructures.Buffers;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class CircularBuffer {
|
||||
private char[] _buffer;
|
||||
public final int _buffer_size;
|
||||
private int _write_index = 0;
|
||||
private int _read_index = 0;
|
||||
private AtomicInteger _readable_data = new AtomicInteger(0);
|
||||
|
||||
public CircularBuffer(int buffer_size) {
|
||||
if (!IsPowerOfTwo(buffer_size)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this._buffer_size = buffer_size;
|
||||
_buffer = new char[buffer_size];
|
||||
}
|
||||
|
||||
private boolean IsPowerOfTwo(int i) {
|
||||
return (i & (i - 1)) == 0;
|
||||
}
|
||||
|
||||
private int getTrueIndex(int i) {
|
||||
return i % _buffer_size;
|
||||
}
|
||||
|
||||
public Character readOutChar() {
|
||||
Character result = null;
|
||||
|
||||
// if we have data to read
|
||||
if (_readable_data.get() > 0) {
|
||||
|
||||
result = Character.valueOf(_buffer[getTrueIndex(_read_index)]);
|
||||
_readable_data.decrementAndGet();
|
||||
_read_index++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean writeToCharBuffer(char c) {
|
||||
boolean result = false;
|
||||
|
||||
// if we can write to the buffer
|
||||
if (_readable_data.get() < _buffer_size) {
|
||||
// write to buffer
|
||||
_buffer[getTrueIndex(_write_index)] = c;
|
||||
_readable_data.incrementAndGet();
|
||||
_write_index++;
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class TestWriteWorker implements Runnable {
|
||||
String _alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
Random _random = new Random();
|
||||
CircularBuffer _buffer;
|
||||
|
||||
public TestWriteWorker(CircularBuffer cb) {
|
||||
this._buffer = cb;
|
||||
}
|
||||
|
||||
private char getRandomChar() {
|
||||
return _alphabet.charAt(_random.nextInt(_alphabet.length()));
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (!Thread.interrupted()) {
|
||||
if (!_buffer.writeToCharBuffer(getRandomChar())) {
|
||||
Thread.yield();
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestReadWorker implements Runnable {
|
||||
CircularBuffer _buffer;
|
||||
|
||||
public TestReadWorker(CircularBuffer cb) {
|
||||
this._buffer = cb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Printing Buffer:");
|
||||
while (!Thread.interrupted()) {
|
||||
Character c = _buffer.readOutChar();
|
||||
if (c != null) {
|
||||
System.out.print(c.charValue());
|
||||
} else {
|
||||
Thread.yield();
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
int buffer_size = 1024;
|
||||
// create circular buffer
|
||||
CircularBuffer cb = new CircularBuffer(buffer_size);
|
||||
|
||||
// create threads that read and write the buffer.
|
||||
Thread write_thread = new Thread(new TestWriteWorker(cb));
|
||||
Thread read_thread = new Thread(new TestReadWorker(cb));
|
||||
read_thread.start();
|
||||
write_thread.start();
|
||||
|
||||
// wait some amount of time
|
||||
Thread.sleep(10000);
|
||||
|
||||
// interrupt threads and exit
|
||||
write_thread.interrupt();
|
||||
read_thread.interrupt();
|
||||
}
|
||||
}
|
211
DataStructures/DynamicArray/DynamicArray.java
Normal file
211
DataStructures/DynamicArray/DynamicArray.java
Normal file
@ -0,0 +1,211 @@
|
||||
package DataStructures.DynamicArray;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
* This class implements a dynamic array
|
||||
*
|
||||
* @param <E> the type that each index of the array will hold
|
||||
*/
|
||||
public class DynamicArray<E> implements Iterable<E> {
|
||||
private static final int DEFAULT_CAPACITY = 16;
|
||||
|
||||
private int capacity;
|
||||
private int size;
|
||||
private Object[] elements;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*
|
||||
* @param capacity the starting length of the desired array
|
||||
*/
|
||||
public DynamicArray(final int capacity) {
|
||||
this.size = 0;
|
||||
this.capacity = capacity;
|
||||
this.elements = new Object[this.capacity];
|
||||
}
|
||||
|
||||
/** No-args constructor */
|
||||
public DynamicArray() {
|
||||
this(DEFAULT_CAPACITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an element to the array If full, creates a copy array twice the size of the current one
|
||||
*
|
||||
* @param element the element of type <E> to be added to the array
|
||||
*/
|
||||
public void add(final E element) {
|
||||
if (this.size == this.elements.length) {
|
||||
this.elements = Arrays.copyOf(this.elements, newCapacity(2 * this.capacity));
|
||||
}
|
||||
|
||||
this.elements[this.size] = element;
|
||||
size++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Places element of type <E> at the desired index
|
||||
*
|
||||
* @param index the index for the element to be placed
|
||||
* @param element the element to be inserted
|
||||
*/
|
||||
public void put(final int index, E element) {
|
||||
this.elements[index] = element;
|
||||
}
|
||||
|
||||
/**
|
||||
* get method for element at a given index returns null if the index is empty
|
||||
*
|
||||
* @param index the desired index of the element
|
||||
* @return <E> the element at the specified index
|
||||
*/
|
||||
public E get(final int index) {
|
||||
return getElement(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an element from the array
|
||||
*
|
||||
* @param index the index of the element to be removed
|
||||
* @return <E> the element removed
|
||||
*/
|
||||
public E remove(final int index) {
|
||||
final E oldElement = getElement(index);
|
||||
fastRemove(this.elements, index);
|
||||
|
||||
if (this.capacity > DEFAULT_CAPACITY && size * 4 <= this.capacity)
|
||||
this.elements = Arrays.copyOf(this.elements, newCapacity(this.capacity / 2));
|
||||
return oldElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* get method for size field
|
||||
*
|
||||
* @return int size
|
||||
*/
|
||||
public int getSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* isEmpty helper method
|
||||
*
|
||||
* @return boolean true if the array contains no elements, false otherwise
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return this.size == 0;
|
||||
}
|
||||
|
||||
public Stream<E> stream() {
|
||||
return StreamSupport.stream(spliterator(), false);
|
||||
}
|
||||
|
||||
private void fastRemove(final Object[] elements, final int index) {
|
||||
final int newSize = this.size - 1;
|
||||
|
||||
if (newSize > index) {
|
||||
System.arraycopy(elements, index + 1, elements, index, newSize - index);
|
||||
}
|
||||
|
||||
elements[this.size = newSize] = null;
|
||||
}
|
||||
|
||||
private E getElement(final int index) {
|
||||
return (E) this.elements[index];
|
||||
}
|
||||
|
||||
private int newCapacity(int capacity) {
|
||||
this.capacity = capacity;
|
||||
return this.capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a String representation of this object
|
||||
*
|
||||
* @return String a String representing the array
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(Arrays.stream(this.elements).filter(Objects::nonNull).toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a new Dynamic Array Iterator
|
||||
*
|
||||
* @return Iterator a Dynamic Array Iterator
|
||||
*/
|
||||
@Override
|
||||
public Iterator iterator() {
|
||||
return new DynamicArrayIterator();
|
||||
}
|
||||
|
||||
private class DynamicArrayIterator implements Iterator<E> {
|
||||
|
||||
private int cursor;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return this.cursor != size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
if (this.cursor > DynamicArray.this.size) throw new NoSuchElementException();
|
||||
|
||||
if (this.cursor > DynamicArray.this.elements.length)
|
||||
throw new ConcurrentModificationException();
|
||||
|
||||
final E element = DynamicArray.this.getElement(this.cursor);
|
||||
this.cursor++;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (this.cursor < 0) throw new IllegalStateException();
|
||||
|
||||
DynamicArray.this.remove(this.cursor);
|
||||
this.cursor--;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(Consumer<? super E> action) {
|
||||
Objects.requireNonNull(action);
|
||||
|
||||
for (int i = 0; i < DynamicArray.this.size; i++) {
|
||||
action.accept(DynamicArray.this.getElement(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is the driver for the DynamicArray<E> class it tests a variety of methods and prints
|
||||
* the output
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
DynamicArray<String> names = new DynamicArray<>();
|
||||
names.add("Peubes");
|
||||
names.add("Marley");
|
||||
|
||||
for (String name : names) {
|
||||
System.out.println(name);
|
||||
}
|
||||
|
||||
names.stream().forEach(System.out::println);
|
||||
|
||||
System.out.println(names);
|
||||
|
||||
System.out.println(names.getSize());
|
||||
|
||||
names.remove(0);
|
||||
|
||||
for (String name : names) {
|
||||
System.out.println(name);
|
||||
}
|
||||
}
|
||||
}
|
180
DataStructures/Graphs/A_Star.java
Normal file
180
DataStructures/Graphs/A_Star.java
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
Time Complexity = O(E), where E is equal to the number of edges
|
||||
*/
|
||||
|
||||
package Graphs;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.*;
|
||||
|
||||
public class A_Star {
|
||||
|
||||
private static class Graph {
|
||||
// Graph's structure can be changed only applying changes to this class.
|
||||
private ArrayList<ArrayList<Edge>> graph;
|
||||
|
||||
// Initialise ArrayLists in Constructor
|
||||
public Graph(int size) {
|
||||
this.graph = new ArrayList<>();
|
||||
for (int i = 0; i < size; i++) {
|
||||
this.graph.set(i, new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<Edge> getNeighbours(int from) {
|
||||
return this.graph.get(from);
|
||||
}
|
||||
|
||||
// Graph is bidirectional, for just one direction remove second instruction of this method.
|
||||
private void addEdge(Edge edge) {
|
||||
this.graph.get(edge.getFrom()).add(new Edge(edge.getFrom(), edge.getTo(), edge.getWeight()));
|
||||
this.graph.get(edge.getTo()).add(new Edge(edge.getTo(), edge.getFrom(), edge.getWeight()));
|
||||
}
|
||||
}
|
||||
|
||||
private static class Edge {
|
||||
private int from;
|
||||
private int to;
|
||||
private int weight;
|
||||
|
||||
public Edge(int from, int to, int weight) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public int getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public int getTo() {
|
||||
return to;
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
}
|
||||
}
|
||||
|
||||
// class to iterate during the algorithm execution, and also used to return the solution.
|
||||
private static class PathAndDistance {
|
||||
private int distance; // distance advanced so far.
|
||||
private ArrayList<Integer> path; // list of visited nodes in this path.
|
||||
private int
|
||||
estimated; // heuristic value associated to the last node od the path (current node).
|
||||
|
||||
public PathAndDistance(int distance, ArrayList<Integer> path, int estimated) {
|
||||
this.distance = distance;
|
||||
this.path = path;
|
||||
this.estimated = estimated;
|
||||
}
|
||||
|
||||
public int getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public ArrayList<Integer> getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public int getEstimated() {
|
||||
return estimated;
|
||||
}
|
||||
|
||||
private void printSolution() {
|
||||
if (this.path != null)
|
||||
System.out.println(
|
||||
"Optimal path: " + this.path + ", distance: " + this.distance);
|
||||
else System.out.println("There is no path available to connect the points");
|
||||
}
|
||||
}
|
||||
|
||||
private static void initializeGraph(Graph graph, ArrayList<Integer> data) {
|
||||
for (int i = 0; i < data.size(); i += 4) {
|
||||
graph.addEdge(new Edge(data.get(i), data.get(i + 1), data.get(i + 2)));
|
||||
}
|
||||
/*
|
||||
.x. node
|
||||
(y) cost
|
||||
- or | or / bidirectional connection
|
||||
|
||||
( 98)- .7. -(86)- .4.
|
||||
|
|
||||
( 85)- .17. -(142)- .18. -(92)- .8. -(87)- .11.
|
||||
|
|
||||
. 1. -------------------- (160)
|
||||
| \ |
|
||||
(211) \ .6.
|
||||
| \ |
|
||||
. 5. (101)-.13. -(138) (115)
|
||||
| | | /
|
||||
( 99) ( 97) | /
|
||||
| | | /
|
||||
.12. -(151)- .15. -(80)- .14. | /
|
||||
| | | | /
|
||||
( 71) (140) (146)- .2. -(120)
|
||||
| | |
|
||||
.19. -( 75)- . 0. .10. -(75)- .3.
|
||||
| |
|
||||
(118) ( 70)
|
||||
| |
|
||||
.16. -(111)- .9.
|
||||
*/
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// heuristic function optimistic values
|
||||
int[] heuristic = {
|
||||
366, 0, 160, 242, 161, 178, 77, 151, 226, 244, 241, 234, 380, 98, 193, 253, 329, 80, 199, 374
|
||||
};
|
||||
|
||||
Graph graph = new Graph(20);
|
||||
ArrayList<Integer> graphData =
|
||||
new ArrayList<>(
|
||||
Arrays.asList(
|
||||
0, 19, 75, null, 0, 15, 140, null, 0, 16, 118, null, 19, 12, 71, null, 12, 15, 151,
|
||||
null, 16, 9, 111, null, 9, 10, 70, null, 10, 3, 75, null, 3, 2, 120, null, 2, 14,
|
||||
146, null, 2, 13, 138, null, 2, 6, 115, null, 15, 14, 80, null, 15, 5, 99, null, 14,
|
||||
13, 97, null, 5, 1, 211, null, 13, 1, 101, null, 6, 1, 160, null, 1, 17, 85, null,
|
||||
17, 7, 98, null, 7, 4, 86, null, 17, 18, 142, null, 18, 8, 92, null, 8, 11, 87));
|
||||
initializeGraph(graph, graphData);
|
||||
|
||||
PathAndDistance solution = aStar(3, 1, graph, heuristic);
|
||||
solution.printSolution();
|
||||
}
|
||||
|
||||
public static PathAndDistance aStar(int from, int to, Graph graph, int[] heuristic) {
|
||||
// nodes are prioritised by the less value of the current distance of their paths, and the
|
||||
// estimated value
|
||||
// given by the heuristic function to reach the destination point from the current point.
|
||||
PriorityQueue<PathAndDistance> queue =
|
||||
new PriorityQueue<>(Comparator.comparingInt(a -> (a.getDistance() + a.getEstimated())));
|
||||
|
||||
// dummy data to start the algorithm from the beginning point
|
||||
queue.add(new PathAndDistance(0, new ArrayList<>(List.of(from)), 0));
|
||||
|
||||
boolean solutionFound = false;
|
||||
PathAndDistance currentData = new PathAndDistance(-1, null, -1);
|
||||
while (!queue.isEmpty() && !solutionFound) {
|
||||
currentData = queue.poll(); // first in the queue, best node so keep exploring.
|
||||
int currentPosition =
|
||||
currentData.getPath().get(currentData.getPath().size() - 1); // current node.
|
||||
if (currentPosition == to) solutionFound = true;
|
||||
else
|
||||
for (Edge edge : graph.getNeighbours(currentPosition))
|
||||
if (!currentData.getPath().contains(edge.getTo())) { // Avoid Cycles
|
||||
ArrayList<Integer> updatedPath = new ArrayList<>(currentData.getPath());
|
||||
updatedPath.add(edge.getTo()); // Add the new node to the path, update the distance,
|
||||
// and the heuristic function value associated to that path.
|
||||
queue.add(
|
||||
new PathAndDistance(
|
||||
currentData.getDistance() + edge.getWeight(),
|
||||
updatedPath,
|
||||
heuristic[edge.getTo()]));
|
||||
}
|
||||
}
|
||||
return (solutionFound) ? currentData : new PathAndDistance(-1, null, -1);
|
||||
// Out of while loop, if there is a solution, the current Data stores the optimal path, and its
|
||||
// distance
|
||||
}
|
||||
}
|
161
DataStructures/Graphs/BellmanFord.java
Normal file
161
DataStructures/Graphs/BellmanFord.java
Normal file
@ -0,0 +1,161 @@
|
||||
package DataStructures.Graphs;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class BellmanFord
|
||||
/*Implementation of Bellman ford to detect negative cycles. Graph accepts inputs in form of edges which have
|
||||
start vertex, end vertex and weights. Vertices should be labelled with a number between 0 and total number of vertices-1,both inclusive*/
|
||||
{
|
||||
int vertex, edge;
|
||||
private Edge edges[];
|
||||
private int index = 0;
|
||||
|
||||
BellmanFord(int v, int e) {
|
||||
vertex = v;
|
||||
edge = e;
|
||||
edges = new Edge[e];
|
||||
}
|
||||
|
||||
class Edge {
|
||||
int u, v;
|
||||
int w;
|
||||
/**
|
||||
* @param u Source Vertex
|
||||
* @param v End vertex
|
||||
* @param c Weight
|
||||
*/
|
||||
public Edge(int a, int b, int c) {
|
||||
u = a;
|
||||
v = b;
|
||||
w = c;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param p[] Parent array which shows updates in edges
|
||||
* @param i Current vertex under consideration
|
||||
*/
|
||||
void printPath(int p[], int i) {
|
||||
if (p[i] == -1) // Found the path back to parent
|
||||
return;
|
||||
printPath(p, p[i]);
|
||||
System.out.print(i + " ");
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
BellmanFord obj = new BellmanFord(0, 0); // Dummy object to call nonstatic variables
|
||||
obj.go();
|
||||
}
|
||||
|
||||
public void
|
||||
go() // Interactive run for understanding the class first time. Assumes source vertex is 0 and
|
||||
// shows distance to all vertices
|
||||
{
|
||||
Scanner sc = new Scanner(System.in); // Grab scanner object for user input
|
||||
int i, v, e, u, ve, w, j, neg = 0;
|
||||
System.out.println("Enter no. of vertices and edges please");
|
||||
v = sc.nextInt();
|
||||
e = sc.nextInt();
|
||||
Edge arr[] = new Edge[e]; // Array of edges
|
||||
System.out.println("Input edges");
|
||||
for (i = 0; i < e; i++) {
|
||||
u = sc.nextInt();
|
||||
ve = sc.nextInt();
|
||||
w = sc.nextInt();
|
||||
arr[i] = new Edge(u, ve, w);
|
||||
}
|
||||
int dist[] =
|
||||
new int
|
||||
[v]; // Distance array for holding the finalized shortest path distance between source
|
||||
// and all vertices
|
||||
int p[] = new int[v]; // Parent array for holding the paths
|
||||
for (i = 0; i < v; i++) dist[i] = Integer.MAX_VALUE; // Initializing distance values
|
||||
dist[0] = 0;
|
||||
p[0] = -1;
|
||||
for (i = 0; i < v - 1; i++) {
|
||||
for (j = 0; j < e; j++) {
|
||||
if ((int) dist[arr[j].u] != Integer.MAX_VALUE
|
||||
&& dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
|
||||
dist[arr[j].v] = dist[arr[j].u] + arr[j].w; // Update
|
||||
p[arr[j].v] = arr[j].u;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Final cycle for negative checking
|
||||
for (j = 0; j < e; j++)
|
||||
if ((int) dist[arr[j].u] != Integer.MAX_VALUE && dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
|
||||
neg = 1;
|
||||
System.out.println("Negative cycle");
|
||||
break;
|
||||
}
|
||||
if (neg == 0) // Go ahead and show results of computation
|
||||
{
|
||||
System.out.println("Distances are: ");
|
||||
for (i = 0; i < v; i++) System.out.println(i + " " + dist[i]);
|
||||
System.out.println("Path followed:");
|
||||
for (i = 0; i < v; i++) {
|
||||
System.out.print("0 ");
|
||||
printPath(p, i);
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
sc.close();
|
||||
}
|
||||
/**
|
||||
* @param source Starting vertex
|
||||
* @param end Ending vertex
|
||||
* @param Edge Array of edges
|
||||
*/
|
||||
public void show(
|
||||
int source,
|
||||
int end,
|
||||
Edge arr[]) // Just shows results of computation, if graph is passed to it. The graph should
|
||||
// be created by using addEdge() method and passed by calling getEdgeArray() method
|
||||
{
|
||||
int i, j, v = vertex, e = edge, neg = 0;
|
||||
double dist[] =
|
||||
new double
|
||||
[v]; // Distance array for holding the finalized shortest path distance between source
|
||||
// and all vertices
|
||||
int p[] = new int[v]; // Parent array for holding the paths
|
||||
for (i = 0; i < v; i++) dist[i] = Integer.MAX_VALUE; // Initializing distance values
|
||||
dist[source] = 0;
|
||||
p[source] = -1;
|
||||
for (i = 0; i < v - 1; i++) {
|
||||
for (j = 0; j < e; j++) {
|
||||
if ((int) dist[arr[j].u] != Integer.MAX_VALUE
|
||||
&& dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
|
||||
dist[arr[j].v] = dist[arr[j].u] + arr[j].w; // Update
|
||||
p[arr[j].v] = arr[j].u;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Final cycle for negative checking
|
||||
for (j = 0; j < e; j++)
|
||||
if ((int) dist[arr[j].u] != Integer.MAX_VALUE && dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
|
||||
neg = 1;
|
||||
System.out.println("Negative cycle");
|
||||
break;
|
||||
}
|
||||
if (neg == 0) // Go ahead and show results of computaion
|
||||
{
|
||||
System.out.println("Distance is: " + dist[end]);
|
||||
System.out.println("Path followed:");
|
||||
System.out.print(source + " ");
|
||||
printPath(p, end);
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param x Source Vertex
|
||||
* @param y End vertex
|
||||
* @param z Weight
|
||||
*/
|
||||
public void addEdge(int x, int y, int z) // Adds unidirectional edge
|
||||
{
|
||||
edges[index++] = new Edge(x, y, z);
|
||||
}
|
||||
|
||||
public Edge[] getEdgeArray() {
|
||||
return edges;
|
||||
}
|
||||
}
|
139
DataStructures/Graphs/ConnectedComponent.java
Normal file
139
DataStructures/Graphs/ConnectedComponent.java
Normal file
@ -0,0 +1,139 @@
|
||||
package DataStructures.Graphs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A class that counts the number of different connected components in a graph
|
||||
*
|
||||
* @author Lukas Keul, Florian Mercks
|
||||
*/
|
||||
class Graph<E extends Comparable<E>> {
|
||||
|
||||
class Node {
|
||||
E name;
|
||||
|
||||
public Node(E name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
class Edge {
|
||||
Node startNode, endNode;
|
||||
|
||||
public Edge(Node startNode, Node endNode) {
|
||||
this.startNode = startNode;
|
||||
this.endNode = endNode;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<Edge> edgeList;
|
||||
ArrayList<Node> nodeList;
|
||||
|
||||
public Graph() {
|
||||
edgeList = new ArrayList<Edge>();
|
||||
nodeList = new ArrayList<Node>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new Edge to the graph. If the nodes aren't yet in nodeList, they will be added to it.
|
||||
*
|
||||
* @param startNode the starting Node from the edge
|
||||
* @param endNode the ending Node from the edge
|
||||
*/
|
||||
public void addEdge(E startNode, E endNode) {
|
||||
Node start = null, end = null;
|
||||
for (Node node : nodeList) {
|
||||
if (startNode.compareTo(node.name) == 0) {
|
||||
start = node;
|
||||
} else if (endNode.compareTo(node.name) == 0) {
|
||||
end = node;
|
||||
}
|
||||
}
|
||||
if (start == null) {
|
||||
start = new Node(startNode);
|
||||
nodeList.add(start);
|
||||
}
|
||||
if (end == null) {
|
||||
end = new Node(endNode);
|
||||
nodeList.add(end);
|
||||
}
|
||||
|
||||
edgeList.add(new Edge(start, end));
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method used for counting the connected components. Iterates through the array of nodes to
|
||||
* do a depth first search to get all nodes of the graph from the actual node. These nodes are
|
||||
* added to the array markedNodes and will be ignored if they are chosen in the nodeList.
|
||||
*
|
||||
* @return returns the amount of unconnected graphs
|
||||
*/
|
||||
public int countGraphs() {
|
||||
int count = 0;
|
||||
Set<Node> markedNodes = new HashSet<Node>();
|
||||
|
||||
for (Node n : nodeList) {
|
||||
if (!markedNodes.contains(n)) {
|
||||
markedNodes.add(n);
|
||||
markedNodes.addAll(depthFirstSearch(n, new ArrayList<Node>()));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of depth first search.
|
||||
*
|
||||
* @param n the actual visiting node
|
||||
* @param visited A list of already visited nodes in the depth first search
|
||||
* @return returns a set of visited nodes
|
||||
*/
|
||||
public ArrayList<Node> depthFirstSearch(Node n, ArrayList<Node> visited) {
|
||||
visited.add(n);
|
||||
for (Edge e : edgeList) {
|
||||
if (e.startNode.equals(n) && !visited.contains(e.endNode)) {
|
||||
depthFirstSearch(e.endNode, visited);
|
||||
}
|
||||
}
|
||||
return visited;
|
||||
}
|
||||
}
|
||||
|
||||
public class ConnectedComponent {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Graph<Character> graphChars = new Graph<>();
|
||||
|
||||
// Graph 1
|
||||
graphChars.addEdge('a', 'b');
|
||||
graphChars.addEdge('a', 'e');
|
||||
graphChars.addEdge('b', 'e');
|
||||
graphChars.addEdge('b', 'c');
|
||||
graphChars.addEdge('c', 'd');
|
||||
graphChars.addEdge('d', 'a');
|
||||
|
||||
graphChars.addEdge('x', 'y');
|
||||
graphChars.addEdge('x', 'z');
|
||||
|
||||
graphChars.addEdge('w', 'w');
|
||||
|
||||
Graph<Integer> graphInts = new Graph<>();
|
||||
|
||||
// Graph 2
|
||||
graphInts.addEdge(1, 2);
|
||||
graphInts.addEdge(2, 3);
|
||||
graphInts.addEdge(2, 4);
|
||||
graphInts.addEdge(3, 5);
|
||||
|
||||
graphInts.addEdge(7, 8);
|
||||
graphInts.addEdge(8, 10);
|
||||
graphInts.addEdge(10, 8);
|
||||
|
||||
System.out.println("Amount of different char-graphs: " + graphChars.countGraphs());
|
||||
System.out.println("Amount of different int-graphs: " + graphInts.countGraphs());
|
||||
}
|
||||
}
|
87
DataStructures/Graphs/Cycles.java
Normal file
87
DataStructures/Graphs/Cycles.java
Normal file
@ -0,0 +1,87 @@
|
||||
package DataStructures.Graphs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Scanner;
|
||||
|
||||
class Cycle {
|
||||
|
||||
private int nodes, edges;
|
||||
private int[][] adjacencyMatrix;
|
||||
private boolean[] visited;
|
||||
ArrayList<ArrayList<Integer>> cycles = new ArrayList<ArrayList<Integer>>();
|
||||
|
||||
public Cycle() {
|
||||
Scanner in = new Scanner(System.in);
|
||||
System.out.print("Enter the no. of nodes: ");
|
||||
nodes = in.nextInt();
|
||||
System.out.print("Enter the no. of Edges: ");
|
||||
edges = in.nextInt();
|
||||
|
||||
adjacencyMatrix = new int[nodes][nodes];
|
||||
visited = new boolean[nodes];
|
||||
|
||||
for (int i = 0; i < nodes; i++) {
|
||||
visited[i] = false;
|
||||
}
|
||||
|
||||
System.out.println("Enter the details of each edges <Start Node> <End Node>");
|
||||
|
||||
for (int i = 0; i < edges; i++) {
|
||||
int start, end;
|
||||
start = in.nextInt();
|
||||
end = in.nextInt();
|
||||
adjacencyMatrix[start][end] = 1;
|
||||
}
|
||||
in.close();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
for (int i = 0; i < nodes; i++) {
|
||||
ArrayList<Integer> temp = new ArrayList<>();
|
||||
dfs(i, i, temp);
|
||||
for (int j = 0; j < nodes; j++) {
|
||||
adjacencyMatrix[i][j] = 0;
|
||||
adjacencyMatrix[j][i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dfs(Integer start, Integer curr, ArrayList<Integer> temp) {
|
||||
temp.add(curr);
|
||||
visited[curr] = true;
|
||||
for (int i = 0; i < nodes; i++) {
|
||||
if (adjacencyMatrix[curr][i] == 1) {
|
||||
if (i == start) {
|
||||
cycles.add(new ArrayList<Integer>(temp));
|
||||
} else {
|
||||
if (!visited[i]) {
|
||||
dfs(start, i, temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (temp.size() > 0) {
|
||||
temp.remove(temp.size() - 1);
|
||||
}
|
||||
visited[curr] = false;
|
||||
}
|
||||
|
||||
public void printAll() {
|
||||
for (int i = 0; i < cycles.size(); i++) {
|
||||
for (int j = 0; j < cycles.get(i).size(); j++) {
|
||||
System.out.print(cycles.get(i).get(j) + " -> ");
|
||||
}
|
||||
System.out.println(cycles.get(i).get(0));
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Cycles {
|
||||
public static void main(String[] args) {
|
||||
Cycle c = new Cycle();
|
||||
c.start();
|
||||
c.printAll();
|
||||
}
|
||||
}
|
76
DataStructures/Graphs/FloydWarshall.java
Normal file
76
DataStructures/Graphs/FloydWarshall.java
Normal file
@ -0,0 +1,76 @@
|
||||
package DataStructures.Graphs;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
public class FloydWarshall {
|
||||
private int DistanceMatrix[][];
|
||||
private int numberofvertices; // number of vertices in the graph
|
||||
public static final int INFINITY = 999;
|
||||
|
||||
public FloydWarshall(int numberofvertices) {
|
||||
DistanceMatrix =
|
||||
new int[numberofvertices + 1]
|
||||
[numberofvertices
|
||||
+ 1]; // stores the value of distance from all the possible path form the source
|
||||
// vertex to destination vertex
|
||||
// The matrix is initialized with 0's by default
|
||||
this.numberofvertices = numberofvertices;
|
||||
}
|
||||
|
||||
public void floydwarshall(
|
||||
int AdjacencyMatrix[][]) // calculates all the distances from source to destination vertex
|
||||
{
|
||||
for (int source = 1; source <= numberofvertices; source++) {
|
||||
for (int destination = 1; destination <= numberofvertices; destination++) {
|
||||
DistanceMatrix[source][destination] = AdjacencyMatrix[source][destination];
|
||||
}
|
||||
}
|
||||
for (int intermediate = 1; intermediate <= numberofvertices; intermediate++) {
|
||||
for (int source = 1; source <= numberofvertices; source++) {
|
||||
for (int destination = 1; destination <= numberofvertices; destination++) {
|
||||
if (DistanceMatrix[source][intermediate] + DistanceMatrix[intermediate][destination]
|
||||
< DistanceMatrix[source][destination])
|
||||
// if the new distance calculated is less then the earlier shortest
|
||||
// calculated distance it get replaced as new shortest distance
|
||||
{
|
||||
DistanceMatrix[source][destination] =
|
||||
DistanceMatrix[source][intermediate] + DistanceMatrix[intermediate][destination];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int source = 1; source <= numberofvertices; source++) System.out.print("\t" + source);
|
||||
System.out.println();
|
||||
for (int source = 1; source <= numberofvertices; source++) {
|
||||
System.out.print(source + "\t");
|
||||
for (int destination = 1; destination <= numberofvertices; destination++) {
|
||||
System.out.print(DistanceMatrix[source][destination] + "\t");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String... arg) {
|
||||
Scanner scan = new Scanner(System.in);
|
||||
System.out.println("Enter the number of vertices");
|
||||
int numberOfVertices = scan.nextInt();
|
||||
int[][] adjacencyMatrix = new int[numberOfVertices + 1][numberOfVertices + 1];
|
||||
System.out.println("Enter the Weighted Matrix for the graph");
|
||||
for (int source = 1; source <= numberOfVertices; source++) {
|
||||
for (int destination = 1; destination <= numberOfVertices; destination++) {
|
||||
adjacencyMatrix[source][destination] = scan.nextInt();
|
||||
if (source == destination) {
|
||||
adjacencyMatrix[source][destination] = 0;
|
||||
continue;
|
||||
}
|
||||
if (adjacencyMatrix[source][destination] == 0) {
|
||||
adjacencyMatrix[source][destination] = INFINITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("The Transitive Closure of the Graph");
|
||||
FloydWarshall floydwarshall = new FloydWarshall(numberOfVertices);
|
||||
floydwarshall.floydwarshall(adjacencyMatrix);
|
||||
scan.close();
|
||||
}
|
||||
}
|
129
DataStructures/Graphs/Graphs.java
Normal file
129
DataStructures/Graphs/Graphs.java
Normal file
@ -0,0 +1,129 @@
|
||||
package DataStructures.Graphs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
class AdjacencyListGraph<E extends Comparable<E>> {
|
||||
|
||||
ArrayList<Vertex> verticies;
|
||||
|
||||
public AdjacencyListGraph() {
|
||||
verticies = new ArrayList<>();
|
||||
}
|
||||
|
||||
private class Vertex {
|
||||
E data;
|
||||
ArrayList<Vertex> adjacentVerticies;
|
||||
|
||||
public Vertex(E data) {
|
||||
adjacentVerticies = new ArrayList<>();
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean addAdjacentVertex(Vertex to) {
|
||||
for (Vertex v : adjacentVerticies) {
|
||||
if (v.data.compareTo(to.data) == 0) {
|
||||
return false; // the edge already exists
|
||||
}
|
||||
}
|
||||
return adjacentVerticies.add(to); // this will return true;
|
||||
}
|
||||
|
||||
public boolean removeAdjacentVertex(E to) {
|
||||
// use indexes here so it is possible to
|
||||
// remove easily without implementing
|
||||
// equals method that ArrayList.remove(Object o) uses
|
||||
for (int i = 0; i < adjacentVerticies.size(); i++) {
|
||||
if (adjacentVerticies.get(i).data.compareTo(to) == 0) {
|
||||
adjacentVerticies.remove(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this method removes an edge from the graph between two specified verticies
|
||||
*
|
||||
* @param from the data of the vertex the edge is from
|
||||
* @param to the data of the vertex the edge is going to
|
||||
* @return returns false if the edge doesn't exist, returns true if the edge exists and is removed
|
||||
*/
|
||||
public boolean removeEdge(E from, E to) {
|
||||
Vertex fromV = null;
|
||||
for (Vertex v : verticies) {
|
||||
if (from.compareTo(v.data) == 0) {
|
||||
fromV = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fromV == null) return false;
|
||||
return fromV.removeAdjacentVertex(to);
|
||||
}
|
||||
|
||||
/**
|
||||
* this method adds an edge to the graph between two specified verticies
|
||||
*
|
||||
* @param from the data of the vertex the edge is from
|
||||
* @param to the data of the vertex the edge is going to
|
||||
* @return returns true if the edge did not exist, return false if it already did
|
||||
*/
|
||||
public boolean addEdge(E from, E to) {
|
||||
Vertex fromV = null, toV = null;
|
||||
for (Vertex v : verticies) {
|
||||
if (from.compareTo(v.data) == 0) { // see if from vertex already exists
|
||||
fromV = v;
|
||||
} else if (to.compareTo(v.data) == 0) { // see if to vertex already exists
|
||||
toV = v;
|
||||
}
|
||||
if (fromV != null && toV != null) break; // both nodes exist so stop searching
|
||||
}
|
||||
if (fromV == null) {
|
||||
fromV = new Vertex(from);
|
||||
verticies.add(fromV);
|
||||
}
|
||||
if (toV == null) {
|
||||
toV = new Vertex(to);
|
||||
verticies.add(toV);
|
||||
}
|
||||
return fromV.addAdjacentVertex(toV);
|
||||
}
|
||||
|
||||
/**
|
||||
* this gives a list of verticies in the graph and their adjacencies
|
||||
*
|
||||
* @return returns a string describing this graph
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Vertex v : verticies) {
|
||||
sb.append("Vertex: ");
|
||||
sb.append(v.data);
|
||||
sb.append("\n");
|
||||
sb.append("Adjacent verticies: ");
|
||||
for (Vertex v2 : v.adjacentVerticies) {
|
||||
sb.append(v2.data);
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public class Graphs {
|
||||
|
||||
public static void main(String args[]) {
|
||||
AdjacencyListGraph<Integer> graph = new AdjacencyListGraph<>();
|
||||
assert graph.addEdge(1, 2);
|
||||
assert graph.addEdge(1, 5);
|
||||
assert graph.addEdge(2, 5);
|
||||
assert !graph.addEdge(1, 2);
|
||||
assert graph.addEdge(2, 3);
|
||||
assert graph.addEdge(3, 4);
|
||||
assert graph.addEdge(4, 1);
|
||||
assert !graph.addEdge(2, 3);
|
||||
System.out.println(graph);
|
||||
}
|
||||
}
|
103
DataStructures/Graphs/Kruskal.java
Normal file
103
DataStructures/Graphs/Kruskal.java
Normal file
@ -0,0 +1,103 @@
|
||||
// Problem -> Connect all the edges with the minimum cost.
|
||||
// Possible Solution -> Kruskal Algorithm (KA), KA finds the minimum-spanning-tree, which means, the
|
||||
// group of edges with the minimum sum of their weights that connect the whole graph.
|
||||
// The graph needs to be connected, because if there are nodes impossible to reach, there are no
|
||||
// edges that could connect every node in the graph.
|
||||
// KA is a Greedy Algorithm, because edges are analysed based on their weights, that is why a
|
||||
// Priority Queue is used, to take first those less weighted.
|
||||
// This implementations below has some changes compared to conventional ones, but they are explained
|
||||
// all along the code.
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
public class Kruskal {
|
||||
|
||||
// Complexity: O(E log V) time, where E is the number of edges in the graph and V is the number of
|
||||
// vertices
|
||||
|
||||
private static class Edge {
|
||||
private int from;
|
||||
private int to;
|
||||
private int weight;
|
||||
|
||||
public Edge(int from, int to, int weight) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.weight = weight;
|
||||
}
|
||||
}
|
||||
|
||||
private static void addEdge(HashSet<Edge>[] graph, int from, int to, int weight) {
|
||||
graph[from].add(new Edge(from, to, weight));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
HashSet<Edge>[] graph = new HashSet[7];
|
||||
for (int i = 0; i < graph.length; i++) {
|
||||
graph[i] = new HashSet<>();
|
||||
}
|
||||
addEdge(graph, 0, 1, 2);
|
||||
addEdge(graph, 0, 2, 3);
|
||||
addEdge(graph, 0, 3, 3);
|
||||
addEdge(graph, 1, 2, 4);
|
||||
addEdge(graph, 2, 3, 5);
|
||||
addEdge(graph, 1, 4, 3);
|
||||
addEdge(graph, 2, 4, 1);
|
||||
addEdge(graph, 3, 5, 7);
|
||||
addEdge(graph, 4, 5, 8);
|
||||
addEdge(graph, 5, 6, 9);
|
||||
|
||||
System.out.println("Initial Graph: ");
|
||||
for (int i = 0; i < graph.length; i++) {
|
||||
for (Edge edge : graph[i]) {
|
||||
System.out.println(i + " <-- weight " + edge.weight + " --> " + edge.to);
|
||||
}
|
||||
}
|
||||
|
||||
Kruskal k = new Kruskal();
|
||||
HashSet<Edge>[] solGraph = k.kruskal(graph);
|
||||
|
||||
System.out.println("\nMinimal Graph: ");
|
||||
for (int i = 0; i < solGraph.length; i++) {
|
||||
for (Edge edge : solGraph[i]) {
|
||||
System.out.println(i + " <-- weight " + edge.weight + " --> " + edge.to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HashSet<Edge>[] kruskal(HashSet<Edge>[] graph) {
|
||||
int nodes = graph.length;
|
||||
int[] captain = new int[nodes];
|
||||
// captain of i, stores the set with all the connected nodes to i
|
||||
HashSet<Integer>[] connectedGroups = new HashSet[nodes];
|
||||
HashSet<Edge>[] minGraph = new HashSet[nodes];
|
||||
PriorityQueue<Edge> edges = new PriorityQueue<>((Comparator.comparingInt(edge -> edge.weight)));
|
||||
for (int i = 0; i < nodes; i++) {
|
||||
minGraph[i] = new HashSet<>();
|
||||
connectedGroups[i] = new HashSet<>();
|
||||
connectedGroups[i].add(i);
|
||||
captain[i] = i;
|
||||
edges.addAll(graph[i]);
|
||||
}
|
||||
int connectedElements = 0;
|
||||
// as soon as two sets merge all the elements, the algorithm must stop
|
||||
while (connectedElements != nodes && !edges.isEmpty()) {
|
||||
Edge edge = edges.poll();
|
||||
// This if avoids cycles
|
||||
if (!connectedGroups[captain[edge.from]].contains(edge.to)
|
||||
&& !connectedGroups[captain[edge.to]].contains(edge.from)) {
|
||||
// merge sets of the captains of each point connected by the edge
|
||||
connectedGroups[captain[edge.from]].addAll(connectedGroups[captain[edge.to]]);
|
||||
// update captains of the elements merged
|
||||
connectedGroups[captain[edge.from]].forEach(i -> captain[i] = captain[edge.from]);
|
||||
// add Edge to minimal graph
|
||||
addEdge(minGraph, edge.from, edge.to, edge.weight);
|
||||
// count how many elements have been merged
|
||||
connectedElements = connectedGroups[captain[edge.from]].size();
|
||||
}
|
||||
}
|
||||
return minGraph;
|
||||
}
|
||||
}
|
142
DataStructures/Graphs/MatrixGraphs.java
Normal file
142
DataStructures/Graphs/MatrixGraphs.java
Normal file
@ -0,0 +1,142 @@
|
||||
package DataStructures.Graphs;
|
||||
|
||||
public class MatrixGraphs {
|
||||
|
||||
public static void main(String args[]) {
|
||||
AdjacencyMatrixGraph graph = new AdjacencyMatrixGraph(10);
|
||||
graph.addEdge(1, 2);
|
||||
graph.addEdge(1, 5);
|
||||
graph.addEdge(2, 5);
|
||||
graph.addEdge(1, 2);
|
||||
graph.addEdge(2, 3);
|
||||
graph.addEdge(3, 4);
|
||||
graph.addEdge(4, 1);
|
||||
graph.addEdge(2, 3);
|
||||
System.out.println(graph);
|
||||
}
|
||||
}
|
||||
|
||||
class AdjacencyMatrixGraph {
|
||||
private int _numberOfVertices;
|
||||
private int _numberOfEdges;
|
||||
private int[][] _adjacency;
|
||||
|
||||
static final int EDGE_EXIST = 1;
|
||||
static final int EDGE_NONE = 0;
|
||||
|
||||
public AdjacencyMatrixGraph(int givenNumberOfVertices) {
|
||||
this.setNumberOfVertices(givenNumberOfVertices);
|
||||
this.setNumberOfEdges(0);
|
||||
this.setAdjacency(new int[givenNumberOfVertices][givenNumberOfVertices]);
|
||||
for (int i = 0; i < givenNumberOfVertices; i++) {
|
||||
for (int j = 0; j < givenNumberOfVertices; j++) {
|
||||
this.adjacency()[i][j] = AdjacencyMatrixGraph.EDGE_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setNumberOfVertices(int newNumberOfVertices) {
|
||||
this._numberOfVertices = newNumberOfVertices;
|
||||
}
|
||||
|
||||
public int numberOfVertices() {
|
||||
return this._numberOfVertices;
|
||||
}
|
||||
|
||||
private void setNumberOfEdges(int newNumberOfEdges) {
|
||||
this._numberOfEdges = newNumberOfEdges;
|
||||
}
|
||||
|
||||
public int numberOfEdges() {
|
||||
return this._numberOfEdges;
|
||||
}
|
||||
|
||||
private void setAdjacency(int[][] newAdjacency) {
|
||||
this._adjacency = newAdjacency;
|
||||
}
|
||||
|
||||
private int[][] adjacency() {
|
||||
return this._adjacency;
|
||||
}
|
||||
|
||||
private boolean adjacencyOfEdgeDoesExist(int from, int to) {
|
||||
return (this.adjacency()[from][to] != AdjacencyMatrixGraph.EDGE_NONE);
|
||||
}
|
||||
|
||||
public boolean vertexDoesExist(int aVertex) {
|
||||
if (aVertex >= 0 && aVertex < this.numberOfVertices()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean edgeDoesExist(int from, int to) {
|
||||
if (this.vertexDoesExist(from) && this.vertexDoesExist(to)) {
|
||||
return (this.adjacencyOfEdgeDoesExist(from, to));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adds an edge to the graph between two specified vertices
|
||||
*
|
||||
* @param from the data of the vertex the edge is from
|
||||
* @param to the data of the vertex the edge is going to
|
||||
* @return returns true if the edge did not exist, return false if it already did
|
||||
*/
|
||||
public boolean addEdge(int from, int to) {
|
||||
if (this.vertexDoesExist(from) && this.vertexDoesExist(to)) {
|
||||
if (!this.adjacencyOfEdgeDoesExist(from, to)) {
|
||||
this.adjacency()[from][to] = AdjacencyMatrixGraph.EDGE_EXIST;
|
||||
this.adjacency()[to][from] = AdjacencyMatrixGraph.EDGE_EXIST;
|
||||
this.setNumberOfEdges(this.numberOfEdges() + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* this method removes an edge from the graph between two specified vertices
|
||||
*
|
||||
* @param from the data of the vertex the edge is from
|
||||
* @param to the data of the vertex the edge is going to
|
||||
* @return returns false if the edge doesn't exist, returns true if the edge exists and is removed
|
||||
*/
|
||||
public boolean removeEdge(int from, int to) {
|
||||
if (!this.vertexDoesExist(from) || !this.vertexDoesExist(to)) {
|
||||
if (this.adjacencyOfEdgeDoesExist(from, to)) {
|
||||
this.adjacency()[from][to] = AdjacencyMatrixGraph.EDGE_NONE;
|
||||
this.adjacency()[to][from] = AdjacencyMatrixGraph.EDGE_NONE;
|
||||
this.setNumberOfEdges(this.numberOfEdges() - 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* this gives a list of vertices in the graph and their adjacencies
|
||||
*
|
||||
* @return returns a string describing this graph
|
||||
*/
|
||||
public String toString() {
|
||||
String s = " ";
|
||||
for (int i = 0; i < this.numberOfVertices(); i++) {
|
||||
s = s + String.valueOf(i) + " ";
|
||||
}
|
||||
s = s + " \n";
|
||||
|
||||
for (int i = 0; i < this.numberOfVertices(); i++) {
|
||||
s = s + String.valueOf(i) + " : ";
|
||||
for (int j = 0; j < this.numberOfVertices(); j++) {
|
||||
s = s + String.valueOf(this._adjacency[i][j]) + " ";
|
||||
}
|
||||
s = s + "\n";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
102
DataStructures/Graphs/PrimMST.java
Normal file
102
DataStructures/Graphs/PrimMST.java
Normal file
@ -0,0 +1,102 @@
|
||||
package DataStructures.Graphs;
|
||||
|
||||
/**
|
||||
* A Java program for Prim's Minimum Spanning Tree (MST) algorithm. adjacency matrix representation
|
||||
* of the graph
|
||||
*/
|
||||
class PrimMST {
|
||||
// Number of vertices in the graph
|
||||
private static final int V = 5;
|
||||
|
||||
// A utility function to find the vertex with minimum key
|
||||
// value, from the set of vertices not yet included in MST
|
||||
int minKey(int key[], Boolean mstSet[]) {
|
||||
// Initialize min value
|
||||
int min = Integer.MAX_VALUE, min_index = -1;
|
||||
|
||||
for (int v = 0; v < V; v++)
|
||||
if (mstSet[v] == false && key[v] < min) {
|
||||
min = key[v];
|
||||
min_index = v;
|
||||
}
|
||||
|
||||
return min_index;
|
||||
}
|
||||
|
||||
// A utility function to print the constructed MST stored in
|
||||
// parent[]
|
||||
void printMST(int parent[], int n, int graph[][]) {
|
||||
System.out.println("Edge Weight");
|
||||
for (int i = 1; i < V; i++)
|
||||
System.out.println(parent[i] + " - " + i + " " + graph[i][parent[i]]);
|
||||
}
|
||||
|
||||
// Function to construct and print MST for a graph represented
|
||||
// using adjacency matrix representation
|
||||
void primMST(int graph[][]) {
|
||||
// Array to store constructed MST
|
||||
int parent[] = new int[V];
|
||||
|
||||
// Key values used to pick minimum weight edge in cut
|
||||
int key[] = new int[V];
|
||||
|
||||
// To represent set of vertices not yet included in MST
|
||||
Boolean mstSet[] = new Boolean[V];
|
||||
|
||||
// Initialize all keys as INFINITE
|
||||
for (int i = 0; i < V; i++) {
|
||||
key[i] = Integer.MAX_VALUE;
|
||||
mstSet[i] = false;
|
||||
}
|
||||
|
||||
// Always include first 1st vertex in MST.
|
||||
key[0] = 0; // Make key 0 so that this vertex is
|
||||
// picked as first vertex
|
||||
parent[0] = -1; // First node is always root of MST
|
||||
|
||||
// The MST will have V vertices
|
||||
for (int count = 0; count < V - 1; count++) {
|
||||
// Pick thd minimum key vertex from the set of vertices
|
||||
// not yet included in MST
|
||||
int u = minKey(key, mstSet);
|
||||
|
||||
// Add the picked vertex to the MST Set
|
||||
mstSet[u] = true;
|
||||
|
||||
// Update key value and parent index of the adjacent
|
||||
// vertices of the picked vertex. Consider only those
|
||||
// vertices which are not yet included in MST
|
||||
for (int v = 0; v < V; v++)
|
||||
|
||||
// graph[u][v] is non zero only for adjacent vertices of m
|
||||
// mstSet[v] is false for vertices not yet included in MST
|
||||
// Update the key only if graph[u][v] is smaller than key[v]
|
||||
if (graph[u][v] != 0 && mstSet[v] == false && graph[u][v] < key[v]) {
|
||||
parent[v] = u;
|
||||
key[v] = graph[u][v];
|
||||
}
|
||||
}
|
||||
|
||||
// print the constructed MST
|
||||
printMST(parent, V, graph);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
/* Let us create the following graph
|
||||
2 3
|
||||
(0)--(1)--(2)
|
||||
| / \ |
|
||||
6| 8/ \5 |7
|
||||
| / \ |
|
||||
(3)-------(4)
|
||||
9 */
|
||||
PrimMST t = new PrimMST();
|
||||
int graph[][] =
|
||||
new int[][] {
|
||||
{0, 2, 0, 6, 0}, {2, 0, 3, 8, 5}, {0, 3, 0, 0, 7}, {6, 8, 0, 0, 9}, {0, 5, 7, 9, 0},
|
||||
};
|
||||
|
||||
// Print the solution
|
||||
t.primMST(graph);
|
||||
}
|
||||
}
|
145
DataStructures/HashMap/Hashing/HashMap.java
Normal file
145
DataStructures/HashMap/Hashing/HashMap.java
Normal file
@ -0,0 +1,145 @@
|
||||
package DataStructures.HashMap.Hashing;
|
||||
|
||||
public class HashMap {
|
||||
private int hsize;
|
||||
private LinkedList[] buckets;
|
||||
|
||||
public HashMap(int hsize) {
|
||||
buckets = new LinkedList[hsize];
|
||||
for (int i = 0; i < hsize; i++) {
|
||||
buckets[i] = new LinkedList();
|
||||
// Java requires explicit initialisaton of each object
|
||||
}
|
||||
this.hsize = hsize;
|
||||
}
|
||||
|
||||
public int hashing(int key) {
|
||||
int hash = key % hsize;
|
||||
if (hash < 0) hash += hsize;
|
||||
return hash;
|
||||
}
|
||||
|
||||
public void insertHash(int key) {
|
||||
int hash = hashing(key);
|
||||
buckets[hash].insert(key);
|
||||
}
|
||||
|
||||
public void deleteHash(int key) {
|
||||
int hash = hashing(key);
|
||||
|
||||
buckets[hash].delete(key);
|
||||
}
|
||||
|
||||
public void displayHashtable() {
|
||||
for (int i = 0; i < hsize; i++) {
|
||||
System.out.printf("Bucket %d :", i);
|
||||
System.out.println(buckets[i].display());
|
||||
}
|
||||
}
|
||||
|
||||
public static class LinkedList {
|
||||
private Node first;
|
||||
|
||||
public LinkedList() {
|
||||
first = null;
|
||||
}
|
||||
|
||||
public void insert(int key) {
|
||||
if (isEmpty()) {
|
||||
first = new Node(key);
|
||||
return;
|
||||
}
|
||||
|
||||
Node temp = findEnd(first);
|
||||
temp.setNext(new Node(key));
|
||||
}
|
||||
|
||||
private Node findEnd(Node n) {
|
||||
if (n.getNext() == null) {
|
||||
return n;
|
||||
} else {
|
||||
return findEnd(n.getNext());
|
||||
}
|
||||
}
|
||||
|
||||
public Node findKey(int key) {
|
||||
if (!isEmpty()) {
|
||||
return findKey(first, key);
|
||||
} else {
|
||||
System.out.println("List is empty");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Node findKey(Node n, int key) {
|
||||
if (n.getKey() == key) {
|
||||
return n;
|
||||
} else if (n.getNext() == null) {
|
||||
System.out.println("Key not found");
|
||||
return null;
|
||||
} else {
|
||||
return findKey(n.getNext(), key);
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(int key) {
|
||||
if (!isEmpty()) {
|
||||
if (first.getKey() == key) {
|
||||
first = null;
|
||||
} else {
|
||||
delete(first, key);
|
||||
}
|
||||
} else {
|
||||
System.out.println("List is empty");
|
||||
}
|
||||
}
|
||||
|
||||
private void delete(Node n, int key) {
|
||||
if (n.getNext().getKey() == key) {
|
||||
if (n.getNext().getNext() == null) {
|
||||
n.setNext(null);
|
||||
} else {
|
||||
n.setNext(n.getNext().getNext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String display() {
|
||||
return display(first);
|
||||
}
|
||||
|
||||
private String display(Node n) {
|
||||
if (n == null) {
|
||||
return "null";
|
||||
} else {
|
||||
return n.getKey() + "->" + display(n.getNext());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return first == null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Node {
|
||||
private Node next;
|
||||
private int key;
|
||||
|
||||
public Node(int key) {
|
||||
next = null;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public Node getNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
public int getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setNext(Node next) {
|
||||
this.next = next;
|
||||
}
|
||||
}
|
||||
}
|
196
DataStructures/HashMap/Hashing/HashMapLinearProbing.java
Normal file
196
DataStructures/HashMap/Hashing/HashMapLinearProbing.java
Normal file
@ -0,0 +1,196 @@
|
||||
package DataStructures.HashMap.Hashing;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This class is an implementation of a hash table using linear probing It uses a dynamic array to
|
||||
* lengthen the size of the hash table when load factor > .7
|
||||
*/
|
||||
public class HashMapLinearProbing {
|
||||
private int hsize; // size of the hash table
|
||||
private Integer[] buckets; // array representing the table
|
||||
private Integer AVAILABLE;
|
||||
private int size; // amount of elements in the hash table
|
||||
|
||||
/**
|
||||
* Constructor initializes buckets array, hsize, and creates dummy object for AVAILABLE
|
||||
*
|
||||
* @param hsize the desired size of the hash map
|
||||
*/
|
||||
public HashMapLinearProbing(int hsize) {
|
||||
this.buckets = new Integer[hsize];
|
||||
this.hsize = hsize;
|
||||
this.AVAILABLE = Integer.MIN_VALUE;
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Hash Function takes a given key and finds an index based on its data
|
||||
*
|
||||
* @param key the desired key to be converted
|
||||
* @return int an index corresponding to the key
|
||||
*/
|
||||
public int hashing(int key) {
|
||||
int hash = key % hsize;
|
||||
if (hash < 0) {
|
||||
hash += hsize;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* inserts the key into the hash map by wrapping it as an Integer object
|
||||
*
|
||||
* @param key the desired key to be inserted in the hash map
|
||||
*/
|
||||
public void insertHash(int key) {
|
||||
Integer wrappedInt = key;
|
||||
int hash = hashing(key);
|
||||
|
||||
if (isFull()) {
|
||||
System.out.println("Hash table is full");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < hsize; i++) {
|
||||
if (buckets[hash] == null || buckets[hash] == AVAILABLE) {
|
||||
buckets[hash] = wrappedInt;
|
||||
size++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (hash + 1 < hsize) {
|
||||
hash++;
|
||||
} else {
|
||||
hash = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes a key from the hash map and adds an available placeholder
|
||||
*
|
||||
* @param key the desired key to be deleted
|
||||
*/
|
||||
public void deleteHash(int key) {
|
||||
Integer wrappedInt = key;
|
||||
int hash = hashing(key);
|
||||
|
||||
if (isEmpty()) {
|
||||
System.out.println("Table is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < hsize; i++) {
|
||||
if (buckets[hash] != null && buckets[hash].equals(wrappedInt)) {
|
||||
buckets[hash] = AVAILABLE;
|
||||
size--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (hash + 1 < hsize) {
|
||||
hash++;
|
||||
} else {
|
||||
hash = 0;
|
||||
}
|
||||
}
|
||||
System.out.println("Key " + key + " not found");
|
||||
}
|
||||
|
||||
/** Displays the hash table line by line */
|
||||
public void displayHashtable() {
|
||||
for (int i = 0; i < hsize; i++) {
|
||||
if (buckets[i] == null || buckets[i] == AVAILABLE) {
|
||||
System.out.println("Bucket " + i + ": Empty");
|
||||
} else {
|
||||
System.out.println("Bucket " + i + ": " + buckets[i].toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the index of location based on an inputed key
|
||||
*
|
||||
* @param key the desired key to be found
|
||||
* @return int the index where the key is located
|
||||
*/
|
||||
public int findHash(int key) {
|
||||
Integer wrappedInt = key;
|
||||
int hash = hashing(key);
|
||||
|
||||
if (isEmpty()) {
|
||||
System.out.println("Table is empty");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < hsize; i++) {
|
||||
try {
|
||||
if (buckets[hash].equals(wrappedInt)) {
|
||||
buckets[hash] = AVAILABLE;
|
||||
return hash;
|
||||
}
|
||||
} catch (Exception E) {
|
||||
}
|
||||
|
||||
if (hash + 1 < hsize) {
|
||||
hash++;
|
||||
} else {
|
||||
hash = 0;
|
||||
}
|
||||
}
|
||||
System.out.println("Key " + key + " not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void lengthenTable() {
|
||||
buckets = Arrays.copyOf(buckets, hsize * 2);
|
||||
hsize *= 2;
|
||||
System.out.println("Table size is now: " + hsize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the load factor of the hash table if greater than .7, automatically lengthens table to
|
||||
* prevent further collisions
|
||||
*/
|
||||
public void checkLoadFactor() {
|
||||
double factor = (double) size / hsize;
|
||||
if (factor > .7) {
|
||||
System.out.println("Load factor is " + factor + ", lengthening table");
|
||||
lengthenTable();
|
||||
} else {
|
||||
System.out.println("Load factor is " + factor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* isFull returns true if the hash map is full and false if not full
|
||||
*
|
||||
* @return boolean is Empty
|
||||
*/
|
||||
public boolean isFull() {
|
||||
boolean response = true;
|
||||
for (int i = 0; i < hsize; i++) {
|
||||
if (buckets[i] == null || buckets[i] == AVAILABLE) {
|
||||
response = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* isEmpty returns true if the hash map is empty and false if not empty
|
||||
*
|
||||
* @return boolean is Empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
boolean response = true;
|
||||
for (int i = 0; i < hsize; i++) {
|
||||
if (buckets[i] != null) {
|
||||
response = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
64
DataStructures/HashMap/Hashing/Intersection
Normal file
64
DataStructures/HashMap/Hashing/Intersection
Normal file
@ -0,0 +1,64 @@
|
||||
package DataStructures.HashMap.Hashing;
|
||||
/*
|
||||
* this is algo which implies common mathematical set theory concept
|
||||
* called intersection in which result is common values of both the sets
|
||||
* here metaphor of sets is HashMap
|
||||
|
||||
|
||||
Test Case:
|
||||
Scanner scn=new Scanner(System.in);
|
||||
int len =scn.nextInt();
|
||||
int arr[]=new int[len];
|
||||
int arr2[]=new int[len];
|
||||
|
||||
for(int i=0;i<2*len;i++) {
|
||||
|
||||
if(i<len)
|
||||
arr[i]=scn.nextInt();
|
||||
if(i>=len) {
|
||||
arr2[i-len]=scn.nextInt();
|
||||
}
|
||||
}
|
||||
System.out.println(Main(arr,arr2));
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
|
||||
public class Intersection {
|
||||
|
||||
public static ArrayList Main(int arr[],int arr2[]) {
|
||||
HashMap<Integer,Integer> hmap=new HashMap<>();
|
||||
HashMap<Integer,Integer> hmap2=new HashMap<>();
|
||||
for(int i=0;i<arr.length;i++) {
|
||||
if(hmap.containsKey(arr[i])) {
|
||||
int val=hmap.get(arr[i]);
|
||||
hmap.put(arr[i],val+1);
|
||||
}else
|
||||
hmap.put(arr[i],1);
|
||||
|
||||
}
|
||||
ArrayList<Integer> res=new ArrayList<>();
|
||||
for(int i=0;i<arr2.length;i++) {
|
||||
if(hmap.containsKey(arr2[i])&&hmap.get(arr2[i])>0) {
|
||||
int val=hmap.get(arr2[i]);
|
||||
hmap.put(arr2[i],val-1);
|
||||
res.add(arr2[i]);
|
||||
}
|
||||
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public Intersection() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
51
DataStructures/HashMap/Hashing/Main.java
Normal file
51
DataStructures/HashMap/Hashing/Main.java
Normal file
@ -0,0 +1,51 @@
|
||||
package DataStructures.HashMap.Hashing;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
|
||||
int choice, key;
|
||||
|
||||
HashMap h = new HashMap(7);
|
||||
Scanner In = new Scanner(System.in);
|
||||
|
||||
while (true) {
|
||||
System.out.println("Enter your Choice :");
|
||||
System.out.println("1. Add Key");
|
||||
System.out.println("2. Delete Key");
|
||||
System.out.println("3. Print Table");
|
||||
System.out.println("4. Exit");
|
||||
|
||||
choice = In.nextInt();
|
||||
|
||||
switch (choice) {
|
||||
case 1:
|
||||
{
|
||||
System.out.println("Enter the Key: ");
|
||||
key = In.nextInt();
|
||||
h.insertHash(key);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
System.out.println("Enter the Key delete: ");
|
||||
key = In.nextInt();
|
||||
h.deleteHash(key);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
System.out.println("Print table");
|
||||
h.displayHashtable();
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
In.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
65
DataStructures/HashMap/Hashing/MainLinearProbing.java
Normal file
65
DataStructures/HashMap/Hashing/MainLinearProbing.java
Normal file
@ -0,0 +1,65 @@
|
||||
package DataStructures.HashMap.Hashing;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
public class MainLinearProbing {
|
||||
public static void main(String[] args) {
|
||||
|
||||
int choice, key;
|
||||
|
||||
HashMapLinearProbing h = new HashMapLinearProbing(7);
|
||||
Scanner In = new Scanner(System.in);
|
||||
|
||||
while (true) {
|
||||
System.out.println("Enter your Choice :");
|
||||
System.out.println("1. Add Key");
|
||||
System.out.println("2. Delete Key");
|
||||
System.out.println("3. Print Table");
|
||||
System.out.println("4. Exit");
|
||||
System.out.println("5. Search and print key index");
|
||||
System.out.println("6. Check load factor");
|
||||
|
||||
choice = In.nextInt();
|
||||
|
||||
switch (choice) {
|
||||
case 1:
|
||||
{
|
||||
System.out.println("Enter the Key: ");
|
||||
key = In.nextInt();
|
||||
h.insertHash(key);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
System.out.println("Enter the Key delete: ");
|
||||
key = In.nextInt();
|
||||
h.deleteHash(key);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
System.out.println("Print table");
|
||||
h.displayHashtable();
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
In.close();
|
||||
return;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
System.out.println("Enter the Key to find and print: ");
|
||||
key = In.nextInt();
|
||||
System.out.println("Key: " + key + " is at index: " + h.findHash(key));
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
h.checkLoadFactor();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
DataStructures/Heaps/EmptyHeapException.java
Normal file
12
DataStructures/Heaps/EmptyHeapException.java
Normal file
@ -0,0 +1,12 @@
|
||||
package DataStructures.Heaps;
|
||||
|
||||
/**
|
||||
* @author Nicolas Renard Exception to be thrown if the getElement method is used on an empty heap.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class EmptyHeapException extends Exception {
|
||||
|
||||
public EmptyHeapException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
69
DataStructures/Heaps/GenericHeap
Normal file
69
DataStructures/Heaps/GenericHeap
Normal file
@ -0,0 +1,69 @@
|
||||
import java.util.*;
|
||||
|
||||
public class GenericHeap <T extends Comparable <T> >{
|
||||
ArrayList <T> data=new ArrayList<>();
|
||||
HashMap<T,Integer> map=new HashMap<>();
|
||||
public void add(T item) {
|
||||
this.data.add(item);
|
||||
map.put(item,this.data.size()-1);//
|
||||
upHeapify(this.data.size()-1);
|
||||
}
|
||||
private void upHeapify(int ci) {
|
||||
int pi=(ci-1)/2;
|
||||
if(isLarger(this.data.get(ci),this.data.get(pi))>0) {
|
||||
swap(pi,ci);
|
||||
upHeapify(pi);
|
||||
}
|
||||
}
|
||||
public void display() {
|
||||
System.out.println(this.data);
|
||||
}
|
||||
public int size() {
|
||||
return this.data.size();
|
||||
}
|
||||
public boolean isEmpty() {
|
||||
return this.size()==0;
|
||||
}
|
||||
public T remove() {
|
||||
this.swap(0,this.size()-1);
|
||||
T rv=this.data.remove(this.size()-1);
|
||||
downHeapify(0);
|
||||
map.remove(rv);
|
||||
return rv;
|
||||
}
|
||||
private void downHeapify(int pi) {
|
||||
int lci=2*pi+1;
|
||||
int rci=2*pi+2;
|
||||
int mini=pi;
|
||||
if(lci<this.size() && isLarger(this.data.get(lci),this.data.get(mini))>0) {
|
||||
mini=lci;
|
||||
}
|
||||
if(rci<this.size() && isLarger(this.data.get(rci),this.data.get(mini))>0) {
|
||||
mini=rci;
|
||||
}
|
||||
if(mini!=pi) {
|
||||
this.swap(pi,mini);
|
||||
downHeapify(mini);
|
||||
}
|
||||
}
|
||||
public T get() {
|
||||
return this.data.get(0);
|
||||
}
|
||||
//t has higher property then return +ve
|
||||
private int isLarger(T t,T o) {
|
||||
return t.compareTo(o);
|
||||
}
|
||||
private void swap(int i,int j) {
|
||||
T ith=this.data.get(i);
|
||||
T jth=this.data.get(j);
|
||||
this.data.set(i,jth);
|
||||
this.data.set(j,ith);
|
||||
map.put(ith,j);
|
||||
map.put(jth,i);
|
||||
}
|
||||
public void updatePriority(T item) {
|
||||
int index=map.get(item);
|
||||
//because we enter lesser value then old vale
|
||||
upHeapify(index);
|
||||
}
|
||||
}
|
40
DataStructures/Heaps/Heap.java
Normal file
40
DataStructures/Heaps/Heap.java
Normal file
@ -0,0 +1,40 @@
|
||||
package DataStructures.Heaps;
|
||||
|
||||
/**
|
||||
* Interface common to heap data structures.<br>
|
||||
*
|
||||
* <p>Heaps are tree-like data structures that allow storing elements in a specific way. Each node
|
||||
* corresponds to an element and has one parent node (except for the root) and at most two children
|
||||
* nodes. Every element contains a key, and those keys indicate how the tree shall be built. For
|
||||
* instance, for a min-heap, the key of a node shall be greater than or equal to its parent's and
|
||||
* lower than or equal to its children's (the opposite rule applies to a max-heap).
|
||||
*
|
||||
* <p>All heap-related operations (inserting or deleting an element, extracting the min or max) are
|
||||
* performed in O(log n) time.
|
||||
*
|
||||
* @author Nicolas Renard
|
||||
*/
|
||||
public interface Heap {
|
||||
|
||||
/**
|
||||
* @return the top element in the heap, the one with lowest key for min-heap or with the highest
|
||||
* key for max-heap
|
||||
* @throws EmptyHeapException if heap is empty
|
||||
*/
|
||||
HeapElement getElement() throws EmptyHeapException;
|
||||
|
||||
/**
|
||||
* Inserts an element in the heap. Adds it to then end and toggle it until it finds its right
|
||||
* position.
|
||||
*
|
||||
* @param element an instance of the HeapElement class.
|
||||
*/
|
||||
void insertElement(HeapElement element);
|
||||
|
||||
/**
|
||||
* Delete an element in the heap.
|
||||
*
|
||||
* @param elementIndex int containing the position in the heap of the element to be deleted.
|
||||
*/
|
||||
void deleteElement(int elementIndex);
|
||||
}
|
124
DataStructures/Heaps/HeapElement.java
Normal file
124
DataStructures/Heaps/HeapElement.java
Normal file
@ -0,0 +1,124 @@
|
||||
package DataStructures.Heaps;
|
||||
|
||||
/**
|
||||
* Class for heap elements.<br>
|
||||
*
|
||||
* <p>A heap element contains two attributes: a key which will be used to build the tree (int or
|
||||
* double, either primitive type or object) and any kind of IMMUTABLE object the user sees fit to
|
||||
* carry any information he/she likes. Be aware that the use of a mutable object might jeopardize
|
||||
* the integrity of this information.
|
||||
*
|
||||
* @author Nicolas Renard
|
||||
*/
|
||||
public class HeapElement {
|
||||
private final double key;
|
||||
private final Object additionalInfo;
|
||||
|
||||
// Constructors
|
||||
|
||||
/**
|
||||
* @param key : a number of primitive type 'double'
|
||||
* @param info : any kind of IMMUTABLE object. May be null, since the purpose is only to carry
|
||||
* additional information of use for the user
|
||||
*/
|
||||
public HeapElement(double key, Object info) {
|
||||
this.key = key;
|
||||
this.additionalInfo = info;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key : a number of primitive type 'int'
|
||||
* @param info : any kind of IMMUTABLE object. May be null, since the purpose is only to carry
|
||||
* additional information of use for the user
|
||||
*/
|
||||
public HeapElement(int key, Object info) {
|
||||
this.key = key;
|
||||
this.additionalInfo = info;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key : a number of object type 'Integer'
|
||||
* @param info : any kind of IMMUTABLE object. May be null, since the purpose is only to carry
|
||||
* additional information of use for the user
|
||||
*/
|
||||
public HeapElement(Integer key, Object info) {
|
||||
this.key = key;
|
||||
this.additionalInfo = info;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key : a number of object type 'Double'
|
||||
* @param info : any kind of IMMUTABLE object. May be null, since the purpose is only to carry
|
||||
* additional information of use for the user
|
||||
*/
|
||||
public HeapElement(Double key, Object info) {
|
||||
this.key = key;
|
||||
this.additionalInfo = info;
|
||||
}
|
||||
|
||||
/** @param key : a number of primitive type 'double' */
|
||||
public HeapElement(double key) {
|
||||
this.key = key;
|
||||
this.additionalInfo = null;
|
||||
}
|
||||
|
||||
/** @param key : a number of primitive type 'int' */
|
||||
public HeapElement(int key) {
|
||||
this.key = key;
|
||||
this.additionalInfo = null;
|
||||
}
|
||||
|
||||
/** @param key : a number of object type 'Integer' */
|
||||
public HeapElement(Integer key) {
|
||||
this.key = key;
|
||||
this.additionalInfo = null;
|
||||
}
|
||||
|
||||
/** @param key : a number of object type 'Double' */
|
||||
public HeapElement(Double key) {
|
||||
this.key = key;
|
||||
this.additionalInfo = null;
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
/** @return the object containing the additional info provided by the user. */
|
||||
public Object getInfo() {
|
||||
return additionalInfo;
|
||||
}
|
||||
|
||||
/** @return the key value of the element */
|
||||
public double getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
// Overridden object methods
|
||||
|
||||
public String toString() {
|
||||
return "Key: " + key + " - " + additionalInfo.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param otherHeapElement
|
||||
* @return true if the keys on both elements are identical and the additional info objects are
|
||||
* identical.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o != null) {
|
||||
if (!(o instanceof HeapElement)) return false;
|
||||
HeapElement otherHeapElement = (HeapElement) o;
|
||||
return (this.key == otherHeapElement.key)
|
||||
&& (this.additionalInfo.equals(otherHeapElement.additionalInfo));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 0;
|
||||
result = 31 * result + (int) key;
|
||||
result = 31 * result + (additionalInfo != null ? additionalInfo.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
125
DataStructures/Heaps/MaxHeap.java
Normal file
125
DataStructures/Heaps/MaxHeap.java
Normal file
@ -0,0 +1,125 @@
|
||||
package DataStructures.Heaps;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Heap tree where a node's key is higher than or equal to its parent's and lower than or equal to
|
||||
* its children's.
|
||||
*
|
||||
* @author Nicolas Renard
|
||||
*/
|
||||
public class MaxHeap implements Heap {
|
||||
|
||||
private final List<HeapElement> maxHeap;
|
||||
|
||||
public MaxHeap(List<HeapElement> listElements) {
|
||||
maxHeap = new ArrayList<>();
|
||||
for (HeapElement heapElement : listElements) {
|
||||
if (heapElement != null) insertElement(heapElement);
|
||||
else System.out.println("Null element. Not added to heap");
|
||||
}
|
||||
if (maxHeap.size() == 0) System.out.println("No element has been added, empty heap.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element at a given index. The key for the list is equal to index value - 1
|
||||
*
|
||||
* @param elementIndex index
|
||||
* @return heapElement
|
||||
*/
|
||||
public HeapElement getElement(int elementIndex) {
|
||||
if ((elementIndex <= 0) || (elementIndex > maxHeap.size()))
|
||||
throw new IndexOutOfBoundsException("Index out of heap range");
|
||||
return maxHeap.get(elementIndex - 1);
|
||||
}
|
||||
|
||||
// Get the key of the element at a given index
|
||||
private double getElementKey(int elementIndex) {
|
||||
return maxHeap.get(elementIndex - 1).getKey();
|
||||
}
|
||||
|
||||
// Swaps two elements in the heap
|
||||
private void swap(int index1, int index2) {
|
||||
HeapElement temporaryElement = maxHeap.get(index1 - 1);
|
||||
maxHeap.set(index1 - 1, maxHeap.get(index2 - 1));
|
||||
maxHeap.set(index2 - 1, temporaryElement);
|
||||
}
|
||||
|
||||
// Toggle an element up to its right place as long as its key is lower than its parent's
|
||||
private void toggleUp(int elementIndex) {
|
||||
double key = maxHeap.get(elementIndex - 1).getKey();
|
||||
while (getElementKey((int) Math.floor(elementIndex / 2.0)) < key) {
|
||||
swap(elementIndex, (int) Math.floor(elementIndex / 2.0));
|
||||
elementIndex = (int) Math.floor(elementIndex / 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle an element down to its right place as long as its key is higher
|
||||
// than any of its children's
|
||||
private void toggleDown(int elementIndex) {
|
||||
double key = maxHeap.get(elementIndex - 1).getKey();
|
||||
boolean wrongOrder =
|
||||
(key < getElementKey(elementIndex * 2))
|
||||
|| (key < getElementKey(Math.min(elementIndex * 2, maxHeap.size())));
|
||||
while ((2 * elementIndex <= maxHeap.size()) && wrongOrder) {
|
||||
// Check whether it shall swap the element with its left child or its right one if any.
|
||||
if ((2 * elementIndex < maxHeap.size())
|
||||
&& (getElementKey(elementIndex * 2 + 1) > getElementKey(elementIndex * 2))) {
|
||||
swap(elementIndex, 2 * elementIndex + 1);
|
||||
elementIndex = 2 * elementIndex + 1;
|
||||
} else {
|
||||
swap(elementIndex, 2 * elementIndex);
|
||||
elementIndex = 2 * elementIndex;
|
||||
}
|
||||
wrongOrder =
|
||||
(key < getElementKey(elementIndex * 2))
|
||||
|| (key < getElementKey(Math.min(elementIndex * 2, maxHeap.size())));
|
||||
}
|
||||
}
|
||||
|
||||
private HeapElement extractMax() {
|
||||
HeapElement result = maxHeap.get(0);
|
||||
deleteElement(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertElement(HeapElement element) {
|
||||
maxHeap.add(element);
|
||||
toggleUp(maxHeap.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteElement(int elementIndex) {
|
||||
if (maxHeap.isEmpty())
|
||||
try {
|
||||
throw new EmptyHeapException("Attempt to delete an element from an empty heap");
|
||||
} catch (EmptyHeapException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if ((elementIndex > maxHeap.size()) || (elementIndex <= 0))
|
||||
throw new IndexOutOfBoundsException("Index out of heap range");
|
||||
// The last element in heap replaces the one to be deleted
|
||||
maxHeap.set(elementIndex - 1, getElement(maxHeap.size()));
|
||||
maxHeap.remove(maxHeap.size());
|
||||
// Shall the new element be moved up...
|
||||
if (getElementKey(elementIndex) > getElementKey((int) Math.floor(elementIndex / 2.0)))
|
||||
toggleUp(elementIndex);
|
||||
// ... or down ?
|
||||
else if (((2 * elementIndex <= maxHeap.size())
|
||||
&& (getElementKey(elementIndex) < getElementKey(elementIndex * 2)))
|
||||
|| ((2 * elementIndex < maxHeap.size())
|
||||
&& (getElementKey(elementIndex) < getElementKey(elementIndex * 2))))
|
||||
toggleDown(elementIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeapElement getElement() throws EmptyHeapException {
|
||||
try {
|
||||
return extractMax();
|
||||
} catch (Exception e) {
|
||||
throw new EmptyHeapException("Heap is empty. Error retrieving element");
|
||||
}
|
||||
}
|
||||
}
|
120
DataStructures/Heaps/MinHeap.java
Normal file
120
DataStructures/Heaps/MinHeap.java
Normal file
@ -0,0 +1,120 @@
|
||||
package DataStructures.Heaps;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Heap tree where a node's key is higher than or equal to its parent's and lower than or equal to
|
||||
* its children's.
|
||||
*
|
||||
* @author Nicolas Renard
|
||||
*/
|
||||
public class MinHeap implements Heap {
|
||||
|
||||
private final List<HeapElement> minHeap;
|
||||
|
||||
public MinHeap(List<HeapElement> listElements) {
|
||||
minHeap = new ArrayList<>();
|
||||
for (HeapElement heapElement : listElements) {
|
||||
if (heapElement != null) insertElement(heapElement);
|
||||
else System.out.println("Null element. Not added to heap");
|
||||
}
|
||||
if (minHeap.size() == 0) System.out.println("No element has been added, empty heap.");
|
||||
}
|
||||
|
||||
// Get the element at a given index. The key for the list is equal to index value - 1
|
||||
public HeapElement getElement(int elementIndex) {
|
||||
if ((elementIndex <= 0) || (elementIndex > minHeap.size()))
|
||||
throw new IndexOutOfBoundsException("Index out of heap range");
|
||||
return minHeap.get(elementIndex - 1);
|
||||
}
|
||||
|
||||
// Get the key of the element at a given index
|
||||
private double getElementKey(int elementIndex) {
|
||||
return minHeap.get(elementIndex - 1).getKey();
|
||||
}
|
||||
|
||||
// Swaps two elements in the heap
|
||||
private void swap(int index1, int index2) {
|
||||
HeapElement temporaryElement = minHeap.get(index1 - 1);
|
||||
minHeap.set(index1 - 1, minHeap.get(index2 - 1));
|
||||
minHeap.set(index2 - 1, temporaryElement);
|
||||
}
|
||||
|
||||
// Toggle an element up to its right place as long as its key is lower than its parent's
|
||||
private void toggleUp(int elementIndex) {
|
||||
double key = minHeap.get(elementIndex - 1).getKey();
|
||||
while (getElementKey((int) Math.floor(elementIndex / 2.0)) > key) {
|
||||
swap(elementIndex, (int) Math.floor(elementIndex / 2.0));
|
||||
elementIndex = (int) Math.floor(elementIndex / 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle an element down to its right place as long as its key is higher
|
||||
// than any of its children's
|
||||
private void toggleDown(int elementIndex) {
|
||||
double key = minHeap.get(elementIndex - 1).getKey();
|
||||
boolean wrongOrder =
|
||||
(key > getElementKey(elementIndex * 2))
|
||||
|| (key > getElementKey(Math.min(elementIndex * 2, minHeap.size())));
|
||||
while ((2 * elementIndex <= minHeap.size()) && wrongOrder) {
|
||||
// Check whether it shall swap the element with its left child or its right one if any.
|
||||
if ((2 * elementIndex < minHeap.size())
|
||||
&& (getElementKey(elementIndex * 2 + 1) < getElementKey(elementIndex * 2))) {
|
||||
swap(elementIndex, 2 * elementIndex + 1);
|
||||
elementIndex = 2 * elementIndex + 1;
|
||||
} else {
|
||||
swap(elementIndex, 2 * elementIndex);
|
||||
elementIndex = 2 * elementIndex;
|
||||
}
|
||||
wrongOrder =
|
||||
(key > getElementKey(elementIndex * 2))
|
||||
|| (key > getElementKey(Math.min(elementIndex * 2, minHeap.size())));
|
||||
}
|
||||
}
|
||||
|
||||
private HeapElement extractMin() {
|
||||
HeapElement result = minHeap.get(0);
|
||||
deleteElement(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertElement(HeapElement element) {
|
||||
minHeap.add(element);
|
||||
toggleUp(minHeap.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteElement(int elementIndex) {
|
||||
if (minHeap.isEmpty())
|
||||
try {
|
||||
throw new EmptyHeapException("Attempt to delete an element from an empty heap");
|
||||
} catch (EmptyHeapException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if ((elementIndex > minHeap.size()) || (elementIndex <= 0))
|
||||
throw new IndexOutOfBoundsException("Index out of heap range");
|
||||
// The last element in heap replaces the one to be deleted
|
||||
minHeap.set(elementIndex - 1, getElement(minHeap.size()));
|
||||
minHeap.remove(minHeap.size());
|
||||
// Shall the new element be moved up...
|
||||
if (getElementKey(elementIndex) < getElementKey((int) Math.floor(elementIndex / 2.0)))
|
||||
toggleUp(elementIndex);
|
||||
// ... or down ?
|
||||
else if (((2 * elementIndex <= minHeap.size())
|
||||
&& (getElementKey(elementIndex) > getElementKey(elementIndex * 2)))
|
||||
|| ((2 * elementIndex < minHeap.size())
|
||||
&& (getElementKey(elementIndex) > getElementKey(elementIndex * 2))))
|
||||
toggleDown(elementIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeapElement getElement() throws EmptyHeapException {
|
||||
try {
|
||||
return extractMin();
|
||||
} catch (Exception e) {
|
||||
throw new EmptyHeapException("Heap is empty. Error retrieving element");
|
||||
}
|
||||
}
|
||||
}
|
125
DataStructures/Heaps/MinPriorityQueue.java
Normal file
125
DataStructures/Heaps/MinPriorityQueue.java
Normal file
@ -0,0 +1,125 @@
|
||||
package DataStructures.Heaps;
|
||||
|
||||
/**
|
||||
* Minimum Priority Queue It is a part of heap data structure A heap is a specific tree based data
|
||||
* structure in which all the nodes of tree are in a specific order. that is the children are
|
||||
* arranged in some respect of their parents, can either be greater or less than the parent. This
|
||||
* makes it a min priority queue or max priority queue.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* <p>Functions: insert, delete, peek, isEmpty, print, heapSort, sink
|
||||
*/
|
||||
public class MinPriorityQueue {
|
||||
private int[] heap;
|
||||
private int capacity;
|
||||
private int size;
|
||||
|
||||
// calss the constructor and initializes the capacity
|
||||
MinPriorityQueue(int c) {
|
||||
this.capacity = c;
|
||||
this.size = 0;
|
||||
this.heap = new int[c + 1];
|
||||
}
|
||||
|
||||
// inserts the key at the end and rearranges it
|
||||
// so that the binary heap is in appropriate order
|
||||
public void insert(int key) {
|
||||
if (this.isFull()) return;
|
||||
this.heap[this.size + 1] = key;
|
||||
int k = this.size + 1;
|
||||
while (k > 1) {
|
||||
if (this.heap[k] < this.heap[k / 2]) {
|
||||
int temp = this.heap[k];
|
||||
this.heap[k] = this.heap[k / 2];
|
||||
this.heap[k / 2] = temp;
|
||||
}
|
||||
k = k / 2;
|
||||
}
|
||||
this.size++;
|
||||
}
|
||||
|
||||
// returns the highest priority value
|
||||
public int peek() {
|
||||
return this.heap[1];
|
||||
}
|
||||
|
||||
// returns boolean value whether the heap is empty or not
|
||||
public boolean isEmpty() {
|
||||
if (0 == this.size) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// returns boolean value whether the heap is full or not
|
||||
public boolean isFull() {
|
||||
if (this.size == this.capacity) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// prints the heap
|
||||
public void print() {
|
||||
for (int i = 1; i <= this.capacity; i++) System.out.print(this.heap[i] + " ");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
// heap sorting can be done by performing
|
||||
// delete function to the number of times of the size of the heap
|
||||
// it returns reverse sort because it is a min priority queue
|
||||
public void heapSort() {
|
||||
for (int i = 1; i < this.capacity; i++) this.delete();
|
||||
}
|
||||
|
||||
// this function reorders the heap after every delete function
|
||||
private void sink() {
|
||||
int k = 1;
|
||||
while (2 * k <= this.size || 2 * k + 1 <= this.size) {
|
||||
int minIndex;
|
||||
if (this.heap[2 * k] >= this.heap[k]) {
|
||||
if (2 * k + 1 <= this.size && this.heap[2 * k + 1] >= this.heap[k]) {
|
||||
break;
|
||||
} else if (2 * k + 1 > this.size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (2 * k + 1 > this.size) {
|
||||
minIndex = this.heap[2 * k] < this.heap[k] ? 2 * k : k;
|
||||
} else {
|
||||
if (this.heap[k] > this.heap[2 * k] || this.heap[k] > this.heap[2 * k + 1]) {
|
||||
minIndex = this.heap[2 * k] < this.heap[2 * k + 1] ? 2 * k : 2 * k + 1;
|
||||
} else {
|
||||
minIndex = k;
|
||||
}
|
||||
}
|
||||
int temp = this.heap[k];
|
||||
this.heap[k] = this.heap[minIndex];
|
||||
this.heap[minIndex] = temp;
|
||||
k = minIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// deletes the highest priority value from the heap
|
||||
public int delete() {
|
||||
int min = this.heap[1];
|
||||
this.heap[1] = this.heap[this.size];
|
||||
this.heap[this.size] = min;
|
||||
this.size--;
|
||||
this.sink();
|
||||
return min;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// testing
|
||||
MinPriorityQueue q = new MinPriorityQueue(8);
|
||||
q.insert(5);
|
||||
q.insert(2);
|
||||
q.insert(4);
|
||||
q.insert(1);
|
||||
q.insert(7);
|
||||
q.insert(6);
|
||||
q.insert(3);
|
||||
q.insert(8);
|
||||
q.print(); // [ 1, 2, 3, 5, 7, 6, 4, 8 ]
|
||||
q.heapSort();
|
||||
q.print(); // [ 8, 7, 6, 5, 4, 3, 2, 1 ]
|
||||
}
|
||||
}
|
65
DataStructures/Lists/CircleLinkedList.java
Normal file
65
DataStructures/Lists/CircleLinkedList.java
Normal file
@ -0,0 +1,65 @@
|
||||
package DataStructures.Lists;
|
||||
|
||||
public class CircleLinkedList<E> {
|
||||
private static class Node<E> {
|
||||
Node<E> next;
|
||||
E value;
|
||||
|
||||
private Node(E value, Node<E> next) {
|
||||
this.value = value;
|
||||
this.next = next;
|
||||
}
|
||||
}
|
||||
|
||||
// For better O.O design this should be private allows for better black box design
|
||||
private int size;
|
||||
// this will point to dummy node;
|
||||
private Node<E> head = null;
|
||||
|
||||
// constructer for class.. here we will make a dummy node for circly linked list implementation
|
||||
// with reduced error catching as our list will never be empty;
|
||||
public CircleLinkedList() {
|
||||
// creation of the dummy node
|
||||
head = new Node<E>(null, head);
|
||||
size = 0;
|
||||
}
|
||||
|
||||
// getter for the size... needed because size is private.
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
// for the sake of simplistiy this class will only contain the append function or addLast other
|
||||
// add functions can be implemented however this is the basses of them all really.
|
||||
public void append(E value) {
|
||||
if (value == null) {
|
||||
// we do not want to add null elements to the list.
|
||||
throw new NullPointerException("Cannot add null element to the list");
|
||||
}
|
||||
// head.next points to the last element;
|
||||
head.next = new Node<E>(value, head);
|
||||
size++;
|
||||
}
|
||||
|
||||
public E remove(int pos) {
|
||||
if (pos > size || pos < 0) {
|
||||
// catching errors
|
||||
throw new IndexOutOfBoundsException("position cannot be greater than size or negative");
|
||||
}
|
||||
// we need to keep track of the element before the element we want to remove we can see why
|
||||
// bellow.
|
||||
Node<E> before = head;
|
||||
for (int i = 1; i <= pos; i++) {
|
||||
before = before.next;
|
||||
}
|
||||
Node<E> destroy = before.next;
|
||||
E saved = destroy.value;
|
||||
// assigning the next reference to the the element following the element we want to remove...
|
||||
// the last element will be assigned to the head.
|
||||
before.next = before.next.next;
|
||||
// scrubbing
|
||||
destroy = null;
|
||||
size--;
|
||||
return saved;
|
||||
}
|
||||
}
|
26
DataStructures/Lists/CountSinglyLinkedListRecursion.java
Normal file
26
DataStructures/Lists/CountSinglyLinkedListRecursion.java
Normal file
@ -0,0 +1,26 @@
|
||||
package DataStructures.Lists;
|
||||
|
||||
public class CountSinglyLinkedListRecursion extends SinglyLinkedList {
|
||||
public static void main(String[] args) {
|
||||
CountSinglyLinkedListRecursion list = new CountSinglyLinkedListRecursion();
|
||||
for (int i = 1; i <= 5; ++i) {
|
||||
list.insert(i);
|
||||
}
|
||||
assert list.count() == 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the count of the list manually using recursion.
|
||||
*
|
||||
* @param head head of the list.
|
||||
* @return count of the list.
|
||||
*/
|
||||
private int countRecursion(Node head) {
|
||||
return head == null ? 0 : 1 + countRecursion(head.next);
|
||||
}
|
||||
/** Returns the count of the list. */
|
||||
@Override
|
||||
public int count() {
|
||||
return countRecursion(getHead());
|
||||
}
|
||||
}
|
188
DataStructures/Lists/CursorLinkedList.java
Normal file
188
DataStructures/Lists/CursorLinkedList.java
Normal file
@ -0,0 +1,188 @@
|
||||
package DataStructures.Lists;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class CursorLinkedList<T> {
|
||||
|
||||
private static class Node<T> {
|
||||
|
||||
T element;
|
||||
int next;
|
||||
|
||||
Node(T element, int next) {
|
||||
this.element = element;
|
||||
this.next = next;
|
||||
}
|
||||
}
|
||||
|
||||
private final int os;
|
||||
private int head;
|
||||
private final Node<T>[] cursorSpace;
|
||||
private int count;
|
||||
private static final int CURSOR_SPACE_SIZE = 100;
|
||||
|
||||
{
|
||||
// init at loading time
|
||||
cursorSpace = new Node[CURSOR_SPACE_SIZE];
|
||||
for (int i = 0; i < CURSOR_SPACE_SIZE; i++) {
|
||||
cursorSpace[i] = new Node<>(null, i + 1);
|
||||
}
|
||||
cursorSpace[CURSOR_SPACE_SIZE - 1].next = 0;
|
||||
}
|
||||
|
||||
public CursorLinkedList() {
|
||||
os = 0;
|
||||
count = 0;
|
||||
head = -1;
|
||||
}
|
||||
|
||||
public void printList() {
|
||||
|
||||
if (head != -1) {
|
||||
|
||||
int start = head;
|
||||
while (start != -1) {
|
||||
|
||||
T element = cursorSpace[start].element;
|
||||
System.out.println(element.toString());
|
||||
start = cursorSpace[start].next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the logical index of the element within the list , not the actual index of the
|
||||
* [cursorSpace] array
|
||||
*/
|
||||
public int indexOf(T element) {
|
||||
|
||||
Objects.requireNonNull(element);
|
||||
Node<T> iterator = cursorSpace[head];
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (iterator.element.equals(element)) {
|
||||
return i;
|
||||
}
|
||||
iterator = cursorSpace[iterator.next];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param position , the logical index of the element , not the actual one within the
|
||||
* [cursorSpace] array . this method should be used to get the index give by indexOf() method.
|
||||
* @return
|
||||
*/
|
||||
public T get(int position) {
|
||||
|
||||
if (position >= 0 && position < count) {
|
||||
|
||||
int start = head;
|
||||
int counter = 0;
|
||||
while (start != -1) {
|
||||
|
||||
T element = cursorSpace[start].element;
|
||||
if (counter == position) {
|
||||
return element;
|
||||
}
|
||||
|
||||
start = cursorSpace[start].next;
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void removeByIndex(int index) {
|
||||
|
||||
if (index >= 0 && index < count) {
|
||||
|
||||
T element = get(index);
|
||||
remove(element);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(T element) {
|
||||
|
||||
Objects.requireNonNull(element);
|
||||
|
||||
// case element is in the head
|
||||
T temp_element = cursorSpace[head].element;
|
||||
int temp_next = cursorSpace[head].next;
|
||||
if (temp_element.equals(element)) {
|
||||
free(head);
|
||||
head = temp_next;
|
||||
} else { // otherwise cases
|
||||
|
||||
int prev_index = head;
|
||||
int current_index = cursorSpace[prev_index].next;
|
||||
|
||||
while (current_index != -1) {
|
||||
|
||||
T current_element = cursorSpace[current_index].element;
|
||||
if (current_element.equals(element)) {
|
||||
cursorSpace[prev_index].next = cursorSpace[current_index].next;
|
||||
free(current_index);
|
||||
break;
|
||||
}
|
||||
|
||||
prev_index = current_index;
|
||||
current_index = cursorSpace[prev_index].next;
|
||||
}
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
|
||||
private void free(int index) {
|
||||
|
||||
Node os_node = cursorSpace[os];
|
||||
int os_next = os_node.next;
|
||||
cursorSpace[os].next = index;
|
||||
cursorSpace[index].element = null;
|
||||
cursorSpace[index].next = os_next;
|
||||
}
|
||||
|
||||
public void append(T element) {
|
||||
|
||||
Objects.requireNonNull(element);
|
||||
int availableIndex = alloc();
|
||||
cursorSpace[availableIndex].element = element;
|
||||
|
||||
if (head == -1) {
|
||||
head = availableIndex;
|
||||
}
|
||||
|
||||
int iterator = head;
|
||||
while (cursorSpace[iterator].next != -1) {
|
||||
iterator = cursorSpace[iterator].next;
|
||||
}
|
||||
|
||||
cursorSpace[iterator].next = availableIndex;
|
||||
cursorSpace[availableIndex].next = -1;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
/** @return the index of the next available node */
|
||||
private int alloc() {
|
||||
|
||||
// 1- get the index at which the os is pointing
|
||||
int availableNodeIndex = cursorSpace[os].next;
|
||||
|
||||
if (availableNodeIndex == 0) {
|
||||
throw new OutOfMemoryError();
|
||||
}
|
||||
|
||||
// 2- make the os point to the next of the @var{availableNodeIndex}
|
||||
int availableNext = cursorSpace[availableNodeIndex].next;
|
||||
cursorSpace[os].next = availableNext;
|
||||
|
||||
// this to indicate an end of the list , helpful at testing since any err
|
||||
// would throw an outOfBoundException
|
||||
cursorSpace[availableNodeIndex].next = -1;
|
||||
|
||||
return availableNodeIndex;
|
||||
}
|
||||
}
|
307
DataStructures/Lists/DoublyLinkedList.java
Normal file
307
DataStructures/Lists/DoublyLinkedList.java
Normal file
@ -0,0 +1,307 @@
|
||||
package DataStructures.Lists;
|
||||
|
||||
/**
|
||||
* This class implements a DoublyLinkedList. This is done using the classes LinkedList and Link.
|
||||
*
|
||||
* <p>A linked list is similar to an array, it holds values. However, links in a linked list do not
|
||||
* have indexes. With a linked list you do not need to predetermine it's size as it grows and
|
||||
* shrinks as it is edited. This is an example of a double ended, doubly linked list. Each link
|
||||
* references the next link and the previous one.
|
||||
*
|
||||
* @author Unknown
|
||||
*/
|
||||
public class DoublyLinkedList {
|
||||
/** Head refers to the front of the list */
|
||||
private Link head;
|
||||
/** Tail refers to the back of the list */
|
||||
private Link tail;
|
||||
|
||||
/** Size refers to the number of elements present in the list */
|
||||
private int size;
|
||||
|
||||
/** Default Constructor */
|
||||
public DoublyLinkedList() {
|
||||
head = null;
|
||||
tail = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a list containing the elements of the array
|
||||
*
|
||||
* @param array the array whose elements are to be placed into this list
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
*/
|
||||
public DoublyLinkedList(int[] array) {
|
||||
if (array == null) throw new NullPointerException();
|
||||
for (int i : array) {
|
||||
insertTail(i);
|
||||
}
|
||||
size = array.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an element at the head
|
||||
*
|
||||
* @param x Element to be inserted
|
||||
*/
|
||||
public void insertHead(int x) {
|
||||
Link newLink = new Link(x); // Create a new link with a value attached to it
|
||||
if (isEmpty()) // Set the first element added to be the tail
|
||||
tail = newLink;
|
||||
else head.previous = newLink; // newLink <-- currenthead(head)
|
||||
newLink.next = head; // newLink <--> currenthead(head)
|
||||
head = newLink; // newLink(head) <--> oldhead
|
||||
++size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an element at the tail
|
||||
*
|
||||
* @param x Element to be inserted
|
||||
*/
|
||||
public void insertTail(int x) {
|
||||
Link newLink = new Link(x);
|
||||
newLink.next = null; // currentTail(tail) newlink -->
|
||||
if (isEmpty()) { // Check if there are no elements in list then it adds first element
|
||||
tail = newLink;
|
||||
head = tail;
|
||||
} else {
|
||||
tail.next = newLink; // currentTail(tail) --> newLink -->
|
||||
newLink.previous = tail; // currentTail(tail) <--> newLink -->
|
||||
tail = newLink; // oldTail <--> newLink(tail) -->
|
||||
}
|
||||
++size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an element at the index
|
||||
*
|
||||
* @param x Element to be inserted
|
||||
* @param index Index(from start) at which the element x to be inserted
|
||||
*/
|
||||
public void insertElementByIndex(int x, int index) {
|
||||
if (index > size) throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
|
||||
if (index == 0) {
|
||||
insertHead(x);
|
||||
} else {
|
||||
if (index == size) {
|
||||
insertTail(x);
|
||||
} else {
|
||||
Link newLink = new Link(x);
|
||||
Link previousLink = head; //
|
||||
for (int i = 1; i < index; i++) { // Loop to reach the index
|
||||
previousLink = previousLink.next;
|
||||
}
|
||||
// previousLink is the Link at index - 1 from start
|
||||
previousLink.next.previous = newLink;
|
||||
newLink.next = previousLink.next;
|
||||
newLink.previous = previousLink;
|
||||
previousLink.next = newLink;
|
||||
}
|
||||
}
|
||||
++size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the element at the head
|
||||
*
|
||||
* @return The new head
|
||||
*/
|
||||
public Link deleteHead() {
|
||||
Link temp = head;
|
||||
head = head.next; // oldHead <--> 2ndElement(head)
|
||||
|
||||
if (head == null) {
|
||||
tail = null;
|
||||
} else {
|
||||
head.previous =
|
||||
null; // oldHead --> 2ndElement(head) nothing pointing at old head so will be removed
|
||||
}
|
||||
--size;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the element at the tail
|
||||
*
|
||||
* @return The new tail
|
||||
*/
|
||||
public Link deleteTail() {
|
||||
Link temp = tail;
|
||||
tail = tail.previous; // 2ndLast(tail) <--> oldTail --> null
|
||||
|
||||
if (tail == null) {
|
||||
head = null;
|
||||
} else {
|
||||
tail.next = null; // 2ndLast(tail) --> null
|
||||
}
|
||||
--size;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the element from somewhere in the list
|
||||
*
|
||||
* @param x element to be deleted
|
||||
* @return Link deleted
|
||||
*/
|
||||
public void delete(int x) {
|
||||
Link current = head;
|
||||
|
||||
while (current.value != x) { // Find the position to delete
|
||||
if (current != tail) {
|
||||
current = current.next;
|
||||
} else { // If we reach the tail and the element is still not found
|
||||
throw new RuntimeException("The element to be deleted does not exist!");
|
||||
}
|
||||
}
|
||||
|
||||
if (current == head) deleteHead();
|
||||
else if (current == tail) deleteTail();
|
||||
else { // Before: 1 <--> 2(current) <--> 3
|
||||
current.previous.next = current.next; // 1 --> 3
|
||||
current.next.previous = current.previous; // 1 <--> 3
|
||||
}
|
||||
--size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts element and reorders
|
||||
*
|
||||
* @param x Element to be added
|
||||
*/
|
||||
public void insertOrdered(int x) {
|
||||
Link newLink = new Link(x);
|
||||
Link current = head;
|
||||
while (current != null && x > current.value) // Find the position to insert
|
||||
current = current.next;
|
||||
|
||||
if (current == head) insertHead(x);
|
||||
else if (current == null) insertTail(x);
|
||||
else { // Before: 1 <--> 2(current) <--> 3
|
||||
newLink.previous = current.previous; // 1 <-- newLink
|
||||
current.previous.next = newLink; // 1 <--> newLink
|
||||
newLink.next = current; // 1 <--> newLink --> 2(current) <--> 3
|
||||
current.previous = newLink; // 1 <--> newLink <--> 2(current) <--> 3
|
||||
}
|
||||
++size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the passed node from the current list
|
||||
*
|
||||
* @param z Element to be deleted
|
||||
*/
|
||||
public void deleteNode(Link z) {
|
||||
if (z.next == null) {
|
||||
deleteTail();
|
||||
} else if (z == head) {
|
||||
deleteHead();
|
||||
} else { // before <-- 1 <--> 2(z) <--> 3 -->
|
||||
z.previous.next = z.next; // 1 --> 3
|
||||
z.next.previous = z.previous; // 1 <--> 3
|
||||
}
|
||||
--size;
|
||||
}
|
||||
|
||||
public static void removeDuplicates(DoublyLinkedList l) {
|
||||
Link linkOne = l.head;
|
||||
while (linkOne.next != null) { // list is present
|
||||
Link linkTwo = linkOne.next; // second link for comparison
|
||||
while (linkTwo.next != null) {
|
||||
if (linkOne.value == linkTwo.value) // if there are duplicates values then
|
||||
l.delete(linkTwo.value); // delete the link
|
||||
linkTwo = linkTwo.next; // go to next link
|
||||
}
|
||||
linkOne = linkOne.next; // go to link link to iterate the whole list again
|
||||
}
|
||||
}
|
||||
|
||||
/** Clears List */
|
||||
public void clearList() {
|
||||
head = null;
|
||||
tail = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if list is empty
|
||||
*
|
||||
* @return true if list is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (head == null);
|
||||
}
|
||||
|
||||
/** Prints contents of the list */
|
||||
public void display() { // Prints contents of the list
|
||||
Link current = head;
|
||||
while (current != null) {
|
||||
current.displayLink();
|
||||
current = current.next;
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used to implement the nodes of the linked list.
|
||||
*
|
||||
* @author Unknown
|
||||
*/
|
||||
class Link {
|
||||
/** Value of node */
|
||||
public int value;
|
||||
/** This points to the link in front of the new link */
|
||||
public Link next;
|
||||
/** This points to the link behind the new link */
|
||||
public Link previous;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param value Value of node
|
||||
*/
|
||||
public Link(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/** Displays the node */
|
||||
public void displayLink() {
|
||||
System.out.print(value + " ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Main Method
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
DoublyLinkedList myList = new DoublyLinkedList();
|
||||
myList.insertHead(13);
|
||||
myList.insertHead(7);
|
||||
myList.insertHead(10);
|
||||
myList.display(); // <-- 10(head) <--> 7 <--> 13(tail) -->
|
||||
|
||||
myList.insertTail(11);
|
||||
myList.display(); // <-- 10(head) <--> 7 <--> 13 <--> 11(tail) -->
|
||||
|
||||
myList.deleteTail();
|
||||
myList.display(); // <-- 10(head) <--> 7 <--> 13(tail) -->
|
||||
|
||||
myList.delete(7);
|
||||
myList.display(); // <-- 10(head) <--> 13(tail) -->
|
||||
|
||||
myList.insertOrdered(23);
|
||||
myList.insertOrdered(67);
|
||||
myList.insertOrdered(3);
|
||||
myList.display(); // <-- 3(head) <--> 10 <--> 13 <--> 23 <--> 67(tail) -->
|
||||
myList.insertElementByIndex(5, 1);
|
||||
myList.display(); // <-- 3(head) <--> 5 <--> 10 <--> 13 <--> 23 <--> 67(tail) -->
|
||||
myList.clearList();
|
||||
myList.display();
|
||||
myList.insertHead(20);
|
||||
myList.display();
|
||||
}
|
||||
}
|
56
DataStructures/Lists/MergeSortedArrayList.java
Normal file
56
DataStructures/Lists/MergeSortedArrayList.java
Normal file
@ -0,0 +1,56 @@
|
||||
package DataStructures.Lists;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** @author https://github.com/shellhub */
|
||||
public class MergeSortedArrayList {
|
||||
public static void main(String[] args) {
|
||||
List<Integer> listA = new ArrayList<>();
|
||||
List<Integer> listB = new ArrayList<>();
|
||||
List<Integer> listC = new ArrayList<>();
|
||||
|
||||
/* init ListA and List B */
|
||||
for (int i = 1; i <= 10; i += 2) {
|
||||
listA.add(i); /* listA: [1, 3, 5, 7, 9] */
|
||||
listB.add(i + 1); /* listB: [2, 4, 6, 8, 10] */
|
||||
}
|
||||
|
||||
/* merge listA and listB to listC */
|
||||
merge(listA, listB, listC);
|
||||
|
||||
System.out.println("listA: " + listA);
|
||||
System.out.println("listB: " + listB);
|
||||
System.out.println("listC: " + listC);
|
||||
}
|
||||
|
||||
/**
|
||||
* merge two sorted ArrayList
|
||||
*
|
||||
* @param listA the first list to merge
|
||||
* @param listB the second list to merge
|
||||
* @param listC the result list after merging
|
||||
*/
|
||||
public static void merge(List<Integer> listA, List<Integer> listB, List<Integer> listC) {
|
||||
int pa = 0; /* the index of listA */
|
||||
int pb = 0; /* the index of listB */
|
||||
|
||||
while (pa < listA.size() && pb < listB.size()) {
|
||||
if (listA.get(pa) <= listB.get(pb)) {
|
||||
listC.add(listA.get(pa++));
|
||||
} else {
|
||||
listC.add(listB.get(pb++));
|
||||
}
|
||||
}
|
||||
|
||||
/* copy left element of listA to listC */
|
||||
while (pa < listA.size()) {
|
||||
listC.add(listA.get(pa++));
|
||||
}
|
||||
|
||||
/* copy left element of listB to listC */
|
||||
while (pb < listB.size()) {
|
||||
listC.add(listB.get(pb++));
|
||||
}
|
||||
}
|
||||
}
|
51
DataStructures/Lists/MergeSortedSinglyLinkedList.java
Normal file
51
DataStructures/Lists/MergeSortedSinglyLinkedList.java
Normal file
@ -0,0 +1,51 @@
|
||||
package DataStructures.Lists;
|
||||
|
||||
public class MergeSortedSinglyLinkedList extends SinglyLinkedList {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SinglyLinkedList listA = new SinglyLinkedList();
|
||||
SinglyLinkedList listB = new SinglyLinkedList();
|
||||
|
||||
for (int i = 2; i <= 10; i += 2) {
|
||||
listA.insert(i);
|
||||
listB.insert(i - 1);
|
||||
}
|
||||
assert listA.toString().equals("2->4->6->8->10");
|
||||
assert listB.toString().equals("1->3->5->7->9");
|
||||
assert merge(listA, listB).toString().equals("1->2->3->4->5->6->7->8->9->10");
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two sorted SingleLinkedList
|
||||
*
|
||||
* @param listA the first sorted list
|
||||
* @param listB the second sored list
|
||||
* @return merged sorted list
|
||||
*/
|
||||
public static SinglyLinkedList merge(SinglyLinkedList listA, SinglyLinkedList listB) {
|
||||
Node headA = listA.getHead();
|
||||
Node headB = listB.getHead();
|
||||
|
||||
int size = listA.size() + listB.size();
|
||||
|
||||
Node head = new Node();
|
||||
Node tail = head;
|
||||
while (headA != null && headB != null) {
|
||||
if (headA.value <= headB.value) {
|
||||
tail.next = headA;
|
||||
headA = headA.next;
|
||||
} else {
|
||||
tail.next = headB;
|
||||
headB = headB.next;
|
||||
}
|
||||
tail = tail.next;
|
||||
}
|
||||
if (headA == null) {
|
||||
tail.next = headB;
|
||||
}
|
||||
if (headB == null) {
|
||||
tail.next = headA;
|
||||
}
|
||||
return new SinglyLinkedList(head.next, size);
|
||||
}
|
||||
}
|
54
DataStructures/Lists/Merge_K_SortedLinkedlist.java
Normal file
54
DataStructures/Lists/Merge_K_SortedLinkedlist.java
Normal file
@ -0,0 +1,54 @@
|
||||
package DataStructures.Lists;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
/** @author Arun Pandey (https://github.com/pandeyarun709) */
|
||||
public class Merge_K_SortedLinkedlist {
|
||||
|
||||
/**
|
||||
* This function merge K sorted LinkedList
|
||||
*
|
||||
* @param a array of LinkedList
|
||||
* @param N size of array
|
||||
* @return node
|
||||
*/
|
||||
Node mergeKList(Node[] a, int N) {
|
||||
// Min Heap
|
||||
PriorityQueue<Node> min = new PriorityQueue<>(Comparator.comparingInt(x -> x.data));
|
||||
|
||||
// adding head of all linkedList in min heap
|
||||
min.addAll(Arrays.asList(a).subList(0, N));
|
||||
|
||||
// Make new head among smallest heads in K linkedList
|
||||
Node head = min.poll();
|
||||
min.add(head.next);
|
||||
Node curr = head;
|
||||
|
||||
// merging LinkedList
|
||||
while (!min.isEmpty()) {
|
||||
|
||||
Node temp = min.poll();
|
||||
curr.next = temp;
|
||||
curr = temp;
|
||||
|
||||
// Add Node in min Heap only if temp.next is not null
|
||||
if (temp.next != null) {
|
||||
min.add(temp.next);
|
||||
}
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
private class Node {
|
||||
private int data;
|
||||
private Node next;
|
||||
|
||||
public Node(int d) {
|
||||
this.data = d;
|
||||
next = null;
|
||||
}
|
||||
}
|
||||
}
|
31
DataStructures/Lists/SearchSinglyLinkedListRecursion.java
Normal file
31
DataStructures/Lists/SearchSinglyLinkedListRecursion.java
Normal file
@ -0,0 +1,31 @@
|
||||
package DataStructures.Lists;
|
||||
|
||||
public class SearchSinglyLinkedListRecursion extends SinglyLinkedList {
|
||||
public static void main(String[] args) {
|
||||
SearchSinglyLinkedListRecursion list = new SearchSinglyLinkedListRecursion();
|
||||
for (int i = 1; i <= 10; ++i) {
|
||||
list.insert(i);
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 10; ++i) {
|
||||
assert list.search(i);
|
||||
}
|
||||
assert !list.search(-1) && !list.search(100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the value key is present in the list using recursion.
|
||||
*
|
||||
* @param node the head node.
|
||||
* @param key the value to be searched.
|
||||
* @return {@code true} if key is present in the list, otherwise {@code false}.
|
||||
*/
|
||||
private boolean searchRecursion(Node node, int key) {
|
||||
return node != null && (node.value == key || searchRecursion(node.next, key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean search(int key) {
|
||||
return searchRecursion(getHead(), key);
|
||||
}
|
||||
}
|
292
DataStructures/Lists/SinglyLinkedList.java
Normal file
292
DataStructures/Lists/SinglyLinkedList.java
Normal file
@ -0,0 +1,292 @@
|
||||
package DataStructures.Lists;
|
||||
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/** https://en.wikipedia.org/wiki/Linked_list */
|
||||
public class SinglyLinkedList {
|
||||
/** Head refer to the front of the list */
|
||||
private Node head;
|
||||
|
||||
/** Size of SinglyLinkedList */
|
||||
private int size;
|
||||
|
||||
/** Init SinglyLinkedList */
|
||||
public SinglyLinkedList() {
|
||||
head = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init SinglyLinkedList with specified head node and size
|
||||
*
|
||||
* @param head the head node of list
|
||||
* @param size the size of list
|
||||
*/
|
||||
public SinglyLinkedList(Node head, int size) {
|
||||
this.head = head;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an element at the head of the list
|
||||
*
|
||||
* @param x element to be added
|
||||
*/
|
||||
public void insertHead(int x) {
|
||||
insertNth(x, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an element at the tail of the list
|
||||
*
|
||||
* @param data element to be added
|
||||
*/
|
||||
public void insert(int data) {
|
||||
insertNth(data, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new node at a specified position of the list
|
||||
*
|
||||
* @param data data to be stored in a new node
|
||||
* @param position position at which a new node is to be inserted
|
||||
*/
|
||||
public void insertNth(int data, int position) {
|
||||
checkBounds(position, 0, size);
|
||||
Node newNode = new Node(data);
|
||||
if (head == null) {
|
||||
/* the list is empty */
|
||||
head = newNode;
|
||||
size++;
|
||||
return;
|
||||
} else if (position == 0) {
|
||||
/* insert at the head of the list */
|
||||
newNode.next = head;
|
||||
head = newNode;
|
||||
size++;
|
||||
return;
|
||||
}
|
||||
Node cur = head;
|
||||
for (int i = 0; i < position - 1; ++i) {
|
||||
cur = cur.next;
|
||||
}
|
||||
newNode.next = cur.next;
|
||||
cur.next = newNode;
|
||||
size++;
|
||||
}
|
||||
|
||||
/** Deletes a node at the head */
|
||||
public void deleteHead() {
|
||||
deleteNth(0);
|
||||
}
|
||||
|
||||
/** Deletes an element at the tail */
|
||||
public void delete() {
|
||||
deleteNth(size - 1);
|
||||
}
|
||||
|
||||
/** Deletes an element at Nth position */
|
||||
public void deleteNth(int position) {
|
||||
checkBounds(position, 0, size - 1);
|
||||
if (position == 0) {
|
||||
Node destroy = head;
|
||||
head = head.next;
|
||||
destroy = null; /* clear to let GC do its work */
|
||||
size--;
|
||||
return;
|
||||
}
|
||||
Node cur = head;
|
||||
for (int i = 0; i < position - 1; ++i) {
|
||||
cur = cur.next;
|
||||
}
|
||||
|
||||
Node destroy = cur.next;
|
||||
cur.next = cur.next.next;
|
||||
destroy = null; // clear to let GC do its work
|
||||
|
||||
size--;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param position to check position
|
||||
* @param low low index
|
||||
* @param high high index
|
||||
* @throws IndexOutOfBoundsException if {@code position} not in range {@code low} to {@code high}
|
||||
*/
|
||||
public void checkBounds(int position, int low, int high) {
|
||||
if (position > high || position < low) {
|
||||
throw new IndexOutOfBoundsException(position + "");
|
||||
}
|
||||
}
|
||||
|
||||
/** Clear all nodes in the list */
|
||||
public void clear() {
|
||||
Node cur = head;
|
||||
while (cur != null) {
|
||||
Node prev = cur;
|
||||
cur = cur.next;
|
||||
prev = null; // clear to let GC do its work
|
||||
}
|
||||
head = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the list is empty
|
||||
*
|
||||
* @return {@code true} if list is empty, otherwise {@code false}.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the linked list.
|
||||
*
|
||||
* @return the size of the list.
|
||||
*/
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get head of the list.
|
||||
*
|
||||
* @return head of the list.
|
||||
*/
|
||||
public Node getHead() {
|
||||
return head;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the count of the list manually
|
||||
*
|
||||
* @return count of the list
|
||||
*/
|
||||
public int count() {
|
||||
int count = 0;
|
||||
Node cur = head;
|
||||
while (cur != null) {
|
||||
cur = cur.next;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the value key is present in the list.
|
||||
*
|
||||
* @param key the value to be searched.
|
||||
* @return {@code true} if key is present in the list, otherwise {@code false}.
|
||||
*/
|
||||
public boolean search(int key) {
|
||||
Node cur = head;
|
||||
while (cur != null) {
|
||||
if (cur.value == key) {
|
||||
return true;
|
||||
}
|
||||
cur = cur.next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return element at special index.
|
||||
*
|
||||
* @param index given index of element
|
||||
* @return element at special index.
|
||||
*/
|
||||
public int getNth(int index) {
|
||||
checkBounds(index, 0, size - 1);
|
||||
Node cur = head;
|
||||
for (int i = 0; i < index; ++i) {
|
||||
cur = cur.next;
|
||||
}
|
||||
return cur.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringJoiner joiner = new StringJoiner("->");
|
||||
Node cur = head;
|
||||
while (cur != null) {
|
||||
joiner.add(cur.value + "");
|
||||
cur = cur.next;
|
||||
}
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
/** Driver Code */
|
||||
public static void main(String[] arg) {
|
||||
SinglyLinkedList list = new SinglyLinkedList();
|
||||
assert list.isEmpty();
|
||||
assert list.size() == 0 && list.count() == 0;
|
||||
assert list.toString().equals("");
|
||||
|
||||
/* Test insert function */
|
||||
list.insertHead(5);
|
||||
list.insertHead(7);
|
||||
list.insertHead(10);
|
||||
list.insert(3);
|
||||
list.insertNth(1, 4);
|
||||
assert list.toString().equals("10->7->5->3->1");
|
||||
|
||||
/* Test search function */
|
||||
assert list.search(10) && list.search(5) && list.search(1) && !list.search(100);
|
||||
|
||||
/* Test get function */
|
||||
assert list.getNth(0) == 10 && list.getNth(2) == 5 && list.getNth(4) == 1;
|
||||
|
||||
/* Test delete function */
|
||||
list.deleteHead();
|
||||
list.deleteNth(1);
|
||||
list.delete();
|
||||
assert list.toString().equals("7->3");
|
||||
|
||||
assert list.size == 2 && list.size() == list.count();
|
||||
|
||||
list.clear();
|
||||
assert list.isEmpty();
|
||||
|
||||
try {
|
||||
list.delete();
|
||||
assert false; /* this should not happen */
|
||||
} catch (Exception e) {
|
||||
assert true; /* this should happen */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is the nodes of the SinglyLinked List. They consist of a value and a pointer to the
|
||||
* node after them.
|
||||
*/
|
||||
class Node {
|
||||
/** The value of the node */
|
||||
int value;
|
||||
|
||||
/** Point to the next node */
|
||||
Node next;
|
||||
|
||||
Node() {}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param value Value to be put in the node
|
||||
*/
|
||||
Node(int value) {
|
||||
this(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param value Value to be put in the node
|
||||
* @param next Reference to the next node
|
||||
*/
|
||||
Node(int value, Node next) {
|
||||
this.value = value;
|
||||
this.next = next;
|
||||
}
|
||||
}
|
83
DataStructures/Queues/GenericArrayListQueue.java
Normal file
83
DataStructures/Queues/GenericArrayListQueue.java
Normal file
@ -0,0 +1,83 @@
|
||||
package DataStructures.Queues;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This class implements a GenericArrayListQueue.
|
||||
*
|
||||
* <p>A GenericArrayListQueue data structure functions the same as any specific-typed queue. The
|
||||
* GenericArrayListQueue holds elemets of types to-be-specified at runtime. The elements that are
|
||||
* added first are the first to be removed (FIFO) New elements are added to the back/rear of the
|
||||
* queue.
|
||||
*/
|
||||
public class GenericArrayListQueue<T> {
|
||||
/** The generic ArrayList for the queue T is the generic element */
|
||||
ArrayList<T> _queue = new ArrayList<T>();
|
||||
|
||||
/**
|
||||
* Checks if the queue has elements (not empty)
|
||||
*
|
||||
* @return True if the queue has elements. False otherwise.
|
||||
*/
|
||||
private boolean hasElements() {
|
||||
return !_queue.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks what's at the front of the queue
|
||||
*
|
||||
* @return If queue is not empty, element at the front of the queue. Otherwise, null
|
||||
*/
|
||||
public T peek() {
|
||||
T result = null;
|
||||
if (this.hasElements()) {
|
||||
result = _queue.get(0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an element of type T to the queue.
|
||||
*
|
||||
* @param element of type T to be added
|
||||
* @return True if the element was added successfully
|
||||
*/
|
||||
public boolean add(T element) {
|
||||
return _queue.add(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve what's at the front of the queue
|
||||
*
|
||||
* @return If queue is not empty, element retrieved. Otherwise, null
|
||||
*/
|
||||
public T poll() {
|
||||
T result = null;
|
||||
if (this.hasElements()) {
|
||||
result = _queue.remove(0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
GenericArrayListQueue<Integer> queue = new GenericArrayListQueue<Integer>();
|
||||
System.out.println("Running...");
|
||||
assert queue.peek() == null;
|
||||
assert queue.poll() == null;
|
||||
assert queue.add(1) == true;
|
||||
assert queue.peek() == 1;
|
||||
assert queue.add(2) == true;
|
||||
assert queue.peek() == 1;
|
||||
assert queue.poll() == 1;
|
||||
assert queue.peek() == 2;
|
||||
assert queue.poll() == 2;
|
||||
assert queue.peek() == null;
|
||||
assert queue.poll() == null;
|
||||
System.out.println("Finished.");
|
||||
}
|
||||
}
|
159
DataStructures/Queues/LinkedQueue.java
Normal file
159
DataStructures/Queues/LinkedQueue.java
Normal file
@ -0,0 +1,159 @@
|
||||
package DataStructures.Queues;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class LinkedQueue {
|
||||
class Node {
|
||||
int data;
|
||||
Node next;
|
||||
|
||||
public Node() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public Node(int data) {
|
||||
this(data, null);
|
||||
}
|
||||
|
||||
public Node(int data, Node next) {
|
||||
this.data = data;
|
||||
this.next = next;
|
||||
}
|
||||
}
|
||||
|
||||
/** Front of Queue */
|
||||
private Node front;
|
||||
|
||||
/** Rear of Queue */
|
||||
private Node rear;
|
||||
|
||||
/** Size of Queue */
|
||||
private int size;
|
||||
|
||||
/** Init LinkedQueue */
|
||||
public LinkedQueue() {
|
||||
front = rear = new Node();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if queue is empty
|
||||
*
|
||||
* @return <tt>true</tt> if queue is empty, otherwise <tt>false</tt>
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add element to rear of queue
|
||||
*
|
||||
* @param data insert value
|
||||
* @return <tt>true</tt> if add successfully
|
||||
*/
|
||||
public boolean enqueue(int data) {
|
||||
Node newNode = new Node(data);
|
||||
rear.next = newNode;
|
||||
rear = newNode; /* make rear point at last node */
|
||||
size++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove element at the front of queue
|
||||
*
|
||||
* @return element at the front of queue
|
||||
*/
|
||||
public int dequeue() {
|
||||
if (isEmpty()) {
|
||||
throw new NoSuchElementException("queue is empty");
|
||||
}
|
||||
Node destroy = front.next;
|
||||
int retValue = destroy.data;
|
||||
front.next = front.next.next;
|
||||
destroy = null; /* clear let GC do it's work */
|
||||
size--;
|
||||
|
||||
if (isEmpty()) {
|
||||
front = rear;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek element at the front of queue without removing
|
||||
*
|
||||
* @return element at the front
|
||||
*/
|
||||
public int peekFront() {
|
||||
if (isEmpty()) {
|
||||
throw new NoSuchElementException("queue is empty");
|
||||
}
|
||||
return front.next.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek element at the rear of queue without removing
|
||||
*
|
||||
* @return element at the front
|
||||
*/
|
||||
public int peekRear() {
|
||||
if (isEmpty()) {
|
||||
throw new NoSuchElementException("queue is empty");
|
||||
}
|
||||
return rear.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size of queue
|
||||
*
|
||||
* @return size of queue
|
||||
*/
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/** Clear all nodes in queue */
|
||||
public void clear() {
|
||||
while (!isEmpty()) {
|
||||
dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isEmpty()) {
|
||||
return "[]";
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Node cur = front.next;
|
||||
builder.append("[");
|
||||
while (cur != null) {
|
||||
builder.append(cur.data).append(", ");
|
||||
cur = cur.next;
|
||||
}
|
||||
builder.replace(builder.length() - 2, builder.length(), "]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
public static void main(String[] args) {
|
||||
LinkedQueue queue = new LinkedQueue();
|
||||
assert queue.isEmpty();
|
||||
|
||||
queue.enqueue(1); /* 1 */
|
||||
queue.enqueue(2); /* 1 2 */
|
||||
queue.enqueue(3); /* 1 2 3 */
|
||||
System.out.println(queue); /* [1, 2, 3] */
|
||||
|
||||
assert queue.size() == 3;
|
||||
assert queue.dequeue() == 1;
|
||||
assert queue.peekFront() == 2;
|
||||
assert queue.peekRear() == 3;
|
||||
|
||||
queue.clear();
|
||||
assert queue.isEmpty();
|
||||
|
||||
System.out.println(queue); /* [] */
|
||||
}
|
||||
}
|
120
DataStructures/Queues/PriorityQueues.java
Normal file
120
DataStructures/Queues/PriorityQueues.java
Normal file
@ -0,0 +1,120 @@
|
||||
package DataStructures.Queues;
|
||||
|
||||
/**
|
||||
* This class implements a PriorityQueue.
|
||||
*
|
||||
* <p>A priority queue adds elements into positions based on their priority. So the most important
|
||||
* elements are placed at the front/on the top. In this example I give numbers that are bigger, a
|
||||
* higher priority. Queues in theory have no fixed size but when using an array implementation it
|
||||
* does.
|
||||
*/
|
||||
class PriorityQueue {
|
||||
/** The max size of the queue */
|
||||
private int maxSize;
|
||||
/** The array for the queue */
|
||||
private int[] queueArray;
|
||||
/** How many items are in the queue */
|
||||
private int nItems;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param size Size of the queue
|
||||
*/
|
||||
public PriorityQueue(int size) {
|
||||
maxSize = size;
|
||||
queueArray = new int[size];
|
||||
nItems = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an element in it's appropriate place
|
||||
*
|
||||
* @param value Value to be inserted
|
||||
*/
|
||||
public void insert(int value) {
|
||||
if (isFull()) {
|
||||
throw new RuntimeException("Queue is full");
|
||||
} else {
|
||||
int j = nItems - 1; // index of last element
|
||||
while (j >= 0 && queueArray[j] > value) {
|
||||
queueArray[j + 1] = queueArray[j]; // Shifts every element up to make room for insertion
|
||||
j--;
|
||||
}
|
||||
queueArray[j + 1] = value; // Once the correct position is found the value is inserted
|
||||
nItems++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the element from the front of the queue
|
||||
*
|
||||
* @return The element removed
|
||||
*/
|
||||
public int remove() {
|
||||
return queueArray[--nItems];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks what's at the front of the queue
|
||||
*
|
||||
* @return element at the front of the queue
|
||||
*/
|
||||
public int peek() {
|
||||
return queueArray[nItems - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the queue is empty
|
||||
*
|
||||
* @return true if the queue is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (nItems == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the queue is full
|
||||
*
|
||||
* @return true if the queue is full
|
||||
*/
|
||||
public boolean isFull() {
|
||||
return (nItems == maxSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in the queue
|
||||
*
|
||||
* @return number of elements in the queue
|
||||
*/
|
||||
public int getSize() {
|
||||
return nItems;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class implements the PriorityQueue class above.
|
||||
*
|
||||
* @author Unknown
|
||||
*/
|
||||
public class PriorityQueues {
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args Command Line Arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
PriorityQueue myQueue = new PriorityQueue(4);
|
||||
myQueue.insert(10);
|
||||
myQueue.insert(2);
|
||||
myQueue.insert(5);
|
||||
myQueue.insert(3);
|
||||
// [2, 3, 5, 10] Here higher numbers have higher priority, so they are on the top
|
||||
|
||||
for (int i = 3; i >= 0; i--)
|
||||
System.out.print(
|
||||
myQueue.remove() + " "); // will print the queue in reverse order [10, 5, 3, 2]
|
||||
|
||||
// As you can see, a Priority Queue can be used as a sorting algotithm
|
||||
}
|
||||
}
|
163
DataStructures/Queues/Queues.java
Normal file
163
DataStructures/Queues/Queues.java
Normal file
@ -0,0 +1,163 @@
|
||||
package DataStructures.Queues;
|
||||
|
||||
/**
|
||||
* This implements Queues by using the class Queue.
|
||||
*
|
||||
* <p>A queue data structure functions the same as a real world queue. The elements that are added
|
||||
* first are the first to be removed. New elements are added to the back/rear of the queue.
|
||||
*/
|
||||
class Queue {
|
||||
/** Default initial capacity. */
|
||||
private static final int DEFAULT_CAPACITY = 10;
|
||||
|
||||
/** Max size of the queue */
|
||||
private int maxSize;
|
||||
/** The array representing the queue */
|
||||
private int[] queueArray;
|
||||
/** Front of the queue */
|
||||
private int front;
|
||||
/** Rear of the queue */
|
||||
private int rear;
|
||||
/** How many items are in the queue */
|
||||
private int nItems;
|
||||
|
||||
/** init with DEFAULT_CAPACITY */
|
||||
public Queue() {
|
||||
this(DEFAULT_CAPACITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param size Size of the new queue
|
||||
*/
|
||||
public Queue(int size) {
|
||||
maxSize = size;
|
||||
queueArray = new int[size];
|
||||
front = 0;
|
||||
rear = -1;
|
||||
nItems = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an element at the rear of the queue
|
||||
*
|
||||
* @param x element to be added
|
||||
* @return True if the element was added successfully
|
||||
*/
|
||||
public boolean insert(int x) {
|
||||
if (isFull()) return false;
|
||||
// If the back of the queue is the end of the array wrap around to the front
|
||||
rear = (rear + 1) % maxSize;
|
||||
queueArray[rear] = x;
|
||||
nItems++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element from the front of the queue
|
||||
*
|
||||
* @return the new front of the queue
|
||||
*/
|
||||
public int remove() {
|
||||
if (isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
int temp = queueArray[front];
|
||||
front = (front + 1) % maxSize;
|
||||
nItems--;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks what's at the front of the queue
|
||||
*
|
||||
* @return element at the front of the queue
|
||||
*/
|
||||
public int peekFront() {
|
||||
return queueArray[front];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks what's at the rear of the queue
|
||||
*
|
||||
* @return element at the rear of the queue
|
||||
*/
|
||||
public int peekRear() {
|
||||
return queueArray[rear];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the queue is empty
|
||||
*
|
||||
* @return true if the queue is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return nItems == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the queue is full
|
||||
*
|
||||
* @return true if the queue is full
|
||||
*/
|
||||
public boolean isFull() {
|
||||
return nItems == maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in the queue
|
||||
*
|
||||
* @return number of elements in the queue
|
||||
*/
|
||||
public int getSize() {
|
||||
return nItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
for (int i = front; ; i = ++i % maxSize) {
|
||||
sb.append(queueArray[i]).append(", ");
|
||||
if (i == rear) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
sb.replace(sb.length() - 2, sb.length(), "]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is the example for the Queue class
|
||||
*
|
||||
* @author Unknown
|
||||
*/
|
||||
public class Queues {
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Queue myQueue = new Queue(4);
|
||||
myQueue.insert(10);
|
||||
myQueue.insert(2);
|
||||
myQueue.insert(5);
|
||||
myQueue.insert(3);
|
||||
// [10(front), 2, 5, 3(rear)]
|
||||
|
||||
System.out.println(myQueue.isFull()); // Will print true
|
||||
|
||||
myQueue.remove(); // Will make 2 the new front, making 10 no longer part of the queue
|
||||
// [10, 2(front), 5, 3(rear)]
|
||||
|
||||
myQueue.insert(7); // Insert 7 at the rear which will be index 0 because of wrap around
|
||||
// [7(rear), 2(front), 5, 3]
|
||||
|
||||
System.out.println(myQueue.peekFront()); // Will print 2
|
||||
System.out.println(myQueue.peekRear()); // Will print 7
|
||||
System.out.println(myQueue.toString()); // Will print [2, 5, 3, 7]
|
||||
}
|
||||
}
|
78
DataStructures/Stacks/BalancedBrackets.java
Normal file
78
DataStructures/Stacks/BalancedBrackets.java
Normal file
@ -0,0 +1,78 @@
|
||||
package DataStructures.Stacks;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* The nested brackets problem is a problem that determines if a sequence of brackets are properly
|
||||
* nested. A sequence of brackets s is considered properly nested if any of the following conditions
|
||||
* are true: - s is empty - s has the form (U) or [U] or {U} where U is a properly nested string - s
|
||||
* has the form VW where V and W are properly nested strings For example, the string "()()[()]" is
|
||||
* properly nested but "[(()]" is not. The function called is_balanced takes as input a string S
|
||||
* which is a sequence of brackets and returns true if S is nested and false otherwise.
|
||||
*
|
||||
* @author akshay sharma
|
||||
* @author <a href="https://github.com/khalil2535">khalil2535<a>
|
||||
* @author shellhub
|
||||
*/
|
||||
class BalancedBrackets {
|
||||
|
||||
/**
|
||||
* Check if {@code leftBracket} and {@code rightBracket} is paired or not
|
||||
*
|
||||
* @param leftBracket left bracket
|
||||
* @param rightBracket right bracket
|
||||
* @return {@code true} if {@code leftBracket} and {@code rightBracket} is paired, otherwise
|
||||
* {@code false}
|
||||
*/
|
||||
public static boolean isPaired(char leftBracket, char rightBracket) {
|
||||
char[][] pairedBrackets = {
|
||||
{'(', ')'},
|
||||
{'[', ']'},
|
||||
{'{', '}'},
|
||||
{'<', '>'}
|
||||
};
|
||||
for (char[] pairedBracket : pairedBrackets) {
|
||||
if (pairedBracket[0] == leftBracket && pairedBracket[1] == rightBracket) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if {@code brackets} is balanced
|
||||
*
|
||||
* @param brackets the brackets
|
||||
* @return {@code true} if {@code brackets} is balanced, otherwise {@code false}
|
||||
*/
|
||||
public static boolean isBalanced(String brackets) {
|
||||
if (brackets == null) {
|
||||
throw new IllegalArgumentException("brackets is null");
|
||||
}
|
||||
Stack<Character> bracketsStack = new Stack<>();
|
||||
for (char bracket : brackets.toCharArray()) {
|
||||
switch (bracket) {
|
||||
case '(':
|
||||
case '[':
|
||||
case '{':
|
||||
bracketsStack.push(bracket);
|
||||
break;
|
||||
case ')':
|
||||
case ']':
|
||||
case '}':
|
||||
if (bracketsStack.isEmpty() || !isPaired(bracketsStack.pop(), bracket)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default: /* other character is invalid */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return bracketsStack.isEmpty();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
assert isBalanced("[()]{}{[()()]()}");
|
||||
assert !isBalanced("[(])");
|
||||
}
|
||||
}
|
42
DataStructures/Stacks/DecimalToAnyUsingStack.java
Normal file
42
DataStructures/Stacks/DecimalToAnyUsingStack.java
Normal file
@ -0,0 +1,42 @@
|
||||
package DataStructures.Stacks;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
public class DecimalToAnyUsingStack {
|
||||
public static void main(String[] args) {
|
||||
assert convert(0, 2).equals("0");
|
||||
assert convert(30, 2).equals("11110");
|
||||
assert convert(30, 8).equals("36");
|
||||
assert convert(30, 10).equals("30");
|
||||
assert convert(30, 16).equals("1E");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert decimal number to another radix
|
||||
*
|
||||
* @param number the number to be converted
|
||||
* @param radix the radix
|
||||
* @return another radix
|
||||
* @throws ArithmeticException if <tt>number</tt> or <tt>radius</tt> is invalid
|
||||
*/
|
||||
private static String convert(int number, int radix) {
|
||||
if (radix < 2 || radix > 16) {
|
||||
throw new ArithmeticException(
|
||||
String.format("Invalid input -> number:%d,radius:%d", number, radix));
|
||||
}
|
||||
char[] tables = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
||||
};
|
||||
Stack<Character> bits = new Stack<>();
|
||||
do {
|
||||
bits.push(tables[number % radix]);
|
||||
number = number / radix;
|
||||
} while (number != 0);
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
while (!bits.isEmpty()) {
|
||||
result.append(bits.pop());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
55
DataStructures/Stacks/InfixToPostfix.java
Normal file
55
DataStructures/Stacks/InfixToPostfix.java
Normal file
@ -0,0 +1,55 @@
|
||||
package DataStructures.Stacks;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
public class InfixToPostfix {
|
||||
public static void main(String[] args) throws Exception {
|
||||
assert "32+".equals(infix2PostFix("3+2"));
|
||||
assert "123++".equals(infix2PostFix("1+(2+3)"));
|
||||
assert "34+5*6-".equals(infix2PostFix("(3+4)*5-6"));
|
||||
}
|
||||
|
||||
public static String infix2PostFix(String infixExpression) throws Exception {
|
||||
if (!BalancedBrackets.isBalanced(infixExpression)) {
|
||||
throw new Exception("invalid expression");
|
||||
}
|
||||
StringBuilder output = new StringBuilder();
|
||||
Stack<Character> stack = new Stack<>();
|
||||
for (char element : infixExpression.toCharArray()) {
|
||||
if (Character.isLetterOrDigit(element)) {
|
||||
output.append(element);
|
||||
} else if (element == '(') {
|
||||
stack.push(element);
|
||||
} else if (element == ')') {
|
||||
while (!stack.isEmpty() && stack.peek() != '(') {
|
||||
output.append(stack.pop());
|
||||
}
|
||||
stack.pop();
|
||||
} else {
|
||||
while (!stack.isEmpty() && precedence(element) <= precedence(stack.peek())) {
|
||||
output.append(stack.pop());
|
||||
}
|
||||
stack.push(element);
|
||||
}
|
||||
}
|
||||
while (!stack.isEmpty()) {
|
||||
output.append(stack.pop());
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
private static int precedence(char operator) {
|
||||
switch (operator) {
|
||||
case '+':
|
||||
case '-':
|
||||
return 0;
|
||||
case '*':
|
||||
case '/':
|
||||
return 1;
|
||||
case '^':
|
||||
return 2;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
171
DataStructures/Stacks/NodeStack.java
Normal file
171
DataStructures/Stacks/NodeStack.java
Normal file
@ -0,0 +1,171 @@
|
||||
package DataStructures.Stacks;
|
||||
/**
|
||||
* Implementation of a stack using nodes. Unlimited size, no arraylist.
|
||||
*
|
||||
* @author Kyler Smith, 2017
|
||||
*/
|
||||
public class NodeStack<Item> {
|
||||
|
||||
/** Entry point for the program. */
|
||||
public static void main(String[] args) {
|
||||
NodeStack<Integer> Stack = new NodeStack<Integer>();
|
||||
|
||||
Stack.push(3);
|
||||
Stack.push(4);
|
||||
Stack.push(5);
|
||||
System.out.println("Testing :");
|
||||
Stack.print(); // prints : 5 4 3
|
||||
|
||||
Integer x = Stack.pop(); // x = 5
|
||||
Stack.push(1);
|
||||
Stack.push(8);
|
||||
Integer y = Stack.peek(); // y = 8
|
||||
System.out.println("Testing :");
|
||||
Stack.print(); // prints : 8 1 4 3
|
||||
|
||||
System.out.println("Testing :");
|
||||
System.out.println("x : " + x);
|
||||
System.out.println("y : " + y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Information each node should contain.
|
||||
*
|
||||
* @value data : information of the value in the node
|
||||
* @value head : the head of the stack
|
||||
* @value next : the next value from this node
|
||||
* @value previous : the last value from this node
|
||||
* @value size : size of the stack
|
||||
*/
|
||||
private Item data;
|
||||
|
||||
private static NodeStack<?> head;
|
||||
private NodeStack<?> next;
|
||||
private NodeStack<?> previous;
|
||||
private static int size = 0;
|
||||
|
||||
/** Constructors for the NodeStack. */
|
||||
public NodeStack() {}
|
||||
|
||||
private NodeStack(Item item) {
|
||||
this.data = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value onto the stack.
|
||||
*
|
||||
* @param item : value to be put on the stack.
|
||||
*/
|
||||
public void push(Item item) {
|
||||
|
||||
NodeStack<Item> newNs = new NodeStack<Item>(item);
|
||||
|
||||
if (this.isEmpty()) {
|
||||
NodeStack.setHead(new NodeStack<>(item));
|
||||
newNs.setNext(null);
|
||||
newNs.setPrevious(null);
|
||||
} else {
|
||||
newNs.setPrevious(NodeStack.head);
|
||||
NodeStack.head.setNext(newNs);
|
||||
NodeStack.head.setHead(newNs);
|
||||
}
|
||||
|
||||
NodeStack.setSize(NodeStack.getSize() + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Value to be taken off the stack.
|
||||
*
|
||||
* @return item : value that is returned.
|
||||
*/
|
||||
public Item pop() {
|
||||
|
||||
Item item = (Item) NodeStack.head.getData();
|
||||
|
||||
NodeStack.head.setHead(NodeStack.head.getPrevious());
|
||||
NodeStack.head.setNext(null);
|
||||
|
||||
NodeStack.setSize(NodeStack.getSize() - 1);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Value that is next to be taken off the stack.
|
||||
*
|
||||
* @return item : the next value that would be popped off the stack.
|
||||
*/
|
||||
public Item peek() {
|
||||
return (Item) NodeStack.head.getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the stack is empty or there is a value in.
|
||||
*
|
||||
* @return boolean : whether or not the stack has anything in it.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return NodeStack.getSize() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the stack.
|
||||
*
|
||||
* @return int : number of values in the stack.
|
||||
*/
|
||||
public int size() {
|
||||
return NodeStack.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the contents of the stack in the following format.
|
||||
*
|
||||
* <p>x <- head (next out) y z <- tail (first in) . . .
|
||||
*/
|
||||
public void print() {
|
||||
for (NodeStack<?> n = NodeStack.head; n != null; n = n.previous) {
|
||||
System.out.println(n.getData().toString());
|
||||
}
|
||||
}
|
||||
|
||||
/** Getters and setters (private) */
|
||||
private NodeStack<?> getHead() {
|
||||
return NodeStack.head;
|
||||
}
|
||||
|
||||
private static void setHead(NodeStack<?> ns) {
|
||||
NodeStack.head = ns;
|
||||
}
|
||||
|
||||
private NodeStack<?> getNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
private void setNext(NodeStack<?> next) {
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
private NodeStack<?> getPrevious() {
|
||||
return previous;
|
||||
}
|
||||
|
||||
private void setPrevious(NodeStack<?> previous) {
|
||||
this.previous = previous;
|
||||
}
|
||||
|
||||
private static int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
private static void setSize(int size) {
|
||||
NodeStack.size = size;
|
||||
}
|
||||
|
||||
private Item getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
private void setData(Item item) {
|
||||
this.data = item;
|
||||
}
|
||||
}
|
20
DataStructures/Stacks/README.md
Normal file
20
DataStructures/Stacks/README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# STACK
|
||||
|
||||
stack is an ADT (abstract data type ) that act like list of objects but there is a diffrents.
|
||||
|
||||
stack act is _LIFO_ (Last In First Out), it means that when we want to get an element from the stack we get the last element in the stack.
|
||||
|
||||
stack is bast on two methods ( functions)
|
||||
|
||||
## push & pop
|
||||
|
||||
**push**: add an alement to last index of stack.
|
||||
|
||||
for example: we have `1, 3, 5` in stack, then we call push(9),
|
||||
|
||||
`9` will add to last index of stack -> `1, 3, 5 , 9`
|
||||
|
||||
**pop**: remove the last element from stack.
|
||||
for example: we have `1, 3, 5 , 9` in stack, then we call pop(),
|
||||
|
||||
the function will return `9` and the stack will change to `1, 3, 5`.
|
158
DataStructures/Stacks/StackArray.java
Normal file
158
DataStructures/Stacks/StackArray.java
Normal file
@ -0,0 +1,158 @@
|
||||
package DataStructures.Stacks;
|
||||
|
||||
/**
|
||||
* This class implements a Stack using a regular array.
|
||||
*
|
||||
* <p>A stack is exactly what it sounds like. An element gets added to the top of the stack and only
|
||||
* the element on the top may be removed. This is an example of an array implementation of a Stack.
|
||||
* So an element can only be added/removed from the end of the array. In theory stack have no fixed
|
||||
* size, but with an array implementation it does.
|
||||
*/
|
||||
public class StackArray {
|
||||
|
||||
/** Driver Code */
|
||||
public static void main(String[] args) {
|
||||
// Declare a stack of maximum size 4
|
||||
StackArray myStackArray = new StackArray(4);
|
||||
|
||||
assert myStackArray.isEmpty();
|
||||
assert !myStackArray.isFull();
|
||||
|
||||
// Populate the stack
|
||||
myStackArray.push(5);
|
||||
myStackArray.push(8);
|
||||
myStackArray.push(2);
|
||||
myStackArray.push(9);
|
||||
|
||||
assert !myStackArray.isEmpty();
|
||||
assert myStackArray.isFull();
|
||||
assert myStackArray.peek() == 9;
|
||||
assert myStackArray.pop() == 9;
|
||||
assert myStackArray.peek() == 2;
|
||||
assert myStackArray.size() == 3;
|
||||
}
|
||||
|
||||
/** Default initial capacity. */
|
||||
private static final int DEFAULT_CAPACITY = 10;
|
||||
|
||||
/** The max size of the Stack */
|
||||
private int maxSize;
|
||||
|
||||
/** The array representation of the Stack */
|
||||
private int[] stackArray;
|
||||
|
||||
/** The top of the stack */
|
||||
private int top;
|
||||
|
||||
/** init Stack with DEFAULT_CAPACITY */
|
||||
public StackArray() {
|
||||
this(DEFAULT_CAPACITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param size Size of the Stack
|
||||
*/
|
||||
public StackArray(int size) {
|
||||
maxSize = size;
|
||||
stackArray = new int[maxSize];
|
||||
top = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an element to the top of the stack
|
||||
*
|
||||
* @param value The element added
|
||||
*/
|
||||
public void push(int value) {
|
||||
if (!isFull()) { // Checks for a full stack
|
||||
top++;
|
||||
stackArray[top] = value;
|
||||
} else {
|
||||
resize(maxSize * 2);
|
||||
push(value); // don't forget push after resizing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the top element of the stack and returns the value you've removed
|
||||
*
|
||||
* @return value popped off the Stack
|
||||
*/
|
||||
public int pop() {
|
||||
if (!isEmpty()) { // Checks for an empty stack
|
||||
return stackArray[top--];
|
||||
}
|
||||
|
||||
if (top < maxSize / 4) {
|
||||
resize(maxSize / 2);
|
||||
return pop(); // don't forget pop after resizing
|
||||
} else {
|
||||
System.out.println("The stack is already empty");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element at the top of the stack
|
||||
*
|
||||
* @return element at the top of the stack
|
||||
*/
|
||||
public int peek() {
|
||||
if (!isEmpty()) { // Checks for an empty stack
|
||||
return stackArray[top];
|
||||
} else {
|
||||
System.out.println("The stack is empty, cant peek");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private void resize(int newSize) {
|
||||
int[] transferArray = new int[newSize];
|
||||
|
||||
for (int i = 0; i < stackArray.length; i++) {
|
||||
transferArray[i] = stackArray[i];
|
||||
}
|
||||
// This reference change might be nice in here
|
||||
stackArray = transferArray;
|
||||
maxSize = newSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the stack is empty
|
||||
*
|
||||
* @return true if the stack is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (top == -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the stack is full
|
||||
*
|
||||
* @return true if the stack is full
|
||||
*/
|
||||
public boolean isFull() {
|
||||
return (top + 1 == maxSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes everything in the Stack
|
||||
*
|
||||
* <p>Doesn't delete elements in the array but if you call push method after calling makeEmpty it
|
||||
* will overwrite previous values
|
||||
*/
|
||||
public void makeEmpty() { // Doesn't delete elements in the array but if you call
|
||||
top = -1; // push method after calling makeEmpty it will overwrite previous values
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size of stack
|
||||
*
|
||||
* @return size of stack
|
||||
*/
|
||||
public int size() {
|
||||
return top + 1;
|
||||
}
|
||||
}
|
105
DataStructures/Stacks/StackArrayList.java
Normal file
105
DataStructures/Stacks/StackArrayList.java
Normal file
@ -0,0 +1,105 @@
|
||||
package DataStructures.Stacks;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EmptyStackException;
|
||||
|
||||
/**
|
||||
* This class implements a Stack using an ArrayList.
|
||||
*
|
||||
* <p>A stack is exactly what it sounds like. An element gets added to the top of the stack and only
|
||||
* the element on the top may be removed.
|
||||
*
|
||||
* <p>This is an ArrayList Implementation of a stack, where size is not a problem we can extend the
|
||||
* stack as much as we want.
|
||||
*/
|
||||
public class StackArrayList {
|
||||
|
||||
/** Driver Code */
|
||||
public static void main(String[] args) {
|
||||
StackArrayList stack = new StackArrayList();
|
||||
assert stack.isEmpty();
|
||||
|
||||
for (int i = 1; i <= 5; ++i) {
|
||||
stack.push(i);
|
||||
assert stack.size() == i;
|
||||
}
|
||||
|
||||
assert stack.size() == 5;
|
||||
assert stack.peek() == 5 && stack.pop() == 5 && stack.peek() == 4;
|
||||
|
||||
/* pop elements at the top of this stack one by one */
|
||||
while (!stack.isEmpty()) {
|
||||
stack.pop();
|
||||
}
|
||||
assert stack.isEmpty();
|
||||
|
||||
try {
|
||||
stack.pop();
|
||||
assert false; /* this should not happen */
|
||||
} catch (EmptyStackException e) {
|
||||
assert true; /* this should happen */
|
||||
}
|
||||
}
|
||||
|
||||
/** ArrayList representation of the stack */
|
||||
private ArrayList<Integer> stack;
|
||||
|
||||
/** Constructor */
|
||||
public StackArrayList() {
|
||||
stack = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds value to the end of list which is the top for stack
|
||||
*
|
||||
* @param value value to be added
|
||||
*/
|
||||
public void push(int value) {
|
||||
stack.add(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at the top of this stack and returns
|
||||
*
|
||||
* @return Element popped
|
||||
* @throws EmptyStackException if the stack is empty.
|
||||
*/
|
||||
public int pop() {
|
||||
if (isEmpty()) {
|
||||
throw new EmptyStackException();
|
||||
}
|
||||
|
||||
/* remove the element on the top of the stack */
|
||||
return stack.remove(stack.size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the stack is empty.
|
||||
*
|
||||
* @return {@code true} if this stack is empty, {@code false} otherwise.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return stack.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the element at the top of this stack without removing it from the stack.
|
||||
*
|
||||
* @return the element at the top of this stack.
|
||||
*/
|
||||
public int peek() {
|
||||
if (isEmpty()) {
|
||||
throw new EmptyStackException();
|
||||
}
|
||||
return stack.get(stack.size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size of this stack.
|
||||
*
|
||||
* @return size of this stack.
|
||||
*/
|
||||
public int size() {
|
||||
return stack.size();
|
||||
}
|
||||
}
|
135
DataStructures/Stacks/StackOfLinkedList.java
Normal file
135
DataStructures/Stacks/StackOfLinkedList.java
Normal file
@ -0,0 +1,135 @@
|
||||
package DataStructures.Stacks;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/** @author Varun Upadhyay (https://github.com/varunu28) */
|
||||
|
||||
// An implementation of a Stack using a Linked List
|
||||
|
||||
class StackOfLinkedList {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
LinkedListStack stack = new LinkedListStack();
|
||||
stack.push(1);
|
||||
stack.push(2);
|
||||
stack.push(3);
|
||||
stack.push(4);
|
||||
stack.push(5);
|
||||
|
||||
System.out.println(stack);
|
||||
|
||||
System.out.println("Size of stack currently is: " + stack.getSize());
|
||||
|
||||
assert stack.pop() == 5;
|
||||
assert stack.pop() == 4;
|
||||
|
||||
System.out.println("Top element of stack currently is: " + stack.peek());
|
||||
}
|
||||
}
|
||||
|
||||
// A node class
|
||||
|
||||
class Node {
|
||||
public int data;
|
||||
public Node next;
|
||||
|
||||
public Node(int data) {
|
||||
this.data = data;
|
||||
this.next = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class which implements a stack using a linked list
|
||||
*
|
||||
* <p>Contains all the stack methods : push, pop, printStack, isEmpty
|
||||
*/
|
||||
class LinkedListStack {
|
||||
|
||||
/** Top of stack */
|
||||
Node head;
|
||||
|
||||
/** Size of stack */
|
||||
private int size;
|
||||
|
||||
/** Init properties */
|
||||
public LinkedListStack() {
|
||||
head = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add element at top
|
||||
*
|
||||
* @param x to be added
|
||||
* @return <tt>true</tt> if add successfully
|
||||
*/
|
||||
public boolean push(int x) {
|
||||
Node newNode = new Node(x);
|
||||
newNode.next = head;
|
||||
head = newNode;
|
||||
size++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop element at top of stack
|
||||
*
|
||||
* @return element at top of stack
|
||||
* @throws NoSuchElementException if stack is empty
|
||||
*/
|
||||
public int pop() {
|
||||
if (size == 0) {
|
||||
throw new NoSuchElementException("Empty stack. Nothing to pop");
|
||||
}
|
||||
Node destroy = head;
|
||||
head = head.next;
|
||||
int retValue = destroy.data;
|
||||
destroy = null; // clear to let GC do it's work
|
||||
size--;
|
||||
return retValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek element at top of stack
|
||||
*
|
||||
* @return element at top of stack
|
||||
* @throws NoSuchElementException if stack is empty
|
||||
*/
|
||||
public int peek() {
|
||||
if (size == 0) {
|
||||
throw new NoSuchElementException("Empty stack. Nothing to pop");
|
||||
}
|
||||
return head.data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
Node cur = head;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
while (cur != null) {
|
||||
builder.append(cur.data).append("->");
|
||||
cur = cur.next;
|
||||
}
|
||||
return builder.replace(builder.length() - 2, builder.length(), "").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if stack is empty
|
||||
*
|
||||
* @return <tt>true</tt> if stack is empty, otherwise <tt>false</tt>
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size of stack
|
||||
*
|
||||
* @return size of stack
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
}
|
137
DataStructures/Trees/AVLSimple
Normal file
137
DataStructures/Trees/AVLSimple
Normal file
@ -0,0 +1,137 @@
|
||||
|
||||
package DataStructures.Trees;
|
||||
|
||||
/*
|
||||
* Avl is algo that balance itself while adding new alues to tree
|
||||
* by rotating branches of binary tree and make itself Binary seaarch tree
|
||||
* there are four cases which has to tackle
|
||||
* rotating - left right ,left left,right right,right left
|
||||
|
||||
Test Case:
|
||||
|
||||
AVLTree tree=new AVLTree();
|
||||
tree.insert(20);
|
||||
tree.insert(25);
|
||||
tree.insert(30);
|
||||
tree.insert(10);
|
||||
tree.insert(5);
|
||||
tree.insert(15);
|
||||
tree.insert(27);
|
||||
tree.insert(19);
|
||||
tree.insert(16);
|
||||
|
||||
tree.display();
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
public class AVLTree {
|
||||
private class Node{
|
||||
int data;
|
||||
int height;
|
||||
Node left;
|
||||
Node right;
|
||||
Node(int data){
|
||||
this.data=data;
|
||||
this.height=1;
|
||||
}
|
||||
|
||||
}
|
||||
private Node root;
|
||||
public void insert(int data) {
|
||||
this.root=insert(this.root,data);
|
||||
}
|
||||
private Node insert(Node node,int item) {
|
||||
if(node==null) {
|
||||
Node add=new Node(item);
|
||||
return add;
|
||||
}
|
||||
if(node.data>item) {
|
||||
node.left=insert(node.left,item);
|
||||
}
|
||||
if(node.data<item) {
|
||||
node.right=insert(node.right,item);
|
||||
}
|
||||
node.height=Math.max(height(node.left),height(node.right))+1;
|
||||
int bf=bf(node);
|
||||
//LL case
|
||||
if(bf>1&&item<node.left.data)
|
||||
return rightRotate(node);
|
||||
//RR case
|
||||
if(bf<-1&&item>node.right.data)
|
||||
return leftRotate(node);
|
||||
//RL case
|
||||
if(bf<-1&&item<node.right.data) {
|
||||
node.right=rightRotate(node.right);
|
||||
return leftRotate(node);
|
||||
}
|
||||
//LR case
|
||||
if(bf>1&&item>node.left.data) {
|
||||
node.left=leftRotate(node.left);
|
||||
return rightRotate(node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
public void display() {
|
||||
this.display(this.root);
|
||||
System.out.println(this.root.height);
|
||||
}
|
||||
private void display (Node node) {
|
||||
Strings str="";
|
||||
if(node.left!=null)
|
||||
str+=node.left.data+"=>";
|
||||
else
|
||||
str+="END=>";
|
||||
str+=node.data+"";
|
||||
if(node.right!=null)
|
||||
str+="<="+node.right.data;
|
||||
else
|
||||
str+="<=END";
|
||||
System.out.println(str);
|
||||
if(node.left!=null)
|
||||
display(node.left);
|
||||
if(node.right!=null)
|
||||
display(node.right);
|
||||
}
|
||||
private int height(Node node) {
|
||||
if(node==null) {
|
||||
return 0;
|
||||
}
|
||||
return node.height;
|
||||
|
||||
}
|
||||
private int bf(Node node) {
|
||||
if(node==null)
|
||||
return 0;
|
||||
return height(node.left)-height(node.right);
|
||||
}
|
||||
|
||||
private Node rightRotate(Node c) {
|
||||
Node b=c.left;
|
||||
Node T3=b.right;
|
||||
|
||||
b.right=c;
|
||||
c.left=T3;
|
||||
c.height=Math.max(height(c.left),height(c.right))+1;
|
||||
b.height=Math.max(height(b.left),height(b.right))+1;
|
||||
return b;
|
||||
|
||||
}
|
||||
private Node leftRotate(Node c) {
|
||||
Node b=c.right;
|
||||
Node T3=b.left;
|
||||
|
||||
b.left=c;
|
||||
c.right=T3;
|
||||
c.height=Math.max(height(c.left),height(c.right))+1;
|
||||
b.height=Math.max(height(b.left),height(b.right))+1;
|
||||
return b;
|
||||
|
||||
}
|
||||
|
||||
}
|
224
DataStructures/Trees/AVLTree.java
Normal file
224
DataStructures/Trees/AVLTree.java
Normal file
@ -0,0 +1,224 @@
|
||||
package DataStructures.Trees;
|
||||
|
||||
public class AVLTree {
|
||||
|
||||
private Node root;
|
||||
|
||||
private class Node {
|
||||
private int key;
|
||||
private int balance;
|
||||
private int height;
|
||||
private Node left, right, parent;
|
||||
|
||||
Node(int k, Node p) {
|
||||
key = k;
|
||||
parent = p;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean insert(int key) {
|
||||
if (root == null) root = new Node(key, null);
|
||||
else {
|
||||
Node n = root;
|
||||
Node parent;
|
||||
while (true) {
|
||||
if (n.key == key) return false;
|
||||
|
||||
parent = n;
|
||||
|
||||
boolean goLeft = n.key > key;
|
||||
n = goLeft ? n.left : n.right;
|
||||
|
||||
if (n == null) {
|
||||
if (goLeft) {
|
||||
parent.left = new Node(key, parent);
|
||||
} else {
|
||||
parent.right = new Node(key, parent);
|
||||
}
|
||||
rebalance(parent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void delete(Node node) {
|
||||
if (node.left == null && node.right == null) {
|
||||
if (node.parent == null) root = null;
|
||||
else {
|
||||
Node parent = node.parent;
|
||||
if (parent.left == node) {
|
||||
parent.left = null;
|
||||
} else parent.right = null;
|
||||
rebalance(parent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (node.left != null) {
|
||||
Node child = node.left;
|
||||
while (child.right != null) child = child.right;
|
||||
node.key = child.key;
|
||||
delete(child);
|
||||
} else {
|
||||
Node child = node.right;
|
||||
while (child.left != null) child = child.left;
|
||||
node.key = child.key;
|
||||
delete(child);
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(int delKey) {
|
||||
if (root == null) return;
|
||||
Node node = root;
|
||||
Node child = root;
|
||||
|
||||
while (child != null) {
|
||||
node = child;
|
||||
child = delKey >= node.key ? node.right : node.left;
|
||||
if (delKey == node.key) {
|
||||
delete(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void rebalance(Node n) {
|
||||
setBalance(n);
|
||||
|
||||
if (n.balance == -2) {
|
||||
if (height(n.left.left) >= height(n.left.right)) n = rotateRight(n);
|
||||
else n = rotateLeftThenRight(n);
|
||||
|
||||
} else if (n.balance == 2) {
|
||||
if (height(n.right.right) >= height(n.right.left)) n = rotateLeft(n);
|
||||
else n = rotateRightThenLeft(n);
|
||||
}
|
||||
|
||||
if (n.parent != null) {
|
||||
rebalance(n.parent);
|
||||
} else {
|
||||
root = n;
|
||||
}
|
||||
}
|
||||
|
||||
private Node rotateLeft(Node a) {
|
||||
|
||||
Node b = a.right;
|
||||
b.parent = a.parent;
|
||||
|
||||
a.right = b.left;
|
||||
|
||||
if (a.right != null) a.right.parent = a;
|
||||
|
||||
b.left = a;
|
||||
a.parent = b;
|
||||
|
||||
if (b.parent != null) {
|
||||
if (b.parent.right == a) {
|
||||
b.parent.right = b;
|
||||
} else {
|
||||
b.parent.left = b;
|
||||
}
|
||||
}
|
||||
|
||||
setBalance(a, b);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
private Node rotateRight(Node a) {
|
||||
|
||||
Node b = a.left;
|
||||
b.parent = a.parent;
|
||||
|
||||
a.left = b.right;
|
||||
|
||||
if (a.left != null) a.left.parent = a;
|
||||
|
||||
b.right = a;
|
||||
a.parent = b;
|
||||
|
||||
if (b.parent != null) {
|
||||
if (b.parent.right == a) {
|
||||
b.parent.right = b;
|
||||
} else {
|
||||
b.parent.left = b;
|
||||
}
|
||||
}
|
||||
|
||||
setBalance(a, b);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
private Node rotateLeftThenRight(Node n) {
|
||||
n.left = rotateLeft(n.left);
|
||||
return rotateRight(n);
|
||||
}
|
||||
|
||||
private Node rotateRightThenLeft(Node n) {
|
||||
n.right = rotateRight(n.right);
|
||||
return rotateLeft(n);
|
||||
}
|
||||
|
||||
private int height(Node n) {
|
||||
if (n == null) return -1;
|
||||
return n.height;
|
||||
}
|
||||
|
||||
private void setBalance(Node... nodes) {
|
||||
for (Node n : nodes) {
|
||||
reheight(n);
|
||||
n.balance = height(n.right) - height(n.left);
|
||||
}
|
||||
}
|
||||
|
||||
public void printBalance() {
|
||||
printBalance(root);
|
||||
}
|
||||
|
||||
private void printBalance(Node n) {
|
||||
if (n != null) {
|
||||
printBalance(n.left);
|
||||
System.out.printf("%s ", n.balance);
|
||||
printBalance(n.right);
|
||||
}
|
||||
}
|
||||
|
||||
private void reheight(Node node) {
|
||||
if (node != null) {
|
||||
node.height = 1 + Math.max(height(node.left), height(node.right));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean search(int key) {
|
||||
Node result = searchHelper(this.root, key);
|
||||
if (result != null) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Node searchHelper(Node root, int key) {
|
||||
// root is null or key is present at root
|
||||
if (root == null || root.key == key) return root;
|
||||
|
||||
// key is greater than root's key
|
||||
if (root.key > key)
|
||||
return searchHelper(root.left, key); // call the function on the node's left child
|
||||
|
||||
// key is less than root's key then
|
||||
// call the function on the node's right child as it is greater
|
||||
return searchHelper(root.right, key);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
AVLTree tree = new AVLTree();
|
||||
|
||||
System.out.println("Inserting values 1 to 10");
|
||||
for (int i = 1; i < 10; i++) tree.insert(i);
|
||||
|
||||
System.out.print("Printing balance: ");
|
||||
tree.printBalance();
|
||||
}
|
||||
}
|
287
DataStructures/Trees/BSTIterative.java
Normal file
287
DataStructures/Trees/BSTIterative.java
Normal file
@ -0,0 +1,287 @@
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <h1>Binary Search Tree (Iterative)</h1>
|
||||
*
|
||||
* <p>An implementation of BST iteratively. Binary Search Tree is a binary tree which satisfies
|
||||
* three properties: left child is less than root node, right child is grater than root node, both
|
||||
* left and right childs must themselves be a BST.
|
||||
*
|
||||
* @author [Lakhan Nad](https://github.com/Lakhan-Nad)
|
||||
*/
|
||||
import java.util.Stack;
|
||||
|
||||
public class BSTIterative {
|
||||
/** Reference for the node of BST. */
|
||||
private Node root;
|
||||
|
||||
/** Default Constructor Initializes the root of BST with null. */
|
||||
BSTIterative() {
|
||||
root = null;
|
||||
}
|
||||
|
||||
/** main function for tests */
|
||||
public static void main(String[] args) {
|
||||
BSTIterative tree = new BSTIterative();
|
||||
tree.add(3);
|
||||
tree.add(2);
|
||||
tree.add(9);
|
||||
assert !tree.find(4) : "4 is not yet present in BST";
|
||||
assert tree.find(2) : "2 should be present in BST";
|
||||
tree.remove(2);
|
||||
assert !tree.find(2) : "2 was just deleted from BST";
|
||||
tree.remove(1);
|
||||
assert !tree.find(1) : "Since 1 was not present so find deleting would do no change";
|
||||
tree.add(30);
|
||||
tree.add(40);
|
||||
assert tree.find(40) : "40 was inserted but not found";
|
||||
/*
|
||||
Will print following order
|
||||
3 9 30 40
|
||||
*/
|
||||
tree.inorder();
|
||||
}
|
||||
|
||||
/**
|
||||
* A method to insert a new value in BST. If the given value is already present in BST the
|
||||
* insertion is ignored.
|
||||
*
|
||||
* @param data the value to be inserted
|
||||
*/
|
||||
public void add(int data) {
|
||||
Node parent = null;
|
||||
Node temp = this.root;
|
||||
int rightOrLeft = -1;
|
||||
/* Finds the proper place this node can
|
||||
* be placed in according to rules of BST.
|
||||
*/
|
||||
while (temp != null) {
|
||||
if (temp.data > data) {
|
||||
parent = temp;
|
||||
temp = parent.left;
|
||||
rightOrLeft = 0;
|
||||
} else if (temp.data < data) {
|
||||
parent = temp;
|
||||
temp = parent.right;
|
||||
rightOrLeft = 1;
|
||||
} else {
|
||||
System.out.println(data + " is already present in BST.");
|
||||
return; // if data already present we ignore insertion
|
||||
}
|
||||
}
|
||||
/* Creates a newNode with the value passed
|
||||
* Since this data doesn't already exists
|
||||
*/
|
||||
Node newNode = new Node(data);
|
||||
/* If the parent node is null
|
||||
* then the insertion is to be done in
|
||||
* root itself.
|
||||
*/
|
||||
if (parent == null) {
|
||||
this.root = newNode;
|
||||
} else {
|
||||
/* Check if insertion is to be made in
|
||||
* left or right subtree.
|
||||
*/
|
||||
if (rightOrLeft == 0) {
|
||||
parent.left = newNode;
|
||||
} else {
|
||||
parent.right = newNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A method to delete the node in BST. If node is present it will be deleted
|
||||
*
|
||||
* @param data the value that needs to be deleted
|
||||
*/
|
||||
public void remove(int data) {
|
||||
Node parent = null;
|
||||
Node temp = this.root;
|
||||
int rightOrLeft = -1;
|
||||
/* Find the parent of the node and node itself
|
||||
* That is to be deleted.
|
||||
* parent variable store parent
|
||||
* temp stores node itself.
|
||||
* rightOrLeft use to keep track weather child
|
||||
* is left or right subtree
|
||||
*/
|
||||
while (temp != null) {
|
||||
if (temp.data == data) {
|
||||
break;
|
||||
} else if (temp.data > data) {
|
||||
parent = temp;
|
||||
temp = parent.left;
|
||||
rightOrLeft = 0;
|
||||
} else {
|
||||
parent = temp;
|
||||
temp = parent.right;
|
||||
rightOrLeft = 1;
|
||||
}
|
||||
}
|
||||
/* If temp is null than node with given value is not
|
||||
* present in our tree.
|
||||
*/
|
||||
if (temp != null) {
|
||||
Node replacement; // used to store the new values for replacing nodes
|
||||
if (temp.right == null && temp.left == null) { // Leaf node Case
|
||||
replacement = null;
|
||||
} else if (temp.right == null) { // Node with only right child
|
||||
replacement = temp.left;
|
||||
temp.left = null;
|
||||
} else if (temp.left == null) { // Node with only left child
|
||||
replacement = temp.right;
|
||||
temp.right = null;
|
||||
} else {
|
||||
/* If both left and right child are present
|
||||
* we replace this nodes data with
|
||||
* leftmost node's data in its right subtree
|
||||
* to maintain the balance of BST.
|
||||
* And then delete that node
|
||||
*/
|
||||
if (temp.right.left == null) {
|
||||
temp.data = temp.right.data;
|
||||
replacement = temp;
|
||||
temp.right = temp.right.right;
|
||||
} else {
|
||||
Node parent2 = temp.right;
|
||||
Node child = temp.right.left;
|
||||
while (child.left != null) {
|
||||
parent2 = child;
|
||||
child = parent2.left;
|
||||
}
|
||||
temp.data = child.data;
|
||||
parent2.left = child.right;
|
||||
replacement = temp;
|
||||
}
|
||||
}
|
||||
/* Change references of parent after
|
||||
* deleting the child.
|
||||
*/
|
||||
if (parent == null) {
|
||||
this.root = replacement;
|
||||
} else {
|
||||
if (rightOrLeft == 0) {
|
||||
parent.left = replacement;
|
||||
} else {
|
||||
parent.right = replacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** A method for inorder traversal of BST. */
|
||||
public void inorder() {
|
||||
if (this.root == null) {
|
||||
System.out.println("This BST is empty.");
|
||||
return;
|
||||
}
|
||||
System.out.println("Inorder traversal of this tree is:");
|
||||
Stack<Node> st = new Stack<Node>();
|
||||
Node cur = this.root;
|
||||
while (cur != null || !st.empty()) {
|
||||
while (cur != null) {
|
||||
st.push(cur);
|
||||
cur = cur.left;
|
||||
}
|
||||
cur = st.pop();
|
||||
System.out.print(cur.data + " ");
|
||||
cur = cur.right;
|
||||
}
|
||||
System.out.println(); // for next line
|
||||
}
|
||||
|
||||
/** A method used to print postorder traversal of BST. */
|
||||
public void postorder() {
|
||||
if (this.root == null) {
|
||||
System.out.println("This BST is empty.");
|
||||
return;
|
||||
}
|
||||
System.out.println("Postorder traversal of this tree is:");
|
||||
Stack<Node> st = new Stack<Node>();
|
||||
Node cur = this.root, temp2;
|
||||
while (cur != null || !st.empty()) {
|
||||
if (cur != null) {
|
||||
st.push(cur);
|
||||
cur = cur.left;
|
||||
} else {
|
||||
temp2 = st.peek();
|
||||
if (temp2.right != null) {
|
||||
cur = temp2.right;
|
||||
} else {
|
||||
st.pop();
|
||||
while (!st.empty() && st.peek().right == temp2) {
|
||||
System.out.print(temp2.data + " ");
|
||||
temp2 = st.pop();
|
||||
}
|
||||
System.out.print(temp2.data + " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println(); // for next line
|
||||
}
|
||||
|
||||
/** Method used to display preorder traversal of BST. */
|
||||
public void preorder() {
|
||||
if (this.root == null) {
|
||||
System.out.println("This BST is empty.");
|
||||
return;
|
||||
}
|
||||
System.out.println("Preorder traversal of this tree is:");
|
||||
Stack<Node> st = new Stack<Node>();
|
||||
st.push(this.root);
|
||||
Node temp;
|
||||
while (!st.empty()) {
|
||||
temp = st.pop();
|
||||
System.out.print(temp.data + " ");
|
||||
if (temp.right != null) {
|
||||
st.push(temp.right);
|
||||
}
|
||||
if (temp.left != null) {
|
||||
st.push(temp.left);
|
||||
}
|
||||
}
|
||||
System.out.println(); // for next line
|
||||
}
|
||||
|
||||
/**
|
||||
* A method to check if given data exists in out Binary Search Tree.
|
||||
*
|
||||
* @param data the value that needs to be searched for
|
||||
* @return boolean representing if the value was find
|
||||
*/
|
||||
public boolean find(int data) {
|
||||
Node temp = this.root;
|
||||
/* Check if node exists
|
||||
*/
|
||||
while (temp != null) {
|
||||
if (temp.data > data) {
|
||||
temp = temp.left;
|
||||
} else if (temp.data < data) {
|
||||
temp = temp.right;
|
||||
} else {
|
||||
/* If found return true
|
||||
*/
|
||||
System.out.println(data + " is present in the BST.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
System.out.println(data + " not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/** The Node class used for building binary search tree */
|
||||
private static class Node {
|
||||
int data;
|
||||
Node left;
|
||||
Node right;
|
||||
|
||||
/** Constructor with data as parameter */
|
||||
Node(int d) {
|
||||
data = d;
|
||||
left = null;
|
||||
right = null;
|
||||
}
|
||||
}
|
||||
}
|
242
DataStructures/Trees/BSTRecursive.java
Normal file
242
DataStructures/Trees/BSTRecursive.java
Normal file
@ -0,0 +1,242 @@
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <h1>Binary Search Tree (Recursive)</h1>
|
||||
*
|
||||
* An implementation of BST recursively. In recursive implementation the checks are down the tree
|
||||
* First root is checked if not found then its childs are checked Binary Search Tree is a binary
|
||||
* tree which satisfies three properties: left child is less than root node, right child is grater
|
||||
* than root node, both left and right childs must themselves be a BST.
|
||||
*
|
||||
* <p>I have made public functions as methods and to actually implement recursive approach I have
|
||||
* used private methods
|
||||
*
|
||||
* @author [Lakhan Nad](https://github.com/Lakhan-Nad)
|
||||
*/
|
||||
public class BSTRecursive {
|
||||
/** only data member is root of BST */
|
||||
private Node root;
|
||||
|
||||
/** Constructor use to initialize node as null */
|
||||
BSTRecursive() {
|
||||
root = null;
|
||||
}
|
||||
|
||||
/** main function for tests */
|
||||
public static void main(String[] args) {
|
||||
BSTIterative tree = new BSTIterative();
|
||||
tree.add(5);
|
||||
tree.add(10);
|
||||
tree.add(9);
|
||||
assert !tree.find(4) : "4 is not yet present in BST";
|
||||
assert tree.find(10) : "10 should be present in BST";
|
||||
tree.remove(9);
|
||||
assert !tree.find(9) : "9 was just deleted from BST";
|
||||
tree.remove(1);
|
||||
assert !tree.find(1) : "Since 1 was not present so find deleting would do no change";
|
||||
tree.add(20);
|
||||
tree.add(70);
|
||||
assert tree.find(70) : "70 was inserted but not found";
|
||||
/*
|
||||
Will print in following order
|
||||
5 10 20 70
|
||||
*/
|
||||
tree.inorder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive method to delete a data if present in BST.
|
||||
*
|
||||
* @param node the current node to search for data
|
||||
* @param data the value to be deleted
|
||||
* @return Node the updated value of root parameter after delete operation
|
||||
*/
|
||||
private Node delete(Node node, int data) {
|
||||
if (node == null) {
|
||||
System.out.println("No such data present in BST.");
|
||||
} else if (node.data > data) {
|
||||
node.left = delete(node.left, data);
|
||||
} else if (node.data < data) {
|
||||
node.right = delete(node.right, data);
|
||||
} else {
|
||||
if (node.right == null && node.left == null) { // If it is leaf node
|
||||
node = null;
|
||||
} else if (node.left == null) { // If only right node is present
|
||||
Node temp = node.right;
|
||||
node.right = null;
|
||||
node = temp;
|
||||
} else if (node.right == null) { // Only left node is present
|
||||
Node temp = node.left;
|
||||
node.left = null;
|
||||
node = temp;
|
||||
} else { // both child are present
|
||||
Node temp = node.right;
|
||||
// Find leftmost child of right subtree
|
||||
while (temp.left != null) {
|
||||
temp = temp.left;
|
||||
}
|
||||
node.data = temp.data;
|
||||
node.right = delete(node.right, temp.data);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive insertion of value in BST.
|
||||
*
|
||||
* @param node to check if the data can be inserted in current node or its subtree
|
||||
* @param data the value to be inserted
|
||||
* @return the modified value of the root parameter after insertion
|
||||
*/
|
||||
private Node insert(Node node, int data) {
|
||||
if (node == null) {
|
||||
node = new Node(data);
|
||||
} else if (node.data > data) {
|
||||
node.left = insert(node.left, data);
|
||||
} else if (node.data < data) {
|
||||
node.right = insert(node.right, data);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively print Preorder traversal of the BST
|
||||
*
|
||||
* @param node the root node
|
||||
*/
|
||||
private void preOrder(Node node) {
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
System.out.print(node.data + " ");
|
||||
if (node.left != null) {
|
||||
preOrder(node.left);
|
||||
}
|
||||
if (node.right != null) {
|
||||
preOrder(node.right);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively print Postorder travesal of BST.
|
||||
*
|
||||
* @param node the root node
|
||||
*/
|
||||
private void postOrder(Node node) {
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
if (node.left != null) {
|
||||
postOrder(node.left);
|
||||
}
|
||||
if (node.right != null) {
|
||||
postOrder(node.right);
|
||||
}
|
||||
System.out.print(node.data + " ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively print Inorder traversal of BST.
|
||||
*
|
||||
* @param node the root node
|
||||
*/
|
||||
private void inOrder(Node node) {
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
if (node.left != null) {
|
||||
inOrder(node.left);
|
||||
}
|
||||
System.out.print(node.data + " ");
|
||||
if (node.right != null) {
|
||||
inOrder(node.right);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serach recursively if the given value is present in BST or not.
|
||||
*
|
||||
* @param node the current node to check
|
||||
* @param data the value to be checked
|
||||
* @return boolean if data is present or not
|
||||
*/
|
||||
private boolean search(Node node, int data) {
|
||||
if (node == null) {
|
||||
return false;
|
||||
} else if (node.data == data) {
|
||||
return true;
|
||||
} else if (node.data > data) {
|
||||
return search(node.left, data);
|
||||
} else {
|
||||
return search(node.right, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add in BST. if the value is not already present it is inserted or else no change takes place.
|
||||
*
|
||||
* @param data the value to be inserted
|
||||
*/
|
||||
public void add(int data) {
|
||||
this.root = insert(this.root, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* If data is present in BST delete it else do nothing.
|
||||
*
|
||||
* @param data the value to be removed
|
||||
*/
|
||||
public void remove(int data) {
|
||||
this.root = delete(this.root, data);
|
||||
}
|
||||
|
||||
/** To call inorder traversal on tree */
|
||||
public void inorder() {
|
||||
System.out.println("Inorder traversal of this tree is:");
|
||||
inOrder(this.root);
|
||||
System.out.println(); // for next line
|
||||
}
|
||||
|
||||
/** To call postorder traversal on tree */
|
||||
public void postorder() {
|
||||
System.out.println("Postorder traversal of this tree is:");
|
||||
postOrder(this.root);
|
||||
System.out.println(); // for next li
|
||||
}
|
||||
|
||||
/** To call preorder traversal on tree. */
|
||||
public void preorder() {
|
||||
System.out.println("Preorder traversal of this tree is:");
|
||||
preOrder(this.root);
|
||||
System.out.println(); // for next li
|
||||
}
|
||||
|
||||
/**
|
||||
* To check if given value is present in tree or not.
|
||||
*
|
||||
* @param data the data to be found for
|
||||
*/
|
||||
public boolean find(int data) {
|
||||
if (search(this.root, data)) {
|
||||
System.out.println(data + " is present in given BST.");
|
||||
return true;
|
||||
}
|
||||
System.out.println(data + " not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/** The Node class used for building binary search tree */
|
||||
private static class Node {
|
||||
int data;
|
||||
Node left;
|
||||
Node right;
|
||||
|
||||
/** Constructor with data as parameter */
|
||||
Node(int d) {
|
||||
data = d;
|
||||
left = null;
|
||||
right = null;
|
||||
}
|
||||
}
|
||||
}
|
259
DataStructures/Trees/BinaryTree.java
Normal file
259
DataStructures/Trees/BinaryTree.java
Normal file
@ -0,0 +1,259 @@
|
||||
package DataStructures.Trees;
|
||||
|
||||
/**
|
||||
* This entire class is used to build a Binary Tree data structure. There is the Node Class and the
|
||||
* Tree Class, both explained below.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A binary tree is a data structure in which an element has two successors(children). The left
|
||||
* child is usually smaller than the parent, and the right child is usually bigger.
|
||||
*
|
||||
* @author Unknown
|
||||
*/
|
||||
public class BinaryTree {
|
||||
|
||||
/**
|
||||
* This class implements the nodes that will go on the Binary Tree. They consist of the data in
|
||||
* them, the node to the left, the node to the right, and the parent from which they came from.
|
||||
*
|
||||
* @author Unknown
|
||||
*/
|
||||
class Node {
|
||||
/** Data for the node */
|
||||
public int data;
|
||||
/** The Node to the left of this one */
|
||||
public Node left;
|
||||
/** The Node to the right of this one */
|
||||
public Node right;
|
||||
/** The parent of this node */
|
||||
public Node parent;
|
||||
|
||||
/**
|
||||
* Constructor of Node
|
||||
*
|
||||
* @param value Value to put in the node
|
||||
*/
|
||||
public Node(int value) {
|
||||
data = value;
|
||||
left = null;
|
||||
right = null;
|
||||
parent = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** The root of the Binary Tree */
|
||||
private Node root;
|
||||
|
||||
/** Constructor */
|
||||
public BinaryTree() {
|
||||
root = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to find a Node with a certain value
|
||||
*
|
||||
* @param key Value being looked for
|
||||
* @return The node if it finds it, otherwise returns the parent
|
||||
*/
|
||||
public Node find(int key) {
|
||||
Node current = root;
|
||||
while (current != null) {
|
||||
if (key < current.data) {
|
||||
if (current.left == null) return current; // The key isn't exist, returns the parent
|
||||
current = current.left;
|
||||
} else if (key > current.data) {
|
||||
if (current.right == null) return current;
|
||||
current = current.right;
|
||||
} else { // If you find the value return it
|
||||
return current;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts certain value into the Binary Tree
|
||||
*
|
||||
* @param value Value to be inserted
|
||||
*/
|
||||
public void put(int value) {
|
||||
Node newNode = new Node(value);
|
||||
if (root == null) root = newNode;
|
||||
else {
|
||||
// This will return the soon to be parent of the value you're inserting
|
||||
Node parent = find(value);
|
||||
|
||||
// This if/else assigns the new node to be either the left or right child of the parent
|
||||
if (value < parent.data) {
|
||||
parent.left = newNode;
|
||||
parent.left.parent = parent;
|
||||
return;
|
||||
} else {
|
||||
parent.right = newNode;
|
||||
parent.right.parent = parent;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a given value from the Binary Tree
|
||||
*
|
||||
* @param value Value to be deleted
|
||||
* @return If the value was deleted
|
||||
*/
|
||||
public boolean remove(int value) {
|
||||
// temp is the node to be deleted
|
||||
Node temp = find(value);
|
||||
|
||||
// If the value doesn't exist
|
||||
if (temp.data != value) return false;
|
||||
|
||||
// No children
|
||||
if (temp.right == null && temp.left == null) {
|
||||
if (temp == root) root = null;
|
||||
|
||||
// This if/else assigns the new node to be either the left or right child of the parent
|
||||
else if (temp.parent.data < temp.data) temp.parent.right = null;
|
||||
else temp.parent.left = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Two children
|
||||
else if (temp.left != null && temp.right != null) {
|
||||
Node successor = findSuccessor(temp);
|
||||
|
||||
// The left tree of temp is made the left tree of the successor
|
||||
successor.left = temp.left;
|
||||
successor.left.parent = successor;
|
||||
|
||||
// If the successor has a right child, the child's grandparent is it's new parent
|
||||
if (successor.parent != temp) {
|
||||
if (successor.right != null) {
|
||||
successor.right.parent = successor.parent;
|
||||
successor.parent.left = successor.right;
|
||||
successor.right = temp.right;
|
||||
successor.right.parent = successor;
|
||||
} else {
|
||||
successor.parent.left = null;
|
||||
successor.right = temp.right;
|
||||
successor.right.parent = successor;
|
||||
}
|
||||
}
|
||||
|
||||
if (temp == root) {
|
||||
successor.parent = null;
|
||||
root = successor;
|
||||
return true;
|
||||
}
|
||||
|
||||
// If you're not deleting the root
|
||||
else {
|
||||
successor.parent = temp.parent;
|
||||
|
||||
// This if/else assigns the new node to be either the left or right child of the parent
|
||||
if (temp.parent.data < temp.data) temp.parent.right = successor;
|
||||
else temp.parent.left = successor;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// One child
|
||||
else {
|
||||
// If it has a right child
|
||||
if (temp.right != null) {
|
||||
if (temp == root) {
|
||||
root = temp.right;
|
||||
return true;
|
||||
}
|
||||
|
||||
temp.right.parent = temp.parent;
|
||||
|
||||
// Assigns temp to left or right child
|
||||
if (temp.data < temp.parent.data) temp.parent.left = temp.right;
|
||||
else temp.parent.right = temp.right;
|
||||
return true;
|
||||
}
|
||||
// If it has a left child
|
||||
else {
|
||||
if (temp == root) {
|
||||
root = temp.left;
|
||||
return true;
|
||||
}
|
||||
|
||||
temp.left.parent = temp.parent;
|
||||
|
||||
// Assigns temp to left or right side
|
||||
if (temp.data < temp.parent.data) temp.parent.left = temp.left;
|
||||
else temp.parent.right = temp.left;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method finds the Successor to the Node given. Move right once and go left down the tree as
|
||||
* far as you can
|
||||
*
|
||||
* @param n Node that you want to find the Successor of
|
||||
* @return The Successor of the node
|
||||
*/
|
||||
public Node findSuccessor(Node n) {
|
||||
if (n.right == null) return n;
|
||||
Node current = n.right;
|
||||
Node parent = n.right;
|
||||
while (current != null) {
|
||||
parent = current;
|
||||
current = current.left;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root of the Binary Tree
|
||||
*
|
||||
* @return the root of the Binary Tree
|
||||
*/
|
||||
public Node getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints leftChild - root - rightChild
|
||||
*
|
||||
* @param localRoot The local root of the binary tree
|
||||
*/
|
||||
public void inOrder(Node localRoot) {
|
||||
if (localRoot != null) {
|
||||
inOrder(localRoot.left);
|
||||
System.out.print(localRoot.data + " ");
|
||||
inOrder(localRoot.right);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints root - leftChild - rightChild
|
||||
*
|
||||
* @param localRoot The local root of the binary tree
|
||||
*/
|
||||
public void preOrder(Node localRoot) {
|
||||
if (localRoot != null) {
|
||||
System.out.print(localRoot.data + " ");
|
||||
preOrder(localRoot.left);
|
||||
preOrder(localRoot.right);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints rightChild - leftChild - root
|
||||
*
|
||||
* @param localRoot The local root of the binary tree
|
||||
*/
|
||||
public void postOrder(Node localRoot) {
|
||||
if (localRoot != null) {
|
||||
postOrder(localRoot.left);
|
||||
postOrder(localRoot.right);
|
||||
System.out.print(localRoot.data + " ");
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user