Fomrat the JS and TS codes with prettier.

This commit is contained in:
krahets 2023-04-17 21:58:11 +08:00
parent 9a98ff8a5e
commit c4ea4e39f3
68 changed files with 634 additions and 510 deletions

View file

@ -0,0 +1,6 @@
{
"tabWidth": 4,
"useTabs": false,
"semi": true,
"singleQuote": true
}

View file

@ -69,29 +69,29 @@ function find(nums, target) {
/* Driver Codes*/
/* 初始化数组 */
const arr = new Array(5).fill(0);
console.log("数组 arr =", arr);
console.log('数组 arr =', arr);
let nums = [1, 3, 2, 5, 4];
console.log("数组 nums =", nums);
console.log('数组 nums =', nums);
/* 随机访问 */
let random_num = randomAccess(nums);
console.log("在 nums 中获取随机元素", random_num);
console.log('在 nums 中获取随机元素', random_num);
/* 长度扩展 */
nums = extend(nums, 3);
console.log("将数组长度扩展至 8 ,得到 nums =", nums);
console.log('将数组长度扩展至 8 ,得到 nums =', nums);
/* 插入元素 */
insert(nums, 6, 3);
console.log("在索引 3 处插入数字 6 ,得到 nums =", nums);
console.log('在索引 3 处插入数字 6 ,得到 nums =', nums);
/* 删除元素 */
remove(nums, 2);
console.log("删除索引 2 处的元素,得到 nums =", nums);
console.log('删除索引 2 处的元素,得到 nums =', nums);
/* 遍历数组 */
traverse(nums);
/* 查找元素 */
let index = find(nums, 3);
console.log("在 nums 中查找元素 3 ,得到索引 =", index);
console.log('在 nums 中查找元素 3 ,得到索引 =', index);

View file

@ -4,8 +4,8 @@
* Author: IsChristina (christinaxia77@foxmail.com), Justin (xiefahit@gmail.com)
*/
const { printLinkedList } = require("../modules/PrintUtil");
const { ListNode } = require("../modules/ListNode");
const { printLinkedList } = require('../modules/PrintUtil');
const { ListNode } = require('../modules/ListNode');
/* 在链表的节点 n0 之后插入节点 P */
function insert(n0, P) {
@ -16,8 +16,7 @@ function insert(n0, P) {
/* 删除链表的节点 n0 之后的首个节点 */
function remove(n0) {
if (!n0.next)
return;
if (!n0.next) return;
// n0 -> P -> n1
const P = n0.next;
const n1 = P.next;
@ -61,23 +60,23 @@ n0.next = n1;
n1.next = n2;
n2.next = n3;
n3.next = n4;
console.log("初始化的链表为");
console.log('初始化的链表为');
printLinkedList(n0);
/* 插入节点 */
insert(n0, new ListNode(0));
console.log("插入节点后的链表为");
console.log('插入节点后的链表为');
printLinkedList(n0);
/* 删除节点 */
remove(n0);
console.log("删除节点后的链表为");
console.log('删除节点后的链表为');
printLinkedList(n0);
/* 访问节点 */
const node = access(n0, 3);
console.log("链表中索引 3 处的节点的值 = " + node.val);
console.log('链表中索引 3 处的节点的值 = ' + node.val);
/* 查找节点 */
const index = find(n0, 2);
console.log("链表中值为 2 的节点的索引 = " + index);
console.log('链表中值为 2 的节点的索引 = ' + index);

View file

@ -29,15 +29,13 @@ class MyList {
/* 访问元素 */
get(index) {
// 索引如果越界则抛出异常,下同
if (index < 0 || index >= this.#size)
throw new Error('索引越界');
if (index < 0 || index >= this.#size) throw new Error('索引越界');
return this.#nums[index];
}
/* 更新元素 */
set(index, num) {
if (index < 0 || index >= this.#size)
throw new Error('索引越界');
if (index < 0 || index >= this.#size) throw new Error('索引越界');
this.#nums[index] = num;
}
@ -54,8 +52,7 @@ class MyList {
/* 中间插入元素 */
insert(index, num) {
if (index < 0 || index >= this.#size)
throw new Error('索引越界');
if (index < 0 || index >= this.#size) throw new Error('索引越界');
// 元素数量超出容量时,触发扩容机制
if (this.#size === this.#capacity) {
this.extendCapacity();
@ -71,8 +68,7 @@ class MyList {
/* 删除元素 */
remove(index) {
if (index < 0 || index >= this.#size)
throw new Error('索引越界');
if (index < 0 || index >= this.#size) throw new Error('索引越界');
let num = this.#nums[index];
// 将索引 index 之后的元素都向前移动一位
for (let j = index; j < this.#size - 1; j++) {

View file

@ -7,16 +7,19 @@
/* 二分查找(双闭区间) */
function binarySearch(nums, target) {
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
let i = 0, j = nums.length - 1;
let i = 0,
j = nums.length - 1;
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
while (i <= j) {
const m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
// 计算中点索引 m ,使用 parseInt() 向下取整
const m = parseInt((i + j) / 2);
if (nums[m] < target)
// 此情况说明 target 在区间 [m+1, j] 中
i = m + 1;
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
else if (nums[m] > target)
// 此情况说明 target 在区间 [i, m-1] 中
j = m - 1;
else
return m; // 找到目标元素,返回其索引
else return m; // 找到目标元素,返回其索引
}
// 未找到目标元素,返回 -1
return -1;
@ -25,16 +28,20 @@ function binarySearch(nums, target) {
/* 二分查找(左闭右开) */
function binarySearch1(nums, target) {
// 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
let i = 0, j = nums.length;
let i = 0,
j = nums.length;
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
while (i < j) {
const m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
// 计算中点索引 m ,使用 parseInt() 向下取整
const m = parseInt((i + j) / 2);
if (nums[m] < target)
// 此情况说明 target 在区间 [m+1, j) 中
i = m + 1;
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
else if (nums[m] > target)
// 此情况说明 target 在区间 [i, m) 中
j = m;
else // 找到目标元素,返回其索引
return m;
// 找到目标元素,返回其索引
else return m;
}
// 未找到目标元素,返回 -1
return -1;
@ -46,8 +53,8 @@ const nums = [1, 3, 6, 8, 12, 15, 23, 67, 70, 92];
/* 二分查找(双闭区间) */
let index = binarySearch(nums, target);
console.log("目标元素 6 的索引 = " + index);
console.log('目标元素 6 的索引 = ' + index);
/* 二分查找(左闭右开) */
index = binarySearch1(nums, target);
console.log("目标元素 6 的索引 = " + index);
console.log('目标元素 6 的索引 = ' + index);

View file

@ -57,7 +57,9 @@ function linearRecur(n) {
/* 平方阶 */
function quadratic(n) {
// 矩阵占用 O(n^2) 空间
const numMatrix = Array(n).fill(null).map(() => Array(n).fill(null));
const numMatrix = Array(n)
.fill(null)
.map(() => Array(n).fill(null));
// 二维列表占用 O(n^2) 空间
const numList = [];
for (let i = 0; i < n; i++) {

View file

@ -121,35 +121,35 @@ function factorialRecur(n) {
/* Driver Code */
// 可以修改 n 运行,体会一下各种复杂度的操作数量变化趋势
const n = 8;
console.log("输入数据大小 n = " + n);
console.log('输入数据大小 n = ' + n);
let count = constant(n);
console.log("常数阶的计算操作数量 = " + count);
console.log('常数阶的计算操作数量 = ' + count);
count = linear(n);
console.log("线性阶的计算操作数量 = " + count);
console.log('线性阶的计算操作数量 = ' + count);
count = arrayTraversal(new Array(n));
console.log("线性阶(遍历数组)的计算操作数量 = " + count);
console.log('线性阶(遍历数组)的计算操作数量 = ' + count);
count = quadratic(n);
console.log("平方阶的计算操作数量 = " + count);
console.log('平方阶的计算操作数量 = ' + count);
let nums = new Array(n);
for (let i = 0; i < n; i++) nums[i] = n - i; // [n,n-1,...,2,1]
count = bubbleSort(nums);
console.log("平方阶(冒泡排序)的计算操作数量 = " + count);
console.log('平方阶(冒泡排序)的计算操作数量 = ' + count);
count = exponential(n);
console.log("指数阶(循环实现)的计算操作数量 = " + count);
console.log('指数阶(循环实现)的计算操作数量 = ' + count);
count = expRecur(n);
console.log("指数阶(递归实现)的计算操作数量 = " + count);
console.log('指数阶(递归实现)的计算操作数量 = ' + count);
count = logarithmic(n);
console.log("对数阶(循环实现)的计算操作数量 = " + count);
console.log('对数阶(循环实现)的计算操作数量 = ' + count);
count = logRecur(n);
console.log("对数阶(递归实现)的计算操作数量 = " + count);
console.log('对数阶(递归实现)的计算操作数量 = ' + count);
count = linearLogRecur(n);
console.log("线性对数阶(递归实现)的计算操作数量 = " + count);
console.log('线性对数阶(递归实现)的计算操作数量 = ' + count);
count = factorialRecur(n);
console.log("阶乘阶(递归实现)的计算操作数量 = " + count);
console.log('阶乘阶(递归实现)的计算操作数量 = ' + count);

View file

@ -38,8 +38,6 @@ for (let i = 0; i < 10; i++) {
const n = 100;
const nums = randomNumbers(n);
const index = findOne(nums);
console.log(
"\n数组 [ 1, 2, ..., n ] 被打乱后 = [" + nums.join(", ") + "]"
);
console.log("数字 1 的索引为 " + index);
console.log('\n数组 [ 1, 2, ..., n ] 被打乱后 = [' + nums.join(', ') + ']');
console.log('数字 1 的索引为 ' + index);
}

View file

@ -4,7 +4,7 @@
* Author: Justin (xiefahit@gmail.com)
*/
const { Vertex } = require('../modules/Vertex')
const { Vertex } = require('../modules/Vertex');
/* 基于邻接表实现的无向图类 */
class GraphAdjList {
@ -29,8 +29,12 @@ class GraphAdjList {
/* 添加边 */
addEdge(vet1, vet2) {
if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) {
throw new Error("Illegal Argument Exception");
if (
!this.adjList.has(vet1) ||
!this.adjList.has(vet2) ||
vet1 === vet2
) {
throw new Error('Illegal Argument Exception');
}
// 添加边 vet1 - vet2
this.adjList.get(vet1).push(vet2);
@ -39,8 +43,12 @@ class GraphAdjList {
/* 删除边 */
removeEdge(vet1, vet2) {
if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) {
throw new Error("Illegal Argument Exception");
if (
!this.adjList.has(vet1) ||
!this.adjList.has(vet2) ||
vet1 === vet2
) {
throw new Error('Illegal Argument Exception');
}
// 删除边 vet1 - vet2
this.adjList.get(vet1).splice(this.adjList.get(vet1).indexOf(vet2), 1);
@ -57,7 +65,7 @@ class GraphAdjList {
/* 删除顶点 */
removeVertex(vet) {
if (!this.adjList.has(vet)) {
throw new Error("Illegal Argument Exception");
throw new Error('Illegal Argument Exception');
}
// 在邻接表中删除顶点 vet 对应的链表
this.adjList.delete(vet);
@ -72,13 +80,13 @@ class GraphAdjList {
/* 打印邻接表 */
print() {
console.log("邻接表 =");
console.log('邻接表 =');
for (const [key, value] of this.adjList) {
const tmp = [];
for (const vertex of value) {
tmp.push(vertex.val);
}
console.log(key.val + ": " + tmp.join());
console.log(key.val + ': ' + tmp.join());
}
}
}
@ -91,37 +99,43 @@ if (require.main === module) {
v2 = new Vertex(2),
v3 = new Vertex(5),
v4 = new Vertex(4);
const edges = [[v0, v1], [v1, v2], [v2, v3], [v0, v3], [v2, v4], [v3, v4]];
const edges = [
[v0, v1],
[v1, v2],
[v2, v3],
[v0, v3],
[v2, v4],
[v3, v4],
];
const graph = new GraphAdjList(edges);
console.log("\n初始化后图为");
console.log('\n初始化后图为');
graph.print();
/* 添加边 */
// 顶点 1, 2 即 v0, v2
graph.addEdge(v0, v2);
console.log("\n添加边 1-2 后,图为");
console.log('\n添加边 1-2 后,图为');
graph.print();
/* 删除边 */
// 顶点 1, 3 即 v0, v1
graph.removeEdge(v0, v1);
console.log("\n删除边 1-3 后,图为");
console.log('\n删除边 1-3 后,图为');
graph.print();
/* 添加顶点 */
const v5 = new Vertex(6);
graph.addVertex(v5);
console.log("\n添加顶点 6 后,图为");
console.log('\n添加顶点 6 后,图为');
graph.print();
/* 删除顶点 */
// 顶点 3 即 v1
graph.removeVertex(v1);
console.log("\n删除顶点 3 后,图为");
console.log('\n删除顶点 3 后,图为');
graph.print();
}
module.exports = {
GraphAdjList
GraphAdjList,
};

View file

@ -6,8 +6,8 @@
/* 基于邻接矩阵实现的无向图类 */
class GraphAdjMat {
vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
adjMat; // 邻接矩阵,行列索引对应“顶点索引”
vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
adjMat; // 邻接矩阵,行列索引对应“顶点索引”
/* 构造函数 */
constructor(vertices, edges) {
@ -49,7 +49,7 @@ class GraphAdjMat {
/* 删除顶点 */
removeVertex(index) {
if (index >= this.size()) {
throw new RangeError("Index Out Of Bounds Exception");
throw new RangeError('Index Out Of Bounds Exception');
}
// 在顶点列表中移除索引 index 的顶点
this.vertices.splice(index, 1);
@ -67,7 +67,7 @@ class GraphAdjMat {
addEdge(i, j) {
// 索引越界与相等处理
if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) {
throw new RangeError("Index Out Of Bounds Exception");
throw new RangeError('Index Out Of Bounds Exception');
}
// 在无向图中,邻接矩阵沿主对角线对称,即满足 (i, j) == (j, i)
this.adjMat[i][j] = 1;
@ -79,7 +79,7 @@ class GraphAdjMat {
removeEdge(i, j) {
// 索引越界与相等处理
if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) {
throw new RangeError("Index Out Of Bounds Exception");
throw new RangeError('Index Out Of Bounds Exception');
}
this.adjMat[i][j] = 0;
this.adjMat[j][i] = 0;
@ -87,8 +87,8 @@ class GraphAdjMat {
/* 打印邻接矩阵 */
print() {
console.log("顶点列表 = ", this.vertices);
console.log("邻接矩阵 =", this.adjMat);
console.log('顶点列表 = ', this.vertices);
console.log('邻接矩阵 =', this.adjMat);
}
}
@ -96,32 +96,37 @@ class GraphAdjMat {
/* 初始化无向图 */
// 请注意edges 元素代表顶点索引,即对应 vertices 元素索引
const vertices = [1, 3, 2, 5, 4];
const edges = [[0, 1], [1, 2], [2, 3], [0, 3], [2, 4], [3, 4]
const edges = [
[0, 1],
[1, 2],
[2, 3],
[0, 3],
[2, 4],
[3, 4],
];
const graph = new GraphAdjMat(vertices, edges);
console.log("\n初始化后图为");
console.log('\n初始化后图为');
graph.print();
/* 添加边 */
// 顶点 1, 2 的索引分别为 0, 2
graph.addEdge(0, 2);
console.log("\n添加边 1-2 后,图为");
console.log('\n添加边 1-2 后,图为');
graph.print();
/* 删除边 */
// 顶点 1, 3 的索引分别为 0, 1
graph.removeEdge(0, 1);
console.log("\n删除边 1-3 后,图为");
console.log('\n删除边 1-3 后,图为');
graph.print();
/* 添加顶点 */
graph.addVertex(6);
console.log("\n添加顶点 6 后,图为");
console.log('\n添加顶点 6 后,图为');
graph.print();
/* 删除顶点 */
// 顶点 3 的索引为 1
graph.removeVertex(1);
console.log("\n删除顶点 3 后,图为");
console.log('\n删除顶点 3 后,图为');
graph.print();

View file

@ -19,15 +19,15 @@ function graphBFS(graph, startVet) {
const que = [startVet];
// 以顶点 vet 为起点,循环直至访问完所有顶点
while (que.length) {
const vet = que.shift(); // 队首顶点出队
res.push(vet); // 记录访问顶点
const vet = que.shift(); // 队首顶点出队
res.push(vet); // 记录访问顶点
// 遍历该顶点的所有邻接顶点
for (const adjVet of graph.adjList.get(vet) ?? []) {
if (visited.has(adjVet)) {
continue; // 跳过已被访问过的顶点
continue; // 跳过已被访问过的顶点
}
que.push(adjVet); // 只入队未访问的顶点
visited.add(adjVet); // 标记该顶点已被访问
que.push(adjVet); // 只入队未访问的顶点
visited.add(adjVet); // 标记该顶点已被访问
}
}
// 返回顶点遍历序列
@ -37,14 +37,25 @@ function graphBFS(graph, startVet) {
/* Driver Code */
/* 初始化无向图 */
const v = Vertex.valsToVets([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
const edges = [[v[0], v[1]], [v[0], v[3]], [v[1], v[2]], [v[1], v[4]],
[v[2], v[5]], [v[3], v[4]], [v[3], v[6]], [v[4], v[5]],
[v[4], v[7]], [v[5], v[8]], [v[6], v[7]], [v[7], v[8]]];
const edges = [
[v[0], v[1]],
[v[0], v[3]],
[v[1], v[2]],
[v[1], v[4]],
[v[2], v[5]],
[v[3], v[4]],
[v[3], v[6]],
[v[4], v[5]],
[v[4], v[7]],
[v[5], v[8]],
[v[6], v[7]],
[v[7], v[8]],
];
const graph = new GraphAdjList(edges);
console.log("\n初始化后图为");
console.log('\n初始化后图为');
graph.print();
/* 广度优先遍历 BFS */
const res = graphBFS(graph, v[0]);
console.log("\n广度优先遍历BFS顶点序列为");
console.log('\n广度优先遍历BFS顶点序列为');
console.log(Vertex.vetsToVals(res));

View file

@ -10,8 +10,8 @@ const { GraphAdjList } = require('./graph_adjacency_list');
/* 深度优先遍历 DFS */
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
function dfs(graph, visited, res, vet) {
res.push(vet); // 记录访问顶点
visited.add(vet); // 标记该顶点已被访问
res.push(vet); // 记录访问顶点
visited.add(vet); // 标记该顶点已被访问
// 遍历该顶点的所有邻接顶点
for (const adjVet of graph.adjList.get(vet)) {
if (visited.has(adjVet)) {
@ -36,13 +36,19 @@ function graphDFS(graph, startVet) {
/* Driver Code */
/* 初始化无向图 */
const v = Vertex.valsToVets([0, 1, 2, 3, 4, 5, 6]);
const edges = [[v[0], v[1]], [v[0], v[3]], [v[1], v[2]],
[v[2], v[5]], [v[4], v[5]], [v[5], v[6]]];
const edges = [
[v[0], v[1]],
[v[0], v[3]],
[v[1], v[2]],
[v[2], v[5]],
[v[4], v[5]],
[v[5], v[6]],
];
const graph = new GraphAdjList(edges);
console.log("\n初始化后图为");
console.log('\n初始化后图为');
graph.print();
/* 深度优先遍历 DFS */
const res = graphDFS(graph, v[0]);
console.log("\n深度优先遍历DFS顶点序列为");
console.log('\n深度优先遍历DFS顶点序列为');
console.log(Vertex.vetsToVals(res));

View file

@ -4,7 +4,7 @@
* Author: what-is-me (whatisme@outlook.jp)
*/
const { printHeap } = require("../modules/PrintUtil");
const { printHeap } = require('../modules/PrintUtil');
/* 最大堆类 */
class MaxHeap {
@ -84,7 +84,7 @@ class MaxHeap {
/* 元素出堆 */
pop() {
// 判空处理
if (this.isEmpty()) throw new Error("堆为空");
if (this.isEmpty()) throw new Error('堆为空');
// 交换根节点与最右叶节点(即交换首元素与尾元素)
this.#swap(0, this.size() - 1);
// 删除节点
@ -122,7 +122,7 @@ class MaxHeap {
/* Driver Code */
/* 初始化大顶堆 */
const maxHeap = new MaxHeap([9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2]);
console.log("\n输入列表并建堆后");
console.log('\n输入列表并建堆后');
maxHeap.print();
/* 获取堆顶元素 */

View file

@ -4,7 +4,7 @@
* Author: Zhuo Qinyue (1403450829@qq.com)
*/
const { arrToLinkedList } = require("../modules/ListNode");
const { arrToLinkedList } = require('../modules/ListNode');
/* 哈希查找(数组) */
function hashingSearchArray(map, target) {
@ -28,18 +28,18 @@ const nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8];
// 初始化哈希表
const map = new Map();
for (let i = 0; i < nums.length; i++) {
map.set(nums[i], i); // key: 元素value: 索引
map.set(nums[i], i); // key: 元素value: 索引
}
const index = hashingSearchArray(map, target);
console.log("目标元素 3 的索引 = " + index);
console.log('目标元素 3 的索引 = ' + index);
/* 哈希查找(链表) */
let head = arrToLinkedList(nums)
let head = arrToLinkedList(nums);
// 初始化哈希表
const map1 = new Map();
while (head != null) {
map1.set(head.val, head); // key: 节点值value: 节点
map1.set(head.val, head); // key: 节点值value: 节点
head = head.next;
}
const node = hashingSearchLinkedList(map1, target);
console.log("目标节点值 3 的对应节点对象为", node);
console.log('目标节点值 3 的对应节点对象为', node);

View file

@ -35,11 +35,12 @@ function twoSumHashTable(nums, target) {
/* Driver Code */
// 方法一
const nums = [2, 7, 11, 15], target = 9;
const nums = [2, 7, 11, 15],
target = 9;
let res = twoSumBruteForce(nums, target);
console.log("方法一 res = ", res);
console.log('方法一 res = ', res);
// 方法二
res = twoSumHashTable(nums, target);
console.log("方法二 res = ", res);
console.log('方法二 res = ', res);

View file

@ -4,7 +4,7 @@
* Author: JoseHung (szhong@link.cuhk.edu.hk)
*/
const { ListNode, arrToLinkedList } = require("../modules/ListNode");
const { ListNode, arrToLinkedList } = require('../modules/ListNode');
/* 线性查找(数组) */
function linearSearchArray(nums, target) {
@ -16,15 +16,15 @@ function linearSearchArray(nums, target) {
}
}
// 未找到目标元素,返回 -1
return -1;
return -1;
}
/* 线性查找(链表)*/
function linearSearchLinkedList(head, target) {
// 遍历链表
while(head) {
while (head) {
// 找到目标节点,返回之
if(head.val === target) {
if (head.val === target) {
return head;
}
head = head.next;
@ -39,9 +39,9 @@ const target = 3;
/* 在数组中执行线性查找 */
const nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8];
const index = linearSearchArray(nums, target);
console.log("目标元素 3 的索引 = " + index);
console.log('目标元素 3 的索引 = ' + index);
/* 在链表中执行线性查找 */
const head = arrToLinkedList(nums);
const node = linearSearchLinkedList(head, target);
console.log("目标节点值 3 的对应节点对象为 ", node);
console.log('目标节点值 3 的对应节点对象为 ', node);

View file

@ -32,18 +32,18 @@ function bubbleSortWithFlag(nums) {
let tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
flag = true; // 记录交换元素
flag = true; // 记录交换元素
}
}
if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出
if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出
}
}
/* Driver Code */
const nums = [4, 1, 3, 1, 5, 2];
bubbleSort(nums);
console.log("排序后数组 nums =", nums);
console.log('排序后数组 nums =', nums);
const nums1 = [4, 1, 3, 1, 5, 2];
bubbleSortWithFlag(nums1);
console.log("排序后数组 nums =", nums1);
console.log('排序后数组 nums =', nums1);

View file

@ -8,13 +8,14 @@
function insertionSort(nums) {
// 外循环base = nums[1], nums[2], ..., nums[n-1]
for (let i = 1; i < nums.length; i++) {
let base = nums[i], j = i - 1;
let base = nums[i],
j = i - 1;
// 内循环:将 base 插入到左边的正确位置
while (j >= 0 && nums[j] > base) {
nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位
nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位
j--;
}
nums[j + 1] = base; // 2. 将 base 赋值到正确位置
nums[j + 1] = base; // 2. 将 base 赋值到正确位置
}
}

View file

@ -9,23 +9,26 @@
// 右子数组区间 [mid + 1, right]
function merge(nums, left, mid, right) {
// 初始化辅助数组
let tmp = nums.slice(left, right + 1);
// 左子数组的起始索引和结束索引
let leftStart = left - left, leftEnd = mid - left;
// 右子数组的起始索引和结束索引
let rightStart = mid + 1 - left, rightEnd = right - left;
let tmp = nums.slice(left, right + 1);
// 左子数组的起始索引和结束索引
let leftStart = left - left,
leftEnd = mid - left;
// 右子数组的起始索引和结束索引
let rightStart = mid + 1 - left,
rightEnd = right - left;
// i, j 分别指向左子数组、右子数组的首元素
let i = leftStart, j = rightStart;
let i = leftStart,
j = rightStart;
// 通过覆盖原数组 nums 来合并左子数组和右子数组
for (let k = left; k <= right; k++) {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
if (i > leftEnd) {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
nums[k] = tmp[j++];
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
} else if (j > rightEnd || tmp[i] <= tmp[j]) {
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
nums[k] = tmp[i++];
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
} else {
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
nums[k] = tmp[j++];
}
}
@ -34,10 +37,10 @@ function merge(nums, left, mid, right) {
/* 归并排序 */
function mergeSort(nums, left, right) {
// 终止条件
if (left >= right) return; // 当子数组长度为 1 时终止递归
if (left >= right) return; // 当子数组长度为 1 时终止递归
// 划分阶段
let mid = Math.floor((left + right) / 2); // 计算中点
mergeSort(nums, left, mid); // 递归左子数组
let mid = Math.floor((left + right) / 2); // 计算中点
mergeSort(nums, left, mid); // 递归左子数组
mergeSort(nums, mid + 1, right); // 递归右子数组
// 合并阶段
merge(nums, left, mid, right);

View file

@ -16,7 +16,8 @@ class QuickSort {
/* 哨兵划分 */
partition(nums, left, right) {
// 以 nums[left] 作为基准数
let i = left, j = right;
let i = left,
j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left]) {
j -= 1; // 从右向左找首个小于基准数的元素
@ -57,18 +58,25 @@ class QuickSortMedian {
// 此处使用异或运算来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right])) return left;
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right])) return mid;
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))
return mid;
else return right;
}
/* 哨兵划分(三数取中值) */
partition(nums, left, right) {
// 选取三个候选元素的中位数
let med = this.medianThree(nums, left, Math.floor((left + right) / 2), right);
let med = this.medianThree(
nums,
left,
Math.floor((left + right) / 2),
right
);
// 将中位数交换至数组最左端
this.swap(nums, left, med);
// 以 nums[left] 作为基准数
let i = left, j = right;
let i = left,
j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left]) j--; // 从右向左找首个小于基准数的元素
while (i < j && nums[i] <= nums[left]) i++; // 从左向右找首个大于基准数的元素
@ -102,7 +110,8 @@ class QuickSortTailCall {
/* 哨兵划分 */
partition(nums, left, right) {
// 以 nums[left] 作为基准数
let i = left, j = right;
let i = left,
j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left]) j--; // 从右向左找首个小于基准数的元素
while (i < j && nums[i] <= nums[left]) i++; // 从左向右找首个大于基准数的元素

View file

@ -18,7 +18,7 @@ function countingSortDigit(nums, exp) {
// 统计 0~9 各数字的出现次数
for (let i = 0; i < n; i++) {
const d = digit(nums[i], exp); // 获取 nums[i] 第 k 位,记为 d
counter[d]++; // 统计数字 d 的出现次数
counter[d]++; // 统计数字 d 的出现次数
}
// 求前缀和,将“出现个数”转换为“数组索引”
for (let i = 1; i < 10; i++) {
@ -29,8 +29,8 @@ function countingSortDigit(nums, exp) {
for (let i = n - 1; i >= 0; i--) {
const d = digit(nums[i], exp);
const j = counter[d] - 1; // 获取 d 在数组中的索引 j
res[j] = nums[i]; // 将当前元素填入索引 j
counter[d]--; // 将 d 的数量减 1
res[j] = nums[i]; // 将当前元素填入索引 j
counter[d]--; // 将 d 的数量减 1
}
// 使用结果覆盖原数组 nums
for (let i = 0; i < n; i++) {
@ -58,7 +58,9 @@ function radixSort(nums) {
}
/* Driver Code */
const nums = [10546151, 35663510, 42865989, 34862445, 81883077,
88906420, 72429244, 30524779, 82060337, 63832996];
const nums = [
10546151, 35663510, 42865989, 34862445, 81883077, 88906420, 72429244,
30524779, 82060337, 63832996,
];
radixSort(nums);
console.log('基数排序完成后 nums =', nums);

View file

@ -6,9 +6,9 @@
/* 基于环形数组实现的双向队列 */
class ArrayDeque {
#nums; // 用于存储双向队列元素的数组
#front; // 队首指针,指向队首元素
#queSize; // 双向队列长度
#nums; // 用于存储双向队列元素的数组
#front; // 队首指针,指向队首元素
#queSize; // 双向队列长度
/* 构造方法 */
constructor(capacity) {
@ -43,7 +43,7 @@ class ArrayDeque {
/* 队首入队 */
pushFirst(num) {
if (this.#queSize === this.capacity()) {
console.log("双向队列已满");
console.log('双向队列已满');
return;
}
// 队首指针向左移动一位
@ -57,7 +57,7 @@ class ArrayDeque {
/* 队尾入队 */
pushLast(num) {
if (this.#queSize === this.capacity()) {
console.log("双向队列已满");
console.log('双向队列已满');
return;
}
// 计算尾指针,指向队尾索引 + 1
@ -85,15 +85,13 @@ class ArrayDeque {
/* 访问队首元素 */
peekFirst() {
if (this.isEmpty())
throw new Error("The Deque Is Empty.");
if (this.isEmpty()) throw new Error('The Deque Is Empty.');
return this.#nums[this.#front];
}
/* 访问队尾元素 */
peekLast() {
if (this.isEmpty())
throw new Error("The Deque Is Empty.");
if (this.isEmpty()) throw new Error('The Deque Is Empty.');
// 计算尾元素索引
const last = this.index(this.#front + this.#queSize - 1);
return this.#nums[last];
@ -117,30 +115,42 @@ const deque = new ArrayDeque(capacity);
deque.pushLast(3);
deque.pushLast(2);
deque.pushLast(5);
console.log("双向队列 deque = [" + deque.toArray() + "]");
console.log('双向队列 deque = [' + deque.toArray() + ']');
/* 访问元素 */
const peekFirst = deque.peekFirst();
console.log("队首元素 peekFirst = " + peekFirst);
console.log('队首元素 peekFirst = ' + peekFirst);
const peekLast = deque.peekLast();
console.log("队尾元素 peekLast = " + peekLast);
console.log('队尾元素 peekLast = ' + peekLast);
/* 元素入队 */
deque.pushLast(4);
console.log("元素 4 队尾入队后 deque = [" + deque.toArray() + "]");
console.log('元素 4 队尾入队后 deque = [' + deque.toArray() + ']');
deque.pushFirst(1);
console.log("元素 1 队首入队后 deque = [" + deque.toArray() + "]");
console.log('元素 1 队首入队后 deque = [' + deque.toArray() + ']');
/* 元素出队 */
const popLast = deque.popLast();
console.log("队尾出队元素 = " + popLast + ",队尾出队后 deque = [" + deque.toArray() + "]");
console.log(
'队尾出队元素 = ' +
popLast +
',队尾出队后 deque = [' +
deque.toArray() +
']'
);
const popFirst = deque.popFirst();
console.log("队首出队元素 = " + popFirst + ",队首出队后 deque = [" + deque.toArray()+ "]");
console.log(
'队首出队元素 = ' +
popFirst +
',队首出队后 deque = [' +
deque.toArray() +
']'
);
/* 获取双向队列的长度 */
const size = deque.size();
console.log("双向队列长度 size = " + size);
console.log('双向队列长度 size = ' + size);
/* 判断双向队列是否为空 */
const isEmpty = deque.isEmpty();
console.log("双向队列是否为空 = " + isEmpty);
console.log('双向队列是否为空 = ' + isEmpty);

View file

@ -6,9 +6,9 @@
/* 基于环形数组实现的队列 */
class ArrayQueue {
#nums; // 用于存储队列元素的数组
#front = 0; // 队首指针,指向队首元素
#queSize = 0; // 队列长度
#nums; // 用于存储队列元素的数组
#front = 0; // 队首指针,指向队首元素
#queSize = 0; // 队列长度
constructor(capacity) {
this.#nums = new Array(capacity);
@ -32,7 +32,7 @@ class ArrayQueue {
/* 入队 */
push(num) {
if (this.size == this.capacity) {
console.log("队列已满");
console.log('队列已满');
return;
}
// 计算尾指针,指向队尾索引 + 1
@ -54,8 +54,7 @@ class ArrayQueue {
/* 访问队首元素 */
peek() {
if (this.empty())
throw new Error("队列为空");
if (this.empty()) throw new Error('队列为空');
return this.#nums[this.#front];
}
@ -70,7 +69,6 @@ class ArrayQueue {
}
}
/* Driver Code */
/* 初始化队列 */
const capacity = 10;
@ -82,27 +80,27 @@ queue.push(3);
queue.push(2);
queue.push(5);
queue.push(4);
console.log("队列 queue =", queue.toArray());
console.log('队列 queue =', queue.toArray());
/* 访问队首元素 */
const peek = queue.peek();
console.log("队首元素 peek = " + peek);
console.log('队首元素 peek = ' + peek);
/* 元素出队 */
const pop = queue.pop();
console.log("出队元素 pop = " + pop + ",出队后 queue =", queue.toArray());
console.log('出队元素 pop = ' + pop + ',出队后 queue =', queue.toArray());
/* 获取队列的长度 */
const size = queue.size;
console.log("队列长度 size = " + size);
console.log('队列长度 size = ' + size);
/* 判断队列是否为空 */
const empty = queue.empty();
console.log("队列是否为空 = " + empty);
console.log('队列是否为空 = ' + empty);
/* 测试环形数组 */
for (let i = 0; i < 10; i++) {
queue.push(i);
queue.pop();
console.log("第 " + i + " 轮入队 + 出队后 queue =", queue.toArray());
console.log('第 ' + i + ' 轮入队 + 出队后 queue =', queue.toArray());
}

View file

@ -4,14 +4,13 @@
* Author: S-N-O-R-L-A-X (snorlax.xu@outlook.com)
*/
/* 基于数组实现的栈 */
class ArrayStack {
#stack;
constructor() {
this.#stack = [];
}
/* 获取栈的长度 */
get size() {
return this.#stack.length;
@ -29,15 +28,13 @@ class ArrayStack {
/* 出栈 */
pop() {
if (this.empty())
throw new Error("栈为空");
if (this.empty()) throw new Error('栈为空');
return this.#stack.pop();
}
/* 访问栈顶元素 */
top() {
if (this.empty())
throw new Error("栈为空");
if (this.empty()) throw new Error('栈为空');
return this.#stack[this.#stack.length - 1];
}
@ -45,8 +42,7 @@ class ArrayStack {
toArray() {
return this.#stack;
}
};
}
/* Driver Code */
/* 初始化栈 */
@ -58,22 +54,22 @@ stack.push(3);
stack.push(2);
stack.push(5);
stack.push(4);
console.log("栈 stack = ");
console.log('栈 stack = ');
console.log(stack.toArray());
/* 访问栈顶元素 */
const top = stack.top();
console.log("栈顶元素 top = " + top);
console.log('栈顶元素 top = ' + top);
/* 元素出栈 */
const pop = stack.pop();
console.log("出栈元素 pop = " + pop + ",出栈后 stack = ");
console.log('出栈元素 pop = ' + pop + ',出栈后 stack = ');
console.log(stack.toArray());
/* 获取栈的长度 */
const size = stack.size;
console.log("栈的长度 size = " + size);
console.log('栈的长度 size = ' + size);
/* 判断是否为空 */
const empty = stack.empty();
console.log("栈是否为空 = " + empty);
console.log('栈是否为空 = ' + empty);

View file

@ -16,25 +16,29 @@ deque.push(4);
// 请注意由于是数组unshift() 方法的时间复杂度为 O(n)
deque.unshift(3);
deque.unshift(1);
console.log("双向队列 deque = ", deque);
console.log('双向队列 deque = ', deque);
/* 访问元素 */
const peekFirst = deque[0];
console.log("队首元素 peekFirst = " + peekFirst);
console.log('队首元素 peekFirst = ' + peekFirst);
const peekLast = deque[deque.length - 1];
console.log("队尾元素 peekLast = " + peekLast);
console.log('队尾元素 peekLast = ' + peekLast);
/* 元素出队 */
// 请注意由于是数组shift() 方法的时间复杂度为 O(n)
const popFront = deque.shift();
console.log("队首出队元素 popFront = " + popFront + ",队首出队后 deque = " + deque);
console.log(
'队首出队元素 popFront = ' + popFront + ',队首出队后 deque = ' + deque
);
const popBack = deque.pop();
console.log("队尾出队元素 popBack = " + popBack + ",队尾出队后 deque = " + deque);
console.log(
'队尾出队元素 popBack = ' + popBack + ',队尾出队后 deque = ' + deque
);
/* 获取双向队列的长度 */
const size = deque.length;
console.log("双向队列长度 size = " + size);
console.log('双向队列长度 size = ' + size);
/* 判断双向队列是否为空 */
const isEmpty = size === 0;
console.log("双向队列是否为空 = " + isEmpty);
console.log('双向队列是否为空 = ' + isEmpty);

View file

@ -6,10 +6,10 @@
/* 双向链表节点 */
class ListNode {
prev; // 前驱节点引用 (指针)
next; // 后继节点引用 (指针)
val; // 节点值
prev; // 前驱节点引用 (指针)
next; // 后继节点引用 (指针)
val; // 节点值
constructor(val) {
this.val = val;
this.next = null;
@ -19,9 +19,9 @@ class ListNode {
/* 基于双向链表实现的双向队列 */
class LinkedListDeque {
#front; // 头节点 front
#rear; // 尾节点 rear
#queSize; // 双向队列的长度
#front; // 头节点 front
#rear; // 尾节点 rear
#queSize; // 双向队列的长度
constructor() {
this.#front = null;
@ -73,7 +73,7 @@ class LinkedListDeque {
temp.next = null;
this.#rear.prev = null;
}
this.#rear = temp; // 更新尾节点
this.#rear = temp; // 更新尾节点
this.#queSize--;
return value;
}
@ -90,7 +90,7 @@ class LinkedListDeque {
temp.prev = null;
this.#front.next = null;
}
this.#front = temp; // 更新头节点
this.#front = temp; // 更新头节点
this.#queSize--;
return value;
}
@ -123,7 +123,7 @@ class LinkedListDeque {
arr.push(temp.val);
temp = temp.next;
}
console.log("[" + arr.join(", ") + "]");
console.log('[' + arr.join(', ') + ']');
}
}
@ -133,35 +133,35 @@ const linkedListDeque = new LinkedListDeque();
linkedListDeque.pushLast(3);
linkedListDeque.pushLast(2);
linkedListDeque.pushLast(5);
console.log("双向队列 linkedListDeque = ");
console.log('双向队列 linkedListDeque = ');
linkedListDeque.print();
/* 访问元素 */
const peekFirst = linkedListDeque.peekFirst();
console.log("队首元素 peekFirst = " + peekFirst);
console.log('队首元素 peekFirst = ' + peekFirst);
const peekLast = linkedListDeque.peekLast();
console.log("队尾元素 peekLast = " + peekLast);
console.log('队尾元素 peekLast = ' + peekLast);
/* 元素入队 */
linkedListDeque.pushLast(4);
console.log("元素 4 队尾入队后 linkedListDeque = ");
console.log('元素 4 队尾入队后 linkedListDeque = ');
linkedListDeque.print();
linkedListDeque.pushFirst(1);
console.log("元素 1 队首入队后 linkedListDeque = ");
console.log('元素 1 队首入队后 linkedListDeque = ');
linkedListDeque.print();
/* 元素出队 */
const popLast = linkedListDeque.popLast();
console.log("队尾出队元素 = " + popLast + ",队尾出队后 linkedListDeque = ");
console.log('队尾出队元素 = ' + popLast + ',队尾出队后 linkedListDeque = ');
linkedListDeque.print();
const popFirst = linkedListDeque.popFirst();
console.log("队首出队元素 = " + popFirst + ",队首出队后 linkedListDeque = ");
console.log('队首出队元素 = ' + popFirst + ',队首出队后 linkedListDeque = ');
linkedListDeque.print();
/* 获取双向队列的长度 */
const size = linkedListDeque.size();
console.log("双向队列长度 size = " + size);
console.log('双向队列长度 size = ' + size);
/* 判断双向队列是否为空 */
const isEmpty = linkedListDeque.isEmpty();
console.log("双向队列是否为空 = " + isEmpty);
console.log('双向队列是否为空 = ' + isEmpty);

View file

@ -4,12 +4,12 @@
* Author: S-N-O-R-L-A-X (snorlax.xu@outlook.com)
*/
const { ListNode } = require("../modules/ListNode");
const { ListNode } = require('../modules/ListNode');
/* 基于链表实现的队列 */
class LinkedListQueue {
#front; // 头节点 #front
#rear; // 尾节点 #rear
#front; // 头节点 #front
#rear; // 尾节点 #rear
#queSize = 0;
constructor() {
@ -54,8 +54,7 @@ class LinkedListQueue {
/* 访问队首元素 */
peek() {
if (this.size === 0)
throw new Error("队列为空");
if (this.size === 0) throw new Error('队列为空');
return this.#front.val;
}
@ -71,8 +70,6 @@ class LinkedListQueue {
}
}
/* Driver Code */
/* 初始化队列 */
const queue = new LinkedListQueue();
@ -83,20 +80,20 @@ queue.push(3);
queue.push(2);
queue.push(5);
queue.push(4);
console.log("队列 queue = " + queue.toArray());
console.log('队列 queue = ' + queue.toArray());
/* 访问队首元素 */
const peek = queue.peek();
console.log("队首元素 peek = " + peek);
console.log('队首元素 peek = ' + peek);
/* 元素出队 */
const pop = queue.pop();
console.log("出队元素 pop = " + pop + ",出队后 queue = " + queue.toArray());
console.log('出队元素 pop = ' + pop + ',出队后 queue = ' + queue.toArray());
/* 获取队列的长度 */
const size = queue.size;
console.log("队列长度 size = " + size);
console.log('队列长度 size = ' + size);
/* 判断队列是否为空 */
const isEmpty = queue.isEmpty();
console.log("队列是否为空 = " + isEmpty);
console.log('队列是否为空 = ' + isEmpty);

View file

@ -4,12 +4,12 @@
* Author: S-N-O-R-L-A-X (snorlax.xu@outlook.com)
*/
const { ListNode } = require("../modules/ListNode");
const { ListNode } = require('../modules/ListNode');
/* 基于链表实现的栈 */
class LinkedListStack {
#stackPeek; // 将头节点作为栈顶
#stkSize = 0; // 栈的长度
#stackPeek; // 将头节点作为栈顶
#stkSize = 0; // 栈的长度
constructor() {
this.#stackPeek = null;
@ -43,8 +43,7 @@ class LinkedListStack {
/* 访问栈顶元素 */
peek() {
if (!this.#stackPeek)
throw new Error("栈为空");
if (!this.#stackPeek) throw new Error('栈为空');
return this.#stackPeek.val;
}
@ -70,20 +69,20 @@ stack.push(3);
stack.push(2);
stack.push(5);
stack.push(4);
console.log("栈 stack = " + stack.toArray());
console.log('栈 stack = ' + stack.toArray());
/* 访问栈顶元素 */
const peek = stack.peek();
console.log("栈顶元素 peek = " + peek);
console.log('栈顶元素 peek = ' + peek);
/* 元素出栈 */
const pop = stack.pop();
console.log("出栈元素 pop = " + pop + ",出栈后 stack = " + stack.toArray());
console.log('出栈元素 pop = ' + pop + ',出栈后 stack = ' + stack.toArray());
/* 获取栈的长度 */
const size = stack.size;
console.log("栈的长度 size = " + size);
console.log('栈的长度 size = ' + size);
/* 判断是否为空 */
const isEmpty = stack.isEmpty();
console.log("栈是否为空 = " + isEmpty);
console.log('栈是否为空 = ' + isEmpty);

View file

@ -15,21 +15,21 @@ queue.push(3);
queue.push(2);
queue.push(5);
queue.push(4);
console.log("队列 queue =", queue);
console.log('队列 queue =', queue);
/* 访问队首元素 */
const peek = queue[0];
console.log("队首元素 peek =", peek);
console.log('队首元素 peek =', peek);
/* 元素出队 */
// 底层是数组,因此 shift() 方法的时间复杂度为 O(n)
const pop = queue.shift();
console.log("出队元素 pop =", pop, ",出队后 queue = ", queue);
console.log('出队元素 pop =', pop, ',出队后 queue = ', queue);
/* 获取队列的长度 */
const size = queue.length;
console.log("队列长度 size =", size);
console.log('队列长度 size =', size);
/* 判断队列是否为空 */
const isEmpty = queue.length === 0;
console.log("队列是否为空 = ", isEmpty);
console.log('队列是否为空 = ', isEmpty);

View file

@ -6,7 +6,7 @@
/* Driver Code */
/* 初始化栈 */
// Javascript 没有内置的栈类,可以把 Array 当作栈来使用
// Javascript 没有内置的栈类,可以把 Array 当作栈来使用
const stack = [];
/* 元素入栈 */
@ -15,21 +15,21 @@ stack.push(3);
stack.push(2);
stack.push(5);
stack.push(4);
console.log("栈 stack =", stack);
console.log('栈 stack =', stack);
/* 访问栈顶元素 */
const peek = stack[stack.length - 1];
console.log("栈顶元素 peek =", peek);
console.log('栈顶元素 peek =', peek);
/* 元素出栈 */
const pop = stack.pop();
console.log("出栈元素 pop =", pop);
console.log("出栈后 stack =", stack);
console.log('出栈元素 pop =', pop);
console.log('出栈后 stack =', stack);
/* 获取栈的长度 */
const size = stack.length;
console.log("栈的长度 size =", size);
console.log('栈的长度 size =', size);
/* 判断是否为空 */
const isEmpty = stack.length === 0;
console.log("栈是否为空 =", isEmpty);
console.log('栈是否为空 =', isEmpty);

View file

@ -4,8 +4,8 @@
* Author: what-is-me (whatisme@outlook.jp)
*/
const { TreeNode } = require("../modules/TreeNode");
const { printTree } = require("../modules/PrintUtil");
const { TreeNode } = require('../modules/TreeNode');
const { printTree } = require('../modules/PrintUtil');
/* AVL 树*/
class AVLTree {
@ -23,7 +23,8 @@ class AVLTree {
/* 更新节点高度 */
#updateHeight(node) {
// 节点高度等于最高子树高度 + 1
node.height = Math.max(this.height(node.left), this.height(node.right)) + 1;
node.height =
Math.max(this.height(node.left), this.height(node.right)) + 1;
}
/* 获取平衡因子 */
@ -102,7 +103,8 @@ class AVLTree {
if (node === null) return new TreeNode(val);
/* 1. 查找插入位置,并插入节点 */
if (val < node.val) node.left = this.#insertHelper(node.left, val);
else if (val > node.val) node.right = this.#insertHelper(node.right, val);
else if (val > node.val)
node.right = this.#insertHelper(node.right, val);
else return node; // 重复节点不插入,直接返回
this.#updateHeight(node); // 更新节点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
@ -121,7 +123,8 @@ class AVLTree {
if (node === null) return null;
/* 1. 查找节点,并删除之 */
if (val < node.val) node.left = this.#removeHelper(node.left, val);
else if (val > node.val) node.right = this.#removeHelper(node.right, val);
else if (val > node.val)
node.right = this.#removeHelper(node.right, val);
else {
if (node.left === null || node.right === null) {
const child = node.left !== null ? node.left : node.right;
@ -165,13 +168,13 @@ class AVLTree {
function testInsert(tree, val) {
tree.insert(val);
console.log("\n插入节点 " + val + " 后AVL 树为");
console.log('\n插入节点 ' + val + ' 后AVL 树为');
printTree(tree.root);
}
function testRemove(tree, val) {
tree.remove(val);
console.log("\n删除节点 " + val + " 后AVL 树为");
console.log('\n删除节点 ' + val + ' 后AVL 树为');
printTree(tree.root);
}
@ -202,4 +205,4 @@ testRemove(avlTree, 4); // 删除度为 2 的节点
/* 查询节点 */
const node = avlTree.search(7);
console.log("\n查找到的节点对象为", node, ",节点值 = " + node.val);
console.log('\n查找到的节点对象为', node, ',节点值 = ' + node.val);

View file

@ -4,15 +4,17 @@
* Author: IsChristina (christinaxia77@foxmail.com)
*/
const { TreeNode } = require("../modules/TreeNode");
const { printTree } = require("../modules/PrintUtil");
const { TreeNode } = require('../modules/TreeNode');
const { printTree } = require('../modules/PrintUtil');
/* 二叉搜索树 */
let root;
function BinarySearchTree(nums) {
nums.sort((a, b) => { return a - b }); // 排序数组
root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树
nums.sort((a, b) => {
return a - b;
}); // 排序数组
root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树
}
/* 获取二叉树根节点 */
@ -52,7 +54,8 @@ function search(num) {
function insert(num) {
// 若树为空,直接提前返回
if (root === null) return;
let cur = root, pre = null;
let cur = root,
pre = null;
// 循环查找,越过叶节点后跳出
while (cur !== null) {
// 找到重复节点,直接返回
@ -73,7 +76,8 @@ function insert(num) {
function remove(num) {
// 若树为空,直接提前返回
if (root === null) return;
let cur = root, pre = null;
let cur = root,
pre = null;
// 循环查找,越过叶节点后跳出
while (cur !== null) {
// 找到待删除节点,跳出循环
@ -112,25 +116,25 @@ function remove(num) {
/* 初始化二叉搜索树 */
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
BinarySearchTree(nums);
console.log("\n初始化的二叉树为\n");
console.log('\n初始化的二叉树为\n');
printTree(getRoot());
/* 查找节点 */
let node = search(7);
console.log("\n查找到的节点对象为 " + node + ",节点值 = " + node.val);
console.log('\n查找到的节点对象为 ' + node + ',节点值 = ' + node.val);
/* 插入节点 */
insert(16);
console.log("\n插入节点 16 后,二叉树为\n");
console.log('\n插入节点 16 后,二叉树为\n');
printTree(getRoot());
/* 删除节点 */
remove(1);
console.log("\n删除节点 1 后,二叉树为\n");
console.log('\n删除节点 1 后,二叉树为\n');
printTree(getRoot());
remove(2);
console.log("\n删除节点 2 后,二叉树为\n");
console.log('\n删除节点 2 后,二叉树为\n');
printTree(getRoot());
remove(4);
console.log("\n删除节点 4 后,二叉树为\n");
console.log('\n删除节点 4 后,二叉树为\n');
printTree(getRoot());

View file

@ -4,8 +4,8 @@
* Author: IsChristina (christinaxia77@foxmail.com)
*/
const { TreeNode } = require("../modules/TreeNode");
const { printTree } = require("../modules/PrintUtil");
const { TreeNode } = require('../modules/TreeNode');
const { printTree } = require('../modules/PrintUtil');
/* 初始化二叉树 */
// 初始化节点
@ -19,7 +19,7 @@ n1.left = n2;
n1.right = n3;
n2.left = n4;
n2.right = n5;
console.log("\n初始化二叉树\n");
console.log('\n初始化二叉树\n');
printTree(n1);
/* 插入与删除节点 */
@ -27,9 +27,9 @@ const P = new TreeNode(0);
// 在 n1 -> n2 中间插入节点 P
n1.left = P;
P.left = n2;
console.log("\n插入节点 P 后\n");
console.log('\n插入节点 P 后\n');
printTree(n1);
// 删除节点 P
n1.left = n2;
console.log("\n删除节点 P 后\n");
console.log('\n删除节点 P 后\n');
printTree(n1);

View file

@ -4,8 +4,8 @@
* Author: IsChristina (christinaxia77@foxmail.com)
*/
const { arrToTree } = require("../modules/TreeNode");
const { printTree } = require("../modules/PrintUtil");
const { arrToTree } = require('../modules/TreeNode');
const { printTree } = require('../modules/PrintUtil');
/* 层序遍历 */
function levelOrder(root) {
@ -14,13 +14,10 @@ function levelOrder(root) {
// 初始化一个列表,用于保存遍历序列
const list = [];
while (queue.length) {
let node = queue.shift(); // 队列出队
list.push(node.val); // 保存节点值
if (node.left)
queue.push(node.left); // 左子节点入队
if (node.right)
queue.push(node.right); // 右子节点入队
let node = queue.shift(); // 队列出队
list.push(node.val); // 保存节点值
if (node.left) queue.push(node.left); // 左子节点入队
if (node.right) queue.push(node.right); // 右子节点入队
}
return list;
}
@ -29,9 +26,9 @@ function levelOrder(root) {
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
const root = arrToTree([1, 2, 3, 4, 5, 6, 7]);
console.log("\n初始化二叉树\n");
console.log('\n初始化二叉树\n');
printTree(root);
/* 层序遍历 */
const list = levelOrder(root);
console.log("\n层序遍历的节点打印序列 = " + list);
console.log('\n层序遍历的节点打印序列 = ' + list);

View file

@ -4,8 +4,8 @@
* Author: IsChristina (christinaxia77@foxmail.com)
*/
const { arrToTree } = require("../modules/TreeNode");
const { printTree } = require("../modules/PrintUtil");
const { arrToTree } = require('../modules/TreeNode');
const { printTree } = require('../modules/PrintUtil');
// 初始化列表,用于存储遍历序列
const list = [];
@ -41,20 +41,20 @@ function postOrder(root) {
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
const root = arrToTree([1, 2, 3, 4, 5, 6, 7]);
console.log("\n初始化二叉树\n");
console.log('\n初始化二叉树\n');
printTree(root);
/* 前序遍历 */
list.length = 0;
preOrder(root);
console.log("\n前序遍历的节点打印序列 = " + list);
console.log('\n前序遍历的节点打印序列 = ' + list);
/* 中序遍历 */
list.length = 0;
inOrder(root);
console.log("\n中序遍历的节点打印序列 = " + list);
console.log('\n中序遍历的节点打印序列 = ' + list);
/* 后序遍历 */
list.length = 0;
postOrder(root);
console.log("\n后序遍历的节点打印序列 = " + list);
console.log('\n后序遍历的节点打印序列 = ' + list);

View file

@ -11,8 +11,8 @@ class ListNode {
val;
next;
constructor(val, next) {
this.val = (val === undefined ? 0 : val);
this.next = (next === undefined ? null : next);
this.val = val === undefined ? 0 : val;
this.next = next === undefined ? null : next;
}
}
@ -47,5 +47,5 @@ function getListNode(head, val) {
module.exports = {
ListNode,
arrToLinkedList,
getListNode
getListNode,
};

View file

@ -4,7 +4,7 @@
* Author: IsChristina (christinaxia77@foxmail.com)
*/
const { arrToTree } = require("./TreeNode");
const { arrToTree } = require('./TreeNode');
/**
* Print a linked list
@ -16,7 +16,7 @@ function printLinkedList(head) {
list.push(head.val.toString());
head = head.next;
}
console.log(list.join(" -> "));
console.log(list.join(' -> '));
}
function Trunk(prev, str) {
@ -45,28 +45,28 @@ function printTree(root, prev, isLeft) {
return;
}
let prev_str = " ";
let prev_str = ' ';
let trunk = new Trunk(prev, prev_str);
printTree(root.right, trunk, true);
if (!prev) {
trunk.str = "———";
trunk.str = '———';
} else if (isLeft) {
trunk.str = "/———";
prev_str = " |";
trunk.str = '/———';
prev_str = ' |';
} else {
trunk.str = "\\———";
trunk.str = '\\———';
prev.str = prev_str;
}
showTrunks(trunk);
console.log(" " + root.val);
console.log(' ' + root.val);
if (prev) {
prev.str = prev_str;
}
trunk.str = " |";
trunk.str = ' |';
printTree(root.left, trunk, false);
}
@ -89,14 +89,14 @@ function showTrunks(p) {
* @param arr
*/
function printHeap(arr) {
console.log("堆的数组表示:");
console.log('堆的数组表示:');
console.log(arr);
console.log("堆的树状表示:");
console.log('堆的树状表示:');
printTree(arrToTree(arr));
}
module.exports = {
printLinkedList,
printTree,
printHeap
printHeap,
};

View file

@ -50,5 +50,5 @@ function arrToTree(arr) {
module.exports = {
TreeNode,
arrToTree
arrToTree,
};

View file

@ -4,7 +4,6 @@
* Author: Zhuo Qinyue (1403450829@qq.com)
*/
/* 顶点类 */
class Vertex {
val;
@ -32,5 +31,5 @@ class Vertex {
}
module.exports = {
Vertex
Vertex,
};

View file

@ -0,0 +1,6 @@
{
"tabWidth": 4,
"useTabs": false,
"semi": true,
"singleQuote": true
}

View file

@ -29,23 +29,20 @@ class MyList {
/* 访问元素 */
public get(index: number): number {
// 索引如果越界则抛出异常,下同
if (index < 0 || index >= this._size)
throw new Error('索引越界');
if (index < 0 || index >= this._size) throw new Error('索引越界');
return this.nums[index];
}
/* 更新元素 */
public set(index: number, num: number): void {
if (index < 0 || index >= this._size)
throw new Error('索引越界');
if (index < 0 || index >= this._size) throw new Error('索引越界');
this.nums[index] = num;
}
/* 尾部添加元素 */
public add(num: number): void {
// 如果长度等于容量,则需要扩容
if (this._size === this._capacity)
this.extendCapacity();
if (this._size === this._capacity) this.extendCapacity();
// 将新元素添加到列表尾部
this.nums[this._size] = num;
this._size++;
@ -53,8 +50,7 @@ class MyList {
/* 中间插入元素 */
public insert(index: number, num: number): void {
if (index < 0 || index >= this._size)
throw new Error('索引越界');
if (index < 0 || index >= this._size) throw new Error('索引越界');
// 元素数量超出容量时,触发扩容机制
if (this._size === this._capacity) {
this.extendCapacity();
@ -70,8 +66,7 @@ class MyList {
/* 删除元素 */
public remove(index: number): number {
if (index < 0 || index >= this._size)
throw new Error('索引越界');
if (index < 0 || index >= this._size) throw new Error('索引越界');
let num = this.nums[index];
// 将索引 index 之后的元素都向前移动一位
for (let j = index; j < this._size - 1; j++) {

View file

@ -7,15 +7,20 @@
/* 二分查找(双闭区间) */
function binarySearch(nums: number[], target: number): number {
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
let i = 0, j = nums.length - 1;
let i = 0,
j = nums.length - 1;
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
while (i <= j) {
const m = Math.floor((i + j) / 2); // 计算中点索引 m
if (nums[m] < target) { // 此情况说明 target 在区间 [m+1, j] 中
// 计算中点索引 m
const m = Math.floor((i + j) / 2);
if (nums[m] < target) {
// 此情况说明 target 在区间 [m+1, j] 中
i = m + 1;
} else if (nums[m] > target) { // 此情况说明 target 在区间 [i, m-1] 中
} else if (nums[m] > target) {
// 此情况说明 target 在区间 [i, m-1] 中
j = m - 1;
} else { // 找到目标元素,返回其索引
} else {
// 找到目标元素,返回其索引
return m;
}
}
@ -25,25 +30,29 @@ function binarySearch(nums: number[], target: number): number {
/* 二分查找(左闭右开) */
function binarySearch1(nums: number[], target: number): number {
// 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
let i = 0, j = nums.length;
let i = 0,
j = nums.length;
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
while (i < j) {
const m = Math.floor((i + j) / 2); // 计算中点索引 m
if (nums[m] < target) { // 此情况说明 target 在区间 [m+1, j) 中
// 计算中点索引 m
const m = Math.floor((i + j) / 2);
if (nums[m] < target) {
// 此情况说明 target 在区间 [m+1, j) 中
i = m + 1;
} else if (nums[m] > target) { // 此情况说明 target 在区间 [i, m) 中
} else if (nums[m] > target) {
// 此情况说明 target 在区间 [i, m) 中
j = m;
} else { // 找到目标元素,返回其索引
} else {
// 找到目标元素,返回其索引
return m;
}
}
return -1; // 未找到目标元素,返回 -1
}
/* Driver Code */
const target = 6;
const nums = [ 1, 3, 6, 8, 12, 15, 23, 67, 70, 92 ];
const nums = [1, 3, 6, 8, 12, 15, 23, 67, 70, 92];
/* 二分查找(双闭区间) */
let index = binarySearch(nums, target);

View file

@ -121,37 +121,37 @@ function factorialRecur(n: number): number {
/* Driver Code */
// 可以修改 n 运行,体会一下各种复杂度的操作数量变化趋势
const n = 8;
console.log("输入数据大小 n = " + n);
console.log('输入数据大小 n = ' + n);
let count = constant(n);
console.log("常数阶的计算操作数量 = " + count);
console.log('常数阶的计算操作数量 = ' + count);
count = linear(n);
console.log("线性阶的计算操作数量 = " + count);
console.log('线性阶的计算操作数量 = ' + count);
count = arrayTraversal(new Array(n));
console.log("线性阶(遍历数组)的计算操作数量 = " + count);
console.log('线性阶(遍历数组)的计算操作数量 = ' + count);
count = quadratic(n);
console.log("平方阶的计算操作数量 = " + count);
console.log('平方阶的计算操作数量 = ' + count);
var nums = new Array(n);
for (let i = 0; i < n; i++) nums[i] = n - i; // [n,n-1,...,2,1]
count = bubbleSort(nums);
console.log("平方阶(冒泡排序)的计算操作数量 = " + count);
console.log('平方阶(冒泡排序)的计算操作数量 = ' + count);
count = exponential(n);
console.log("指数阶(循环实现)的计算操作数量 = " + count);
console.log('指数阶(循环实现)的计算操作数量 = ' + count);
count = expRecur(n);
console.log("指数阶(递归实现)的计算操作数量 = " + count);
console.log('指数阶(递归实现)的计算操作数量 = ' + count);
count = logarithmic(n);
console.log("对数阶(循环实现)的计算操作数量 = " + count);
console.log('对数阶(循环实现)的计算操作数量 = ' + count);
count = logRecur(n);
console.log("对数阶(递归实现)的计算操作数量 = " + count);
console.log('对数阶(递归实现)的计算操作数量 = ' + count);
count = linearLogRecur(n);
console.log("线性对数阶(递归实现)的计算操作数量 = " + count);
console.log('线性对数阶(递归实现)的计算操作数量 = ' + count);
count = factorialRecur(n);
console.log("阶乘阶(递归实现)的计算操作数量 = " + count);
console.log('阶乘阶(递归实现)的计算操作数量 = ' + count);
export {};

View file

@ -38,10 +38,8 @@ for (let i = 0; i < 10; i++) {
const n = 100;
const nums = randomNumbers(n);
const index = findOne(nums);
console.log(
"\n数组 [ 1, 2, ..., n ] 被打乱后 = [" + nums.join(", ") + "]"
);
console.log("数字 1 的索引为 " + index);
console.log('\n数组 [ 1, 2, ..., n ] 被打乱后 = [' + nums.join(', ') + ']');
console.log('数字 1 的索引为 ' + index);
}
export {};

View file

@ -29,7 +29,11 @@ class GraphAdjList {
/* 添加边 */
addEdge(vet1: Vertex, vet2: Vertex): void {
if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) {
if (
!this.adjList.has(vet1) ||
!this.adjList.has(vet2) ||
vet1 === vet2
) {
throw new Error('Illegal Argument Exception');
}
// 添加边 vet1 - vet2
@ -39,7 +43,11 @@ class GraphAdjList {
/* 删除边 */
removeEdge(vet1: Vertex, vet2: Vertex): void {
if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) {
if (
!this.adjList.has(vet1) ||
!this.adjList.has(vet2) ||
vet1 === vet2
) {
throw new Error('Illegal Argument Exception');
}
// 删除边 vet1 - vet2
@ -98,7 +106,7 @@ if (require.main === module) {
[v2, v3],
[v0, v3],
[v2, v4],
[v3, v4]
[v3, v4],
];
const graph = new GraphAdjList(edges);
console.log('\n初始化后图为');

View file

@ -6,8 +6,8 @@
/* 基于邻接矩阵实现的无向图类 */
class GraphAdjMat {
vertices: number[]; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
adjMat: number[][]; // 邻接矩阵,行列索引对应“顶点索引”
vertices: number[]; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
adjMat: number[][]; // 邻接矩阵,行列索引对应“顶点索引”
/* 构造函数 */
constructor(vertices: number[], edges: number[][]) {
@ -49,7 +49,7 @@ class GraphAdjMat {
/* 删除顶点 */
removeVertex(index: number): void {
if (index >= this.size()) {
throw new RangeError("Index Out Of Bounds Exception");
throw new RangeError('Index Out Of Bounds Exception');
}
// 在顶点列表中移除索引 index 的顶点
this.vertices.splice(index, 1);
@ -67,7 +67,7 @@ class GraphAdjMat {
addEdge(i: number, j: number): void {
// 索引越界与相等处理
if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) {
throw new RangeError("Index Out Of Bounds Exception");
throw new RangeError('Index Out Of Bounds Exception');
}
// 在无向图中,邻接矩阵沿主对角线对称,即满足 (i, j) == (j, i)
this.adjMat[i][j] = 1;
@ -79,7 +79,7 @@ class GraphAdjMat {
removeEdge(i: number, j: number): void {
// 索引越界与相等处理
if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) {
throw new RangeError("Index Out Of Bounds Exception");
throw new RangeError('Index Out Of Bounds Exception');
}
this.adjMat[i][j] = 0;
this.adjMat[j][i] = 0;
@ -87,8 +87,8 @@ class GraphAdjMat {
/* 打印邻接矩阵 */
print(): void {
console.log("顶点列表 = ", this.vertices);
console.log("邻接矩阵 =", this.adjMat);
console.log('顶点列表 = ', this.vertices);
console.log('邻接矩阵 =', this.adjMat);
}
}
@ -96,33 +96,39 @@ class GraphAdjMat {
/* 初始化无向图 */
// 请注意edges 元素代表顶点索引,即对应 vertices 元素索引
const vertices: number[] = [1, 3, 2, 5, 4];
const edges: number[][] = [[0, 1], [1, 2], [2, 3], [0, 3], [2, 4], [3, 4]
const edges: number[][] = [
[0, 1],
[1, 2],
[2, 3],
[0, 3],
[2, 4],
[3, 4],
];
const graph: GraphAdjMat = new GraphAdjMat(vertices, edges);
console.log("\n初始化后图为");
console.log('\n初始化后图为');
graph.print();
/* 添加边 */
// 顶点 1, 2 的索引分别为 0, 2
graph.addEdge(0, 2);
console.log("\n添加边 1-2 后,图为");
console.log('\n添加边 1-2 后,图为');
graph.print();
/* 删除边 */
// 顶点 1, 3 的索引分别为 0, 1
graph.removeEdge(0, 1);
console.log("\n删除边 1-3 后,图为");
console.log('\n删除边 1-3 后,图为');
graph.print();
/* 添加顶点 */
graph.addVertex(6);
console.log("\n添加顶点 6 后,图为");
console.log('\n添加顶点 6 后,图为');
graph.print();
/* 删除顶点 */
// 顶点 3 的索引为 1
graph.removeVertex(1);
console.log("\n删除顶点 3 后,图为");
console.log('\n删除顶点 3 后,图为');
graph.print();
export {};
export {};

View file

@ -49,7 +49,7 @@ const edges = [
[v[4], v[7]],
[v[5], v[8]],
[v[6], v[7]],
[v[7], v[8]]
[v[7], v[8]],
];
const graph = new GraphAdjList(edges);
console.log('\n初始化后图为');

View file

@ -8,7 +8,12 @@ import { Vertex } from '../modules/Vertex';
import { GraphAdjList } from './graph_adjacency_list';
/* 深度优先遍历 DFS 辅助函数 */
function dfs(graph: GraphAdjList, visited: Set<Vertex>, res: Vertex[], vet: Vertex): void {
function dfs(
graph: GraphAdjList,
visited: Set<Vertex>,
res: Vertex[],
vet: Vertex
): void {
res.push(vet); // 记录访问顶点
visited.add(vet); // 标记该顶点已被访问
// 遍历该顶点的所有邻接顶点
@ -41,7 +46,7 @@ const edges = [
[v[1], v[2]],
[v[2], v[5]],
[v[4], v[5]],
[v[5], v[6]]
[v[5], v[6]],
];
const graph = new GraphAdjList(edges);
console.log('\n初始化后图为');

View file

@ -17,12 +17,11 @@ class Entry {
/* 基于数组简易实现的哈希表 */
class ArrayHashMap {
private readonly buckets: (Entry | null)[];
constructor() {
// 初始化数组,包含 100 个桶
this.buckets = (new Array(100)).fill(null);
this.buckets = new Array(100).fill(null);
}
/* 哈希函数 */

View file

@ -14,7 +14,10 @@ function hashingSearchArray(map: Map<number, number>, target: number): number {
}
/* 哈希查找(链表) */
function hashingSearchLinkedList(map: Map<number, ListNode>, target: number): ListNode | null {
function hashingSearchLinkedList(
map: Map<number, ListNode>,
target: number
): ListNode | null {
// 哈希表的 key: 目标节点值value: 节点对象
// 若哈希表中无此 key ,返回 null
return map.has(target) ? (map.get(target) as ListNode) : null;

View file

@ -1,7 +1,7 @@
/**
* File: leetcode_two_sum.ts
* Created Time: 2022-12-15
* Author: gyt95 (gytkwan@gmail.com)
* Author: gyt95 (gytkwan@gmail.com)
*/
/* 方法一:暴力枚举 */
@ -16,7 +16,7 @@ function twoSumBruteForce(nums: number[], target: number): number[] {
}
}
return [];
};
}
/* 方法二:辅助哈希表 */
function twoSumHashTable(nums: number[], target: number): number[] {
@ -32,17 +32,18 @@ function twoSumHashTable(nums: number[], target: number): number[] {
}
}
return [];
};
}
/* Driver Code */
// 方法一
const nums = [2, 7, 11, 15], target = 9;
const nums = [2, 7, 11, 15],
target = 9;
let res = twoSumBruteForce(nums, target);
console.log("方法一 res = ", res);
console.log('方法一 res = ', res);
// 方法二
res = twoSumHashTable(nums, target);
console.log("方法二 res = ", res);
console.log('方法二 res = ', res);
export {};

View file

@ -20,7 +20,10 @@ function linearSearchArray(nums: number[], target: number): number {
}
/* 线性查找(链表)*/
function linearSearchLinkedList(head: ListNode | null, target: number): ListNode | null {
function linearSearchLinkedList(
head: ListNode | null,
target: number
): ListNode | null {
// 遍历链表
while (head) {
// 找到目标节点,返回之

View file

@ -11,20 +11,23 @@ function merge(nums: number[], left: number, mid: number, right: number): void {
// 初始化辅助数组
let tmp = nums.slice(left, right + 1);
// 左子数组的起始索引和结束索引
let leftStart = left - left, leftEnd = mid - left;
let leftStart = left - left,
leftEnd = mid - left;
// 右子数组的起始索引和结束索引
let rightStart = mid + 1 - left, rightEnd = right - left;
let rightStart = mid + 1 - left,
rightEnd = right - left;
// i, j 分别指向左子数组、右子数组的首元素
let i = leftStart, j = rightStart;
let i = leftStart,
j = rightStart;
// 通过覆盖原数组 nums 来合并左子数组和右子数组
for (let k = left; k <= right; k++) {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
if (i > leftEnd) {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
nums[k] = tmp[j++];
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
} else if (j > rightEnd || tmp[i] <= tmp[j]) {
nums[k] = tmp[i++];
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
} else {
nums[k] = tmp[j++];
}

View file

@ -16,7 +16,8 @@ class QuickSort {
/* 哨兵划分 */
partition(nums: number[], left: number, right: number): number {
// 以 nums[left] 作为基准数
let i = left, j = right;
let i = left,
j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left]) {
j -= 1; // 从右向左找首个小于基准数的元素
@ -55,12 +56,19 @@ class QuickSortMedian {
}
/* 选取三个元素的中位数 */
medianThree(nums: number[], left: number, mid: number, right: number): number {
medianThree(
nums: number[],
left: number,
mid: number,
right: number
): number {
// 此处使用异或运算来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if (Number(nums[left] < nums[mid]) ^ Number(nums[left] < nums[right])) {
return left;
} else if (Number(nums[mid] < nums[left]) ^ Number(nums[mid] < nums[right])) {
} else if (
Number(nums[mid] < nums[left]) ^ Number(nums[mid] < nums[right])
) {
return mid;
} else {
return right;
@ -70,11 +78,17 @@ class QuickSortMedian {
/* 哨兵划分(三数取中值) */
partition(nums: number[], left: number, right: number): number {
// 选取三个候选元素的中位数
let med = this.medianThree(nums, left, Math.floor((left + right) / 2), right);
let med = this.medianThree(
nums,
left,
Math.floor((left + right) / 2),
right
);
// 将中位数交换至数组最左端
this.swap(nums, left, med);
// 以 nums[left] 作为基准数
let i = left, j = right;
let i = left,
j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left]) {
j--; // 从右向左找首个小于基准数的元素
@ -114,7 +128,8 @@ class QuickSortTailCall {
/* 哨兵划分 */
partition(nums: number[], left: number, right: number): number {
// 以 nums[left] 作为基准数
let i = left, j = right;
let i = left,
j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left]) {
j--; // 从右向左找首个小于基准数的元素

View file

@ -18,7 +18,7 @@ function countingSortDigit(nums: number[], exp: number): void {
// 统计 0~9 各数字的出现次数
for (let i = 0; i < n; i++) {
const d = digit(nums[i], exp); // 获取 nums[i] 第 k 位,记为 d
counter[d]++; // 统计数字 d 的出现次数
counter[d]++; // 统计数字 d 的出现次数
}
// 求前缀和,将“出现个数”转换为“数组索引”
for (let i = 1; i < 10; i++) {
@ -29,8 +29,8 @@ function countingSortDigit(nums: number[], exp: number): void {
for (let i = n - 1; i >= 0; i--) {
const d = digit(nums[i], exp);
const j = counter[d] - 1; // 获取 d 在数组中的索引 j
res[j] = nums[i]; // 将当前元素填入索引 j
counter[d]--; // 将 d 的数量减 1
res[j] = nums[i]; // 将当前元素填入索引 j
counter[d]--; // 将 d 的数量减 1
}
// 使用结果覆盖原数组 nums
for (let i = 0; i < n; i++) {
@ -58,8 +58,10 @@ function radixSort(nums: number[]): void {
}
/* Driver Code */
const nums = [10546151, 35663510, 42865989, 34862445, 81883077,
88906420, 72429244, 30524779, 82060337, 63832996];
const nums = [
10546151, 35663510, 42865989, 34862445, 81883077, 88906420, 72429244,
30524779, 82060337, 63832996,
];
radixSort(nums);
console.log('基数排序完成后 nums =', nums);

View file

@ -4,12 +4,11 @@
* Author: Zhuo Qinyue (1403450829@qq.com)
*/
/* 基于环形数组实现的双向队列 */
class ArrayDeque {
private nums: number[]; // 用于存储双向队列元素的数组
private front: number; // 队首指针,指向队首元素
private queSize: number; // 双向队列长度
private nums: number[]; // 用于存储双向队列元素的数组
private front: number; // 队首指针,指向队首元素
private queSize: number; // 双向队列长度
/* 构造方法 */
constructor(capacity: number) {
@ -44,7 +43,7 @@ class ArrayDeque {
/* 队首入队 */
pushFirst(num: number): void {
if (this.queSize === this.capacity()) {
console.log("双向队列已满");
console.log('双向队列已满');
return;
}
// 队首指针向左移动一位
@ -58,7 +57,7 @@ class ArrayDeque {
/* 队尾入队 */
pushLast(num: number): void {
if (this.queSize === this.capacity()) {
console.log("双向队列已满");
console.log('双向队列已满');
return;
}
// 计算尾指针,指向队尾索引 + 1
@ -86,15 +85,13 @@ class ArrayDeque {
/* 访问队首元素 */
peekFirst(): number {
if (this.isEmpty())
throw new Error("The Deque Is Empty.");
if (this.isEmpty()) throw new Error('The Deque Is Empty.');
return this.nums[this.front];
}
/* 访问队尾元素 */
peekLast(): number {
if (this.isEmpty())
throw new Error("The Deque Is Empty.");
if (this.isEmpty()) throw new Error('The Deque Is Empty.');
// 计算尾元素索引
const last = this.index(this.front + this.queSize - 1);
return this.nums[last];
@ -118,32 +115,44 @@ const deque: ArrayDeque = new ArrayDeque(capacity);
deque.pushLast(3);
deque.pushLast(2);
deque.pushLast(5);
console.log("双向队列 deque = [" + deque.toArray() + "]");
console.log('双向队列 deque = [' + deque.toArray() + ']');
/* 访问元素 */
const peekFirst = deque.peekFirst();
console.log("队首元素 peekFirst = " + peekFirst);
console.log('队首元素 peekFirst = ' + peekFirst);
const peekLast = deque.peekLast();
console.log("队尾元素 peekLast = " + peekLast);
console.log('队尾元素 peekLast = ' + peekLast);
/* 元素入队 */
deque.pushLast(4);
console.log("元素 4 队尾入队后 deque = [" + deque.toArray() + "]");
console.log('元素 4 队尾入队后 deque = [' + deque.toArray() + ']');
deque.pushFirst(1);
console.log("元素 1 队首入队后 deque = [" + deque.toArray() + "]");
console.log('元素 1 队首入队后 deque = [' + deque.toArray() + ']');
/* 元素出队 */
const popLast = deque.popLast();
console.log("队尾出队元素 = " + popLast + ",队尾出队后 deque = [" + deque.toArray() + "]");
console.log(
'队尾出队元素 = ' +
popLast +
',队尾出队后 deque = [' +
deque.toArray() +
']'
);
const popFirst = deque.popFirst();
console.log("队首出队元素 = " + popFirst + ",队首出队后 deque = [" + deque.toArray()+ "]");
console.log(
'队首出队元素 = ' +
popFirst +
',队首出队后 deque = [' +
deque.toArray() +
']'
);
/* 获取双向队列的长度 */
const size = deque.size();
console.log("双向队列长度 size = " + size);
console.log('双向队列长度 size = ' + size);
/* 判断双向队列是否为空 */
const isEmpty = deque.isEmpty();
console.log("双向队列是否为空 = " + isEmpty);
console.log('双向队列是否为空 = ' + isEmpty);
export {};

View file

@ -6,8 +6,8 @@
/* 基于环形数组实现的队列 */
class ArrayQueue {
private nums: number[]; // 用于存储队列元素的数组
private front: number; // 队首指针,指向队首元素
private nums: number[]; // 用于存储队列元素的数组
private front: number; // 队首指针,指向队首元素
private queSize: number; // 队列长度
constructor(capacity: number) {
@ -33,7 +33,7 @@ class ArrayQueue {
/* 入队 */
push(num: number): void {
if (this.size == this.capacity) {
console.log("队列已满");
console.log('队列已满');
return;
}
// 计算尾指针,指向队尾索引 + 1
@ -55,8 +55,7 @@ class ArrayQueue {
/* 访问队首元素 */
peek(): number {
if (this.empty())
throw new Error("队列为空");
if (this.empty()) throw new Error('队列为空');
return this.nums[this.front];
}
@ -82,29 +81,29 @@ queue.push(3);
queue.push(2);
queue.push(5);
queue.push(4);
console.log("队列 queue =", queue.toArray());
console.log('队列 queue =', queue.toArray());
/* 访问队首元素 */
const peek = queue.peek();
console.log("队首元素 peek = " + peek);
console.log('队首元素 peek = ' + peek);
/* 元素出队 */
const pop = queue.pop();
console.log("出队元素 pop = " + pop + ",出队后 queue =", queue.toArray());
console.log('出队元素 pop = ' + pop + ',出队后 queue =', queue.toArray());
/* 获取队列的长度 */
const size = queue.size;
console.log("队列长度 size = " + size);
console.log('队列长度 size = ' + size);
/* 判断队列是否为空 */
const empty = queue.empty();
console.log("队列是否为空 = " + empty);
console.log('队列是否为空 = ' + empty);
/* 测试环形数组 */
for (let i = 0; i < 10; i++) {
queue.push(i);
queue.pop();
console.log("第 " + i + " 轮入队 + 出队后 queue =", queue.toArray());
console.log('第 ' + i + ' 轮入队 + 出队后 queue =', queue.toArray());
}
export {};

View file

@ -4,7 +4,6 @@
* Author: S-N-O-R-L-A-X (snorlax.xu@outlook.com)
*/
/* 基于数组实现的栈 */
class ArrayStack {
private stack: number[];
@ -29,15 +28,13 @@ class ArrayStack {
/* 出栈 */
pop(): number | undefined {
if (this.empty())
throw new Error('栈为空');
if (this.empty()) throw new Error('栈为空');
return this.stack.pop();
}
/* 访问栈顶元素 */
top(): number | undefined {
if (this.empty())
throw new Error('栈为空');
if (this.empty()) throw new Error('栈为空');
return this.stack[this.stack.length - 1];
}
@ -45,8 +42,7 @@ class ArrayStack {
toArray() {
return this.stack;
}
};
}
/* Driver Code */
/* 初始化栈 */
@ -58,24 +54,24 @@ stack.push(3);
stack.push(2);
stack.push(5);
stack.push(4);
console.log("栈 stack = ");
console.log('栈 stack = ');
console.log(stack.toArray());
/* 访问栈顶元素 */
const top = stack.top();
console.log("栈顶元素 top = " + top);
console.log('栈顶元素 top = ' + top);
/* 元素出栈 */
const pop = stack.pop();
console.log("出栈元素 pop = " + pop + ",出栈后 stack = ");
console.log('出栈元素 pop = ' + pop + ',出栈后 stack = ');
console.log(stack.toArray());
/* 获取栈的长度 */
const size = stack.size;
console.log("栈的长度 size = " + size);
console.log('栈的长度 size = ' + size);
/* 判断是否为空 */
const empty = stack.empty();
console.log("栈是否为空 = " + empty);
console.log('栈是否为空 = ' + empty);
export {};

View file

@ -16,27 +16,31 @@ deque.push(4);
// 请注意由于是数组unshift() 方法的时间复杂度为 O(n)
deque.unshift(3);
deque.unshift(1);
console.log("双向队列 deque = ", deque);
console.log('双向队列 deque = ', deque);
/* 访问元素 */
const peekFirst: number = deque[0];
console.log("队首元素 peekFirst = " + peekFirst);
console.log('队首元素 peekFirst = ' + peekFirst);
const peekLast: number = deque[deque.length - 1];
console.log("队尾元素 peekLast = " + peekLast);
console.log('队尾元素 peekLast = ' + peekLast);
/* 元素出队 */
// 请注意由于是数组shift() 方法的时间复杂度为 O(n)
const popFront: number = deque.shift() as number;
console.log("队首出队元素 popFront = " + popFront + ",队首出队后 deque = " + deque);
console.log(
'队首出队元素 popFront = ' + popFront + ',队首出队后 deque = ' + deque
);
const popBack: number = deque.pop() as number;
console.log("队尾出队元素 popBack = " + popBack + ",队尾出队后 deque = " + deque);
console.log(
'队尾出队元素 popBack = ' + popBack + ',队尾出队后 deque = ' + deque
);
/* 获取双向队列的长度 */
const size: number = deque.length;
console.log("双向队列长度 size = " + size);
console.log('双向队列长度 size = ' + size);
/* 判断双向队列是否为空 */
const isEmpty: boolean = size === 0;
console.log("双向队列是否为空 = " + isEmpty);
console.log('双向队列是否为空 = ' + isEmpty);
export {};

View file

@ -6,9 +6,9 @@
/* 双向链表节点 */
class ListNode {
prev: ListNode; // 前驱节点引用 (指针)
next: ListNode; // 后继节点引用 (指针)
val: number; // 节点值
prev: ListNode; // 前驱节点引用 (指针)
next: ListNode; // 后继节点引用 (指针)
val: number; // 节点值
constructor(val: number) {
this.val = val;
@ -19,16 +19,16 @@ class ListNode {
/* 基于双向链表实现的双向队列 */
class LinkedListDeque {
private front: ListNode; // 头节点 front
private rear: ListNode; // 尾节点 rear
private queSize: number; // 双向队列的长度
private front: ListNode; // 头节点 front
private rear: ListNode; // 尾节点 rear
private queSize: number; // 双向队列的长度
constructor() {
this.front = null;
this.rear = null;
this.queSize = 0;
}
/* 队尾入队操作 */
pushLast(val: number): void {
const node: ListNode = new ListNode(val);
@ -73,7 +73,7 @@ class LinkedListDeque {
temp.next = null;
this.rear.prev = null;
}
this.rear = temp; // 更新尾节点
this.rear = temp; // 更新尾节点
this.queSize--;
return value;
}
@ -90,7 +90,7 @@ class LinkedListDeque {
temp.prev = null;
this.front.next = null;
}
this.front = temp; // 更新头节点
this.front = temp; // 更新头节点
this.queSize--;
return value;
}
@ -123,7 +123,7 @@ class LinkedListDeque {
arr.push(temp.val);
temp = temp.next;
}
console.log("[" + arr.join(", ") + "]");
console.log('[' + arr.join(', ') + ']');
}
}
@ -133,35 +133,35 @@ const linkedListDeque: LinkedListDeque = new LinkedListDeque();
linkedListDeque.pushLast(3);
linkedListDeque.pushLast(2);
linkedListDeque.pushLast(5);
console.log("双向队列 linkedListDeque = ");
console.log('双向队列 linkedListDeque = ');
linkedListDeque.print();
/* 访问元素 */
const peekFirst: number = linkedListDeque.peekFirst();
console.log("队首元素 peekFirst = " + peekFirst);
console.log('队首元素 peekFirst = ' + peekFirst);
const peekLast: number = linkedListDeque.peekLast();
console.log("队尾元素 peekLast = " + peekLast);
console.log('队尾元素 peekLast = ' + peekLast);
/* 元素入队 */
linkedListDeque.pushLast(4);
console.log("元素 4 队尾入队后 linkedListDeque = ");
console.log('元素 4 队尾入队后 linkedListDeque = ');
linkedListDeque.print();
linkedListDeque.pushFirst(1);
console.log("元素 1 队首入队后 linkedListDeque = ");
console.log('元素 1 队首入队后 linkedListDeque = ');
linkedListDeque.print();
/* 元素出队 */
const popLast: number = linkedListDeque.popLast();
console.log("队尾出队元素 = " + popLast + ",队尾出队后 linkedListDeque = ");
console.log('队尾出队元素 = ' + popLast + ',队尾出队后 linkedListDeque = ');
linkedListDeque.print();
const popFirst: number = linkedListDeque.popFirst();
console.log("队首出队元素 = " + popFirst + ",队首出队后 linkedListDeque = ");
console.log('队首出队元素 = ' + popFirst + ',队首出队后 linkedListDeque = ');
linkedListDeque.print();
/* 获取双向队列的长度 */
const size: number = linkedListDeque.size();
console.log("双向队列长度 size = " + size);
console.log('双向队列长度 size = ' + size);
/* 判断双向队列是否为空 */
const isEmpty: boolean = linkedListDeque.isEmpty();
console.log("双向队列是否为空 = " + isEmpty);
console.log('双向队列是否为空 = ' + isEmpty);

View file

@ -6,7 +6,7 @@
/* Driver Code */
/* 初始化队列 */
// TypeScript 没有内置的队列,可以把 Array 当作队列来使用
// TypeScript 没有内置的队列,可以把 Array 当作队列来使用
const queue: number[] = [];
/* 元素入队 */
@ -15,23 +15,23 @@ queue.push(3);
queue.push(2);
queue.push(5);
queue.push(4);
console.log("队列 queue =", queue);
console.log('队列 queue =', queue);
/* 访问队首元素 */
const peek = queue[0];
console.log("队首元素 peek =", peek);
console.log('队首元素 peek =', peek);
/* 元素出队 */
// 底层是数组,因此 shift() 方法的时间复杂度为 O(n)
const pop = queue.shift();
console.log("出队元素 pop =", pop, ",出队后 queue = ", queue);
console.log('出队元素 pop =', pop, ',出队后 queue = ', queue);
/* 获取队列的长度 */
const size = queue.length;
console.log("队列长度 size =", size);
console.log('队列长度 size =', size);
/* 判断队列是否为空 */
const isEmpty = queue.length === 0;
console.log("队列是否为空 = ", isEmpty);
console.log('队列是否为空 = ', isEmpty);
export {};

View file

@ -6,7 +6,7 @@
/* Driver Code */
/* 初始化栈 */
// Typescript 没有内置的栈类,可以把 Array 当作栈来使用
// Typescript 没有内置的栈类,可以把 Array 当作栈来使用
const stack: number[] = [];
/* 元素入栈 */
@ -15,23 +15,23 @@ stack.push(3);
stack.push(2);
stack.push(5);
stack.push(4);
console.log("栈 stack =", stack);
console.log('栈 stack =', stack);
/* 访问栈顶元素 */
const peek = stack[stack.length - 1];
console.log("栈顶元素 peek =", peek);
console.log('栈顶元素 peek =', peek);
/* 元素出栈 */
const pop = stack.pop();
console.log("出栈元素 pop =", pop);
console.log("出栈后 stack =", stack);
console.log('出栈元素 pop =', pop);
console.log('出栈后 stack =', stack);
/* 获取栈的长度 */
const size = stack.length;
console.log("栈的长度 size =", size);
console.log('栈的长度 size =', size);
/* 判断是否为空 */
const isEmpty = stack.length === 0;
console.log("栈是否为空 =", isEmpty);
console.log('栈是否为空 =', isEmpty);
export {};

View file

@ -24,7 +24,8 @@ class AVLTree {
/* 更新节点高度 */
private updateHeight(node: TreeNode): void {
// 节点高度等于最高子树高度 + 1
node.height = Math.max(this.height(node.left), this.height(node.right)) + 1;
node.height =
Math.max(this.height(node.left), this.height(node.right)) + 1;
}
/* 获取平衡因子 */

View file

@ -44,8 +44,4 @@ function getListNode(head: ListNode | null, val: number): ListNode | null {
return head;
}
export {
ListNode,
arrToLinkedList,
getListNode
};
export { ListNode, arrToLinkedList, getListNode };

View file

@ -4,8 +4,8 @@
* Author: Justin (xiefahit@gmail.com)
*/
import { ListNode } from "./ListNode";
import { TreeNode, arrToTree } from "./TreeNode";
import { ListNode } from './ListNode';
import { TreeNode, arrToTree } from './TreeNode';
/**
* Print a linked list
@ -46,7 +46,11 @@ function printTree(root: TreeNode | null) {
* @param prev
* @param isLeft
*/
function printTreeHelper(root: TreeNode | null, prev: Trunk | null, isLeft: boolean) {
function printTreeHelper(
root: TreeNode | null,
prev: Trunk | null,
isLeft: boolean
) {
if (root === null) {
return;
}
@ -98,15 +102,11 @@ function showTrunks(p: Trunk | null) {
* @param arr
*/
function printHeap(arr: number[]): void {
console.log("堆的数组表示:");
console.log('堆的数组表示:');
console.log(arr);
console.log("堆的树状表示:");
console.log('堆的树状表示:');
const root = arrToTree(arr);
printTree(root);
}
export {
printLinkedList,
printTree,
printHeap
};
export { printLinkedList, printTree, printHeap };

View file

@ -8,15 +8,20 @@
* Definition for a binary tree node.
*/
class TreeNode {
val: number; // 节点值
height: number; // 节点高度
left: TreeNode | null; // 左子节点指针
val: number; // 节点值
height: number; // 节点高度
left: TreeNode | null; // 左子节点指针
right: TreeNode | null; // 右子节点指针
constructor(val?: number, height?: number, left?: TreeNode | null, right?: TreeNode | null) {
constructor(
val?: number,
height?: number,
left?: TreeNode | null,
right?: TreeNode | null
) {
this.val = val === undefined ? 0 : val;
this.height = height === undefined ? 0 : height;
this.left = left === undefined ? null : left;
this.right = right === undefined ? null : right;
this.height = height === undefined ? 0 : height;
this.left = left === undefined ? null : left;
this.right = right === undefined ? null : right;
}
}
@ -49,7 +54,4 @@ function arrToTree(arr: (number | null)[]): TreeNode | null {
return root;
}
export {
TreeNode,
arrToTree
};
export { TreeNode, arrToTree };

View file

@ -4,7 +4,6 @@
* Author: Zhuo Qinyue (1403450829@qq.com)
*/
/* 顶点类 */
class Vertex {
val: number;
@ -31,6 +30,4 @@ class Vertex {
}
}
export {
Vertex
};
export { Vertex };

View file

@ -5,4 +5,4 @@
"outDir": "out",
"sourceMap": true
}
}
}