Skip to content

Commit

Permalink
Merge branch '2024fixes' into 2024_sem2
Browse files Browse the repository at this point in the history
AVL tree fixes etc. Radix sorts in menus etc also
  • Loading branch information
lee-naish committed Jan 8, 2025
2 parents f3ab1b9 + 55fc109 commit 817e0c2
Show file tree
Hide file tree
Showing 29 changed files with 13,672 additions and 14,984 deletions.
27,721 changes: 13,135 additions & 14,586 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 3 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@
"last 1 safari version"
]
},
"eslintConfig": {
"extends": "react-app"
},
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
Expand All @@ -58,6 +55,8 @@
]
},
"dependencies": {
"nth-check": ">=2.0.1",
"postcss": ">=8.4.31",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.14.3",
Expand Down Expand Up @@ -91,10 +90,7 @@
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"electron": "^31.4.0",
"enzyme": "^3.11.0",
"eslint": "^7.11.0",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.33.2",
"eslint-config-react-app": "^7.0.1",
"husky": "^4.2.5",
"jest": "^27.5.1",
"lint-staged": "^10.1.3",
Expand Down
218 changes: 131 additions & 87 deletions src/algorithms/controllers/AVLTreeInsertion.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion src/algorithms/controllers/BFS.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ export default {
);

const bfs = (s) => {

const Nodes = [s];
// Seen[s] <- True B8
visited[s] = true;
Expand Down
82 changes: 82 additions & 0 deletions src/algorithms/explanations/AVLExp original Dec 2024.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# AVL Trees

AVL trees are binary search trees that have additional rules to keep them balanced.
In an AVL tree search will always be O(log n), no matter what the input order.

## Binary Search Trees

A **binary tree** is either is either empty (Empty) or else it
it has a root node and two subtrees (which are binary trees).
The root node `t` has a key, `t.key`. Ordinarily it would also
hold other data (`t.data`), which the user would like to find by
searching for the key. Since this attribute has no impact on
how insertion and search take place, we disregard it here.
Note that a newly inserted node will always appear as a leaf
in the tree.
In a **binary search tree (BST)** the BST invariant is always maintained: for each
subtree t, with root key t.key, the left subtree, t.left,
contains no node with key greater than k, and the right subtree,
t.right, contains no node with key smaller than k.

## The left-left case

If the new key was added to the left child of the left child (the
left-left case) and the resulting tree is too unbalanced, the balance can be
restored with a "Right rotation" operation, as explained in the diagram
below. The 6 and 4 nodes and the edge between them rotate clockwise, and
the 5 node changes parents from 4 to 6. This reduces the distance from
the root to the 1 (where the new node was added), restoring the balance
(the distance to the node rooted at 7 is increased but this does not
cause the AVL tree balance condition to be violated). Right rotation is
done by calling rightRotate(t6), where t6 is the tree rooted at 6.

```
6 2
/ \ Right Rotation / \
2 7 - - - - - - - > 1 6
/ \ < - - - - - - - / \
1 4 Left Rotation 4 7
```

## The right-right case

The right-right case is the exact opposite. If the tree on the right in
the diagram above is too unbalanced due to insertion into the subtree
rooted at 7, we can call rightRotate(t2) to lift that subtree and lower
the 1 subtree.

## The left-right case (double rotation)

If the new key was added to the right child of the left child (the
left-right case) and the resulting tree is too unbalanced, the balance can be
restored with a left rotation at node 2 followed by a right rotation at
node 6.
```
6 Rotate 6 Rotate 4
/ \ left at 2 / \ right at 6 / \
2 7 - - - - - > 4 7 - - - - - > 2 6
/ \ / \ / \ / \
1 4 2 5 1 3 5 7
/ \ / \
3 5 1 3
```
Nodes in the subtree rooted at 4 (where the extra element was added,
making the tree unbalanced) are moved closer to the root.
Trees rooted at 1, 3, 5 and 7 are not affected, except the distances from
the root of 3, 5 and 7 are changed by one, affecting the overall balance.

## right-left case (double rotation):

If the new key was added to the left child of the right child (the
right-left case) and the resulting tree is too unbalanced, it is a mirror
image of the left-right case:

```
2 Rotate 2 Rotate 4
/ \ right at 6 / \ left at 2 / \
1 6 - - - - - > 1 4 - - - - - > 2 6
/ \ / \ / \ / \
4 7 3 6 1 3 5 7
/ \ / \
3 5 5 7
```
59 changes: 52 additions & 7 deletions src/algorithms/explanations/AVLExp.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,74 @@
# AVL Tree
# AVL Trees

A binary tree is either is either empty (Empty) or else it
An AVL tree is **self-balancing** binary search tree.

Because the AVL tree is always balanced, search will be *O(log n)*,
no matter what the order of the input data.

### Binary Search Trees

A **binary tree** is either is either empty (`Empty`) or else it
it has a root node and two subtrees (which are binary trees).
The root node t has a key, t.key. Ordinarily it would also
hold other data (t.data), which the user would like to find by
The root node `t` has a key, `t.key`. Ordinarily it would also
hold other data (`t.data`), which the user would like to find by
searching for the key. Since this attribute has no impact on
how insertion and search take place, we disregard it here.
Note that a newly inserted node will always appear as a leaf
in the tree. The BST invariant is always maintained: for each
in the tree.

In a **binary search tree (BST)** the BST invariant is always maintained:\
for each
subtree t, with root key t.key, the left subtree, t.left,
contains no node with key greater than k, and the right subtree,
t.right, contains no node with key smaller than k.

### AVL tree balancing

The AVL tree preserves the balance of the tree by (1) checking after every insertion to detect
when the tree has become unbalanced
and (2) performing one or more rotation operations to restore balance when necessary.
Unbalanced is defined as a difference of more than `1` between the heights of the left and right subtrees.

(Here **MAYBE insert small pictures, thumbnails?** to show -- unbalanced at gp of new node,
and also balanced at gp but unblanaced at ggp.)

A temporarily unbalanced AVL tree takes on one of two configurations, *zig-zag* or *zig-zig*. The
sequence of rotations depends on the configuration around the node where the imbalance is detected.

### Zig-zig case

The *zig-zig* configuration has two mirror-image cases: the child and grandchild nodes or subtrees of the unbalanced node are
either (1) both left subtrees or (2) both right subtrees.


## The left-left case

If the new key was added to the left child of the left child (the
left-left case) and the resulting tree is too unbalanced, the balance can be
restored with a "Right rotation" operation, as explained in the diagram
*left-left* case), the balance can be
restored with a single _**Right Rotation**_ operation.

Note that the imbalance may be located further up the tree than the immediate grandparent of the newly inserted node:

**Insert very small diagrams showing (a) imbalance of the grandparent-parent and (b) imbalance of the great grandparent**
*Note that all diagrams should hae nodes in BST order, and where the subtrees are not necessarily single nodes, represent them as subtree-triangles*
*Have arrow showing which node is not in blanace*


, as explained in the diagram
below. The 6 and 4 nodes and the edge between them rotate clockwise, and
the 5 node changes parents from 4 to 6. This reduces the distance from
the root to the 1 (where the new node was added), restoring the balance
(the distance to the node rooted at 7 is increased but this does not
cause the AVL tree balance condition to be violated). Right rotation is
done by calling rightRotate(t6), where t6 is the tree rooted at 6.

![Alt text if image doesn't open: AVL-left-left](images/AVL/AVL-left-left.jpg){width=120,height=50} This picture is from Greek for Geeks, and is only a placeholder to show proof of concept inserting diagrams, and to check things like size and cropping.






```
6 2
/ \ Right Rotation / \
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 6 additions & 11 deletions src/algorithms/parameters/ASTParam.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import MatrixParam from './helpers/MatrixParam';
import '../../styles/Param.scss';
import EuclideanMatrixParams from './helpers/EuclideanMatrixParams';
import PropTypes from 'prop-types'; // Import this for URL Param
import { withAlgorithmParams } from './helpers/urlHelpers' // Import this for URL Param
import { withAlgorithmParams, addURLGraph } from './helpers/urlHelpers'

// Note: 'A* Algorithm' currently used in EuclideanMatrixParams.js -
// change both or neither!
Expand Down Expand Up @@ -34,28 +34,23 @@ const GRAPH_EGS = [ // XXX think up better examples?
}];
function ASTParam( { mode, xyCoords, edgeWeights, size, start, end, heuristic, min, max } ) {
const [message, setMessage] = useState(null);
const graph_egs = [
{ name: 'URL Input Graph',
size: size || GRAPH_EGS[0].size,
coords: xyCoords || GRAPH_EGS[0].coords,
edges: edgeWeights || GRAPH_EGS[0].edges
}
]
let [start1, size1, graph_egs] =
addURLGraph(GRAPH_EGS, xyCoords, edgeWeights, start, DEFAULT_START);

return (
<>
{/* Matrix input */}
<EuclideanMatrixParams
name="aStar"
mode="find"
defaultSize={ size || DEFAULT_SIZE }
defaultStart={ start || DEFAULT_START }
defaultSize={ size1 }
defaultStart={ start1 }
defaultEnd={ end || DEFAULT_END }
heuristic = { heuristic || DEFAULT_HEUR }
min={ min || 1 }
max={ max || 49 }
symmetric
graphEgs={ graph_egs || GRAPH_EGS }
graphEgs={ graph_egs }
ALGORITHM_NAME={ASTAR}
EXAMPLE={ASTAR_EXAMPLE}
EXAMPLE2={ASTAR_EXAMPLE2}
Expand Down
19 changes: 7 additions & 12 deletions src/algorithms/parameters/BFSParam.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import MatrixParam from './helpers/MatrixParam';
import '../../styles/Param.scss';
import EuclideanMatrixParams from './helpers/EuclideanMatrixParams';
import PropTypes from 'prop-types'; // Import this for URL Param
import { withAlgorithmParams } from './helpers/urlHelpers' // Import this for URL Param
import { withAlgorithmParams, addURLGraph } from './helpers/urlHelpers'

const DEFAULT_SIZE = 5;
const BFS = 'BFS\'s';
Expand Down Expand Up @@ -33,27 +33,22 @@ const GRAPH_EGS = [ // XXX think up better examples?

function BFSParam({ mode, xyCoords, edgeWeights, size, start, end, heuristic, min, max }) {
const [message, setMessage] = useState(null);
const graph_egs = [
{ name: 'URL Input Graph',
size: size || GRAPH_EGS[0].size,
coords: xyCoords || GRAPH_EGS[0].coords,
edges: edgeWeights || GRAPH_EGS[0].edges
}
]
let [start1, size1, graph_egs] =
addURLGraph(GRAPH_EGS, xyCoords, edgeWeights, start, DEFAULT_START);
return (
<>
{/* Matrix input */}
<EuclideanMatrixParams
name="BFS"
mode="find"
defaultSize={ size || DEFAULT_SIZE }
defaultStart={ start || DEFAULT_START }
defaultSize={ size1 }
defaultStart={ start1 }
defaultEnd={ end || DEFAULT_END }
defaultHeur = { heuristic || DEFAULT_HEUR }
defaultHeur = { DEFAULT_HEUR }
min={ min || 1 }
max={ max || 49 }
symmetric
graphEgs={ graph_egs || GRAPH_EGS }
graphEgs={ graph_egs }
ALGORITHM_NAME={BFS}
EXAMPLE={BFS_EXAMPLE}
EXAMPLE2={BFS_EXAMPLE2}
Expand Down
19 changes: 7 additions & 12 deletions src/algorithms/parameters/DFSParam.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import MatrixParam from './helpers/MatrixParam';
import '../../styles/Param.scss';
import EuclideanMatrixParams from './helpers/EuclideanMatrixParams';
import PropTypes from 'prop-types'; // Import this for URL Param
import { withAlgorithmParams } from './helpers/urlHelpers' // Import this for URL Param
import { withAlgorithmParams, addURLGraph } from './helpers/urlHelpers'

const DEFAULT_SIZE = 5;
const DFS = 'DFS\'s';
Expand Down Expand Up @@ -33,26 +33,21 @@ const GRAPH_EGS = [ // XXX think up better examples?

function DFSParam({ mode, xyCoords, edgeWeights, size, start, end, heuristic, min, max }) {
const [message, setMessage] = useState(null);
const graph_egs = [
{ name: 'URL Input Graph',
size: size || GRAPH_EGS[0].size,
coords: xyCoords || GRAPH_EGS[0].coords,
edges: edgeWeights || GRAPH_EGS[0].edges
}
]
let [start1, size1, graph_egs] =
addURLGraph(GRAPH_EGS, xyCoords, edgeWeights, start, DEFAULT_START);
return (
<>
{/* Matrix input */}
<EuclideanMatrixParams
name="DFS"
mode= "find"
defaultSize={ size || DEFAULT_SIZE }
defaultStart={start || DEFAULT_START }
defaultHeur = {heuristic || DEFAULT_HEUR }
defaultSize={ size1 }
defaultStart={ start1 }
defaultEnd={ end || DEFAULT_END }
defaultHeur = {DEFAULT_HEUR }
min={ min || 1 }
max={ max || 49 }
graphEgs={graph_egs || GRAPH_EGS}
graphEgs={graph_egs}
symmetric
ALGORITHM_NAME={DFS}
EXAMPLE={DFS_EXAMPLE}
Expand Down
19 changes: 7 additions & 12 deletions src/algorithms/parameters/DFSrecParam.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import MatrixParam from './helpers/MatrixParam';
import '../../styles/Param.scss';
import EuclideanMatrixParams from './helpers/EuclideanMatrixParams';
import PropTypes from 'prop-types'; // Import this for URL Param
import { withAlgorithmParams } from './helpers/urlHelpers' // Import this for URL Param
import { withAlgorithmParams, addURLGraph } from './helpers/urlHelpers'

const DEFAULT_SIZE = 5;
const DFSrec = 'DFSrec\'s';
Expand Down Expand Up @@ -33,27 +33,22 @@ const GRAPH_EGS = [ // XXX think up better examples?

function DFSrecParam({ mode, xyCoords, edgeWeights, size, start, end, heuristic, min, max }) {
const [message, setMessage] = useState(null);
const graph_egs = [
{ name: 'URL Input Graph',
size: size || GRAPH_EGS[0].size,
coords: xyCoords || GRAPH_EGS[0].coords,
edges: edgeWeights || GRAPH_EGS[0].edges
}
]
let [start1, size1, graph_egs] =
addURLGraph(GRAPH_EGS, xyCoords, edgeWeights, start, DEFAULT_START);

return (
<>
{/* Matrix input */}
<EuclideanMatrixParams
name="DFSrec"
mode="find"
defaultSize={size || DEFAULT_SIZE}
defaultStart={start || DEFAULT_START}
defaultHeur = {heuristic || DEFAULT_HEUR}
defaultSize={ size1 }
defaultStart={ start1 }
defaultHeur = {DEFAULT_HEUR}
defaultEnd={end || DEFAULT_END}
min={min || 1}
max={max || 49}
graphEgs={graph_egs || GRAPH_EGS}
graphEgs={graph_egs}
symmetric
ALGORITHM_NAME={DFSrec}
EXAMPLE={DFSrec_EXAMPLE}
Expand Down
Loading

0 comments on commit 817e0c2

Please sign in to comment.