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*/ /* Driver Codes*/
/* 初始化数组 */ /* 初始化数组 */
const arr = new Array(5).fill(0); const arr = new Array(5).fill(0);
console.log("数组 arr =", arr); console.log('数组 arr =', arr);
let nums = [1, 3, 2, 5, 4]; let nums = [1, 3, 2, 5, 4];
console.log("数组 nums =", nums); console.log('数组 nums =', nums);
/* 随机访问 */ /* 随机访问 */
let random_num = randomAccess(nums); let random_num = randomAccess(nums);
console.log("在 nums 中获取随机元素", random_num); console.log('在 nums 中获取随机元素', random_num);
/* 长度扩展 */ /* 长度扩展 */
nums = extend(nums, 3); nums = extend(nums, 3);
console.log("将数组长度扩展至 8 ,得到 nums =", nums); console.log('将数组长度扩展至 8 ,得到 nums =', nums);
/* 插入元素 */ /* 插入元素 */
insert(nums, 6, 3); insert(nums, 6, 3);
console.log("在索引 3 处插入数字 6 ,得到 nums =", nums); console.log('在索引 3 处插入数字 6 ,得到 nums =', nums);
/* 删除元素 */ /* 删除元素 */
remove(nums, 2); remove(nums, 2);
console.log("删除索引 2 处的元素,得到 nums =", nums); console.log('删除索引 2 处的元素,得到 nums =', nums);
/* 遍历数组 */ /* 遍历数组 */
traverse(nums); traverse(nums);
/* 查找元素 */ /* 查找元素 */
let index = find(nums, 3); 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) * Author: IsChristina (christinaxia77@foxmail.com), Justin (xiefahit@gmail.com)
*/ */
const { printLinkedList } = require("../modules/PrintUtil"); const { printLinkedList } = require('../modules/PrintUtil');
const { ListNode } = require("../modules/ListNode"); const { ListNode } = require('../modules/ListNode');
/* 在链表的节点 n0 之后插入节点 P */ /* 在链表的节点 n0 之后插入节点 P */
function insert(n0, P) { function insert(n0, P) {
@ -16,8 +16,7 @@ function insert(n0, P) {
/* 删除链表的节点 n0 之后的首个节点 */ /* 删除链表的节点 n0 之后的首个节点 */
function remove(n0) { function remove(n0) {
if (!n0.next) if (!n0.next) return;
return;
// n0 -> P -> n1 // n0 -> P -> n1
const P = n0.next; const P = n0.next;
const n1 = P.next; const n1 = P.next;
@ -61,23 +60,23 @@ n0.next = n1;
n1.next = n2; n1.next = n2;
n2.next = n3; n2.next = n3;
n3.next = n4; n3.next = n4;
console.log("初始化的链表为"); console.log('初始化的链表为');
printLinkedList(n0); printLinkedList(n0);
/* 插入节点 */ /* 插入节点 */
insert(n0, new ListNode(0)); insert(n0, new ListNode(0));
console.log("插入节点后的链表为"); console.log('插入节点后的链表为');
printLinkedList(n0); printLinkedList(n0);
/* 删除节点 */ /* 删除节点 */
remove(n0); remove(n0);
console.log("删除节点后的链表为"); console.log('删除节点后的链表为');
printLinkedList(n0); printLinkedList(n0);
/* 访问节点 */ /* 访问节点 */
const node = access(n0, 3); const node = access(n0, 3);
console.log("链表中索引 3 处的节点的值 = " + node.val); console.log('链表中索引 3 处的节点的值 = ' + node.val);
/* 查找节点 */ /* 查找节点 */
const index = find(n0, 2); const index = find(n0, 2);
console.log("链表中值为 2 的节点的索引 = " + index); console.log('链表中值为 2 的节点的索引 = ' + index);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -4,7 +4,7 @@
* Author: Zhuo Qinyue (1403450829@qq.com) * Author: Zhuo Qinyue (1403450829@qq.com)
*/ */
const { arrToLinkedList } = require("../modules/ListNode"); const { arrToLinkedList } = require('../modules/ListNode');
/* 哈希查找(数组) */ /* 哈希查找(数组) */
function hashingSearchArray(map, target) { function hashingSearchArray(map, target) {
@ -28,18 +28,18 @@ const nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8];
// 初始化哈希表 // 初始化哈希表
const map = new Map(); const map = new Map();
for (let i = 0; i < nums.length; i++) { 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); 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(); const map1 = new Map();
while (head != null) { while (head != null) {
map1.set(head.val, head); // key: 节点值value: 节点 map1.set(head.val, head); // key: 节点值value: 节点
head = head.next; head = head.next;
} }
const node = hashingSearchLinkedList(map1, target); 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 */ /* Driver Code */
// 方法一 // 方法一
const nums = [2, 7, 11, 15], target = 9; const nums = [2, 7, 11, 15],
target = 9;
let res = twoSumBruteForce(nums, target); let res = twoSumBruteForce(nums, target);
console.log("方法一 res = ", res); console.log('方法一 res = ', res);
// 方法二 // 方法二
res = twoSumHashTable(nums, target); 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) * Author: JoseHung (szhong@link.cuhk.edu.hk)
*/ */
const { ListNode, arrToLinkedList } = require("../modules/ListNode"); const { ListNode, arrToLinkedList } = require('../modules/ListNode');
/* 线性查找(数组) */ /* 线性查找(数组) */
function linearSearchArray(nums, target) { function linearSearchArray(nums, target) {
@ -16,15 +16,15 @@ function linearSearchArray(nums, target) {
} }
} }
// 未找到目标元素,返回 -1 // 未找到目标元素,返回 -1
return -1; return -1;
} }
/* 线性查找(链表)*/ /* 线性查找(链表)*/
function linearSearchLinkedList(head, target) { function linearSearchLinkedList(head, target) {
// 遍历链表 // 遍历链表
while(head) { while (head) {
// 找到目标节点,返回之 // 找到目标节点,返回之
if(head.val === target) { if (head.val === target) {
return head; return head;
} }
head = head.next; head = head.next;
@ -39,9 +39,9 @@ const target = 3;
/* 在数组中执行线性查找 */ /* 在数组中执行线性查找 */
const nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8]; const nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8];
const index = linearSearchArray(nums, target); const index = linearSearchArray(nums, target);
console.log("目标元素 3 的索引 = " + index); console.log('目标元素 3 的索引 = ' + index);
/* 在链表中执行线性查找 */ /* 在链表中执行线性查找 */
const head = arrToLinkedList(nums); const head = arrToLinkedList(nums);
const node = linearSearchLinkedList(head, target); 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]; let tmp = nums[j];
nums[j] = nums[j + 1]; nums[j] = nums[j + 1];
nums[j + 1] = tmp; nums[j + 1] = tmp;
flag = true; // 记录交换元素 flag = true; // 记录交换元素
} }
} }
if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出 if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出
} }
} }
/* Driver Code */ /* Driver Code */
const nums = [4, 1, 3, 1, 5, 2]; const nums = [4, 1, 3, 1, 5, 2];
bubbleSort(nums); bubbleSort(nums);
console.log("排序后数组 nums =", nums); console.log('排序后数组 nums =', nums);
const nums1 = [4, 1, 3, 1, 5, 2]; const nums1 = [4, 1, 3, 1, 5, 2];
bubbleSortWithFlag(nums1); bubbleSortWithFlag(nums1);
console.log("排序后数组 nums =", nums1); console.log('排序后数组 nums =', nums1);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,9 +6,9 @@
/* 基于环形数组实现的队列 */ /* 基于环形数组实现的队列 */
class ArrayQueue { class ArrayQueue {
#nums; // 用于存储队列元素的数组 #nums; // 用于存储队列元素的数组
#front = 0; // 队首指针,指向队首元素 #front = 0; // 队首指针,指向队首元素
#queSize = 0; // 队列长度 #queSize = 0; // 队列长度
constructor(capacity) { constructor(capacity) {
this.#nums = new Array(capacity); this.#nums = new Array(capacity);
@ -32,7 +32,7 @@ class ArrayQueue {
/* 入队 */ /* 入队 */
push(num) { push(num) {
if (this.size == this.capacity) { if (this.size == this.capacity) {
console.log("队列已满"); console.log('队列已满');
return; return;
} }
// 计算尾指针,指向队尾索引 + 1 // 计算尾指针,指向队尾索引 + 1
@ -54,8 +54,7 @@ class ArrayQueue {
/* 访问队首元素 */ /* 访问队首元素 */
peek() { peek() {
if (this.empty()) if (this.empty()) throw new Error('队列为空');
throw new Error("队列为空");
return this.#nums[this.#front]; return this.#nums[this.#front];
} }
@ -70,7 +69,6 @@ class ArrayQueue {
} }
} }
/* Driver Code */ /* Driver Code */
/* 初始化队列 */ /* 初始化队列 */
const capacity = 10; const capacity = 10;
@ -82,27 +80,27 @@ queue.push(3);
queue.push(2); queue.push(2);
queue.push(5); queue.push(5);
queue.push(4); queue.push(4);
console.log("队列 queue =", queue.toArray()); console.log('队列 queue =', queue.toArray());
/* 访问队首元素 */ /* 访问队首元素 */
const peek = queue.peek(); const peek = queue.peek();
console.log("队首元素 peek = " + peek); console.log('队首元素 peek = ' + peek);
/* 元素出队 */ /* 元素出队 */
const pop = queue.pop(); const pop = queue.pop();
console.log("出队元素 pop = " + pop + ",出队后 queue =", queue.toArray()); console.log('出队元素 pop = ' + pop + ',出队后 queue =', queue.toArray());
/* 获取队列的长度 */ /* 获取队列的长度 */
const size = queue.size; const size = queue.size;
console.log("队列长度 size = " + size); console.log('队列长度 size = ' + size);
/* 判断队列是否为空 */ /* 判断队列是否为空 */
const empty = queue.empty(); const empty = queue.empty();
console.log("队列是否为空 = " + empty); console.log('队列是否为空 = ' + empty);
/* 测试环形数组 */ /* 测试环形数组 */
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
queue.push(i); queue.push(i);
queue.pop(); 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) * Author: S-N-O-R-L-A-X (snorlax.xu@outlook.com)
*/ */
/* 基于数组实现的栈 */ /* 基于数组实现的栈 */
class ArrayStack { class ArrayStack {
#stack; #stack;
constructor() { constructor() {
this.#stack = []; this.#stack = [];
} }
/* 获取栈的长度 */ /* 获取栈的长度 */
get size() { get size() {
return this.#stack.length; return this.#stack.length;
@ -29,15 +28,13 @@ class ArrayStack {
/* 出栈 */ /* 出栈 */
pop() { pop() {
if (this.empty()) if (this.empty()) throw new Error('栈为空');
throw new Error("栈为空");
return this.#stack.pop(); return this.#stack.pop();
} }
/* 访问栈顶元素 */ /* 访问栈顶元素 */
top() { top() {
if (this.empty()) if (this.empty()) throw new Error('栈为空');
throw new Error("栈为空");
return this.#stack[this.#stack.length - 1]; return this.#stack[this.#stack.length - 1];
} }
@ -45,8 +42,7 @@ class ArrayStack {
toArray() { toArray() {
return this.#stack; return this.#stack;
} }
}; }
/* Driver Code */ /* Driver Code */
/* 初始化栈 */ /* 初始化栈 */
@ -58,22 +54,22 @@ stack.push(3);
stack.push(2); stack.push(2);
stack.push(5); stack.push(5);
stack.push(4); stack.push(4);
console.log("栈 stack = "); console.log('栈 stack = ');
console.log(stack.toArray()); console.log(stack.toArray());
/* 访问栈顶元素 */ /* 访问栈顶元素 */
const top = stack.top(); const top = stack.top();
console.log("栈顶元素 top = " + top); console.log('栈顶元素 top = ' + top);
/* 元素出栈 */ /* 元素出栈 */
const pop = stack.pop(); const pop = stack.pop();
console.log("出栈元素 pop = " + pop + ",出栈后 stack = "); console.log('出栈元素 pop = ' + pop + ',出栈后 stack = ');
console.log(stack.toArray()); console.log(stack.toArray());
/* 获取栈的长度 */ /* 获取栈的长度 */
const size = stack.size; const size = stack.size;
console.log("栈的长度 size = " + size); console.log('栈的长度 size = ' + size);
/* 判断是否为空 */ /* 判断是否为空 */
const empty = stack.empty(); const empty = stack.empty();
console.log("栈是否为空 = " + empty); console.log('栈是否为空 = ' + empty);

View file

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

View file

@ -6,10 +6,10 @@
/* 双向链表节点 */ /* 双向链表节点 */
class ListNode { class ListNode {
prev; // 前驱节点引用 (指针) prev; // 前驱节点引用 (指针)
next; // 后继节点引用 (指针) next; // 后继节点引用 (指针)
val; // 节点值 val; // 节点值
constructor(val) { constructor(val) {
this.val = val; this.val = val;
this.next = null; this.next = null;
@ -19,9 +19,9 @@ class ListNode {
/* 基于双向链表实现的双向队列 */ /* 基于双向链表实现的双向队列 */
class LinkedListDeque { class LinkedListDeque {
#front; // 头节点 front #front; // 头节点 front
#rear; // 尾节点 rear #rear; // 尾节点 rear
#queSize; // 双向队列的长度 #queSize; // 双向队列的长度
constructor() { constructor() {
this.#front = null; this.#front = null;
@ -73,7 +73,7 @@ class LinkedListDeque {
temp.next = null; temp.next = null;
this.#rear.prev = null; this.#rear.prev = null;
} }
this.#rear = temp; // 更新尾节点 this.#rear = temp; // 更新尾节点
this.#queSize--; this.#queSize--;
return value; return value;
} }
@ -90,7 +90,7 @@ class LinkedListDeque {
temp.prev = null; temp.prev = null;
this.#front.next = null; this.#front.next = null;
} }
this.#front = temp; // 更新头节点 this.#front = temp; // 更新头节点
this.#queSize--; this.#queSize--;
return value; return value;
} }
@ -123,7 +123,7 @@ class LinkedListDeque {
arr.push(temp.val); arr.push(temp.val);
temp = temp.next; temp = temp.next;
} }
console.log("[" + arr.join(", ") + "]"); console.log('[' + arr.join(', ') + ']');
} }
} }
@ -133,35 +133,35 @@ const linkedListDeque = new LinkedListDeque();
linkedListDeque.pushLast(3); linkedListDeque.pushLast(3);
linkedListDeque.pushLast(2); linkedListDeque.pushLast(2);
linkedListDeque.pushLast(5); linkedListDeque.pushLast(5);
console.log("双向队列 linkedListDeque = "); console.log('双向队列 linkedListDeque = ');
linkedListDeque.print(); linkedListDeque.print();
/* 访问元素 */ /* 访问元素 */
const peekFirst = linkedListDeque.peekFirst(); const peekFirst = linkedListDeque.peekFirst();
console.log("队首元素 peekFirst = " + peekFirst); console.log('队首元素 peekFirst = ' + peekFirst);
const peekLast = linkedListDeque.peekLast(); const peekLast = linkedListDeque.peekLast();
console.log("队尾元素 peekLast = " + peekLast); console.log('队尾元素 peekLast = ' + peekLast);
/* 元素入队 */ /* 元素入队 */
linkedListDeque.pushLast(4); linkedListDeque.pushLast(4);
console.log("元素 4 队尾入队后 linkedListDeque = "); console.log('元素 4 队尾入队后 linkedListDeque = ');
linkedListDeque.print(); linkedListDeque.print();
linkedListDeque.pushFirst(1); linkedListDeque.pushFirst(1);
console.log("元素 1 队首入队后 linkedListDeque = "); console.log('元素 1 队首入队后 linkedListDeque = ');
linkedListDeque.print(); linkedListDeque.print();
/* 元素出队 */ /* 元素出队 */
const popLast = linkedListDeque.popLast(); const popLast = linkedListDeque.popLast();
console.log("队尾出队元素 = " + popLast + ",队尾出队后 linkedListDeque = "); console.log('队尾出队元素 = ' + popLast + ',队尾出队后 linkedListDeque = ');
linkedListDeque.print(); linkedListDeque.print();
const popFirst = linkedListDeque.popFirst(); const popFirst = linkedListDeque.popFirst();
console.log("队首出队元素 = " + popFirst + ",队首出队后 linkedListDeque = "); console.log('队首出队元素 = ' + popFirst + ',队首出队后 linkedListDeque = ');
linkedListDeque.print(); linkedListDeque.print();
/* 获取双向队列的长度 */ /* 获取双向队列的长度 */
const size = linkedListDeque.size(); const size = linkedListDeque.size();
console.log("双向队列长度 size = " + size); console.log('双向队列长度 size = ' + size);
/* 判断双向队列是否为空 */ /* 判断双向队列是否为空 */
const isEmpty = linkedListDeque.isEmpty(); 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) * Author: S-N-O-R-L-A-X (snorlax.xu@outlook.com)
*/ */
const { ListNode } = require("../modules/ListNode"); const { ListNode } = require('../modules/ListNode');
/* 基于链表实现的队列 */ /* 基于链表实现的队列 */
class LinkedListQueue { class LinkedListQueue {
#front; // 头节点 #front #front; // 头节点 #front
#rear; // 尾节点 #rear #rear; // 尾节点 #rear
#queSize = 0; #queSize = 0;
constructor() { constructor() {
@ -54,8 +54,7 @@ class LinkedListQueue {
/* 访问队首元素 */ /* 访问队首元素 */
peek() { peek() {
if (this.size === 0) if (this.size === 0) throw new Error('队列为空');
throw new Error("队列为空");
return this.#front.val; return this.#front.val;
} }
@ -71,8 +70,6 @@ class LinkedListQueue {
} }
} }
/* Driver Code */ /* Driver Code */
/* 初始化队列 */ /* 初始化队列 */
const queue = new LinkedListQueue(); const queue = new LinkedListQueue();
@ -83,20 +80,20 @@ queue.push(3);
queue.push(2); queue.push(2);
queue.push(5); queue.push(5);
queue.push(4); queue.push(4);
console.log("队列 queue = " + queue.toArray()); console.log('队列 queue = ' + queue.toArray());
/* 访问队首元素 */ /* 访问队首元素 */
const peek = queue.peek(); const peek = queue.peek();
console.log("队首元素 peek = " + peek); console.log('队首元素 peek = ' + peek);
/* 元素出队 */ /* 元素出队 */
const pop = queue.pop(); const pop = queue.pop();
console.log("出队元素 pop = " + pop + ",出队后 queue = " + queue.toArray()); console.log('出队元素 pop = ' + pop + ',出队后 queue = ' + queue.toArray());
/* 获取队列的长度 */ /* 获取队列的长度 */
const size = queue.size; const size = queue.size;
console.log("队列长度 size = " + size); console.log('队列长度 size = ' + size);
/* 判断队列是否为空 */ /* 判断队列是否为空 */
const isEmpty = queue.isEmpty(); 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) * Author: S-N-O-R-L-A-X (snorlax.xu@outlook.com)
*/ */
const { ListNode } = require("../modules/ListNode"); const { ListNode } = require('../modules/ListNode');
/* 基于链表实现的栈 */ /* 基于链表实现的栈 */
class LinkedListStack { class LinkedListStack {
#stackPeek; // 将头节点作为栈顶 #stackPeek; // 将头节点作为栈顶
#stkSize = 0; // 栈的长度 #stkSize = 0; // 栈的长度
constructor() { constructor() {
this.#stackPeek = null; this.#stackPeek = null;
@ -43,8 +43,7 @@ class LinkedListStack {
/* 访问栈顶元素 */ /* 访问栈顶元素 */
peek() { peek() {
if (!this.#stackPeek) if (!this.#stackPeek) throw new Error('栈为空');
throw new Error("栈为空");
return this.#stackPeek.val; return this.#stackPeek.val;
} }
@ -70,20 +69,20 @@ stack.push(3);
stack.push(2); stack.push(2);
stack.push(5); stack.push(5);
stack.push(4); stack.push(4);
console.log("栈 stack = " + stack.toArray()); console.log('栈 stack = ' + stack.toArray());
/* 访问栈顶元素 */ /* 访问栈顶元素 */
const peek = stack.peek(); const peek = stack.peek();
console.log("栈顶元素 peek = " + peek); console.log('栈顶元素 peek = ' + peek);
/* 元素出栈 */ /* 元素出栈 */
const pop = stack.pop(); const pop = stack.pop();
console.log("出栈元素 pop = " + pop + ",出栈后 stack = " + stack.toArray()); console.log('出栈元素 pop = ' + pop + ',出栈后 stack = ' + stack.toArray());
/* 获取栈的长度 */ /* 获取栈的长度 */
const size = stack.size; const size = stack.size;
console.log("栈的长度 size = " + size); console.log('栈的长度 size = ' + size);
/* 判断是否为空 */ /* 判断是否为空 */
const isEmpty = stack.isEmpty(); const isEmpty = stack.isEmpty();
console.log("栈是否为空 = " + isEmpty); console.log('栈是否为空 = ' + isEmpty);

View file

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

View file

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

View file

@ -4,8 +4,8 @@
* Author: what-is-me (whatisme@outlook.jp) * Author: what-is-me (whatisme@outlook.jp)
*/ */
const { TreeNode } = require("../modules/TreeNode"); const { TreeNode } = require('../modules/TreeNode');
const { printTree } = require("../modules/PrintUtil"); const { printTree } = require('../modules/PrintUtil');
/* AVL 树*/ /* AVL 树*/
class AVLTree { class AVLTree {
@ -23,7 +23,8 @@ class AVLTree {
/* 更新节点高度 */ /* 更新节点高度 */
#updateHeight(node) { #updateHeight(node) {
// 节点高度等于最高子树高度 + 1 // 节点高度等于最高子树高度 + 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); if (node === null) return new TreeNode(val);
/* 1. 查找插入位置,并插入节点 */ /* 1. 查找插入位置,并插入节点 */
if (val < node.val) node.left = this.#insertHelper(node.left, val); 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; // 重复节点不插入,直接返回 else return node; // 重复节点不插入,直接返回
this.#updateHeight(node); // 更新节点高度 this.#updateHeight(node); // 更新节点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
@ -121,7 +123,8 @@ class AVLTree {
if (node === null) return null; if (node === null) return null;
/* 1. 查找节点,并删除之 */ /* 1. 查找节点,并删除之 */
if (val < node.val) node.left = this.#removeHelper(node.left, val); 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 { else {
if (node.left === null || node.right === null) { if (node.left === null || node.right === null) {
const child = node.left !== null ? node.left : node.right; const child = node.left !== null ? node.left : node.right;
@ -165,13 +168,13 @@ class AVLTree {
function testInsert(tree, val) { function testInsert(tree, val) {
tree.insert(val); tree.insert(val);
console.log("\n插入节点 " + val + " 后AVL 树为"); console.log('\n插入节点 ' + val + ' 后AVL 树为');
printTree(tree.root); printTree(tree.root);
} }
function testRemove(tree, val) { function testRemove(tree, val) {
tree.remove(val); tree.remove(val);
console.log("\n删除节点 " + val + " 后AVL 树为"); console.log('\n删除节点 ' + val + ' 后AVL 树为');
printTree(tree.root); printTree(tree.root);
} }
@ -202,4 +205,4 @@ testRemove(avlTree, 4); // 删除度为 2 的节点
/* 查询节点 */ /* 查询节点 */
const node = avlTree.search(7); 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) * Author: IsChristina (christinaxia77@foxmail.com)
*/ */
const { TreeNode } = require("../modules/TreeNode"); const { TreeNode } = require('../modules/TreeNode');
const { printTree } = require("../modules/PrintUtil"); const { printTree } = require('../modules/PrintUtil');
/* 二叉搜索树 */ /* 二叉搜索树 */
let root; let root;
function BinarySearchTree(nums) { function BinarySearchTree(nums) {
nums.sort((a, b) => { return a - b }); // 排序数组 nums.sort((a, b) => {
root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树 return a - b;
}); // 排序数组
root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树
} }
/* 获取二叉树根节点 */ /* 获取二叉树根节点 */
@ -52,7 +54,8 @@ function search(num) {
function insert(num) { function insert(num) {
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if (root === null) return; if (root === null) return;
let cur = root, pre = null; let cur = root,
pre = null;
// 循环查找,越过叶节点后跳出 // 循环查找,越过叶节点后跳出
while (cur !== null) { while (cur !== null) {
// 找到重复节点,直接返回 // 找到重复节点,直接返回
@ -73,7 +76,8 @@ function insert(num) {
function remove(num) { function remove(num) {
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if (root === null) return; if (root === null) return;
let cur = root, pre = null; let cur = root,
pre = null;
// 循环查找,越过叶节点后跳出 // 循环查找,越过叶节点后跳出
while (cur !== 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]; const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
BinarySearchTree(nums); BinarySearchTree(nums);
console.log("\n初始化的二叉树为\n"); console.log('\n初始化的二叉树为\n');
printTree(getRoot()); printTree(getRoot());
/* 查找节点 */ /* 查找节点 */
let node = search(7); let node = search(7);
console.log("\n查找到的节点对象为 " + node + ",节点值 = " + node.val); console.log('\n查找到的节点对象为 ' + node + ',节点值 = ' + node.val);
/* 插入节点 */ /* 插入节点 */
insert(16); insert(16);
console.log("\n插入节点 16 后,二叉树为\n"); console.log('\n插入节点 16 后,二叉树为\n');
printTree(getRoot()); printTree(getRoot());
/* 删除节点 */ /* 删除节点 */
remove(1); remove(1);
console.log("\n删除节点 1 后,二叉树为\n"); console.log('\n删除节点 1 后,二叉树为\n');
printTree(getRoot()); printTree(getRoot());
remove(2); remove(2);
console.log("\n删除节点 2 后,二叉树为\n"); console.log('\n删除节点 2 后,二叉树为\n');
printTree(getRoot()); printTree(getRoot());
remove(4); remove(4);
console.log("\n删除节点 4 后,二叉树为\n"); console.log('\n删除节点 4 后,二叉树为\n');
printTree(getRoot()); printTree(getRoot());

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -17,12 +17,11 @@ class Entry {
/* 基于数组简易实现的哈希表 */ /* 基于数组简易实现的哈希表 */
class ArrayHashMap { class ArrayHashMap {
private readonly buckets: (Entry | null)[]; private readonly buckets: (Entry | null)[];
constructor() { constructor() {
// 初始化数组,包含 100 个桶 // 初始化数组,包含 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: 目标节点值value: 节点对象
// 若哈希表中无此 key ,返回 null // 若哈希表中无此 key ,返回 null
return map.has(target) ? (map.get(target) as ListNode) : null; return map.has(target) ? (map.get(target) as ListNode) : null;

View file

@ -1,7 +1,7 @@
/** /**
* File: leetcode_two_sum.ts * File: leetcode_two_sum.ts
* Created Time: 2022-12-15 * 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 []; return [];
}; }
/* 方法二:辅助哈希表 */ /* 方法二:辅助哈希表 */
function twoSumHashTable(nums: number[], target: number): number[] { function twoSumHashTable(nums: number[], target: number): number[] {
@ -32,17 +32,18 @@ function twoSumHashTable(nums: number[], target: number): number[] {
} }
} }
return []; return [];
}; }
/* Driver Code */ /* Driver Code */
// 方法一 // 方法一
const nums = [2, 7, 11, 15], target = 9; const nums = [2, 7, 11, 15],
target = 9;
let res = twoSumBruteForce(nums, target); let res = twoSumBruteForce(nums, target);
console.log("方法一 res = ", res); console.log('方法一 res = ', res);
// 方法二 // 方法二
res = twoSumHashTable(nums, target); res = twoSumHashTable(nums, target);
console.log("方法二 res = ", res); console.log('方法二 res = ', res);
export {}; 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) { 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 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 分别指向左子数组、右子数组的首元素 // i, j 分别指向左子数组、右子数组的首元素
let i = leftStart, j = rightStart; let i = leftStart,
j = rightStart;
// 通过覆盖原数组 nums 来合并左子数组和右子数组 // 通过覆盖原数组 nums 来合并左子数组和右子数组
for (let k = left; k <= right; k++) { for (let k = left; k <= right; k++) {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
if (i > leftEnd) { if (i > leftEnd) {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
nums[k] = tmp[j++]; nums[k] = tmp[j++];
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++ // 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
} else if (j > rightEnd || tmp[i] <= tmp[j]) { } else if (j > rightEnd || tmp[i] <= tmp[j]) {
nums[k] = tmp[i++]; nums[k] = tmp[i++];
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++ // 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
} else { } else {
nums[k] = tmp[j++]; nums[k] = tmp[j++];
} }

View file

@ -16,7 +16,8 @@ class QuickSort {
/* 哨兵划分 */ /* 哨兵划分 */
partition(nums: number[], left: number, right: number): number { partition(nums: number[], left: number, right: number): number {
// 以 nums[left] 作为基准数 // 以 nums[left] 作为基准数
let i = left, j = right; let i = left,
j = right;
while (i < j) { while (i < j) {
while (i < j && nums[j] >= nums[left]) { while (i < j && nums[j] >= nums[left]) {
j -= 1; // 从右向左找首个小于基准数的元素 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 // 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if (Number(nums[left] < nums[mid]) ^ Number(nums[left] < nums[right])) { if (Number(nums[left] < nums[mid]) ^ Number(nums[left] < nums[right])) {
return left; 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; return mid;
} else { } else {
return right; return right;
@ -70,11 +78,17 @@ class QuickSortMedian {
/* 哨兵划分(三数取中值) */ /* 哨兵划分(三数取中值) */
partition(nums: number[], left: number, right: number): number { 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); this.swap(nums, left, med);
// 以 nums[left] 作为基准数 // 以 nums[left] 作为基准数
let i = left, j = right; let i = left,
j = right;
while (i < j) { while (i < j) {
while (i < j && nums[j] >= nums[left]) { while (i < j && nums[j] >= nums[left]) {
j--; // 从右向左找首个小于基准数的元素 j--; // 从右向左找首个小于基准数的元素
@ -114,7 +128,8 @@ class QuickSortTailCall {
/* 哨兵划分 */ /* 哨兵划分 */
partition(nums: number[], left: number, right: number): number { partition(nums: number[], left: number, right: number): number {
// 以 nums[left] 作为基准数 // 以 nums[left] 作为基准数
let i = left, j = right; let i = left,
j = right;
while (i < j) { while (i < j) {
while (i < j && nums[j] >= nums[left]) { while (i < j && nums[j] >= nums[left]) {
j--; // 从右向左找首个小于基准数的元素 j--; // 从右向左找首个小于基准数的元素

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -24,7 +24,8 @@ class AVLTree {
/* 更新节点高度 */ /* 更新节点高度 */
private updateHeight(node: TreeNode): void { private updateHeight(node: TreeNode): void {
// 节点高度等于最高子树高度 + 1 // 节点高度等于最高子树高度 + 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; return head;
} }
export { export { ListNode, arrToLinkedList, getListNode };
ListNode,
arrToLinkedList,
getListNode
};

View file

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

View file

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

View file

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

View file

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