Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add JavaScript and TypeScript code of heap sort, selection sort and binary search edge and Fix the indentation of TS code #545

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions codes/javascript/chapter_searching/binary_search_edge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* File: binary_search_edge.js
* Created Time: 2023-06-04
* Author: Justin (xiefahit@gmail.com)
*/

/* 二分查找最左一个元素 */
function binary_search_left_edge(nums, target) {
let i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1]
while (i <= j) {
let m = Math.floor((i + j) / 2); // 计算中点索引 m
if (nums[m] < target) {
i = m + 1; // target 在区间 [m+1, j] 中
} else if (nums[m] > target) {
j = m - 1; // target 在区间 [i, m-1] 中
} else {
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
}
}
if (i == nums.length || nums[i] != target) {
return -1; // 未找到目标元素,返回 -1
}
return i;
}

/* 二分查找最右一个元素 */
function binary_search_right_edge(nums, target) {
let i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1]
while (i <= j) {
let m = Math.floor((i + j) / 2); // 计算中点索引 m
if (nums[m] < target) {
i = m + 1; // target 在区间 [m+1, j] 中
} else if (nums[m] > target) {
j = m - 1; // target 在区间 [i, m-1] 中
} else {
i = m + 1; // 首个大于 target 的元素在区间 [m+1, j] 中
}
}
if (j == nums.length || nums[j] != target) {
return -1; // 未找到目标元素,返回 -1
}
return j;
}

/* Driver Code */
let target = 6;
const nums = [1, 3, 6, 6, 6, 6, 6, 10, 12, 15];

// 二分查找最左一个元素
let index_left = binary_search_left_edge(nums, target);
console.log("数组中最左一个元素 6 的索引 = ", index_left);

// 二分查找最右一个元素
let index_right = binary_search_right_edge(nums, target);
console.log("数组中最右一个元素 6 的索引 = ", index_right);
49 changes: 49 additions & 0 deletions codes/javascript/chapter_sorting/heap_sort.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* File: heap_sort.js
* Created Time: 2023-06-04
* Author: Justin (xiefahit@gmail.com)
*/

/* 堆的长度为 n ,从节点 i 开始,从顶至底堆化 */
function sift_down(nums, n, i) {
while (true) {
// 判断节点 i, l, r 中值最大的节点,记为 ma
let l = 2 * i + 1;
let r = 2 * i + 2;
let ma = i;
if (l < n && nums[l] > nums[ma]) {
ma = l;
}
if (r < n && nums[r] > nums[ma]) {
ma = r;
}
// 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
if (ma === i) {
break;
}
// 交换两节点
[nums[i], nums[ma]] = [nums[ma], nums[i]];
// 循环向下堆化
i = ma;
}
}

/* 堆排序 */
function heap_sort(nums) {
// 建堆操作:堆化除叶节点以外的其他所有节点
for (let i = Math.floor(nums.length / 2) - 1; i >= 0; i--) {
sift_down(nums, nums.length, i);
}
// 从堆中提取最大元素,循环 n-1 轮
for (let i = nums.length - 1; i > 0; i--) {
// 交换根节点与最右叶节点(即交换首元素与尾元素)
[nums[0], nums[i]] = [nums[i], nums[0]];
// 以根节点为起点,从顶至底进行堆化
sift_down(nums, i, 0);
}
}

/* Driver Code */
const nums = [4, 1, 3, 1, 5, 2];
heap_sort(nums);
console.log("堆排序完成后 nums =", nums);
27 changes: 27 additions & 0 deletions codes/javascript/chapter_sorting/selection_sort.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* File: selection_sort.js
* Created Time: 2023-06-04
* Author: Justin (xiefahit@gmail.com)
*/

/* 选择排序 */
function selection_sort(nums) {
let n = nums.length;
// 外循环:未排序区间为 [i, n-1]
for (let i = 0; i < n - 1; i++) {
// 内循环:找到未排序区间内的最小元素
let k = i;
for (let j = i + 1; j < n; j++) {
if (nums[j] < nums[k]) {
k = j; // 记录最小元素的索引
}
}
// 将该最小元素与未排序区间的首个元素交换
[nums[i], nums[k]] = [nums[k], nums[i]];
}
}

/* Driver Code */
const nums = [4, 1, 3, 1, 5, 2];
selection_sort(nums);
console.log("选择排序完成后 nums =", nums);
16 changes: 7 additions & 9 deletions codes/typescript/chapter_backtracking/n_queens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function backtrack(
): void {
// 当放置完所有行时,记录解
if (row === n) {
res.push(state.map((row) => row.slice()));
res.push(state.map(row => row.slice()));
return;
}
// 遍历所有列
Expand All @@ -27,12 +27,12 @@ function backtrack(
// 剪枝:不允许该格子所在 (列 或 主对角线 或 副对角线) 包含皇后
if (!(cols[col] || diags1[diag1] || diags2[diag2])) {
// 尝试:将皇后放置在该格子
state[row][col] = 'Q';
state[row][col] = "Q";
cols[col] = diags1[diag1] = diags2[diag2] = true;
// 放置下一行
backtrack(row + 1, n, state, res, cols, diags1, diags2);
// 回退:将该格子恢复为空位
state[row][col] = '#';
state[row][col] = "#";
cols[col] = diags1[diag1] = diags2[diag2] = false;
}
}
Expand All @@ -41,7 +41,7 @@ function backtrack(
/* 求解 N 皇后 */
function nQueens(n: number): string[][][] {
// 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位
const state = Array.from({ length: n }, () => Array(n).fill('#'));
const state = Array.from({ length: n }, () => Array(n).fill("#"));
const cols = Array(n).fill(false); // 记录列是否有皇后
const diags1 = Array(2 * n - 1).fill(false); // 记录主对角线是否有皇后
const diags2 = Array(2 * n - 1).fill(false); // 记录副对角线是否有皇后
Expand All @@ -57,9 +57,7 @@ const res = nQueens(n);

console.log(`输入棋盘长宽为 ${n}`);
console.log(`皇后放置方案共有 ${res.length} 种`);
res.forEach((state) => {
console.log('--------------------');
state.forEach((row) => console.log(row));
res.forEach(state => {
console.log("--------------------");
state.forEach(row => console.log(row));
});

export {};
55 changes: 55 additions & 0 deletions codes/typescript/chapter_searching/binary_search_edge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* File: binary_search_edge.ts
* Created Time: 2023-06-04
* Author: Justin (xiefahit@gmail.com)
*/

/* 二分查找最左一个元素 */
function binary_search_left_edge(nums: number[], target: number): number {
let i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1]
while (i <= j) {
let m = Math.floor((i + j) / 2); // 计算中点索引 m
if (nums[m] < target) {
i = m + 1; // target 在区间 [m+1, j] 中
} else if (nums[m] > target) {
j = m - 1; // target 在区间 [i, m-1] 中
} else {
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
}
}
if (i == nums.length || nums[i] != target) {
return -1; // 未找到目标元素,返回 -1
}
return i;
}

/* 二分查找最右一个元素 */
function binary_search_right_edge(nums: number[], target: number): number {
let i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1]
while (i <= j) {
let m = Math.floor((i + j) / 2); // 计算中点索引 m
if (nums[m] < target) {
i = m + 1; // target 在区间 [m+1, j] 中
} else if (nums[m] > target) {
j = m - 1; // target 在区间 [i, m-1] 中
} else {
i = m + 1; // 首个大于 target 的元素在区间 [m+1, j] 中
}
}
if (j == nums.length || nums[j] != target) {
return -1; // 未找到目标元素,返回 -1
}
return j;
}

/* Driver Code */
let target: number = 6;
const nums: number[] = [1, 3, 6, 6, 6, 6, 6, 10, 12, 15];

// 二分查找最左一个元素
let index_left: number = binary_search_left_edge(nums, target);
console.log("数组中最左一个元素 6 的索引 = ", index_left);

// 二分查找最右一个元素
let index_right: number = binary_search_right_edge(nums, target);
console.log("数组中最右一个元素 6 的索引 = ", index_right);
51 changes: 51 additions & 0 deletions codes/typescript/chapter_sorting/heap_sort.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* File: heap_sort.ts
* Created Time: 2023-06-04
* Author: Justin (xiefahit@gmail.com)
*/

/* 堆的长度为 n ,从节点 i 开始,从顶至底堆化 */
function sift_down(nums: number[], n: number, i: number): void {
while (true) {
// 判断节点 i, l, r 中值最大的节点,记为 ma
let l = 2 * i + 1;
let r = 2 * i + 2;
let ma = i;
if (l < n && nums[l] > nums[ma]) {
ma = l;
}
if (r < n && nums[r] > nums[ma]) {
ma = r;
}
// 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
if (ma === i) {
break;
}
// 交换两节点
[nums[i], nums[ma]] = [nums[ma], nums[i]];
// 循环向下堆化
i = ma;
}
}

/* 堆排序 */
function heap_sort(nums: number[]): void {
// 建堆操作:堆化除叶节点以外的其他所有节点
for (let i = Math.floor(nums.length / 2) - 1; i >= 0; i--) {
sift_down(nums, nums.length, i);
}
// 从堆中提取最大元素,循环 n-1 轮
for (let i = nums.length - 1; i > 0; i--) {
// 交换根节点与最右叶节点(即交换首元素与尾元素)
[nums[0], nums[i]] = [nums[i], nums[0]];
// 以根节点为起点,从顶至底进行堆化
sift_down(nums, i, 0);
}
}

/* Driver Code */
const nums: number[] = [4, 1, 3, 1, 5, 2];
heap_sort(nums);
console.log("堆排序完成后 nums =", nums);

export { };
29 changes: 29 additions & 0 deletions codes/typescript/chapter_sorting/selection_sort.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* File: selection_sort.ts
* Created Time: 2023-06-04
* Author: Justin (xiefahit@gmail.com)
*/

/* 选择排序 */
function selection_sort(nums: number[]): void {
let n = nums.length;
// 外循环:未排序区间为 [i, n-1]
for (let i = 0; i < n - 1; i++) {
// 内循环:找到未排序区间内的最小元素
let k = i;
for (let j = i + 1; j < n; j++) {
if (nums[j] < nums[k]) {
k = j; // 记录最小元素的索引
}
}
// 将该最小元素与未排序区间的首个元素交换
[nums[i], nums[k]] = [nums[k], nums[i]];
}
}

/* Driver Code */
const nums: number[] = [4, 1, 3, 1, 5, 2];
selection_sort(nums);
console.log("选择排序完成后 nums =", nums);

export { };