mirror of
https://github.com/krahets/hello-algo.git
synced 2024-12-24 03:06:29 +08:00
Fomrat the JS and TS codes with prettier.
This commit is contained in:
parent
9a98ff8a5e
commit
c4ea4e39f3
68 changed files with 634 additions and 510 deletions
6
codes/javascript/.prettierrc
Normal file
6
codes/javascript/.prettierrc
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": true
|
||||
}
|
|
@ -69,29 +69,29 @@ function find(nums, target) {
|
|||
/* Driver Codes*/
|
||||
/* 初始化数组 */
|
||||
const arr = new Array(5).fill(0);
|
||||
console.log("数组 arr =", arr);
|
||||
console.log('数组 arr =', arr);
|
||||
let nums = [1, 3, 2, 5, 4];
|
||||
console.log("数组 nums =", nums);
|
||||
console.log('数组 nums =', nums);
|
||||
|
||||
/* 随机访问 */
|
||||
let random_num = randomAccess(nums);
|
||||
console.log("在 nums 中获取随机元素", random_num);
|
||||
console.log('在 nums 中获取随机元素', random_num);
|
||||
|
||||
/* 长度扩展 */
|
||||
nums = extend(nums, 3);
|
||||
console.log("将数组长度扩展至 8 ,得到 nums =", nums);
|
||||
console.log('将数组长度扩展至 8 ,得到 nums =', nums);
|
||||
|
||||
/* 插入元素 */
|
||||
insert(nums, 6, 3);
|
||||
console.log("在索引 3 处插入数字 6 ,得到 nums =", nums);
|
||||
console.log('在索引 3 处插入数字 6 ,得到 nums =', nums);
|
||||
|
||||
/* 删除元素 */
|
||||
remove(nums, 2);
|
||||
console.log("删除索引 2 处的元素,得到 nums =", nums);
|
||||
console.log('删除索引 2 处的元素,得到 nums =', nums);
|
||||
|
||||
/* 遍历数组 */
|
||||
traverse(nums);
|
||||
|
||||
/* 查找元素 */
|
||||
let index = find(nums, 3);
|
||||
console.log("在 nums 中查找元素 3 ,得到索引 =", index);
|
||||
console.log('在 nums 中查找元素 3 ,得到索引 =', index);
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* Author: IsChristina (christinaxia77@foxmail.com), Justin (xiefahit@gmail.com)
|
||||
*/
|
||||
|
||||
const { printLinkedList } = require("../modules/PrintUtil");
|
||||
const { ListNode } = require("../modules/ListNode");
|
||||
const { printLinkedList } = require('../modules/PrintUtil');
|
||||
const { ListNode } = require('../modules/ListNode');
|
||||
|
||||
/* 在链表的节点 n0 之后插入节点 P */
|
||||
function insert(n0, P) {
|
||||
|
@ -16,8 +16,7 @@ function insert(n0, P) {
|
|||
|
||||
/* 删除链表的节点 n0 之后的首个节点 */
|
||||
function remove(n0) {
|
||||
if (!n0.next)
|
||||
return;
|
||||
if (!n0.next) return;
|
||||
// n0 -> P -> n1
|
||||
const P = n0.next;
|
||||
const n1 = P.next;
|
||||
|
@ -61,23 +60,23 @@ n0.next = n1;
|
|||
n1.next = n2;
|
||||
n2.next = n3;
|
||||
n3.next = n4;
|
||||
console.log("初始化的链表为");
|
||||
console.log('初始化的链表为');
|
||||
printLinkedList(n0);
|
||||
|
||||
/* 插入节点 */
|
||||
insert(n0, new ListNode(0));
|
||||
console.log("插入节点后的链表为");
|
||||
console.log('插入节点后的链表为');
|
||||
printLinkedList(n0);
|
||||
|
||||
/* 删除节点 */
|
||||
remove(n0);
|
||||
console.log("删除节点后的链表为");
|
||||
console.log('删除节点后的链表为');
|
||||
printLinkedList(n0);
|
||||
|
||||
/* 访问节点 */
|
||||
const node = access(n0, 3);
|
||||
console.log("链表中索引 3 处的节点的值 = " + node.val);
|
||||
console.log('链表中索引 3 处的节点的值 = ' + node.val);
|
||||
|
||||
/* 查找节点 */
|
||||
const index = find(n0, 2);
|
||||
console.log("链表中值为 2 的节点的索引 = " + index);
|
||||
console.log('链表中值为 2 的节点的索引 = ' + index);
|
||||
|
|
|
@ -29,15 +29,13 @@ class MyList {
|
|||
/* 访问元素 */
|
||||
get(index) {
|
||||
// 索引如果越界则抛出异常,下同
|
||||
if (index < 0 || index >= this.#size)
|
||||
throw new Error('索引越界');
|
||||
if (index < 0 || index >= this.#size) throw new Error('索引越界');
|
||||
return this.#nums[index];
|
||||
}
|
||||
|
||||
/* 更新元素 */
|
||||
set(index, num) {
|
||||
if (index < 0 || index >= this.#size)
|
||||
throw new Error('索引越界');
|
||||
if (index < 0 || index >= this.#size) throw new Error('索引越界');
|
||||
this.#nums[index] = num;
|
||||
}
|
||||
|
||||
|
@ -54,8 +52,7 @@ class MyList {
|
|||
|
||||
/* 中间插入元素 */
|
||||
insert(index, num) {
|
||||
if (index < 0 || index >= this.#size)
|
||||
throw new Error('索引越界');
|
||||
if (index < 0 || index >= this.#size) throw new Error('索引越界');
|
||||
// 元素数量超出容量时,触发扩容机制
|
||||
if (this.#size === this.#capacity) {
|
||||
this.extendCapacity();
|
||||
|
@ -71,8 +68,7 @@ class MyList {
|
|||
|
||||
/* 删除元素 */
|
||||
remove(index) {
|
||||
if (index < 0 || index >= this.#size)
|
||||
throw new Error('索引越界');
|
||||
if (index < 0 || index >= this.#size) throw new Error('索引越界');
|
||||
let num = this.#nums[index];
|
||||
// 将索引 index 之后的元素都向前移动一位
|
||||
for (let j = index; j < this.#size - 1; j++) {
|
||||
|
|
|
@ -7,16 +7,19 @@
|
|||
/* 二分查找(双闭区间) */
|
||||
function binarySearch(nums, target) {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
let i = 0, j = nums.length - 1;
|
||||
let i = 0,
|
||||
j = nums.length - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while (i <= j) {
|
||||
const m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
|
||||
// 计算中点索引 m ,使用 parseInt() 向下取整
|
||||
const m = parseInt((i + j) / 2);
|
||||
if (nums[m] < target)
|
||||
// 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1;
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
|
||||
else if (nums[m] > target)
|
||||
// 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1;
|
||||
else
|
||||
return m; // 找到目标元素,返回其索引
|
||||
else return m; // 找到目标元素,返回其索引
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
|
@ -25,16 +28,20 @@ function binarySearch(nums, target) {
|
|||
/* 二分查找(左闭右开) */
|
||||
function binarySearch1(nums, target) {
|
||||
// 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
let i = 0, j = nums.length;
|
||||
let i = 0,
|
||||
j = nums.length;
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while (i < j) {
|
||||
const m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整
|
||||
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
|
||||
// 计算中点索引 m ,使用 parseInt() 向下取整
|
||||
const m = parseInt((i + j) / 2);
|
||||
if (nums[m] < target)
|
||||
// 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1;
|
||||
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
|
||||
else if (nums[m] > target)
|
||||
// 此情况说明 target 在区间 [i, m) 中
|
||||
j = m;
|
||||
else // 找到目标元素,返回其索引
|
||||
return m;
|
||||
// 找到目标元素,返回其索引
|
||||
else return m;
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
|
@ -46,8 +53,8 @@ const nums = [1, 3, 6, 8, 12, 15, 23, 67, 70, 92];
|
|||
|
||||
/* 二分查找(双闭区间) */
|
||||
let index = binarySearch(nums, target);
|
||||
console.log("目标元素 6 的索引 = " + index);
|
||||
console.log('目标元素 6 的索引 = ' + index);
|
||||
|
||||
/* 二分查找(左闭右开) */
|
||||
index = binarySearch1(nums, target);
|
||||
console.log("目标元素 6 的索引 = " + index);
|
||||
console.log('目标元素 6 的索引 = ' + index);
|
||||
|
|
|
@ -57,7 +57,9 @@ function linearRecur(n) {
|
|||
/* 平方阶 */
|
||||
function quadratic(n) {
|
||||
// 矩阵占用 O(n^2) 空间
|
||||
const numMatrix = Array(n).fill(null).map(() => Array(n).fill(null));
|
||||
const numMatrix = Array(n)
|
||||
.fill(null)
|
||||
.map(() => Array(n).fill(null));
|
||||
// 二维列表占用 O(n^2) 空间
|
||||
const numList = [];
|
||||
for (let i = 0; i < n; i++) {
|
||||
|
|
|
@ -121,35 +121,35 @@ function factorialRecur(n) {
|
|||
/* Driver Code */
|
||||
// 可以修改 n 运行,体会一下各种复杂度的操作数量变化趋势
|
||||
const n = 8;
|
||||
console.log("输入数据大小 n = " + n);
|
||||
console.log('输入数据大小 n = ' + n);
|
||||
|
||||
let count = constant(n);
|
||||
console.log("常数阶的计算操作数量 = " + count);
|
||||
console.log('常数阶的计算操作数量 = ' + count);
|
||||
|
||||
count = linear(n);
|
||||
console.log("线性阶的计算操作数量 = " + count);
|
||||
console.log('线性阶的计算操作数量 = ' + count);
|
||||
count = arrayTraversal(new Array(n));
|
||||
console.log("线性阶(遍历数组)的计算操作数量 = " + count);
|
||||
console.log('线性阶(遍历数组)的计算操作数量 = ' + count);
|
||||
|
||||
count = quadratic(n);
|
||||
console.log("平方阶的计算操作数量 = " + count);
|
||||
console.log('平方阶的计算操作数量 = ' + count);
|
||||
let nums = new Array(n);
|
||||
for (let i = 0; i < n; i++) nums[i] = n - i; // [n,n-1,...,2,1]
|
||||
count = bubbleSort(nums);
|
||||
console.log("平方阶(冒泡排序)的计算操作数量 = " + count);
|
||||
console.log('平方阶(冒泡排序)的计算操作数量 = ' + count);
|
||||
|
||||
count = exponential(n);
|
||||
console.log("指数阶(循环实现)的计算操作数量 = " + count);
|
||||
console.log('指数阶(循环实现)的计算操作数量 = ' + count);
|
||||
count = expRecur(n);
|
||||
console.log("指数阶(递归实现)的计算操作数量 = " + count);
|
||||
console.log('指数阶(递归实现)的计算操作数量 = ' + count);
|
||||
|
||||
count = logarithmic(n);
|
||||
console.log("对数阶(循环实现)的计算操作数量 = " + count);
|
||||
console.log('对数阶(循环实现)的计算操作数量 = ' + count);
|
||||
count = logRecur(n);
|
||||
console.log("对数阶(递归实现)的计算操作数量 = " + count);
|
||||
console.log('对数阶(递归实现)的计算操作数量 = ' + count);
|
||||
|
||||
count = linearLogRecur(n);
|
||||
console.log("线性对数阶(递归实现)的计算操作数量 = " + count);
|
||||
console.log('线性对数阶(递归实现)的计算操作数量 = ' + count);
|
||||
|
||||
count = factorialRecur(n);
|
||||
console.log("阶乘阶(递归实现)的计算操作数量 = " + count);
|
||||
console.log('阶乘阶(递归实现)的计算操作数量 = ' + count);
|
||||
|
|
|
@ -38,8 +38,6 @@ for (let i = 0; i < 10; i++) {
|
|||
const n = 100;
|
||||
const nums = randomNumbers(n);
|
||||
const index = findOne(nums);
|
||||
console.log(
|
||||
"\n数组 [ 1, 2, ..., n ] 被打乱后 = [" + nums.join(", ") + "]"
|
||||
);
|
||||
console.log("数字 1 的索引为 " + index);
|
||||
console.log('\n数组 [ 1, 2, ..., n ] 被打乱后 = [' + nums.join(', ') + ']');
|
||||
console.log('数字 1 的索引为 ' + index);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Author: Justin (xiefahit@gmail.com)
|
||||
*/
|
||||
|
||||
const { Vertex } = require('../modules/Vertex')
|
||||
const { Vertex } = require('../modules/Vertex');
|
||||
|
||||
/* 基于邻接表实现的无向图类 */
|
||||
class GraphAdjList {
|
||||
|
@ -29,8 +29,12 @@ class GraphAdjList {
|
|||
|
||||
/* 添加边 */
|
||||
addEdge(vet1, vet2) {
|
||||
if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) {
|
||||
throw new Error("Illegal Argument Exception");
|
||||
if (
|
||||
!this.adjList.has(vet1) ||
|
||||
!this.adjList.has(vet2) ||
|
||||
vet1 === vet2
|
||||
) {
|
||||
throw new Error('Illegal Argument Exception');
|
||||
}
|
||||
// 添加边 vet1 - vet2
|
||||
this.adjList.get(vet1).push(vet2);
|
||||
|
@ -39,8 +43,12 @@ class GraphAdjList {
|
|||
|
||||
/* 删除边 */
|
||||
removeEdge(vet1, vet2) {
|
||||
if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) {
|
||||
throw new Error("Illegal Argument Exception");
|
||||
if (
|
||||
!this.adjList.has(vet1) ||
|
||||
!this.adjList.has(vet2) ||
|
||||
vet1 === vet2
|
||||
) {
|
||||
throw new Error('Illegal Argument Exception');
|
||||
}
|
||||
// 删除边 vet1 - vet2
|
||||
this.adjList.get(vet1).splice(this.adjList.get(vet1).indexOf(vet2), 1);
|
||||
|
@ -57,7 +65,7 @@ class GraphAdjList {
|
|||
/* 删除顶点 */
|
||||
removeVertex(vet) {
|
||||
if (!this.adjList.has(vet)) {
|
||||
throw new Error("Illegal Argument Exception");
|
||||
throw new Error('Illegal Argument Exception');
|
||||
}
|
||||
// 在邻接表中删除顶点 vet 对应的链表
|
||||
this.adjList.delete(vet);
|
||||
|
@ -72,13 +80,13 @@ class GraphAdjList {
|
|||
|
||||
/* 打印邻接表 */
|
||||
print() {
|
||||
console.log("邻接表 =");
|
||||
console.log('邻接表 =');
|
||||
for (const [key, value] of this.adjList) {
|
||||
const tmp = [];
|
||||
for (const vertex of value) {
|
||||
tmp.push(vertex.val);
|
||||
}
|
||||
console.log(key.val + ": " + tmp.join());
|
||||
console.log(key.val + ': ' + tmp.join());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,37 +99,43 @@ if (require.main === module) {
|
|||
v2 = new Vertex(2),
|
||||
v3 = new Vertex(5),
|
||||
v4 = new Vertex(4);
|
||||
const edges = [[v0, v1], [v1, v2], [v2, v3], [v0, v3], [v2, v4], [v3, v4]];
|
||||
const edges = [
|
||||
[v0, v1],
|
||||
[v1, v2],
|
||||
[v2, v3],
|
||||
[v0, v3],
|
||||
[v2, v4],
|
||||
[v3, v4],
|
||||
];
|
||||
const graph = new GraphAdjList(edges);
|
||||
console.log("\n初始化后,图为");
|
||||
console.log('\n初始化后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 添加边 */
|
||||
// 顶点 1, 2 即 v0, v2
|
||||
graph.addEdge(v0, v2);
|
||||
console.log("\n添加边 1-2 后,图为");
|
||||
console.log('\n添加边 1-2 后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 删除边 */
|
||||
// 顶点 1, 3 即 v0, v1
|
||||
graph.removeEdge(v0, v1);
|
||||
console.log("\n删除边 1-3 后,图为");
|
||||
console.log('\n删除边 1-3 后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 添加顶点 */
|
||||
const v5 = new Vertex(6);
|
||||
graph.addVertex(v5);
|
||||
console.log("\n添加顶点 6 后,图为");
|
||||
console.log('\n添加顶点 6 后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 删除顶点 */
|
||||
// 顶点 3 即 v1
|
||||
graph.removeVertex(v1);
|
||||
console.log("\n删除顶点 3 后,图为");
|
||||
console.log('\n删除顶点 3 后,图为');
|
||||
graph.print();
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
GraphAdjList
|
||||
GraphAdjList,
|
||||
};
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
/* 基于邻接矩阵实现的无向图类 */
|
||||
class GraphAdjMat {
|
||||
vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
|
||||
adjMat; // 邻接矩阵,行列索引对应“顶点索引”
|
||||
vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
|
||||
adjMat; // 邻接矩阵,行列索引对应“顶点索引”
|
||||
|
||||
/* 构造函数 */
|
||||
constructor(vertices, edges) {
|
||||
|
@ -49,7 +49,7 @@ class GraphAdjMat {
|
|||
/* 删除顶点 */
|
||||
removeVertex(index) {
|
||||
if (index >= this.size()) {
|
||||
throw new RangeError("Index Out Of Bounds Exception");
|
||||
throw new RangeError('Index Out Of Bounds Exception');
|
||||
}
|
||||
// 在顶点列表中移除索引 index 的顶点
|
||||
this.vertices.splice(index, 1);
|
||||
|
@ -67,7 +67,7 @@ class GraphAdjMat {
|
|||
addEdge(i, j) {
|
||||
// 索引越界与相等处理
|
||||
if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) {
|
||||
throw new RangeError("Index Out Of Bounds Exception");
|
||||
throw new RangeError('Index Out Of Bounds Exception');
|
||||
}
|
||||
// 在无向图中,邻接矩阵沿主对角线对称,即满足 (i, j) == (j, i)
|
||||
this.adjMat[i][j] = 1;
|
||||
|
@ -79,7 +79,7 @@ class GraphAdjMat {
|
|||
removeEdge(i, j) {
|
||||
// 索引越界与相等处理
|
||||
if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) {
|
||||
throw new RangeError("Index Out Of Bounds Exception");
|
||||
throw new RangeError('Index Out Of Bounds Exception');
|
||||
}
|
||||
this.adjMat[i][j] = 0;
|
||||
this.adjMat[j][i] = 0;
|
||||
|
@ -87,8 +87,8 @@ class GraphAdjMat {
|
|||
|
||||
/* 打印邻接矩阵 */
|
||||
print() {
|
||||
console.log("顶点列表 = ", this.vertices);
|
||||
console.log("邻接矩阵 =", this.adjMat);
|
||||
console.log('顶点列表 = ', this.vertices);
|
||||
console.log('邻接矩阵 =', this.adjMat);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,32 +96,37 @@ class GraphAdjMat {
|
|||
/* 初始化无向图 */
|
||||
// 请注意,edges 元素代表顶点索引,即对应 vertices 元素索引
|
||||
const vertices = [1, 3, 2, 5, 4];
|
||||
const edges = [[0, 1], [1, 2], [2, 3], [0, 3], [2, 4], [3, 4]
|
||||
const edges = [
|
||||
[0, 1],
|
||||
[1, 2],
|
||||
[2, 3],
|
||||
[0, 3],
|
||||
[2, 4],
|
||||
[3, 4],
|
||||
];
|
||||
const graph = new GraphAdjMat(vertices, edges);
|
||||
console.log("\n初始化后,图为");
|
||||
console.log('\n初始化后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 添加边 */
|
||||
// 顶点 1, 2 的索引分别为 0, 2
|
||||
graph.addEdge(0, 2);
|
||||
console.log("\n添加边 1-2 后,图为");
|
||||
console.log('\n添加边 1-2 后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 删除边 */
|
||||
// 顶点 1, 3 的索引分别为 0, 1
|
||||
graph.removeEdge(0, 1);
|
||||
console.log("\n删除边 1-3 后,图为");
|
||||
console.log('\n删除边 1-3 后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 添加顶点 */
|
||||
graph.addVertex(6);
|
||||
console.log("\n添加顶点 6 后,图为");
|
||||
console.log('\n添加顶点 6 后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 删除顶点 */
|
||||
// 顶点 3 的索引为 1
|
||||
graph.removeVertex(1);
|
||||
console.log("\n删除顶点 3 后,图为");
|
||||
console.log('\n删除顶点 3 后,图为');
|
||||
graph.print();
|
||||
|
||||
|
|
|
@ -19,15 +19,15 @@ function graphBFS(graph, startVet) {
|
|||
const que = [startVet];
|
||||
// 以顶点 vet 为起点,循环直至访问完所有顶点
|
||||
while (que.length) {
|
||||
const vet = que.shift(); // 队首顶点出队
|
||||
res.push(vet); // 记录访问顶点
|
||||
const vet = que.shift(); // 队首顶点出队
|
||||
res.push(vet); // 记录访问顶点
|
||||
// 遍历该顶点的所有邻接顶点
|
||||
for (const adjVet of graph.adjList.get(vet) ?? []) {
|
||||
if (visited.has(adjVet)) {
|
||||
continue; // 跳过已被访问过的顶点
|
||||
continue; // 跳过已被访问过的顶点
|
||||
}
|
||||
que.push(adjVet); // 只入队未访问的顶点
|
||||
visited.add(adjVet); // 标记该顶点已被访问
|
||||
que.push(adjVet); // 只入队未访问的顶点
|
||||
visited.add(adjVet); // 标记该顶点已被访问
|
||||
}
|
||||
}
|
||||
// 返回顶点遍历序列
|
||||
|
@ -37,14 +37,25 @@ function graphBFS(graph, startVet) {
|
|||
/* Driver Code */
|
||||
/* 初始化无向图 */
|
||||
const v = Vertex.valsToVets([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
const edges = [[v[0], v[1]], [v[0], v[3]], [v[1], v[2]], [v[1], v[4]],
|
||||
[v[2], v[5]], [v[3], v[4]], [v[3], v[6]], [v[4], v[5]],
|
||||
[v[4], v[7]], [v[5], v[8]], [v[6], v[7]], [v[7], v[8]]];
|
||||
const edges = [
|
||||
[v[0], v[1]],
|
||||
[v[0], v[3]],
|
||||
[v[1], v[2]],
|
||||
[v[1], v[4]],
|
||||
[v[2], v[5]],
|
||||
[v[3], v[4]],
|
||||
[v[3], v[6]],
|
||||
[v[4], v[5]],
|
||||
[v[4], v[7]],
|
||||
[v[5], v[8]],
|
||||
[v[6], v[7]],
|
||||
[v[7], v[8]],
|
||||
];
|
||||
const graph = new GraphAdjList(edges);
|
||||
console.log("\n初始化后,图为");
|
||||
console.log('\n初始化后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 广度优先遍历 BFS */
|
||||
const res = graphBFS(graph, v[0]);
|
||||
console.log("\n广度优先遍历(BFS)顶点序列为");
|
||||
console.log('\n广度优先遍历(BFS)顶点序列为');
|
||||
console.log(Vertex.vetsToVals(res));
|
||||
|
|
|
@ -10,8 +10,8 @@ const { GraphAdjList } = require('./graph_adjacency_list');
|
|||
/* 深度优先遍历 DFS */
|
||||
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
|
||||
function dfs(graph, visited, res, vet) {
|
||||
res.push(vet); // 记录访问顶点
|
||||
visited.add(vet); // 标记该顶点已被访问
|
||||
res.push(vet); // 记录访问顶点
|
||||
visited.add(vet); // 标记该顶点已被访问
|
||||
// 遍历该顶点的所有邻接顶点
|
||||
for (const adjVet of graph.adjList.get(vet)) {
|
||||
if (visited.has(adjVet)) {
|
||||
|
@ -36,13 +36,19 @@ function graphDFS(graph, startVet) {
|
|||
/* Driver Code */
|
||||
/* 初始化无向图 */
|
||||
const v = Vertex.valsToVets([0, 1, 2, 3, 4, 5, 6]);
|
||||
const edges = [[v[0], v[1]], [v[0], v[3]], [v[1], v[2]],
|
||||
[v[2], v[5]], [v[4], v[5]], [v[5], v[6]]];
|
||||
const edges = [
|
||||
[v[0], v[1]],
|
||||
[v[0], v[3]],
|
||||
[v[1], v[2]],
|
||||
[v[2], v[5]],
|
||||
[v[4], v[5]],
|
||||
[v[5], v[6]],
|
||||
];
|
||||
const graph = new GraphAdjList(edges);
|
||||
console.log("\n初始化后,图为");
|
||||
console.log('\n初始化后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 深度优先遍历 DFS */
|
||||
const res = graphDFS(graph, v[0]);
|
||||
console.log("\n深度优先遍历(DFS)顶点序列为");
|
||||
console.log('\n深度优先遍历(DFS)顶点序列为');
|
||||
console.log(Vertex.vetsToVals(res));
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Author: what-is-me (whatisme@outlook.jp)
|
||||
*/
|
||||
|
||||
const { printHeap } = require("../modules/PrintUtil");
|
||||
const { printHeap } = require('../modules/PrintUtil');
|
||||
|
||||
/* 最大堆类 */
|
||||
class MaxHeap {
|
||||
|
@ -84,7 +84,7 @@ class MaxHeap {
|
|||
/* 元素出堆 */
|
||||
pop() {
|
||||
// 判空处理
|
||||
if (this.isEmpty()) throw new Error("堆为空");
|
||||
if (this.isEmpty()) throw new Error('堆为空');
|
||||
// 交换根节点与最右叶节点(即交换首元素与尾元素)
|
||||
this.#swap(0, this.size() - 1);
|
||||
// 删除节点
|
||||
|
@ -122,7 +122,7 @@ class MaxHeap {
|
|||
/* Driver Code */
|
||||
/* 初始化大顶堆 */
|
||||
const maxHeap = new MaxHeap([9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2]);
|
||||
console.log("\n输入列表并建堆后");
|
||||
console.log('\n输入列表并建堆后');
|
||||
maxHeap.print();
|
||||
|
||||
/* 获取堆顶元素 */
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Author: Zhuo Qinyue (1403450829@qq.com)
|
||||
*/
|
||||
|
||||
const { arrToLinkedList } = require("../modules/ListNode");
|
||||
const { arrToLinkedList } = require('../modules/ListNode');
|
||||
|
||||
/* 哈希查找(数组) */
|
||||
function hashingSearchArray(map, target) {
|
||||
|
@ -28,18 +28,18 @@ const nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8];
|
|||
// 初始化哈希表
|
||||
const map = new Map();
|
||||
for (let i = 0; i < nums.length; i++) {
|
||||
map.set(nums[i], i); // key: 元素,value: 索引
|
||||
map.set(nums[i], i); // key: 元素,value: 索引
|
||||
}
|
||||
const index = hashingSearchArray(map, target);
|
||||
console.log("目标元素 3 的索引 = " + index);
|
||||
console.log('目标元素 3 的索引 = ' + index);
|
||||
|
||||
/* 哈希查找(链表) */
|
||||
let head = arrToLinkedList(nums)
|
||||
let head = arrToLinkedList(nums);
|
||||
// 初始化哈希表
|
||||
const map1 = new Map();
|
||||
while (head != null) {
|
||||
map1.set(head.val, head); // key: 节点值,value: 节点
|
||||
map1.set(head.val, head); // key: 节点值,value: 节点
|
||||
head = head.next;
|
||||
}
|
||||
const node = hashingSearchLinkedList(map1, target);
|
||||
console.log("目标节点值 3 的对应节点对象为", node);
|
||||
console.log('目标节点值 3 的对应节点对象为', node);
|
||||
|
|
|
@ -35,11 +35,12 @@ function twoSumHashTable(nums, target) {
|
|||
|
||||
/* Driver Code */
|
||||
// 方法一
|
||||
const nums = [2, 7, 11, 15], target = 9;
|
||||
const nums = [2, 7, 11, 15],
|
||||
target = 9;
|
||||
|
||||
let res = twoSumBruteForce(nums, target);
|
||||
console.log("方法一 res = ", res);
|
||||
console.log('方法一 res = ', res);
|
||||
|
||||
// 方法二
|
||||
res = twoSumHashTable(nums, target);
|
||||
console.log("方法二 res = ", res);
|
||||
console.log('方法二 res = ', res);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Author: JoseHung (szhong@link.cuhk.edu.hk)
|
||||
*/
|
||||
|
||||
const { ListNode, arrToLinkedList } = require("../modules/ListNode");
|
||||
const { ListNode, arrToLinkedList } = require('../modules/ListNode');
|
||||
|
||||
/* 线性查找(数组) */
|
||||
function linearSearchArray(nums, target) {
|
||||
|
@ -16,15 +16,15 @@ function linearSearchArray(nums, target) {
|
|||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 线性查找(链表)*/
|
||||
function linearSearchLinkedList(head, target) {
|
||||
// 遍历链表
|
||||
while(head) {
|
||||
while (head) {
|
||||
// 找到目标节点,返回之
|
||||
if(head.val === target) {
|
||||
if (head.val === target) {
|
||||
return head;
|
||||
}
|
||||
head = head.next;
|
||||
|
@ -39,9 +39,9 @@ const target = 3;
|
|||
/* 在数组中执行线性查找 */
|
||||
const nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8];
|
||||
const index = linearSearchArray(nums, target);
|
||||
console.log("目标元素 3 的索引 = " + index);
|
||||
console.log('目标元素 3 的索引 = ' + index);
|
||||
|
||||
/* 在链表中执行线性查找 */
|
||||
const head = arrToLinkedList(nums);
|
||||
const node = linearSearchLinkedList(head, target);
|
||||
console.log("目标节点值 3 的对应节点对象为 ", node);
|
||||
console.log('目标节点值 3 的对应节点对象为 ', node);
|
||||
|
|
|
@ -32,18 +32,18 @@ function bubbleSortWithFlag(nums) {
|
|||
let tmp = nums[j];
|
||||
nums[j] = nums[j + 1];
|
||||
nums[j + 1] = tmp;
|
||||
flag = true; // 记录交换元素
|
||||
flag = true; // 记录交换元素
|
||||
}
|
||||
}
|
||||
if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出
|
||||
if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出
|
||||
}
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
const nums = [4, 1, 3, 1, 5, 2];
|
||||
bubbleSort(nums);
|
||||
console.log("排序后数组 nums =", nums);
|
||||
console.log('排序后数组 nums =', nums);
|
||||
|
||||
const nums1 = [4, 1, 3, 1, 5, 2];
|
||||
bubbleSortWithFlag(nums1);
|
||||
console.log("排序后数组 nums =", nums1);
|
||||
console.log('排序后数组 nums =', nums1);
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
function insertionSort(nums) {
|
||||
// 外循环:base = nums[1], nums[2], ..., nums[n-1]
|
||||
for (let i = 1; i < nums.length; i++) {
|
||||
let base = nums[i], j = i - 1;
|
||||
let base = nums[i],
|
||||
j = i - 1;
|
||||
// 内循环:将 base 插入到左边的正确位置
|
||||
while (j >= 0 && nums[j] > base) {
|
||||
nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位
|
||||
nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位
|
||||
j--;
|
||||
}
|
||||
nums[j + 1] = base; // 2. 将 base 赋值到正确位置
|
||||
nums[j + 1] = base; // 2. 将 base 赋值到正确位置
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,23 +9,26 @@
|
|||
// 右子数组区间 [mid + 1, right]
|
||||
function merge(nums, left, mid, right) {
|
||||
// 初始化辅助数组
|
||||
let tmp = nums.slice(left, right + 1);
|
||||
// 左子数组的起始索引和结束索引
|
||||
let leftStart = left - left, leftEnd = mid - left;
|
||||
// 右子数组的起始索引和结束索引
|
||||
let rightStart = mid + 1 - left, rightEnd = right - left;
|
||||
let tmp = nums.slice(left, right + 1);
|
||||
// 左子数组的起始索引和结束索引
|
||||
let leftStart = left - left,
|
||||
leftEnd = mid - left;
|
||||
// 右子数组的起始索引和结束索引
|
||||
let rightStart = mid + 1 - left,
|
||||
rightEnd = right - left;
|
||||
// i, j 分别指向左子数组、右子数组的首元素
|
||||
let i = leftStart, j = rightStart;
|
||||
let i = leftStart,
|
||||
j = rightStart;
|
||||
// 通过覆盖原数组 nums 来合并左子数组和右子数组
|
||||
for (let k = left; k <= right; k++) {
|
||||
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
|
||||
if (i > leftEnd) {
|
||||
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
|
||||
nums[k] = tmp[j++];
|
||||
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
|
||||
} else if (j > rightEnd || tmp[i] <= tmp[j]) {
|
||||
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
|
||||
nums[k] = tmp[i++];
|
||||
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
|
||||
} else {
|
||||
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
|
||||
nums[k] = tmp[j++];
|
||||
}
|
||||
}
|
||||
|
@ -34,10 +37,10 @@ function merge(nums, left, mid, right) {
|
|||
/* 归并排序 */
|
||||
function mergeSort(nums, left, right) {
|
||||
// 终止条件
|
||||
if (left >= right) return; // 当子数组长度为 1 时终止递归
|
||||
if (left >= right) return; // 当子数组长度为 1 时终止递归
|
||||
// 划分阶段
|
||||
let mid = Math.floor((left + right) / 2); // 计算中点
|
||||
mergeSort(nums, left, mid); // 递归左子数组
|
||||
let mid = Math.floor((left + right) / 2); // 计算中点
|
||||
mergeSort(nums, left, mid); // 递归左子数组
|
||||
mergeSort(nums, mid + 1, right); // 递归右子数组
|
||||
// 合并阶段
|
||||
merge(nums, left, mid, right);
|
||||
|
|
|
@ -16,7 +16,8 @@ class QuickSort {
|
|||
/* 哨兵划分 */
|
||||
partition(nums, left, right) {
|
||||
// 以 nums[left] 作为基准数
|
||||
let i = left, j = right;
|
||||
let i = left,
|
||||
j = right;
|
||||
while (i < j) {
|
||||
while (i < j && nums[j] >= nums[left]) {
|
||||
j -= 1; // 从右向左找首个小于基准数的元素
|
||||
|
@ -57,18 +58,25 @@ class QuickSortMedian {
|
|||
// 此处使用异或运算来简化代码
|
||||
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
|
||||
if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right])) return left;
|
||||
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right])) return mid;
|
||||
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))
|
||||
return mid;
|
||||
else return right;
|
||||
}
|
||||
|
||||
/* 哨兵划分(三数取中值) */
|
||||
partition(nums, left, right) {
|
||||
// 选取三个候选元素的中位数
|
||||
let med = this.medianThree(nums, left, Math.floor((left + right) / 2), right);
|
||||
let med = this.medianThree(
|
||||
nums,
|
||||
left,
|
||||
Math.floor((left + right) / 2),
|
||||
right
|
||||
);
|
||||
// 将中位数交换至数组最左端
|
||||
this.swap(nums, left, med);
|
||||
// 以 nums[left] 作为基准数
|
||||
let i = left, j = right;
|
||||
let i = left,
|
||||
j = right;
|
||||
while (i < j) {
|
||||
while (i < j && nums[j] >= nums[left]) j--; // 从右向左找首个小于基准数的元素
|
||||
while (i < j && nums[i] <= nums[left]) i++; // 从左向右找首个大于基准数的元素
|
||||
|
@ -102,7 +110,8 @@ class QuickSortTailCall {
|
|||
/* 哨兵划分 */
|
||||
partition(nums, left, right) {
|
||||
// 以 nums[left] 作为基准数
|
||||
let i = left, j = right;
|
||||
let i = left,
|
||||
j = right;
|
||||
while (i < j) {
|
||||
while (i < j && nums[j] >= nums[left]) j--; // 从右向左找首个小于基准数的元素
|
||||
while (i < j && nums[i] <= nums[left]) i++; // 从左向右找首个大于基准数的元素
|
||||
|
|
|
@ -18,7 +18,7 @@ function countingSortDigit(nums, exp) {
|
|||
// 统计 0~9 各数字的出现次数
|
||||
for (let i = 0; i < n; i++) {
|
||||
const d = digit(nums[i], exp); // 获取 nums[i] 第 k 位,记为 d
|
||||
counter[d]++; // 统计数字 d 的出现次数
|
||||
counter[d]++; // 统计数字 d 的出现次数
|
||||
}
|
||||
// 求前缀和,将“出现个数”转换为“数组索引”
|
||||
for (let i = 1; i < 10; i++) {
|
||||
|
@ -29,8 +29,8 @@ function countingSortDigit(nums, exp) {
|
|||
for (let i = n - 1; i >= 0; i--) {
|
||||
const d = digit(nums[i], exp);
|
||||
const j = counter[d] - 1; // 获取 d 在数组中的索引 j
|
||||
res[j] = nums[i]; // 将当前元素填入索引 j
|
||||
counter[d]--; // 将 d 的数量减 1
|
||||
res[j] = nums[i]; // 将当前元素填入索引 j
|
||||
counter[d]--; // 将 d 的数量减 1
|
||||
}
|
||||
// 使用结果覆盖原数组 nums
|
||||
for (let i = 0; i < n; i++) {
|
||||
|
@ -58,7 +58,9 @@ function radixSort(nums) {
|
|||
}
|
||||
|
||||
/* Driver Code */
|
||||
const nums = [10546151, 35663510, 42865989, 34862445, 81883077,
|
||||
88906420, 72429244, 30524779, 82060337, 63832996];
|
||||
const nums = [
|
||||
10546151, 35663510, 42865989, 34862445, 81883077, 88906420, 72429244,
|
||||
30524779, 82060337, 63832996,
|
||||
];
|
||||
radixSort(nums);
|
||||
console.log('基数排序完成后 nums =', nums);
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
/* 基于环形数组实现的双向队列 */
|
||||
class ArrayDeque {
|
||||
#nums; // 用于存储双向队列元素的数组
|
||||
#front; // 队首指针,指向队首元素
|
||||
#queSize; // 双向队列长度
|
||||
#nums; // 用于存储双向队列元素的数组
|
||||
#front; // 队首指针,指向队首元素
|
||||
#queSize; // 双向队列长度
|
||||
|
||||
/* 构造方法 */
|
||||
constructor(capacity) {
|
||||
|
@ -43,7 +43,7 @@ class ArrayDeque {
|
|||
/* 队首入队 */
|
||||
pushFirst(num) {
|
||||
if (this.#queSize === this.capacity()) {
|
||||
console.log("双向队列已满");
|
||||
console.log('双向队列已满');
|
||||
return;
|
||||
}
|
||||
// 队首指针向左移动一位
|
||||
|
@ -57,7 +57,7 @@ class ArrayDeque {
|
|||
/* 队尾入队 */
|
||||
pushLast(num) {
|
||||
if (this.#queSize === this.capacity()) {
|
||||
console.log("双向队列已满");
|
||||
console.log('双向队列已满');
|
||||
return;
|
||||
}
|
||||
// 计算尾指针,指向队尾索引 + 1
|
||||
|
@ -85,15 +85,13 @@ class ArrayDeque {
|
|||
|
||||
/* 访问队首元素 */
|
||||
peekFirst() {
|
||||
if (this.isEmpty())
|
||||
throw new Error("The Deque Is Empty.");
|
||||
if (this.isEmpty()) throw new Error('The Deque Is Empty.');
|
||||
return this.#nums[this.#front];
|
||||
}
|
||||
|
||||
/* 访问队尾元素 */
|
||||
peekLast() {
|
||||
if (this.isEmpty())
|
||||
throw new Error("The Deque Is Empty.");
|
||||
if (this.isEmpty()) throw new Error('The Deque Is Empty.');
|
||||
// 计算尾元素索引
|
||||
const last = this.index(this.#front + this.#queSize - 1);
|
||||
return this.#nums[last];
|
||||
|
@ -117,30 +115,42 @@ const deque = new ArrayDeque(capacity);
|
|||
deque.pushLast(3);
|
||||
deque.pushLast(2);
|
||||
deque.pushLast(5);
|
||||
console.log("双向队列 deque = [" + deque.toArray() + "]");
|
||||
console.log('双向队列 deque = [' + deque.toArray() + ']');
|
||||
|
||||
/* 访问元素 */
|
||||
const peekFirst = deque.peekFirst();
|
||||
console.log("队首元素 peekFirst = " + peekFirst);
|
||||
console.log('队首元素 peekFirst = ' + peekFirst);
|
||||
const peekLast = deque.peekLast();
|
||||
console.log("队尾元素 peekLast = " + peekLast);
|
||||
console.log('队尾元素 peekLast = ' + peekLast);
|
||||
|
||||
/* 元素入队 */
|
||||
deque.pushLast(4);
|
||||
console.log("元素 4 队尾入队后 deque = [" + deque.toArray() + "]");
|
||||
console.log('元素 4 队尾入队后 deque = [' + deque.toArray() + ']');
|
||||
deque.pushFirst(1);
|
||||
console.log("元素 1 队首入队后 deque = [" + deque.toArray() + "]");
|
||||
console.log('元素 1 队首入队后 deque = [' + deque.toArray() + ']');
|
||||
|
||||
/* 元素出队 */
|
||||
const popLast = deque.popLast();
|
||||
console.log("队尾出队元素 = " + popLast + ",队尾出队后 deque = [" + deque.toArray() + "]");
|
||||
console.log(
|
||||
'队尾出队元素 = ' +
|
||||
popLast +
|
||||
',队尾出队后 deque = [' +
|
||||
deque.toArray() +
|
||||
']'
|
||||
);
|
||||
const popFirst = deque.popFirst();
|
||||
console.log("队首出队元素 = " + popFirst + ",队首出队后 deque = [" + deque.toArray()+ "]");
|
||||
console.log(
|
||||
'队首出队元素 = ' +
|
||||
popFirst +
|
||||
',队首出队后 deque = [' +
|
||||
deque.toArray() +
|
||||
']'
|
||||
);
|
||||
|
||||
/* 获取双向队列的长度 */
|
||||
const size = deque.size();
|
||||
console.log("双向队列长度 size = " + size);
|
||||
console.log('双向队列长度 size = ' + size);
|
||||
|
||||
/* 判断双向队列是否为空 */
|
||||
const isEmpty = deque.isEmpty();
|
||||
console.log("双向队列是否为空 = " + isEmpty);
|
||||
console.log('双向队列是否为空 = ' + isEmpty);
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
/* 基于环形数组实现的队列 */
|
||||
class ArrayQueue {
|
||||
#nums; // 用于存储队列元素的数组
|
||||
#front = 0; // 队首指针,指向队首元素
|
||||
#queSize = 0; // 队列长度
|
||||
#nums; // 用于存储队列元素的数组
|
||||
#front = 0; // 队首指针,指向队首元素
|
||||
#queSize = 0; // 队列长度
|
||||
|
||||
constructor(capacity) {
|
||||
this.#nums = new Array(capacity);
|
||||
|
@ -32,7 +32,7 @@ class ArrayQueue {
|
|||
/* 入队 */
|
||||
push(num) {
|
||||
if (this.size == this.capacity) {
|
||||
console.log("队列已满");
|
||||
console.log('队列已满');
|
||||
return;
|
||||
}
|
||||
// 计算尾指针,指向队尾索引 + 1
|
||||
|
@ -54,8 +54,7 @@ class ArrayQueue {
|
|||
|
||||
/* 访问队首元素 */
|
||||
peek() {
|
||||
if (this.empty())
|
||||
throw new Error("队列为空");
|
||||
if (this.empty()) throw new Error('队列为空');
|
||||
return this.#nums[this.#front];
|
||||
}
|
||||
|
||||
|
@ -70,7 +69,6 @@ class ArrayQueue {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Driver Code */
|
||||
/* 初始化队列 */
|
||||
const capacity = 10;
|
||||
|
@ -82,27 +80,27 @@ queue.push(3);
|
|||
queue.push(2);
|
||||
queue.push(5);
|
||||
queue.push(4);
|
||||
console.log("队列 queue =", queue.toArray());
|
||||
console.log('队列 queue =', queue.toArray());
|
||||
|
||||
/* 访问队首元素 */
|
||||
const peek = queue.peek();
|
||||
console.log("队首元素 peek = " + peek);
|
||||
console.log('队首元素 peek = ' + peek);
|
||||
|
||||
/* 元素出队 */
|
||||
const pop = queue.pop();
|
||||
console.log("出队元素 pop = " + pop + ",出队后 queue =", queue.toArray());
|
||||
console.log('出队元素 pop = ' + pop + ',出队后 queue =', queue.toArray());
|
||||
|
||||
/* 获取队列的长度 */
|
||||
const size = queue.size;
|
||||
console.log("队列长度 size = " + size);
|
||||
console.log('队列长度 size = ' + size);
|
||||
|
||||
/* 判断队列是否为空 */
|
||||
const empty = queue.empty();
|
||||
console.log("队列是否为空 = " + empty);
|
||||
console.log('队列是否为空 = ' + empty);
|
||||
|
||||
/* 测试环形数组 */
|
||||
for (let i = 0; i < 10; i++) {
|
||||
queue.push(i);
|
||||
queue.pop();
|
||||
console.log("第 " + i + " 轮入队 + 出队后 queue =", queue.toArray());
|
||||
console.log('第 ' + i + ' 轮入队 + 出队后 queue =', queue.toArray());
|
||||
}
|
||||
|
|
|
@ -4,14 +4,13 @@
|
|||
* Author: S-N-O-R-L-A-X (snorlax.xu@outlook.com)
|
||||
*/
|
||||
|
||||
|
||||
/* 基于数组实现的栈 */
|
||||
class ArrayStack {
|
||||
#stack;
|
||||
constructor() {
|
||||
this.#stack = [];
|
||||
}
|
||||
|
||||
|
||||
/* 获取栈的长度 */
|
||||
get size() {
|
||||
return this.#stack.length;
|
||||
|
@ -29,15 +28,13 @@ class ArrayStack {
|
|||
|
||||
/* 出栈 */
|
||||
pop() {
|
||||
if (this.empty())
|
||||
throw new Error("栈为空");
|
||||
if (this.empty()) throw new Error('栈为空');
|
||||
return this.#stack.pop();
|
||||
}
|
||||
|
||||
/* 访问栈顶元素 */
|
||||
top() {
|
||||
if (this.empty())
|
||||
throw new Error("栈为空");
|
||||
if (this.empty()) throw new Error('栈为空');
|
||||
return this.#stack[this.#stack.length - 1];
|
||||
}
|
||||
|
||||
|
@ -45,8 +42,7 @@ class ArrayStack {
|
|||
toArray() {
|
||||
return this.#stack;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
/* 初始化栈 */
|
||||
|
@ -58,22 +54,22 @@ stack.push(3);
|
|||
stack.push(2);
|
||||
stack.push(5);
|
||||
stack.push(4);
|
||||
console.log("栈 stack = ");
|
||||
console.log('栈 stack = ');
|
||||
console.log(stack.toArray());
|
||||
|
||||
/* 访问栈顶元素 */
|
||||
const top = stack.top();
|
||||
console.log("栈顶元素 top = " + top);
|
||||
console.log('栈顶元素 top = ' + top);
|
||||
|
||||
/* 元素出栈 */
|
||||
const pop = stack.pop();
|
||||
console.log("出栈元素 pop = " + pop + ",出栈后 stack = ");
|
||||
console.log('出栈元素 pop = ' + pop + ',出栈后 stack = ');
|
||||
console.log(stack.toArray());
|
||||
|
||||
/* 获取栈的长度 */
|
||||
const size = stack.size;
|
||||
console.log("栈的长度 size = " + size);
|
||||
console.log('栈的长度 size = ' + size);
|
||||
|
||||
/* 判断是否为空 */
|
||||
const empty = stack.empty();
|
||||
console.log("栈是否为空 = " + empty);
|
||||
console.log('栈是否为空 = ' + empty);
|
||||
|
|
|
@ -16,25 +16,29 @@ deque.push(4);
|
|||
// 请注意,由于是数组,unshift() 方法的时间复杂度为 O(n)
|
||||
deque.unshift(3);
|
||||
deque.unshift(1);
|
||||
console.log("双向队列 deque = ", deque);
|
||||
console.log('双向队列 deque = ', deque);
|
||||
|
||||
/* 访问元素 */
|
||||
const peekFirst = deque[0];
|
||||
console.log("队首元素 peekFirst = " + peekFirst);
|
||||
console.log('队首元素 peekFirst = ' + peekFirst);
|
||||
const peekLast = deque[deque.length - 1];
|
||||
console.log("队尾元素 peekLast = " + peekLast);
|
||||
console.log('队尾元素 peekLast = ' + peekLast);
|
||||
|
||||
/* 元素出队 */
|
||||
// 请注意,由于是数组,shift() 方法的时间复杂度为 O(n)
|
||||
const popFront = deque.shift();
|
||||
console.log("队首出队元素 popFront = " + popFront + ",队首出队后 deque = " + deque);
|
||||
console.log(
|
||||
'队首出队元素 popFront = ' + popFront + ',队首出队后 deque = ' + deque
|
||||
);
|
||||
const popBack = deque.pop();
|
||||
console.log("队尾出队元素 popBack = " + popBack + ",队尾出队后 deque = " + deque);
|
||||
console.log(
|
||||
'队尾出队元素 popBack = ' + popBack + ',队尾出队后 deque = ' + deque
|
||||
);
|
||||
|
||||
/* 获取双向队列的长度 */
|
||||
const size = deque.length;
|
||||
console.log("双向队列长度 size = " + size);
|
||||
console.log('双向队列长度 size = ' + size);
|
||||
|
||||
/* 判断双向队列是否为空 */
|
||||
const isEmpty = size === 0;
|
||||
console.log("双向队列是否为空 = " + isEmpty);
|
||||
console.log('双向队列是否为空 = ' + isEmpty);
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
|
||||
/* 双向链表节点 */
|
||||
class ListNode {
|
||||
prev; // 前驱节点引用 (指针)
|
||||
next; // 后继节点引用 (指针)
|
||||
val; // 节点值
|
||||
|
||||
prev; // 前驱节点引用 (指针)
|
||||
next; // 后继节点引用 (指针)
|
||||
val; // 节点值
|
||||
|
||||
constructor(val) {
|
||||
this.val = val;
|
||||
this.next = null;
|
||||
|
@ -19,9 +19,9 @@ class ListNode {
|
|||
|
||||
/* 基于双向链表实现的双向队列 */
|
||||
class LinkedListDeque {
|
||||
#front; // 头节点 front
|
||||
#rear; // 尾节点 rear
|
||||
#queSize; // 双向队列的长度
|
||||
#front; // 头节点 front
|
||||
#rear; // 尾节点 rear
|
||||
#queSize; // 双向队列的长度
|
||||
|
||||
constructor() {
|
||||
this.#front = null;
|
||||
|
@ -73,7 +73,7 @@ class LinkedListDeque {
|
|||
temp.next = null;
|
||||
this.#rear.prev = null;
|
||||
}
|
||||
this.#rear = temp; // 更新尾节点
|
||||
this.#rear = temp; // 更新尾节点
|
||||
this.#queSize--;
|
||||
return value;
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ class LinkedListDeque {
|
|||
temp.prev = null;
|
||||
this.#front.next = null;
|
||||
}
|
||||
this.#front = temp; // 更新头节点
|
||||
this.#front = temp; // 更新头节点
|
||||
this.#queSize--;
|
||||
return value;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ class LinkedListDeque {
|
|||
arr.push(temp.val);
|
||||
temp = temp.next;
|
||||
}
|
||||
console.log("[" + arr.join(", ") + "]");
|
||||
console.log('[' + arr.join(', ') + ']');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,35 +133,35 @@ const linkedListDeque = new LinkedListDeque();
|
|||
linkedListDeque.pushLast(3);
|
||||
linkedListDeque.pushLast(2);
|
||||
linkedListDeque.pushLast(5);
|
||||
console.log("双向队列 linkedListDeque = ");
|
||||
console.log('双向队列 linkedListDeque = ');
|
||||
linkedListDeque.print();
|
||||
|
||||
/* 访问元素 */
|
||||
const peekFirst = linkedListDeque.peekFirst();
|
||||
console.log("队首元素 peekFirst = " + peekFirst);
|
||||
console.log('队首元素 peekFirst = ' + peekFirst);
|
||||
const peekLast = linkedListDeque.peekLast();
|
||||
console.log("队尾元素 peekLast = " + peekLast);
|
||||
console.log('队尾元素 peekLast = ' + peekLast);
|
||||
|
||||
/* 元素入队 */
|
||||
linkedListDeque.pushLast(4);
|
||||
console.log("元素 4 队尾入队后 linkedListDeque = ");
|
||||
console.log('元素 4 队尾入队后 linkedListDeque = ');
|
||||
linkedListDeque.print();
|
||||
linkedListDeque.pushFirst(1);
|
||||
console.log("元素 1 队首入队后 linkedListDeque = ");
|
||||
console.log('元素 1 队首入队后 linkedListDeque = ');
|
||||
linkedListDeque.print();
|
||||
|
||||
/* 元素出队 */
|
||||
const popLast = linkedListDeque.popLast();
|
||||
console.log("队尾出队元素 = " + popLast + ",队尾出队后 linkedListDeque = ");
|
||||
console.log('队尾出队元素 = ' + popLast + ',队尾出队后 linkedListDeque = ');
|
||||
linkedListDeque.print();
|
||||
const popFirst = linkedListDeque.popFirst();
|
||||
console.log("队首出队元素 = " + popFirst + ",队首出队后 linkedListDeque = ");
|
||||
console.log('队首出队元素 = ' + popFirst + ',队首出队后 linkedListDeque = ');
|
||||
linkedListDeque.print();
|
||||
|
||||
/* 获取双向队列的长度 */
|
||||
const size = linkedListDeque.size();
|
||||
console.log("双向队列长度 size = " + size);
|
||||
console.log('双向队列长度 size = ' + size);
|
||||
|
||||
/* 判断双向队列是否为空 */
|
||||
const isEmpty = linkedListDeque.isEmpty();
|
||||
console.log("双向队列是否为空 = " + isEmpty);
|
||||
console.log('双向队列是否为空 = ' + isEmpty);
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
* Author: S-N-O-R-L-A-X (snorlax.xu@outlook.com)
|
||||
*/
|
||||
|
||||
const { ListNode } = require("../modules/ListNode");
|
||||
const { ListNode } = require('../modules/ListNode');
|
||||
|
||||
/* 基于链表实现的队列 */
|
||||
class LinkedListQueue {
|
||||
#front; // 头节点 #front
|
||||
#rear; // 尾节点 #rear
|
||||
#front; // 头节点 #front
|
||||
#rear; // 尾节点 #rear
|
||||
#queSize = 0;
|
||||
|
||||
constructor() {
|
||||
|
@ -54,8 +54,7 @@ class LinkedListQueue {
|
|||
|
||||
/* 访问队首元素 */
|
||||
peek() {
|
||||
if (this.size === 0)
|
||||
throw new Error("队列为空");
|
||||
if (this.size === 0) throw new Error('队列为空');
|
||||
return this.#front.val;
|
||||
}
|
||||
|
||||
|
@ -71,8 +70,6 @@ class LinkedListQueue {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Driver Code */
|
||||
/* 初始化队列 */
|
||||
const queue = new LinkedListQueue();
|
||||
|
@ -83,20 +80,20 @@ queue.push(3);
|
|||
queue.push(2);
|
||||
queue.push(5);
|
||||
queue.push(4);
|
||||
console.log("队列 queue = " + queue.toArray());
|
||||
console.log('队列 queue = ' + queue.toArray());
|
||||
|
||||
/* 访问队首元素 */
|
||||
const peek = queue.peek();
|
||||
console.log("队首元素 peek = " + peek);
|
||||
console.log('队首元素 peek = ' + peek);
|
||||
|
||||
/* 元素出队 */
|
||||
const pop = queue.pop();
|
||||
console.log("出队元素 pop = " + pop + ",出队后 queue = " + queue.toArray());
|
||||
console.log('出队元素 pop = ' + pop + ',出队后 queue = ' + queue.toArray());
|
||||
|
||||
/* 获取队列的长度 */
|
||||
const size = queue.size;
|
||||
console.log("队列长度 size = " + size);
|
||||
console.log('队列长度 size = ' + size);
|
||||
|
||||
/* 判断队列是否为空 */
|
||||
const isEmpty = queue.isEmpty();
|
||||
console.log("队列是否为空 = " + isEmpty);
|
||||
console.log('队列是否为空 = ' + isEmpty);
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
* Author: S-N-O-R-L-A-X (snorlax.xu@outlook.com)
|
||||
*/
|
||||
|
||||
const { ListNode } = require("../modules/ListNode");
|
||||
const { ListNode } = require('../modules/ListNode');
|
||||
|
||||
/* 基于链表实现的栈 */
|
||||
class LinkedListStack {
|
||||
#stackPeek; // 将头节点作为栈顶
|
||||
#stkSize = 0; // 栈的长度
|
||||
#stackPeek; // 将头节点作为栈顶
|
||||
#stkSize = 0; // 栈的长度
|
||||
|
||||
constructor() {
|
||||
this.#stackPeek = null;
|
||||
|
@ -43,8 +43,7 @@ class LinkedListStack {
|
|||
|
||||
/* 访问栈顶元素 */
|
||||
peek() {
|
||||
if (!this.#stackPeek)
|
||||
throw new Error("栈为空");
|
||||
if (!this.#stackPeek) throw new Error('栈为空');
|
||||
return this.#stackPeek.val;
|
||||
}
|
||||
|
||||
|
@ -70,20 +69,20 @@ stack.push(3);
|
|||
stack.push(2);
|
||||
stack.push(5);
|
||||
stack.push(4);
|
||||
console.log("栈 stack = " + stack.toArray());
|
||||
console.log('栈 stack = ' + stack.toArray());
|
||||
|
||||
/* 访问栈顶元素 */
|
||||
const peek = stack.peek();
|
||||
console.log("栈顶元素 peek = " + peek);
|
||||
console.log('栈顶元素 peek = ' + peek);
|
||||
|
||||
/* 元素出栈 */
|
||||
const pop = stack.pop();
|
||||
console.log("出栈元素 pop = " + pop + ",出栈后 stack = " + stack.toArray());
|
||||
console.log('出栈元素 pop = ' + pop + ',出栈后 stack = ' + stack.toArray());
|
||||
|
||||
/* 获取栈的长度 */
|
||||
const size = stack.size;
|
||||
console.log("栈的长度 size = " + size);
|
||||
console.log('栈的长度 size = ' + size);
|
||||
|
||||
/* 判断是否为空 */
|
||||
const isEmpty = stack.isEmpty();
|
||||
console.log("栈是否为空 = " + isEmpty);
|
||||
console.log('栈是否为空 = ' + isEmpty);
|
||||
|
|
|
@ -15,21 +15,21 @@ queue.push(3);
|
|||
queue.push(2);
|
||||
queue.push(5);
|
||||
queue.push(4);
|
||||
console.log("队列 queue =", queue);
|
||||
console.log('队列 queue =', queue);
|
||||
|
||||
/* 访问队首元素 */
|
||||
const peek = queue[0];
|
||||
console.log("队首元素 peek =", peek);
|
||||
console.log('队首元素 peek =', peek);
|
||||
|
||||
/* 元素出队 */
|
||||
// 底层是数组,因此 shift() 方法的时间复杂度为 O(n)
|
||||
const pop = queue.shift();
|
||||
console.log("出队元素 pop =", pop, ",出队后 queue = ", queue);
|
||||
console.log('出队元素 pop =', pop, ',出队后 queue = ', queue);
|
||||
|
||||
/* 获取队列的长度 */
|
||||
const size = queue.length;
|
||||
console.log("队列长度 size =", size);
|
||||
console.log('队列长度 size =', size);
|
||||
|
||||
/* 判断队列是否为空 */
|
||||
const isEmpty = queue.length === 0;
|
||||
console.log("队列是否为空 = ", isEmpty);
|
||||
console.log('队列是否为空 = ', isEmpty);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
/* Driver Code */
|
||||
/* 初始化栈 */
|
||||
// Javascript 没有内置的栈类,可以把 Array 当作栈来使用
|
||||
// Javascript 没有内置的栈类,可以把 Array 当作栈来使用
|
||||
const stack = [];
|
||||
|
||||
/* 元素入栈 */
|
||||
|
@ -15,21 +15,21 @@ stack.push(3);
|
|||
stack.push(2);
|
||||
stack.push(5);
|
||||
stack.push(4);
|
||||
console.log("栈 stack =", stack);
|
||||
console.log('栈 stack =', stack);
|
||||
|
||||
/* 访问栈顶元素 */
|
||||
const peek = stack[stack.length - 1];
|
||||
console.log("栈顶元素 peek =", peek);
|
||||
console.log('栈顶元素 peek =', peek);
|
||||
|
||||
/* 元素出栈 */
|
||||
const pop = stack.pop();
|
||||
console.log("出栈元素 pop =", pop);
|
||||
console.log("出栈后 stack =", stack);
|
||||
console.log('出栈元素 pop =', pop);
|
||||
console.log('出栈后 stack =', stack);
|
||||
|
||||
/* 获取栈的长度 */
|
||||
const size = stack.length;
|
||||
console.log("栈的长度 size =", size);
|
||||
console.log('栈的长度 size =', size);
|
||||
|
||||
/* 判断是否为空 */
|
||||
const isEmpty = stack.length === 0;
|
||||
console.log("栈是否为空 =", isEmpty);
|
||||
console.log('栈是否为空 =', isEmpty);
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* Author: what-is-me (whatisme@outlook.jp)
|
||||
*/
|
||||
|
||||
const { TreeNode } = require("../modules/TreeNode");
|
||||
const { printTree } = require("../modules/PrintUtil");
|
||||
const { TreeNode } = require('../modules/TreeNode');
|
||||
const { printTree } = require('../modules/PrintUtil');
|
||||
|
||||
/* AVL 树*/
|
||||
class AVLTree {
|
||||
|
@ -23,7 +23,8 @@ class AVLTree {
|
|||
/* 更新节点高度 */
|
||||
#updateHeight(node) {
|
||||
// 节点高度等于最高子树高度 + 1
|
||||
node.height = Math.max(this.height(node.left), this.height(node.right)) + 1;
|
||||
node.height =
|
||||
Math.max(this.height(node.left), this.height(node.right)) + 1;
|
||||
}
|
||||
|
||||
/* 获取平衡因子 */
|
||||
|
@ -102,7 +103,8 @@ class AVLTree {
|
|||
if (node === null) return new TreeNode(val);
|
||||
/* 1. 查找插入位置,并插入节点 */
|
||||
if (val < node.val) node.left = this.#insertHelper(node.left, val);
|
||||
else if (val > node.val) node.right = this.#insertHelper(node.right, val);
|
||||
else if (val > node.val)
|
||||
node.right = this.#insertHelper(node.right, val);
|
||||
else return node; // 重复节点不插入,直接返回
|
||||
this.#updateHeight(node); // 更新节点高度
|
||||
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
|
||||
|
@ -121,7 +123,8 @@ class AVLTree {
|
|||
if (node === null) return null;
|
||||
/* 1. 查找节点,并删除之 */
|
||||
if (val < node.val) node.left = this.#removeHelper(node.left, val);
|
||||
else if (val > node.val) node.right = this.#removeHelper(node.right, val);
|
||||
else if (val > node.val)
|
||||
node.right = this.#removeHelper(node.right, val);
|
||||
else {
|
||||
if (node.left === null || node.right === null) {
|
||||
const child = node.left !== null ? node.left : node.right;
|
||||
|
@ -165,13 +168,13 @@ class AVLTree {
|
|||
|
||||
function testInsert(tree, val) {
|
||||
tree.insert(val);
|
||||
console.log("\n插入节点 " + val + " 后,AVL 树为");
|
||||
console.log('\n插入节点 ' + val + ' 后,AVL 树为');
|
||||
printTree(tree.root);
|
||||
}
|
||||
|
||||
function testRemove(tree, val) {
|
||||
tree.remove(val);
|
||||
console.log("\n删除节点 " + val + " 后,AVL 树为");
|
||||
console.log('\n删除节点 ' + val + ' 后,AVL 树为');
|
||||
printTree(tree.root);
|
||||
}
|
||||
|
||||
|
@ -202,4 +205,4 @@ testRemove(avlTree, 4); // 删除度为 2 的节点
|
|||
|
||||
/* 查询节点 */
|
||||
const node = avlTree.search(7);
|
||||
console.log("\n查找到的节点对象为", node, ",节点值 = " + node.val);
|
||||
console.log('\n查找到的节点对象为', node, ',节点值 = ' + node.val);
|
||||
|
|
|
@ -4,15 +4,17 @@
|
|||
* Author: IsChristina (christinaxia77@foxmail.com)
|
||||
*/
|
||||
|
||||
const { TreeNode } = require("../modules/TreeNode");
|
||||
const { printTree } = require("../modules/PrintUtil");
|
||||
const { TreeNode } = require('../modules/TreeNode');
|
||||
const { printTree } = require('../modules/PrintUtil');
|
||||
|
||||
/* 二叉搜索树 */
|
||||
let root;
|
||||
|
||||
function BinarySearchTree(nums) {
|
||||
nums.sort((a, b) => { return a - b }); // 排序数组
|
||||
root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树
|
||||
nums.sort((a, b) => {
|
||||
return a - b;
|
||||
}); // 排序数组
|
||||
root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树
|
||||
}
|
||||
|
||||
/* 获取二叉树根节点 */
|
||||
|
@ -52,7 +54,8 @@ function search(num) {
|
|||
function insert(num) {
|
||||
// 若树为空,直接提前返回
|
||||
if (root === null) return;
|
||||
let cur = root, pre = null;
|
||||
let cur = root,
|
||||
pre = null;
|
||||
// 循环查找,越过叶节点后跳出
|
||||
while (cur !== null) {
|
||||
// 找到重复节点,直接返回
|
||||
|
@ -73,7 +76,8 @@ function insert(num) {
|
|||
function remove(num) {
|
||||
// 若树为空,直接提前返回
|
||||
if (root === null) return;
|
||||
let cur = root, pre = null;
|
||||
let cur = root,
|
||||
pre = null;
|
||||
// 循环查找,越过叶节点后跳出
|
||||
while (cur !== null) {
|
||||
// 找到待删除节点,跳出循环
|
||||
|
@ -112,25 +116,25 @@ function remove(num) {
|
|||
/* 初始化二叉搜索树 */
|
||||
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
||||
BinarySearchTree(nums);
|
||||
console.log("\n初始化的二叉树为\n");
|
||||
console.log('\n初始化的二叉树为\n');
|
||||
printTree(getRoot());
|
||||
|
||||
/* 查找节点 */
|
||||
let node = search(7);
|
||||
console.log("\n查找到的节点对象为 " + node + ",节点值 = " + node.val);
|
||||
console.log('\n查找到的节点对象为 ' + node + ',节点值 = ' + node.val);
|
||||
|
||||
/* 插入节点 */
|
||||
insert(16);
|
||||
console.log("\n插入节点 16 后,二叉树为\n");
|
||||
console.log('\n插入节点 16 后,二叉树为\n');
|
||||
printTree(getRoot());
|
||||
|
||||
/* 删除节点 */
|
||||
remove(1);
|
||||
console.log("\n删除节点 1 后,二叉树为\n");
|
||||
console.log('\n删除节点 1 后,二叉树为\n');
|
||||
printTree(getRoot());
|
||||
remove(2);
|
||||
console.log("\n删除节点 2 后,二叉树为\n");
|
||||
console.log('\n删除节点 2 后,二叉树为\n');
|
||||
printTree(getRoot());
|
||||
remove(4);
|
||||
console.log("\n删除节点 4 后,二叉树为\n");
|
||||
console.log('\n删除节点 4 后,二叉树为\n');
|
||||
printTree(getRoot());
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* Author: IsChristina (christinaxia77@foxmail.com)
|
||||
*/
|
||||
|
||||
const { TreeNode } = require("../modules/TreeNode");
|
||||
const { printTree } = require("../modules/PrintUtil");
|
||||
const { TreeNode } = require('../modules/TreeNode');
|
||||
const { printTree } = require('../modules/PrintUtil');
|
||||
|
||||
/* 初始化二叉树 */
|
||||
// 初始化节点
|
||||
|
@ -19,7 +19,7 @@ n1.left = n2;
|
|||
n1.right = n3;
|
||||
n2.left = n4;
|
||||
n2.right = n5;
|
||||
console.log("\n初始化二叉树\n");
|
||||
console.log('\n初始化二叉树\n');
|
||||
printTree(n1);
|
||||
|
||||
/* 插入与删除节点 */
|
||||
|
@ -27,9 +27,9 @@ const P = new TreeNode(0);
|
|||
// 在 n1 -> n2 中间插入节点 P
|
||||
n1.left = P;
|
||||
P.left = n2;
|
||||
console.log("\n插入节点 P 后\n");
|
||||
console.log('\n插入节点 P 后\n');
|
||||
printTree(n1);
|
||||
// 删除节点 P
|
||||
n1.left = n2;
|
||||
console.log("\n删除节点 P 后\n");
|
||||
console.log('\n删除节点 P 后\n');
|
||||
printTree(n1);
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* Author: IsChristina (christinaxia77@foxmail.com)
|
||||
*/
|
||||
|
||||
const { arrToTree } = require("../modules/TreeNode");
|
||||
const { printTree } = require("../modules/PrintUtil");
|
||||
const { arrToTree } = require('../modules/TreeNode');
|
||||
const { printTree } = require('../modules/PrintUtil');
|
||||
|
||||
/* 层序遍历 */
|
||||
function levelOrder(root) {
|
||||
|
@ -14,13 +14,10 @@ function levelOrder(root) {
|
|||
// 初始化一个列表,用于保存遍历序列
|
||||
const list = [];
|
||||
while (queue.length) {
|
||||
let node = queue.shift(); // 队列出队
|
||||
list.push(node.val); // 保存节点值
|
||||
if (node.left)
|
||||
queue.push(node.left); // 左子节点入队
|
||||
if (node.right)
|
||||
queue.push(node.right); // 右子节点入队
|
||||
|
||||
let node = queue.shift(); // 队列出队
|
||||
list.push(node.val); // 保存节点值
|
||||
if (node.left) queue.push(node.left); // 左子节点入队
|
||||
if (node.right) queue.push(node.right); // 右子节点入队
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
@ -29,9 +26,9 @@ function levelOrder(root) {
|
|||
/* 初始化二叉树 */
|
||||
// 这里借助了一个从数组直接生成二叉树的函数
|
||||
const root = arrToTree([1, 2, 3, 4, 5, 6, 7]);
|
||||
console.log("\n初始化二叉树\n");
|
||||
console.log('\n初始化二叉树\n');
|
||||
printTree(root);
|
||||
|
||||
/* 层序遍历 */
|
||||
const list = levelOrder(root);
|
||||
console.log("\n层序遍历的节点打印序列 = " + list);
|
||||
console.log('\n层序遍历的节点打印序列 = ' + list);
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* Author: IsChristina (christinaxia77@foxmail.com)
|
||||
*/
|
||||
|
||||
const { arrToTree } = require("../modules/TreeNode");
|
||||
const { printTree } = require("../modules/PrintUtil");
|
||||
const { arrToTree } = require('../modules/TreeNode');
|
||||
const { printTree } = require('../modules/PrintUtil');
|
||||
|
||||
// 初始化列表,用于存储遍历序列
|
||||
const list = [];
|
||||
|
@ -41,20 +41,20 @@ function postOrder(root) {
|
|||
/* 初始化二叉树 */
|
||||
// 这里借助了一个从数组直接生成二叉树的函数
|
||||
const root = arrToTree([1, 2, 3, 4, 5, 6, 7]);
|
||||
console.log("\n初始化二叉树\n");
|
||||
console.log('\n初始化二叉树\n');
|
||||
printTree(root);
|
||||
|
||||
/* 前序遍历 */
|
||||
list.length = 0;
|
||||
preOrder(root);
|
||||
console.log("\n前序遍历的节点打印序列 = " + list);
|
||||
console.log('\n前序遍历的节点打印序列 = ' + list);
|
||||
|
||||
/* 中序遍历 */
|
||||
list.length = 0;
|
||||
inOrder(root);
|
||||
console.log("\n中序遍历的节点打印序列 = " + list);
|
||||
console.log('\n中序遍历的节点打印序列 = ' + list);
|
||||
|
||||
/* 后序遍历 */
|
||||
list.length = 0;
|
||||
postOrder(root);
|
||||
console.log("\n后序遍历的节点打印序列 = " + list);
|
||||
console.log('\n后序遍历的节点打印序列 = ' + list);
|
||||
|
|
|
@ -11,8 +11,8 @@ class ListNode {
|
|||
val;
|
||||
next;
|
||||
constructor(val, next) {
|
||||
this.val = (val === undefined ? 0 : val);
|
||||
this.next = (next === undefined ? null : next);
|
||||
this.val = val === undefined ? 0 : val;
|
||||
this.next = next === undefined ? null : next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,5 +47,5 @@ function getListNode(head, val) {
|
|||
module.exports = {
|
||||
ListNode,
|
||||
arrToLinkedList,
|
||||
getListNode
|
||||
getListNode,
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Author: IsChristina (christinaxia77@foxmail.com)
|
||||
*/
|
||||
|
||||
const { arrToTree } = require("./TreeNode");
|
||||
const { arrToTree } = require('./TreeNode');
|
||||
|
||||
/**
|
||||
* Print a linked list
|
||||
|
@ -16,7 +16,7 @@ function printLinkedList(head) {
|
|||
list.push(head.val.toString());
|
||||
head = head.next;
|
||||
}
|
||||
console.log(list.join(" -> "));
|
||||
console.log(list.join(' -> '));
|
||||
}
|
||||
|
||||
function Trunk(prev, str) {
|
||||
|
@ -45,28 +45,28 @@ function printTree(root, prev, isLeft) {
|
|||
return;
|
||||
}
|
||||
|
||||
let prev_str = " ";
|
||||
let prev_str = ' ';
|
||||
let trunk = new Trunk(prev, prev_str);
|
||||
|
||||
printTree(root.right, trunk, true);
|
||||
|
||||
if (!prev) {
|
||||
trunk.str = "———";
|
||||
trunk.str = '———';
|
||||
} else if (isLeft) {
|
||||
trunk.str = "/———";
|
||||
prev_str = " |";
|
||||
trunk.str = '/———';
|
||||
prev_str = ' |';
|
||||
} else {
|
||||
trunk.str = "\\———";
|
||||
trunk.str = '\\———';
|
||||
prev.str = prev_str;
|
||||
}
|
||||
|
||||
showTrunks(trunk);
|
||||
console.log(" " + root.val);
|
||||
console.log(' ' + root.val);
|
||||
|
||||
if (prev) {
|
||||
prev.str = prev_str;
|
||||
}
|
||||
trunk.str = " |";
|
||||
trunk.str = ' |';
|
||||
|
||||
printTree(root.left, trunk, false);
|
||||
}
|
||||
|
@ -89,14 +89,14 @@ function showTrunks(p) {
|
|||
* @param arr
|
||||
*/
|
||||
function printHeap(arr) {
|
||||
console.log("堆的数组表示:");
|
||||
console.log('堆的数组表示:');
|
||||
console.log(arr);
|
||||
console.log("堆的树状表示:");
|
||||
console.log('堆的树状表示:');
|
||||
printTree(arrToTree(arr));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
printLinkedList,
|
||||
printTree,
|
||||
printHeap
|
||||
printHeap,
|
||||
};
|
||||
|
|
|
@ -50,5 +50,5 @@ function arrToTree(arr) {
|
|||
|
||||
module.exports = {
|
||||
TreeNode,
|
||||
arrToTree
|
||||
arrToTree,
|
||||
};
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* Author: Zhuo Qinyue (1403450829@qq.com)
|
||||
*/
|
||||
|
||||
|
||||
/* 顶点类 */
|
||||
class Vertex {
|
||||
val;
|
||||
|
@ -32,5 +31,5 @@ class Vertex {
|
|||
}
|
||||
|
||||
module.exports = {
|
||||
Vertex
|
||||
Vertex,
|
||||
};
|
||||
|
|
6
codes/typescript/.prettierrc
Normal file
6
codes/typescript/.prettierrc
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": true
|
||||
}
|
|
@ -29,23 +29,20 @@ class MyList {
|
|||
/* 访问元素 */
|
||||
public get(index: number): number {
|
||||
// 索引如果越界则抛出异常,下同
|
||||
if (index < 0 || index >= this._size)
|
||||
throw new Error('索引越界');
|
||||
if (index < 0 || index >= this._size) throw new Error('索引越界');
|
||||
return this.nums[index];
|
||||
}
|
||||
|
||||
/* 更新元素 */
|
||||
public set(index: number, num: number): void {
|
||||
if (index < 0 || index >= this._size)
|
||||
throw new Error('索引越界');
|
||||
if (index < 0 || index >= this._size) throw new Error('索引越界');
|
||||
this.nums[index] = num;
|
||||
}
|
||||
|
||||
/* 尾部添加元素 */
|
||||
public add(num: number): void {
|
||||
// 如果长度等于容量,则需要扩容
|
||||
if (this._size === this._capacity)
|
||||
this.extendCapacity();
|
||||
if (this._size === this._capacity) this.extendCapacity();
|
||||
// 将新元素添加到列表尾部
|
||||
this.nums[this._size] = num;
|
||||
this._size++;
|
||||
|
@ -53,8 +50,7 @@ class MyList {
|
|||
|
||||
/* 中间插入元素 */
|
||||
public insert(index: number, num: number): void {
|
||||
if (index < 0 || index >= this._size)
|
||||
throw new Error('索引越界');
|
||||
if (index < 0 || index >= this._size) throw new Error('索引越界');
|
||||
// 元素数量超出容量时,触发扩容机制
|
||||
if (this._size === this._capacity) {
|
||||
this.extendCapacity();
|
||||
|
@ -70,8 +66,7 @@ class MyList {
|
|||
|
||||
/* 删除元素 */
|
||||
public remove(index: number): number {
|
||||
if (index < 0 || index >= this._size)
|
||||
throw new Error('索引越界');
|
||||
if (index < 0 || index >= this._size) throw new Error('索引越界');
|
||||
let num = this.nums[index];
|
||||
// 将索引 index 之后的元素都向前移动一位
|
||||
for (let j = index; j < this._size - 1; j++) {
|
||||
|
|
|
@ -7,15 +7,20 @@
|
|||
/* 二分查找(双闭区间) */
|
||||
function binarySearch(nums: number[], target: number): number {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
let i = 0, j = nums.length - 1;
|
||||
let i = 0,
|
||||
j = nums.length - 1;
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while (i <= j) {
|
||||
const m = Math.floor((i + j) / 2); // 计算中点索引 m
|
||||
if (nums[m] < target) { // 此情况说明 target 在区间 [m+1, j] 中
|
||||
// 计算中点索引 m
|
||||
const m = Math.floor((i + j) / 2);
|
||||
if (nums[m] < target) {
|
||||
// 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1;
|
||||
} else if (nums[m] > target) { // 此情况说明 target 在区间 [i, m-1] 中
|
||||
} else if (nums[m] > target) {
|
||||
// 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1;
|
||||
} else { // 找到目标元素,返回其索引
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
@ -25,25 +30,29 @@ function binarySearch(nums: number[], target: number): number {
|
|||
/* 二分查找(左闭右开) */
|
||||
function binarySearch1(nums: number[], target: number): number {
|
||||
// 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
let i = 0, j = nums.length;
|
||||
let i = 0,
|
||||
j = nums.length;
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while (i < j) {
|
||||
const m = Math.floor((i + j) / 2); // 计算中点索引 m
|
||||
if (nums[m] < target) { // 此情况说明 target 在区间 [m+1, j) 中
|
||||
// 计算中点索引 m
|
||||
const m = Math.floor((i + j) / 2);
|
||||
if (nums[m] < target) {
|
||||
// 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1;
|
||||
} else if (nums[m] > target) { // 此情况说明 target 在区间 [i, m) 中
|
||||
} else if (nums[m] > target) {
|
||||
// 此情况说明 target 在区间 [i, m) 中
|
||||
j = m;
|
||||
} else { // 找到目标元素,返回其索引
|
||||
} else {
|
||||
// 找到目标元素,返回其索引
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return -1; // 未找到目标元素,返回 -1
|
||||
}
|
||||
|
||||
|
||||
/* Driver Code */
|
||||
const target = 6;
|
||||
const nums = [ 1, 3, 6, 8, 12, 15, 23, 67, 70, 92 ];
|
||||
const nums = [1, 3, 6, 8, 12, 15, 23, 67, 70, 92];
|
||||
|
||||
/* 二分查找(双闭区间) */
|
||||
let index = binarySearch(nums, target);
|
||||
|
|
|
@ -121,37 +121,37 @@ function factorialRecur(n: number): number {
|
|||
/* Driver Code */
|
||||
// 可以修改 n 运行,体会一下各种复杂度的操作数量变化趋势
|
||||
const n = 8;
|
||||
console.log("输入数据大小 n = " + n);
|
||||
console.log('输入数据大小 n = ' + n);
|
||||
|
||||
let count = constant(n);
|
||||
console.log("常数阶的计算操作数量 = " + count);
|
||||
console.log('常数阶的计算操作数量 = ' + count);
|
||||
|
||||
count = linear(n);
|
||||
console.log("线性阶的计算操作数量 = " + count);
|
||||
console.log('线性阶的计算操作数量 = ' + count);
|
||||
count = arrayTraversal(new Array(n));
|
||||
console.log("线性阶(遍历数组)的计算操作数量 = " + count);
|
||||
console.log('线性阶(遍历数组)的计算操作数量 = ' + count);
|
||||
|
||||
count = quadratic(n);
|
||||
console.log("平方阶的计算操作数量 = " + count);
|
||||
console.log('平方阶的计算操作数量 = ' + count);
|
||||
var nums = new Array(n);
|
||||
for (let i = 0; i < n; i++) nums[i] = n - i; // [n,n-1,...,2,1]
|
||||
count = bubbleSort(nums);
|
||||
console.log("平方阶(冒泡排序)的计算操作数量 = " + count);
|
||||
console.log('平方阶(冒泡排序)的计算操作数量 = ' + count);
|
||||
|
||||
count = exponential(n);
|
||||
console.log("指数阶(循环实现)的计算操作数量 = " + count);
|
||||
console.log('指数阶(循环实现)的计算操作数量 = ' + count);
|
||||
count = expRecur(n);
|
||||
console.log("指数阶(递归实现)的计算操作数量 = " + count);
|
||||
console.log('指数阶(递归实现)的计算操作数量 = ' + count);
|
||||
|
||||
count = logarithmic(n);
|
||||
console.log("对数阶(循环实现)的计算操作数量 = " + count);
|
||||
console.log('对数阶(循环实现)的计算操作数量 = ' + count);
|
||||
count = logRecur(n);
|
||||
console.log("对数阶(递归实现)的计算操作数量 = " + count);
|
||||
console.log('对数阶(递归实现)的计算操作数量 = ' + count);
|
||||
|
||||
count = linearLogRecur(n);
|
||||
console.log("线性对数阶(递归实现)的计算操作数量 = " + count);
|
||||
console.log('线性对数阶(递归实现)的计算操作数量 = ' + count);
|
||||
|
||||
count = factorialRecur(n);
|
||||
console.log("阶乘阶(递归实现)的计算操作数量 = " + count);
|
||||
console.log('阶乘阶(递归实现)的计算操作数量 = ' + count);
|
||||
|
||||
export {};
|
||||
|
|
|
@ -38,10 +38,8 @@ for (let i = 0; i < 10; i++) {
|
|||
const n = 100;
|
||||
const nums = randomNumbers(n);
|
||||
const index = findOne(nums);
|
||||
console.log(
|
||||
"\n数组 [ 1, 2, ..., n ] 被打乱后 = [" + nums.join(", ") + "]"
|
||||
);
|
||||
console.log("数字 1 的索引为 " + index);
|
||||
console.log('\n数组 [ 1, 2, ..., n ] 被打乱后 = [' + nums.join(', ') + ']');
|
||||
console.log('数字 1 的索引为 ' + index);
|
||||
}
|
||||
|
||||
export {};
|
||||
|
|
|
@ -29,7 +29,11 @@ class GraphAdjList {
|
|||
|
||||
/* 添加边 */
|
||||
addEdge(vet1: Vertex, vet2: Vertex): void {
|
||||
if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) {
|
||||
if (
|
||||
!this.adjList.has(vet1) ||
|
||||
!this.adjList.has(vet2) ||
|
||||
vet1 === vet2
|
||||
) {
|
||||
throw new Error('Illegal Argument Exception');
|
||||
}
|
||||
// 添加边 vet1 - vet2
|
||||
|
@ -39,7 +43,11 @@ class GraphAdjList {
|
|||
|
||||
/* 删除边 */
|
||||
removeEdge(vet1: Vertex, vet2: Vertex): void {
|
||||
if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) {
|
||||
if (
|
||||
!this.adjList.has(vet1) ||
|
||||
!this.adjList.has(vet2) ||
|
||||
vet1 === vet2
|
||||
) {
|
||||
throw new Error('Illegal Argument Exception');
|
||||
}
|
||||
// 删除边 vet1 - vet2
|
||||
|
@ -98,7 +106,7 @@ if (require.main === module) {
|
|||
[v2, v3],
|
||||
[v0, v3],
|
||||
[v2, v4],
|
||||
[v3, v4]
|
||||
[v3, v4],
|
||||
];
|
||||
const graph = new GraphAdjList(edges);
|
||||
console.log('\n初始化后,图为');
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
/* 基于邻接矩阵实现的无向图类 */
|
||||
class GraphAdjMat {
|
||||
vertices: number[]; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
|
||||
adjMat: number[][]; // 邻接矩阵,行列索引对应“顶点索引”
|
||||
vertices: number[]; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
|
||||
adjMat: number[][]; // 邻接矩阵,行列索引对应“顶点索引”
|
||||
|
||||
/* 构造函数 */
|
||||
constructor(vertices: number[], edges: number[][]) {
|
||||
|
@ -49,7 +49,7 @@ class GraphAdjMat {
|
|||
/* 删除顶点 */
|
||||
removeVertex(index: number): void {
|
||||
if (index >= this.size()) {
|
||||
throw new RangeError("Index Out Of Bounds Exception");
|
||||
throw new RangeError('Index Out Of Bounds Exception');
|
||||
}
|
||||
// 在顶点列表中移除索引 index 的顶点
|
||||
this.vertices.splice(index, 1);
|
||||
|
@ -67,7 +67,7 @@ class GraphAdjMat {
|
|||
addEdge(i: number, j: number): void {
|
||||
// 索引越界与相等处理
|
||||
if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) {
|
||||
throw new RangeError("Index Out Of Bounds Exception");
|
||||
throw new RangeError('Index Out Of Bounds Exception');
|
||||
}
|
||||
// 在无向图中,邻接矩阵沿主对角线对称,即满足 (i, j) == (j, i)
|
||||
this.adjMat[i][j] = 1;
|
||||
|
@ -79,7 +79,7 @@ class GraphAdjMat {
|
|||
removeEdge(i: number, j: number): void {
|
||||
// 索引越界与相等处理
|
||||
if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) {
|
||||
throw new RangeError("Index Out Of Bounds Exception");
|
||||
throw new RangeError('Index Out Of Bounds Exception');
|
||||
}
|
||||
this.adjMat[i][j] = 0;
|
||||
this.adjMat[j][i] = 0;
|
||||
|
@ -87,8 +87,8 @@ class GraphAdjMat {
|
|||
|
||||
/* 打印邻接矩阵 */
|
||||
print(): void {
|
||||
console.log("顶点列表 = ", this.vertices);
|
||||
console.log("邻接矩阵 =", this.adjMat);
|
||||
console.log('顶点列表 = ', this.vertices);
|
||||
console.log('邻接矩阵 =', this.adjMat);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,33 +96,39 @@ class GraphAdjMat {
|
|||
/* 初始化无向图 */
|
||||
// 请注意,edges 元素代表顶点索引,即对应 vertices 元素索引
|
||||
const vertices: number[] = [1, 3, 2, 5, 4];
|
||||
const edges: number[][] = [[0, 1], [1, 2], [2, 3], [0, 3], [2, 4], [3, 4]
|
||||
const edges: number[][] = [
|
||||
[0, 1],
|
||||
[1, 2],
|
||||
[2, 3],
|
||||
[0, 3],
|
||||
[2, 4],
|
||||
[3, 4],
|
||||
];
|
||||
const graph: GraphAdjMat = new GraphAdjMat(vertices, edges);
|
||||
console.log("\n初始化后,图为");
|
||||
console.log('\n初始化后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 添加边 */
|
||||
// 顶点 1, 2 的索引分别为 0, 2
|
||||
graph.addEdge(0, 2);
|
||||
console.log("\n添加边 1-2 后,图为");
|
||||
console.log('\n添加边 1-2 后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 删除边 */
|
||||
// 顶点 1, 3 的索引分别为 0, 1
|
||||
graph.removeEdge(0, 1);
|
||||
console.log("\n删除边 1-3 后,图为");
|
||||
console.log('\n删除边 1-3 后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 添加顶点 */
|
||||
graph.addVertex(6);
|
||||
console.log("\n添加顶点 6 后,图为");
|
||||
console.log('\n添加顶点 6 后,图为');
|
||||
graph.print();
|
||||
|
||||
/* 删除顶点 */
|
||||
// 顶点 3 的索引为 1
|
||||
graph.removeVertex(1);
|
||||
console.log("\n删除顶点 3 后,图为");
|
||||
console.log('\n删除顶点 3 后,图为');
|
||||
graph.print();
|
||||
|
||||
export {};
|
||||
export {};
|
||||
|
|
|
@ -49,7 +49,7 @@ const edges = [
|
|||
[v[4], v[7]],
|
||||
[v[5], v[8]],
|
||||
[v[6], v[7]],
|
||||
[v[7], v[8]]
|
||||
[v[7], v[8]],
|
||||
];
|
||||
const graph = new GraphAdjList(edges);
|
||||
console.log('\n初始化后,图为');
|
||||
|
|
|
@ -8,7 +8,12 @@ import { Vertex } from '../modules/Vertex';
|
|||
import { GraphAdjList } from './graph_adjacency_list';
|
||||
|
||||
/* 深度优先遍历 DFS 辅助函数 */
|
||||
function dfs(graph: GraphAdjList, visited: Set<Vertex>, res: Vertex[], vet: Vertex): void {
|
||||
function dfs(
|
||||
graph: GraphAdjList,
|
||||
visited: Set<Vertex>,
|
||||
res: Vertex[],
|
||||
vet: Vertex
|
||||
): void {
|
||||
res.push(vet); // 记录访问顶点
|
||||
visited.add(vet); // 标记该顶点已被访问
|
||||
// 遍历该顶点的所有邻接顶点
|
||||
|
@ -41,7 +46,7 @@ const edges = [
|
|||
[v[1], v[2]],
|
||||
[v[2], v[5]],
|
||||
[v[4], v[5]],
|
||||
[v[5], v[6]]
|
||||
[v[5], v[6]],
|
||||
];
|
||||
const graph = new GraphAdjList(edges);
|
||||
console.log('\n初始化后,图为');
|
||||
|
|
|
@ -17,12 +17,11 @@ class Entry {
|
|||
|
||||
/* 基于数组简易实现的哈希表 */
|
||||
class ArrayHashMap {
|
||||
|
||||
private readonly buckets: (Entry | null)[];
|
||||
|
||||
constructor() {
|
||||
// 初始化数组,包含 100 个桶
|
||||
this.buckets = (new Array(100)).fill(null);
|
||||
this.buckets = new Array(100).fill(null);
|
||||
}
|
||||
|
||||
/* 哈希函数 */
|
||||
|
|
|
@ -14,7 +14,10 @@ function hashingSearchArray(map: Map<number, number>, target: number): number {
|
|||
}
|
||||
|
||||
/* 哈希查找(链表) */
|
||||
function hashingSearchLinkedList(map: Map<number, ListNode>, target: number): ListNode | null {
|
||||
function hashingSearchLinkedList(
|
||||
map: Map<number, ListNode>,
|
||||
target: number
|
||||
): ListNode | null {
|
||||
// 哈希表的 key: 目标节点值,value: 节点对象
|
||||
// 若哈希表中无此 key ,返回 null
|
||||
return map.has(target) ? (map.get(target) as ListNode) : null;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* File: leetcode_two_sum.ts
|
||||
* Created Time: 2022-12-15
|
||||
* Author: gyt95 (gytkwan@gmail.com)
|
||||
* Author: gyt95 (gytkwan@gmail.com)
|
||||
*/
|
||||
|
||||
/* 方法一:暴力枚举 */
|
||||
|
@ -16,7 +16,7 @@ function twoSumBruteForce(nums: number[], target: number): number[] {
|
|||
}
|
||||
}
|
||||
return [];
|
||||
};
|
||||
}
|
||||
|
||||
/* 方法二:辅助哈希表 */
|
||||
function twoSumHashTable(nums: number[], target: number): number[] {
|
||||
|
@ -32,17 +32,18 @@ function twoSumHashTable(nums: number[], target: number): number[] {
|
|||
}
|
||||
}
|
||||
return [];
|
||||
};
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
// 方法一
|
||||
const nums = [2, 7, 11, 15], target = 9;
|
||||
const nums = [2, 7, 11, 15],
|
||||
target = 9;
|
||||
|
||||
let res = twoSumBruteForce(nums, target);
|
||||
console.log("方法一 res = ", res);
|
||||
console.log('方法一 res = ', res);
|
||||
|
||||
// 方法二
|
||||
res = twoSumHashTable(nums, target);
|
||||
console.log("方法二 res = ", res);
|
||||
console.log('方法二 res = ', res);
|
||||
|
||||
export {};
|
||||
|
|
|
@ -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) {
|
||||
// 找到目标节点,返回之
|
||||
|
|
|
@ -11,20 +11,23 @@ function merge(nums: number[], left: number, mid: number, right: number): void {
|
|||
// 初始化辅助数组
|
||||
let tmp = nums.slice(left, right + 1);
|
||||
// 左子数组的起始索引和结束索引
|
||||
let leftStart = left - left, leftEnd = mid - left;
|
||||
let leftStart = left - left,
|
||||
leftEnd = mid - left;
|
||||
// 右子数组的起始索引和结束索引
|
||||
let rightStart = mid + 1 - left, rightEnd = right - left;
|
||||
let rightStart = mid + 1 - left,
|
||||
rightEnd = right - left;
|
||||
// i, j 分别指向左子数组、右子数组的首元素
|
||||
let i = leftStart, j = rightStart;
|
||||
let i = leftStart,
|
||||
j = rightStart;
|
||||
// 通过覆盖原数组 nums 来合并左子数组和右子数组
|
||||
for (let k = left; k <= right; k++) {
|
||||
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
|
||||
if (i > leftEnd) {
|
||||
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
|
||||
nums[k] = tmp[j++];
|
||||
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
|
||||
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
|
||||
} else if (j > rightEnd || tmp[i] <= tmp[j]) {
|
||||
nums[k] = tmp[i++];
|
||||
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
|
||||
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
|
||||
} else {
|
||||
nums[k] = tmp[j++];
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@ class QuickSort {
|
|||
/* 哨兵划分 */
|
||||
partition(nums: number[], left: number, right: number): number {
|
||||
// 以 nums[left] 作为基准数
|
||||
let i = left, j = right;
|
||||
let i = left,
|
||||
j = right;
|
||||
while (i < j) {
|
||||
while (i < j && nums[j] >= nums[left]) {
|
||||
j -= 1; // 从右向左找首个小于基准数的元素
|
||||
|
@ -55,12 +56,19 @@ class QuickSortMedian {
|
|||
}
|
||||
|
||||
/* 选取三个元素的中位数 */
|
||||
medianThree(nums: number[], left: number, mid: number, right: number): number {
|
||||
medianThree(
|
||||
nums: number[],
|
||||
left: number,
|
||||
mid: number,
|
||||
right: number
|
||||
): number {
|
||||
// 此处使用异或运算来简化代码
|
||||
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
|
||||
if (Number(nums[left] < nums[mid]) ^ Number(nums[left] < nums[right])) {
|
||||
return left;
|
||||
} else if (Number(nums[mid] < nums[left]) ^ Number(nums[mid] < nums[right])) {
|
||||
} else if (
|
||||
Number(nums[mid] < nums[left]) ^ Number(nums[mid] < nums[right])
|
||||
) {
|
||||
return mid;
|
||||
} else {
|
||||
return right;
|
||||
|
@ -70,11 +78,17 @@ class QuickSortMedian {
|
|||
/* 哨兵划分(三数取中值) */
|
||||
partition(nums: number[], left: number, right: number): number {
|
||||
// 选取三个候选元素的中位数
|
||||
let med = this.medianThree(nums, left, Math.floor((left + right) / 2), right);
|
||||
let med = this.medianThree(
|
||||
nums,
|
||||
left,
|
||||
Math.floor((left + right) / 2),
|
||||
right
|
||||
);
|
||||
// 将中位数交换至数组最左端
|
||||
this.swap(nums, left, med);
|
||||
// 以 nums[left] 作为基准数
|
||||
let i = left, j = right;
|
||||
let i = left,
|
||||
j = right;
|
||||
while (i < j) {
|
||||
while (i < j && nums[j] >= nums[left]) {
|
||||
j--; // 从右向左找首个小于基准数的元素
|
||||
|
@ -114,7 +128,8 @@ class QuickSortTailCall {
|
|||
/* 哨兵划分 */
|
||||
partition(nums: number[], left: number, right: number): number {
|
||||
// 以 nums[left] 作为基准数
|
||||
let i = left, j = right;
|
||||
let i = left,
|
||||
j = right;
|
||||
while (i < j) {
|
||||
while (i < j && nums[j] >= nums[left]) {
|
||||
j--; // 从右向左找首个小于基准数的元素
|
||||
|
|
|
@ -18,7 +18,7 @@ function countingSortDigit(nums: number[], exp: number): void {
|
|||
// 统计 0~9 各数字的出现次数
|
||||
for (let i = 0; i < n; i++) {
|
||||
const d = digit(nums[i], exp); // 获取 nums[i] 第 k 位,记为 d
|
||||
counter[d]++; // 统计数字 d 的出现次数
|
||||
counter[d]++; // 统计数字 d 的出现次数
|
||||
}
|
||||
// 求前缀和,将“出现个数”转换为“数组索引”
|
||||
for (let i = 1; i < 10; i++) {
|
||||
|
@ -29,8 +29,8 @@ function countingSortDigit(nums: number[], exp: number): void {
|
|||
for (let i = n - 1; i >= 0; i--) {
|
||||
const d = digit(nums[i], exp);
|
||||
const j = counter[d] - 1; // 获取 d 在数组中的索引 j
|
||||
res[j] = nums[i]; // 将当前元素填入索引 j
|
||||
counter[d]--; // 将 d 的数量减 1
|
||||
res[j] = nums[i]; // 将当前元素填入索引 j
|
||||
counter[d]--; // 将 d 的数量减 1
|
||||
}
|
||||
// 使用结果覆盖原数组 nums
|
||||
for (let i = 0; i < n; i++) {
|
||||
|
@ -58,8 +58,10 @@ function radixSort(nums: number[]): void {
|
|||
}
|
||||
|
||||
/* Driver Code */
|
||||
const nums = [10546151, 35663510, 42865989, 34862445, 81883077,
|
||||
88906420, 72429244, 30524779, 82060337, 63832996];
|
||||
const nums = [
|
||||
10546151, 35663510, 42865989, 34862445, 81883077, 88906420, 72429244,
|
||||
30524779, 82060337, 63832996,
|
||||
];
|
||||
radixSort(nums);
|
||||
console.log('基数排序完成后 nums =', nums);
|
||||
|
||||
|
|
|
@ -4,12 +4,11 @@
|
|||
* Author: Zhuo Qinyue (1403450829@qq.com)
|
||||
*/
|
||||
|
||||
|
||||
/* 基于环形数组实现的双向队列 */
|
||||
class ArrayDeque {
|
||||
private nums: number[]; // 用于存储双向队列元素的数组
|
||||
private front: number; // 队首指针,指向队首元素
|
||||
private queSize: number; // 双向队列长度
|
||||
private nums: number[]; // 用于存储双向队列元素的数组
|
||||
private front: number; // 队首指针,指向队首元素
|
||||
private queSize: number; // 双向队列长度
|
||||
|
||||
/* 构造方法 */
|
||||
constructor(capacity: number) {
|
||||
|
@ -44,7 +43,7 @@ class ArrayDeque {
|
|||
/* 队首入队 */
|
||||
pushFirst(num: number): void {
|
||||
if (this.queSize === this.capacity()) {
|
||||
console.log("双向队列已满");
|
||||
console.log('双向队列已满');
|
||||
return;
|
||||
}
|
||||
// 队首指针向左移动一位
|
||||
|
@ -58,7 +57,7 @@ class ArrayDeque {
|
|||
/* 队尾入队 */
|
||||
pushLast(num: number): void {
|
||||
if (this.queSize === this.capacity()) {
|
||||
console.log("双向队列已满");
|
||||
console.log('双向队列已满');
|
||||
return;
|
||||
}
|
||||
// 计算尾指针,指向队尾索引 + 1
|
||||
|
@ -86,15 +85,13 @@ class ArrayDeque {
|
|||
|
||||
/* 访问队首元素 */
|
||||
peekFirst(): number {
|
||||
if (this.isEmpty())
|
||||
throw new Error("The Deque Is Empty.");
|
||||
if (this.isEmpty()) throw new Error('The Deque Is Empty.');
|
||||
return this.nums[this.front];
|
||||
}
|
||||
|
||||
/* 访问队尾元素 */
|
||||
peekLast(): number {
|
||||
if (this.isEmpty())
|
||||
throw new Error("The Deque Is Empty.");
|
||||
if (this.isEmpty()) throw new Error('The Deque Is Empty.');
|
||||
// 计算尾元素索引
|
||||
const last = this.index(this.front + this.queSize - 1);
|
||||
return this.nums[last];
|
||||
|
@ -118,32 +115,44 @@ const deque: ArrayDeque = new ArrayDeque(capacity);
|
|||
deque.pushLast(3);
|
||||
deque.pushLast(2);
|
||||
deque.pushLast(5);
|
||||
console.log("双向队列 deque = [" + deque.toArray() + "]");
|
||||
console.log('双向队列 deque = [' + deque.toArray() + ']');
|
||||
|
||||
/* 访问元素 */
|
||||
const peekFirst = deque.peekFirst();
|
||||
console.log("队首元素 peekFirst = " + peekFirst);
|
||||
console.log('队首元素 peekFirst = ' + peekFirst);
|
||||
const peekLast = deque.peekLast();
|
||||
console.log("队尾元素 peekLast = " + peekLast);
|
||||
console.log('队尾元素 peekLast = ' + peekLast);
|
||||
|
||||
/* 元素入队 */
|
||||
deque.pushLast(4);
|
||||
console.log("元素 4 队尾入队后 deque = [" + deque.toArray() + "]");
|
||||
console.log('元素 4 队尾入队后 deque = [' + deque.toArray() + ']');
|
||||
deque.pushFirst(1);
|
||||
console.log("元素 1 队首入队后 deque = [" + deque.toArray() + "]");
|
||||
console.log('元素 1 队首入队后 deque = [' + deque.toArray() + ']');
|
||||
|
||||
/* 元素出队 */
|
||||
const popLast = deque.popLast();
|
||||
console.log("队尾出队元素 = " + popLast + ",队尾出队后 deque = [" + deque.toArray() + "]");
|
||||
console.log(
|
||||
'队尾出队元素 = ' +
|
||||
popLast +
|
||||
',队尾出队后 deque = [' +
|
||||
deque.toArray() +
|
||||
']'
|
||||
);
|
||||
const popFirst = deque.popFirst();
|
||||
console.log("队首出队元素 = " + popFirst + ",队首出队后 deque = [" + deque.toArray()+ "]");
|
||||
console.log(
|
||||
'队首出队元素 = ' +
|
||||
popFirst +
|
||||
',队首出队后 deque = [' +
|
||||
deque.toArray() +
|
||||
']'
|
||||
);
|
||||
|
||||
/* 获取双向队列的长度 */
|
||||
const size = deque.size();
|
||||
console.log("双向队列长度 size = " + size);
|
||||
console.log('双向队列长度 size = ' + size);
|
||||
|
||||
/* 判断双向队列是否为空 */
|
||||
const isEmpty = deque.isEmpty();
|
||||
console.log("双向队列是否为空 = " + isEmpty);
|
||||
console.log('双向队列是否为空 = ' + isEmpty);
|
||||
|
||||
export {};
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
/* 基于环形数组实现的队列 */
|
||||
class ArrayQueue {
|
||||
private nums: number[]; // 用于存储队列元素的数组
|
||||
private front: number; // 队首指针,指向队首元素
|
||||
private nums: number[]; // 用于存储队列元素的数组
|
||||
private front: number; // 队首指针,指向队首元素
|
||||
private queSize: number; // 队列长度
|
||||
|
||||
constructor(capacity: number) {
|
||||
|
@ -33,7 +33,7 @@ class ArrayQueue {
|
|||
/* 入队 */
|
||||
push(num: number): void {
|
||||
if (this.size == this.capacity) {
|
||||
console.log("队列已满");
|
||||
console.log('队列已满');
|
||||
return;
|
||||
}
|
||||
// 计算尾指针,指向队尾索引 + 1
|
||||
|
@ -55,8 +55,7 @@ class ArrayQueue {
|
|||
|
||||
/* 访问队首元素 */
|
||||
peek(): number {
|
||||
if (this.empty())
|
||||
throw new Error("队列为空");
|
||||
if (this.empty()) throw new Error('队列为空');
|
||||
return this.nums[this.front];
|
||||
}
|
||||
|
||||
|
@ -82,29 +81,29 @@ queue.push(3);
|
|||
queue.push(2);
|
||||
queue.push(5);
|
||||
queue.push(4);
|
||||
console.log("队列 queue =", queue.toArray());
|
||||
console.log('队列 queue =', queue.toArray());
|
||||
|
||||
/* 访问队首元素 */
|
||||
const peek = queue.peek();
|
||||
console.log("队首元素 peek = " + peek);
|
||||
console.log('队首元素 peek = ' + peek);
|
||||
|
||||
/* 元素出队 */
|
||||
const pop = queue.pop();
|
||||
console.log("出队元素 pop = " + pop + ",出队后 queue =", queue.toArray());
|
||||
console.log('出队元素 pop = ' + pop + ',出队后 queue =', queue.toArray());
|
||||
|
||||
/* 获取队列的长度 */
|
||||
const size = queue.size;
|
||||
console.log("队列长度 size = " + size);
|
||||
console.log('队列长度 size = ' + size);
|
||||
|
||||
/* 判断队列是否为空 */
|
||||
const empty = queue.empty();
|
||||
console.log("队列是否为空 = " + empty);
|
||||
console.log('队列是否为空 = ' + empty);
|
||||
|
||||
/* 测试环形数组 */
|
||||
for (let i = 0; i < 10; i++) {
|
||||
queue.push(i);
|
||||
queue.pop();
|
||||
console.log("第 " + i + " 轮入队 + 出队后 queue =", queue.toArray());
|
||||
console.log('第 ' + i + ' 轮入队 + 出队后 queue =', queue.toArray());
|
||||
}
|
||||
|
||||
export {};
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* Author: S-N-O-R-L-A-X (snorlax.xu@outlook.com)
|
||||
*/
|
||||
|
||||
|
||||
/* 基于数组实现的栈 */
|
||||
class ArrayStack {
|
||||
private stack: number[];
|
||||
|
@ -29,15 +28,13 @@ class ArrayStack {
|
|||
|
||||
/* 出栈 */
|
||||
pop(): number | undefined {
|
||||
if (this.empty())
|
||||
throw new Error('栈为空');
|
||||
if (this.empty()) throw new Error('栈为空');
|
||||
return this.stack.pop();
|
||||
}
|
||||
|
||||
/* 访问栈顶元素 */
|
||||
top(): number | undefined {
|
||||
if (this.empty())
|
||||
throw new Error('栈为空');
|
||||
if (this.empty()) throw new Error('栈为空');
|
||||
return this.stack[this.stack.length - 1];
|
||||
}
|
||||
|
||||
|
@ -45,8 +42,7 @@ class ArrayStack {
|
|||
toArray() {
|
||||
return this.stack;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
/* 初始化栈 */
|
||||
|
@ -58,24 +54,24 @@ stack.push(3);
|
|||
stack.push(2);
|
||||
stack.push(5);
|
||||
stack.push(4);
|
||||
console.log("栈 stack = ");
|
||||
console.log('栈 stack = ');
|
||||
console.log(stack.toArray());
|
||||
|
||||
/* 访问栈顶元素 */
|
||||
const top = stack.top();
|
||||
console.log("栈顶元素 top = " + top);
|
||||
console.log('栈顶元素 top = ' + top);
|
||||
|
||||
/* 元素出栈 */
|
||||
const pop = stack.pop();
|
||||
console.log("出栈元素 pop = " + pop + ",出栈后 stack = ");
|
||||
console.log('出栈元素 pop = ' + pop + ',出栈后 stack = ');
|
||||
console.log(stack.toArray());
|
||||
|
||||
/* 获取栈的长度 */
|
||||
const size = stack.size;
|
||||
console.log("栈的长度 size = " + size);
|
||||
console.log('栈的长度 size = ' + size);
|
||||
|
||||
/* 判断是否为空 */
|
||||
const empty = stack.empty();
|
||||
console.log("栈是否为空 = " + empty);
|
||||
console.log('栈是否为空 = ' + empty);
|
||||
|
||||
export {};
|
||||
|
|
|
@ -16,27 +16,31 @@ deque.push(4);
|
|||
// 请注意,由于是数组,unshift() 方法的时间复杂度为 O(n)
|
||||
deque.unshift(3);
|
||||
deque.unshift(1);
|
||||
console.log("双向队列 deque = ", deque);
|
||||
console.log('双向队列 deque = ', deque);
|
||||
|
||||
/* 访问元素 */
|
||||
const peekFirst: number = deque[0];
|
||||
console.log("队首元素 peekFirst = " + peekFirst);
|
||||
console.log('队首元素 peekFirst = ' + peekFirst);
|
||||
const peekLast: number = deque[deque.length - 1];
|
||||
console.log("队尾元素 peekLast = " + peekLast);
|
||||
console.log('队尾元素 peekLast = ' + peekLast);
|
||||
|
||||
/* 元素出队 */
|
||||
// 请注意,由于是数组,shift() 方法的时间复杂度为 O(n)
|
||||
const popFront: number = deque.shift() as number;
|
||||
console.log("队首出队元素 popFront = " + popFront + ",队首出队后 deque = " + deque);
|
||||
console.log(
|
||||
'队首出队元素 popFront = ' + popFront + ',队首出队后 deque = ' + deque
|
||||
);
|
||||
const popBack: number = deque.pop() as number;
|
||||
console.log("队尾出队元素 popBack = " + popBack + ",队尾出队后 deque = " + deque);
|
||||
console.log(
|
||||
'队尾出队元素 popBack = ' + popBack + ',队尾出队后 deque = ' + deque
|
||||
);
|
||||
|
||||
/* 获取双向队列的长度 */
|
||||
const size: number = deque.length;
|
||||
console.log("双向队列长度 size = " + size);
|
||||
console.log('双向队列长度 size = ' + size);
|
||||
|
||||
/* 判断双向队列是否为空 */
|
||||
const isEmpty: boolean = size === 0;
|
||||
console.log("双向队列是否为空 = " + isEmpty);
|
||||
console.log('双向队列是否为空 = ' + isEmpty);
|
||||
|
||||
export {};
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
/* 双向链表节点 */
|
||||
class ListNode {
|
||||
prev: ListNode; // 前驱节点引用 (指针)
|
||||
next: ListNode; // 后继节点引用 (指针)
|
||||
val: number; // 节点值
|
||||
prev: ListNode; // 前驱节点引用 (指针)
|
||||
next: ListNode; // 后继节点引用 (指针)
|
||||
val: number; // 节点值
|
||||
|
||||
constructor(val: number) {
|
||||
this.val = val;
|
||||
|
@ -19,16 +19,16 @@ class ListNode {
|
|||
|
||||
/* 基于双向链表实现的双向队列 */
|
||||
class LinkedListDeque {
|
||||
private front: ListNode; // 头节点 front
|
||||
private rear: ListNode; // 尾节点 rear
|
||||
private queSize: number; // 双向队列的长度
|
||||
private front: ListNode; // 头节点 front
|
||||
private rear: ListNode; // 尾节点 rear
|
||||
private queSize: number; // 双向队列的长度
|
||||
|
||||
constructor() {
|
||||
this.front = null;
|
||||
this.rear = null;
|
||||
this.queSize = 0;
|
||||
}
|
||||
|
||||
|
||||
/* 队尾入队操作 */
|
||||
pushLast(val: number): void {
|
||||
const node: ListNode = new ListNode(val);
|
||||
|
@ -73,7 +73,7 @@ class LinkedListDeque {
|
|||
temp.next = null;
|
||||
this.rear.prev = null;
|
||||
}
|
||||
this.rear = temp; // 更新尾节点
|
||||
this.rear = temp; // 更新尾节点
|
||||
this.queSize--;
|
||||
return value;
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ class LinkedListDeque {
|
|||
temp.prev = null;
|
||||
this.front.next = null;
|
||||
}
|
||||
this.front = temp; // 更新头节点
|
||||
this.front = temp; // 更新头节点
|
||||
this.queSize--;
|
||||
return value;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ class LinkedListDeque {
|
|||
arr.push(temp.val);
|
||||
temp = temp.next;
|
||||
}
|
||||
console.log("[" + arr.join(", ") + "]");
|
||||
console.log('[' + arr.join(', ') + ']');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,35 +133,35 @@ const linkedListDeque: LinkedListDeque = new LinkedListDeque();
|
|||
linkedListDeque.pushLast(3);
|
||||
linkedListDeque.pushLast(2);
|
||||
linkedListDeque.pushLast(5);
|
||||
console.log("双向队列 linkedListDeque = ");
|
||||
console.log('双向队列 linkedListDeque = ');
|
||||
linkedListDeque.print();
|
||||
|
||||
/* 访问元素 */
|
||||
const peekFirst: number = linkedListDeque.peekFirst();
|
||||
console.log("队首元素 peekFirst = " + peekFirst);
|
||||
console.log('队首元素 peekFirst = ' + peekFirst);
|
||||
const peekLast: number = linkedListDeque.peekLast();
|
||||
console.log("队尾元素 peekLast = " + peekLast);
|
||||
console.log('队尾元素 peekLast = ' + peekLast);
|
||||
|
||||
/* 元素入队 */
|
||||
linkedListDeque.pushLast(4);
|
||||
console.log("元素 4 队尾入队后 linkedListDeque = ");
|
||||
console.log('元素 4 队尾入队后 linkedListDeque = ');
|
||||
linkedListDeque.print();
|
||||
linkedListDeque.pushFirst(1);
|
||||
console.log("元素 1 队首入队后 linkedListDeque = ");
|
||||
console.log('元素 1 队首入队后 linkedListDeque = ');
|
||||
linkedListDeque.print();
|
||||
|
||||
/* 元素出队 */
|
||||
const popLast: number = linkedListDeque.popLast();
|
||||
console.log("队尾出队元素 = " + popLast + ",队尾出队后 linkedListDeque = ");
|
||||
console.log('队尾出队元素 = ' + popLast + ',队尾出队后 linkedListDeque = ');
|
||||
linkedListDeque.print();
|
||||
const popFirst: number = linkedListDeque.popFirst();
|
||||
console.log("队首出队元素 = " + popFirst + ",队首出队后 linkedListDeque = ");
|
||||
console.log('队首出队元素 = ' + popFirst + ',队首出队后 linkedListDeque = ');
|
||||
linkedListDeque.print();
|
||||
|
||||
/* 获取双向队列的长度 */
|
||||
const size: number = linkedListDeque.size();
|
||||
console.log("双向队列长度 size = " + size);
|
||||
console.log('双向队列长度 size = ' + size);
|
||||
|
||||
/* 判断双向队列是否为空 */
|
||||
const isEmpty: boolean = linkedListDeque.isEmpty();
|
||||
console.log("双向队列是否为空 = " + isEmpty);
|
||||
console.log('双向队列是否为空 = ' + isEmpty);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
/* Driver Code */
|
||||
/* 初始化队列 */
|
||||
// TypeScript 没有内置的队列,可以把 Array 当作队列来使用
|
||||
// TypeScript 没有内置的队列,可以把 Array 当作队列来使用
|
||||
const queue: number[] = [];
|
||||
|
||||
/* 元素入队 */
|
||||
|
@ -15,23 +15,23 @@ queue.push(3);
|
|||
queue.push(2);
|
||||
queue.push(5);
|
||||
queue.push(4);
|
||||
console.log("队列 queue =", queue);
|
||||
console.log('队列 queue =', queue);
|
||||
|
||||
/* 访问队首元素 */
|
||||
const peek = queue[0];
|
||||
console.log("队首元素 peek =", peek);
|
||||
console.log('队首元素 peek =', peek);
|
||||
|
||||
/* 元素出队 */
|
||||
// 底层是数组,因此 shift() 方法的时间复杂度为 O(n)
|
||||
const pop = queue.shift();
|
||||
console.log("出队元素 pop =", pop, ",出队后 queue = ", queue);
|
||||
console.log('出队元素 pop =', pop, ',出队后 queue = ', queue);
|
||||
|
||||
/* 获取队列的长度 */
|
||||
const size = queue.length;
|
||||
console.log("队列长度 size =", size);
|
||||
console.log('队列长度 size =', size);
|
||||
|
||||
/* 判断队列是否为空 */
|
||||
const isEmpty = queue.length === 0;
|
||||
console.log("队列是否为空 = ", isEmpty);
|
||||
console.log('队列是否为空 = ', isEmpty);
|
||||
|
||||
export {};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
/* Driver Code */
|
||||
/* 初始化栈 */
|
||||
// Typescript 没有内置的栈类,可以把 Array 当作栈来使用
|
||||
// Typescript 没有内置的栈类,可以把 Array 当作栈来使用
|
||||
const stack: number[] = [];
|
||||
|
||||
/* 元素入栈 */
|
||||
|
@ -15,23 +15,23 @@ stack.push(3);
|
|||
stack.push(2);
|
||||
stack.push(5);
|
||||
stack.push(4);
|
||||
console.log("栈 stack =", stack);
|
||||
console.log('栈 stack =', stack);
|
||||
|
||||
/* 访问栈顶元素 */
|
||||
const peek = stack[stack.length - 1];
|
||||
console.log("栈顶元素 peek =", peek);
|
||||
console.log('栈顶元素 peek =', peek);
|
||||
|
||||
/* 元素出栈 */
|
||||
const pop = stack.pop();
|
||||
console.log("出栈元素 pop =", pop);
|
||||
console.log("出栈后 stack =", stack);
|
||||
console.log('出栈元素 pop =', pop);
|
||||
console.log('出栈后 stack =', stack);
|
||||
|
||||
/* 获取栈的长度 */
|
||||
const size = stack.length;
|
||||
console.log("栈的长度 size =", size);
|
||||
console.log('栈的长度 size =', size);
|
||||
|
||||
/* 判断是否为空 */
|
||||
const isEmpty = stack.length === 0;
|
||||
console.log("栈是否为空 =", isEmpty);
|
||||
console.log('栈是否为空 =', isEmpty);
|
||||
|
||||
export {};
|
||||
|
|
|
@ -24,7 +24,8 @@ class AVLTree {
|
|||
/* 更新节点高度 */
|
||||
private updateHeight(node: TreeNode): void {
|
||||
// 节点高度等于最高子树高度 + 1
|
||||
node.height = Math.max(this.height(node.left), this.height(node.right)) + 1;
|
||||
node.height =
|
||||
Math.max(this.height(node.left), this.height(node.right)) + 1;
|
||||
}
|
||||
|
||||
/* 获取平衡因子 */
|
||||
|
|
|
@ -44,8 +44,4 @@ function getListNode(head: ListNode | null, val: number): ListNode | null {
|
|||
return head;
|
||||
}
|
||||
|
||||
export {
|
||||
ListNode,
|
||||
arrToLinkedList,
|
||||
getListNode
|
||||
};
|
||||
export { ListNode, arrToLinkedList, getListNode };
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* Author: Justin (xiefahit@gmail.com)
|
||||
*/
|
||||
|
||||
import { ListNode } from "./ListNode";
|
||||
import { TreeNode, arrToTree } from "./TreeNode";
|
||||
import { ListNode } from './ListNode';
|
||||
import { TreeNode, arrToTree } from './TreeNode';
|
||||
|
||||
/**
|
||||
* Print a linked list
|
||||
|
@ -46,7 +46,11 @@ function printTree(root: TreeNode | null) {
|
|||
* @param prev
|
||||
* @param isLeft
|
||||
*/
|
||||
function printTreeHelper(root: TreeNode | null, prev: Trunk | null, isLeft: boolean) {
|
||||
function printTreeHelper(
|
||||
root: TreeNode | null,
|
||||
prev: Trunk | null,
|
||||
isLeft: boolean
|
||||
) {
|
||||
if (root === null) {
|
||||
return;
|
||||
}
|
||||
|
@ -98,15 +102,11 @@ function showTrunks(p: Trunk | null) {
|
|||
* @param arr
|
||||
*/
|
||||
function printHeap(arr: number[]): void {
|
||||
console.log("堆的数组表示:");
|
||||
console.log('堆的数组表示:');
|
||||
console.log(arr);
|
||||
console.log("堆的树状表示:");
|
||||
console.log('堆的树状表示:');
|
||||
const root = arrToTree(arr);
|
||||
printTree(root);
|
||||
}
|
||||
|
||||
export {
|
||||
printLinkedList,
|
||||
printTree,
|
||||
printHeap
|
||||
};
|
||||
export { printLinkedList, printTree, printHeap };
|
||||
|
|
|
@ -8,15 +8,20 @@
|
|||
* Definition for a binary tree node.
|
||||
*/
|
||||
class TreeNode {
|
||||
val: number; // 节点值
|
||||
height: number; // 节点高度
|
||||
left: TreeNode | null; // 左子节点指针
|
||||
val: number; // 节点值
|
||||
height: number; // 节点高度
|
||||
left: TreeNode | null; // 左子节点指针
|
||||
right: TreeNode | null; // 右子节点指针
|
||||
constructor(val?: number, height?: number, left?: TreeNode | null, right?: TreeNode | null) {
|
||||
constructor(
|
||||
val?: number,
|
||||
height?: number,
|
||||
left?: TreeNode | null,
|
||||
right?: TreeNode | null
|
||||
) {
|
||||
this.val = val === undefined ? 0 : val;
|
||||
this.height = height === undefined ? 0 : height;
|
||||
this.left = left === undefined ? null : left;
|
||||
this.right = right === undefined ? null : right;
|
||||
this.height = height === undefined ? 0 : height;
|
||||
this.left = left === undefined ? null : left;
|
||||
this.right = right === undefined ? null : right;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +54,4 @@ function arrToTree(arr: (number | null)[]): TreeNode | null {
|
|||
return root;
|
||||
}
|
||||
|
||||
export {
|
||||
TreeNode,
|
||||
arrToTree
|
||||
};
|
||||
export { TreeNode, arrToTree };
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* Author: Zhuo Qinyue (1403450829@qq.com)
|
||||
*/
|
||||
|
||||
|
||||
/* 顶点类 */
|
||||
class Vertex {
|
||||
val: number;
|
||||
|
@ -31,6 +30,4 @@ class Vertex {
|
|||
}
|
||||
}
|
||||
|
||||
export {
|
||||
Vertex
|
||||
};
|
||||
export { Vertex };
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
"outDir": "out",
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue