Improve readability of kotlin code (#1233)

* style(kotlin): Improve kotlin codes readability.

* remove redundant quotes.
This commit is contained in:
curtishd 2024-04-07 18:56:59 +08:00 committed by GitHub
parent e121665772
commit 5725b8a0f1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 85 additions and 101 deletions

View File

@ -10,7 +10,13 @@ import utils.TreeNode
import utils.printTree import utils.printTree
/* 构建二叉树:分治 */ /* 构建二叉树:分治 */
fun dfs(preorder: IntArray, inorderMap: Map<Int?, Int?>, i: Int, l: Int, r: Int): TreeNode? { fun dfs(
preorder: IntArray,
inorderMap: Map<Int?, Int?>,
i: Int,
l: Int,
r: Int
): TreeNode? {
// 子树区间为空时终止 // 子树区间为空时终止
if (r - l < 0) return null if (r - l < 0) return null
// 初始化根节点 // 初始化根节点
@ -28,7 +34,7 @@ fun dfs(preorder: IntArray, inorderMap: Map<Int?, Int?>, i: Int, l: Int, r: Int)
/* 构建二叉树 */ /* 构建二叉树 */
fun buildTree(preorder: IntArray, inorder: IntArray): TreeNode? { fun buildTree(preorder: IntArray, inorder: IntArray): TreeNode? {
// 初始化哈希表,存储 inorder 元素到索引的映射 // 初始化哈希表,存储 inorder 元素到索引的映射
val inorderMap: MutableMap<Int?, Int?> = HashMap() val inorderMap = HashMap<Int?, Int?>()
for (i in inorder.indices) { for (i in inorder.indices) {
inorderMap[inorder[i]] = i inorderMap[inorder[i]] = i
} }
@ -40,8 +46,8 @@ fun buildTree(preorder: IntArray, inorder: IntArray): TreeNode? {
fun main() { fun main() {
val preorder = intArrayOf(3, 9, 2, 1, 7) val preorder = intArrayOf(3, 9, 2, 1, 7)
val inorder = intArrayOf(9, 3, 1, 2, 7) val inorder = intArrayOf(9, 3, 1, 2, 7)
println("前序遍历 = " + preorder.contentToString()) println("前序遍历 = ${preorder.contentToString()}")
println("中序遍历 = " + inorder.contentToString()) println("中序遍历 = ${inorder.contentToString()}")
val root = buildTree(preorder, inorder) val root = buildTree(preorder, inorder)
println("构建的二叉树为:") println("构建的二叉树为:")

View File

@ -9,7 +9,7 @@ package chapter_divide_and_conquer.hanota
/* 移动一个圆盘 */ /* 移动一个圆盘 */
fun move(src: MutableList<Int>, tar: MutableList<Int>) { fun move(src: MutableList<Int>, tar: MutableList<Int>) {
// 从 src 顶部拿出一个圆盘 // 从 src 顶部拿出一个圆盘
val pan: Int = src.removeAt(src.size - 1) val pan = src.removeAt(src.size - 1)
// 将圆盘放入 tar 顶部 // 将圆盘放入 tar 顶部
tar.add(pan) tar.add(pan)
} }
@ -39,9 +39,9 @@ fun solveHanota(A: MutableList<Int>, B: MutableList<Int>, C: MutableList<Int>) {
/* Driver Code */ /* Driver Code */
fun main() { fun main() {
// 列表尾部是柱子顶部 // 列表尾部是柱子顶部
val A: MutableList<Int> = ArrayList(mutableListOf(5, 4, 3, 2, 1)) val A = mutableListOf(5, 4, 3, 2, 1)
val B: MutableList<Int> = ArrayList() val B = mutableListOf<Int>()
val C: MutableList<Int> = ArrayList() val C = mutableListOf<Int>()
println("初始状态下:") println("初始状态下:")
println("A = $A") println("A = $A")
println("B = $B") println("B = $B")
@ -53,4 +53,4 @@ fun main() {
println("A = $A") println("A = $A")
println("B = $B") println("B = $B")
println("C = $C") println("C = $C")
} }

View File

@ -8,13 +8,14 @@ package chapter_dynamic_programming
/* 回溯 */ /* 回溯 */
fun backtrack( fun backtrack(
choices: List<Int>, choices: MutableList<Int>,
state: Int, state: Int,
n: Int, n: Int,
res: MutableList<Int> res: MutableList<Int>
) { ) {
// 当爬到第 n 阶时,方案数量加 1 // 当爬到第 n 阶时,方案数量加 1
if (state == n) res[0] = res[0] + 1 if (state == n)
res[0] = res[0] + 1
// 遍历所有选择 // 遍历所有选择
for (choice in choices) { for (choice in choices) {
// 剪枝:不允许越过第 n 阶 // 剪枝:不允许越过第 n 阶
@ -29,7 +30,7 @@ fun backtrack(
fun climbingStairsBacktrack(n: Int): Int { fun climbingStairsBacktrack(n: Int): Int {
val choices = mutableListOf(1, 2) // 可选择向上爬 1 阶或 2 阶 val choices = mutableListOf(1, 2) // 可选择向上爬 1 阶或 2 阶
val state = 0 // 从第 0 阶开始爬 val state = 0 // 从第 0 阶开始爬
val res = ArrayList<Int>() val res = mutableListOf<Int>()
res.add(0) // 使用 res[0] 记录方案数量 res.add(0) // 使用 res[0] 记录方案数量
backtrack(choices, state, n, res) backtrack(choices, state, n, res)
return res[0] return res[0]

View File

@ -6,8 +6,6 @@
package chapter_dynamic_programming package chapter_dynamic_programming
import java.util.*
/* 记忆化搜索 */ /* 记忆化搜索 */
fun dfs(i: Int, mem: IntArray): Int { fun dfs(i: Int, mem: IntArray): Int {
// 已知 dp[1] 和 dp[2] ,返回之 // 已知 dp[1] 和 dp[2] ,返回之
@ -25,7 +23,7 @@ fun dfs(i: Int, mem: IntArray): Int {
fun climbingStairsDFSMem(n: Int): Int { fun climbingStairsDFSMem(n: Int): Int {
// mem[i] 记录爬到第 i 阶的方案总数,-1 代表无记录 // mem[i] 记录爬到第 i 阶的方案总数,-1 代表无记录
val mem = IntArray(n + 1) val mem = IntArray(n + 1)
Arrays.fill(mem, -1) mem.fill(-1)
return dfs(n, mem) return dfs(n, mem)
} }
@ -33,6 +31,6 @@ fun climbingStairsDFSMem(n: Int): Int {
fun main() { fun main() {
val n = 9 val n = 9
val res: Int = climbingStairsDFSMem(n) val res = climbingStairsDFSMem(n)
println("$n 阶楼梯共有 $res 种方案") println("$n 阶楼梯共有 $res 种方案")
} }

View File

@ -27,9 +27,7 @@ fun climbingStairsDPComp(n: Int): Int {
var a = 1 var a = 1
var b = 2 var b = 2
for (i in 3..n) { for (i in 3..n) {
val tmp = b b += a.also { a = b }
b += a
a = tmp
} }
return b return b
} }

View File

@ -6,7 +6,6 @@
package chapter_dynamic_programming package chapter_dynamic_programming
import java.util.*
import kotlin.math.min import kotlin.math.min
/* 零钱兑换:动态规划 */ /* 零钱兑换:动态规划 */
@ -27,8 +26,7 @@ fun coinChangeDP(coins: IntArray, amt: Int): Int {
dp[i][a] = dp[i - 1][a] dp[i][a] = dp[i - 1][a]
} else { } else {
// 不选和选硬币 i 这两种方案的较小值 // 不选和选硬币 i 这两种方案的较小值
dp[i][a] = min(dp[i - 1][a].toDouble(), (dp[i][a - coins[i - 1]] + 1).toDouble()) dp[i][a] = min(dp[i - 1][a], dp[i][a - coins[i - 1]] + 1)
.toInt()
} }
} }
} }
@ -41,7 +39,7 @@ fun coinChangeDPComp(coins: IntArray, amt: Int): Int {
val MAX = amt + 1 val MAX = amt + 1
// 初始化 dp 表 // 初始化 dp 表
val dp = IntArray(amt + 1) val dp = IntArray(amt + 1)
Arrays.fill(dp, MAX) dp.fill(MAX)
dp[0] = 0 dp[0] = 0
// 状态转移 // 状态转移
for (i in 1..n) { for (i in 1..n) {
@ -51,7 +49,7 @@ fun coinChangeDPComp(coins: IntArray, amt: Int): Int {
dp[a] = dp[a] dp[a] = dp[a]
} else { } else {
// 不选和选硬币 i 这两种方案的较小值 // 不选和选硬币 i 这两种方案的较小值
dp[a] = min(dp[a].toDouble(), (dp[a - coins[i - 1]] + 1).toDouble()).toInt() dp[a] = min(dp[a], dp[a - coins[i - 1]] + 1)
} }
} }
} }
@ -70,4 +68,4 @@ fun main() {
// 空间优化后的动态规划 // 空间优化后的动态规划
res = coinChangeDPComp(coins, amt) res = coinChangeDPComp(coins, amt)
println("凑到目标金额所需的最少硬币数量为 $res") println("凑到目标金额所需的最少硬币数量为 $res")
} }

View File

@ -6,7 +6,6 @@
package chapter_dynamic_programming package chapter_dynamic_programming
import java.util.*
import kotlin.math.min import kotlin.math.min
/* 编辑距离:暴力搜索 */ /* 编辑距离:暴力搜索 */
@ -29,7 +28,7 @@ fun editDistanceDFS(
val delete = editDistanceDFS(s, t, i - 1, j) val delete = editDistanceDFS(s, t, i - 1, j)
val replace = editDistanceDFS(s, t, i - 1, j - 1) val replace = editDistanceDFS(s, t, i - 1, j - 1)
// 返回最少编辑步数 // 返回最少编辑步数
return (min(min(insert.toDouble(), delete.toDouble()), replace.toDouble()) + 1).toInt() return min(min(insert, delete), replace) + 1
} }
/* 编辑距离:记忆化搜索 */ /* 编辑距离:记忆化搜索 */
@ -55,7 +54,7 @@ fun editDistanceDFSMem(
val delete = editDistanceDFSMem(s, t, mem, i - 1, j) val delete = editDistanceDFSMem(s, t, mem, i - 1, j)
val replace = editDistanceDFSMem(s, t, mem, i - 1, j - 1) val replace = editDistanceDFSMem(s, t, mem, i - 1, j - 1)
// 记录并返回最少编辑步数 // 记录并返回最少编辑步数
mem[i][j] = (min(min(insert.toDouble(), delete.toDouble()), replace.toDouble()) + 1).toInt() mem[i][j] = min(min(insert, delete), replace) + 1
return mem[i][j] return mem[i][j]
} }
@ -79,11 +78,7 @@ fun editDistanceDP(s: String, t: String): Int {
dp[i][j] = dp[i - 1][j - 1] dp[i][j] = dp[i - 1][j - 1]
} else { } else {
// 最少编辑步数 = 插入、删除、替换这三种操作的最少编辑步数 + 1 // 最少编辑步数 = 插入、删除、替换这三种操作的最少编辑步数 + 1
dp[i][j] = dp[i][j] = min(min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1
(min(
min(dp[i][j - 1].toDouble(), dp[i - 1][j].toDouble()),
dp[i - 1][j - 1].toDouble()
) + 1).toInt()
} }
} }
} }
@ -112,7 +107,7 @@ fun editDistanceDPComp(s: String, t: String): Int {
dp[j] = leftup dp[j] = leftup
} else { } else {
// 最少编辑步数 = 插入、删除、替换这三种操作的最少编辑步数 + 1 // 最少编辑步数 = 插入、删除、替换这三种操作的最少编辑步数 + 1
dp[j] = (min(min(dp[j - 1].toDouble(), dp[j].toDouble()), leftup.toDouble()) + 1).toInt() dp[j] = min(min(dp[j - 1], dp[j]), leftup) + 1
} }
leftup = temp // 更新为下一轮的 dp[i-1, j-1] leftup = temp // 更新为下一轮的 dp[i-1, j-1]
} }
@ -133,7 +128,8 @@ fun main() {
// 记忆化搜索 // 记忆化搜索
val mem = Array(n + 1) { IntArray(m + 1) } val mem = Array(n + 1) { IntArray(m + 1) }
for (row in mem) Arrays.fill(row, -1) for (row in mem)
row.fill(-1)
res = editDistanceDFSMem(s, t, mem, n, m) res = editDistanceDFSMem(s, t, mem, n, m)
println("$s 更改为 $t 最少需要编辑 $res") println("$s 更改为 $t 最少需要编辑 $res")

View File

@ -6,7 +6,6 @@
package chapter_dynamic_programming package chapter_dynamic_programming
import java.util.*
import kotlin.math.max import kotlin.math.max
/* 0-1 背包:暴力搜索 */ /* 0-1 背包:暴力搜索 */
@ -28,7 +27,7 @@ fun knapsackDFS(
val no = knapsackDFS(wgt, value, i - 1, c) val no = knapsackDFS(wgt, value, i - 1, c)
val yes = knapsackDFS(wgt, value, i - 1, c - wgt[i - 1]) + value[i - 1] val yes = knapsackDFS(wgt, value, i - 1, c - wgt[i - 1]) + value[i - 1]
// 返回两种方案中价值更大的那一个 // 返回两种方案中价值更大的那一个
return max(no.toDouble(), yes.toDouble()).toInt() return max(no, yes)
} }
/* 0-1 背包:记忆化搜索 */ /* 0-1 背包:记忆化搜索 */
@ -55,7 +54,7 @@ fun knapsackDFSMem(
val no = knapsackDFSMem(wgt, value, mem, i - 1, c) val no = knapsackDFSMem(wgt, value, mem, i - 1, c)
val yes = knapsackDFSMem(wgt, value, mem, i - 1, c - wgt[i - 1]) + value[i - 1] val yes = knapsackDFSMem(wgt, value, mem, i - 1, c - wgt[i - 1]) + value[i - 1]
// 记录并返回两种方案中价值更大的那一个 // 记录并返回两种方案中价值更大的那一个
mem[i][c] = max(no.toDouble(), yes.toDouble()).toInt() mem[i][c] = max(no, yes)
return mem[i][c] return mem[i][c]
} }
@ -76,8 +75,7 @@ fun knapsackDP(
dp[i][c] = dp[i - 1][c] dp[i][c] = dp[i - 1][c]
} else { } else {
// 不选和选物品 i 这两种方案的较大值 // 不选和选物品 i 这两种方案的较大值
dp[i][c] = max(dp[i - 1][c].toDouble(), (dp[i - 1][c - wgt[i - 1]] + value[i - 1]).toDouble()) dp[i][c] = max(dp[i - 1][c], dp[i - 1][c - wgt[i - 1]] + value[i - 1])
.toInt()
} }
} }
} }
@ -100,7 +98,7 @@ fun knapsackDPComp(
if (wgt[i - 1] <= c) { if (wgt[i - 1] <= c) {
// 不选和选物品 i 这两种方案的较大值 // 不选和选物品 i 这两种方案的较大值
dp[c] = dp[c] =
max(dp[c].toDouble(), (dp[c - wgt[i - 1]] + value[i - 1]).toDouble()).toInt() max(dp[c], dp[c - wgt[i - 1]] + value[i - 1])
} }
} }
} }
@ -121,7 +119,7 @@ fun main() {
// 记忆化搜索 // 记忆化搜索
val mem = Array(n + 1) { IntArray(cap + 1) } val mem = Array(n + 1) { IntArray(cap + 1) }
for (row in mem) { for (row in mem) {
Arrays.fill(row, -1) row.fill(-1)
} }
res = knapsackDFSMem(wgt, value, mem, n, cap) res = knapsackDFSMem(wgt, value, mem, n, cap)
println("不超过背包容量的最大物品价值为 $res") println("不超过背包容量的最大物品价值为 $res")

View File

@ -19,7 +19,7 @@ fun minCostClimbingStairsDP(cost: IntArray): Int {
dp[2] = cost[2] dp[2] = cost[2]
// 状态转移:从较小子问题逐步求解较大子问题 // 状态转移:从较小子问题逐步求解较大子问题
for (i in 3..n) { for (i in 3..n) {
dp[i] = (min(dp[i - 1].toDouble(), dp[i - 2].toDouble()) + cost[i]).toInt() dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]
} }
return dp[n] return dp[n]
} }
@ -32,7 +32,7 @@ fun minCostClimbingStairsDPComp(cost: IntArray): Int {
var b = cost[2] var b = cost[2]
for (i in 3..n) { for (i in 3..n) {
val tmp = b val tmp = b
b = (min(a.toDouble(), tmp.toDouble()) + cost[i]).toInt() b = min(a, tmp) + cost[i]
a = tmp a = tmp
} }
return b return b

View File

@ -6,15 +6,10 @@
package chapter_dynamic_programming package chapter_dynamic_programming
import java.util.*
import kotlin.math.min import kotlin.math.min
/* 最小路径和:暴力搜索 */ /* 最小路径和:暴力搜索 */
fun minPathSumDFS( fun minPathSumDFS(grid: Array<IntArray>, i: Int, j: Int): Int {
grid: Array<Array<Int>>,
i: Int,
j: Int
): Int {
// 若为左上角单元格,则终止搜索 // 若为左上角单元格,则终止搜索
if (i == 0 && j == 0) { if (i == 0 && j == 0) {
return grid[0][0] return grid[0][0]
@ -27,13 +22,13 @@ fun minPathSumDFS(
val up = minPathSumDFS(grid, i - 1, j) val up = minPathSumDFS(grid, i - 1, j)
val left = minPathSumDFS(grid, i, j - 1) val left = minPathSumDFS(grid, i, j - 1)
// 返回从左上角到 (i, j) 的最小路径代价 // 返回从左上角到 (i, j) 的最小路径代价
return (min(left.toDouble(), up.toDouble()) + grid[i][j]).toInt() return min(left, up) + grid[i][j]
} }
/* 最小路径和:记忆化搜索 */ /* 最小路径和:记忆化搜索 */
fun minPathSumDFSMem( fun minPathSumDFSMem(
grid: Array<Array<Int>>, grid: Array<IntArray>,
mem: Array<Array<Int>>, mem: Array<IntArray>,
i: Int, i: Int,
j: Int j: Int
): Int { ): Int {
@ -53,12 +48,12 @@ fun minPathSumDFSMem(
val up = minPathSumDFSMem(grid, mem, i - 1, j) val up = minPathSumDFSMem(grid, mem, i - 1, j)
val left = minPathSumDFSMem(grid, mem, i, j - 1) val left = minPathSumDFSMem(grid, mem, i, j - 1)
// 记录并返回左上角到 (i, j) 的最小路径代价 // 记录并返回左上角到 (i, j) 的最小路径代价
mem[i][j] = (min(left.toDouble(), up.toDouble()) + grid[i][j]).toInt() mem[i][j] = min(left, up) + grid[i][j]
return mem[i][j] return mem[i][j]
} }
/* 最小路径和:动态规划 */ /* 最小路径和:动态规划 */
fun minPathSumDP(grid: Array<Array<Int>>): Int { fun minPathSumDP(grid: Array<IntArray>): Int {
val n = grid.size val n = grid.size
val m = grid[0].size val m = grid[0].size
// 初始化 dp 表 // 初始化 dp 表
@ -75,15 +70,14 @@ fun minPathSumDP(grid: Array<Array<Int>>): Int {
// 状态转移:其余行和列 // 状态转移:其余行和列
for (i in 1..<n) { for (i in 1..<n) {
for (j in 1..<m) { for (j in 1..<m) {
dp[i][j] = dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + grid[i][j]
(min(dp[i][j - 1].toDouble(), dp[i - 1][j].toDouble()) + grid[i][j]).toInt()
} }
} }
return dp[n - 1][m - 1] return dp[n - 1][m - 1]
} }
/* 最小路径和:空间优化后的动态规划 */ /* 最小路径和:空间优化后的动态规划 */
fun minPathSumDPComp(grid: Array<Array<Int>>): Int { fun minPathSumDPComp(grid: Array<IntArray>): Int {
val n = grid.size val n = grid.size
val m = grid[0].size val m = grid[0].size
// 初始化 dp 表 // 初始化 dp 表
@ -99,7 +93,7 @@ fun minPathSumDPComp(grid: Array<Array<Int>>): Int {
dp[0] = dp[0] + grid[i][0] dp[0] = dp[0] + grid[i][0]
// 状态转移:其余列 // 状态转移:其余列
for (j in 1..<m) { for (j in 1..<m) {
dp[j] = (min(dp[j - 1].toDouble(), dp[j].toDouble()) + grid[i][j]).toInt() dp[j] = min(dp[j - 1], dp[j]) + grid[i][j]
} }
} }
return dp[m - 1] return dp[m - 1]
@ -108,10 +102,10 @@ fun minPathSumDPComp(grid: Array<Array<Int>>): Int {
/* Driver Code */ /* Driver Code */
fun main() { fun main() {
val grid = arrayOf( val grid = arrayOf(
arrayOf(1, 3, 1, 5), intArrayOf(1, 3, 1, 5),
arrayOf(2, 2, 4, 2), intArrayOf(2, 2, 4, 2),
arrayOf(5, 3, 2, 1), intArrayOf(5, 3, 2, 1),
arrayOf(4, 3, 5, 2) intArrayOf(4, 3, 5, 2)
) )
val n = grid.size val n = grid.size
val m = grid[0].size val m = grid[0].size
@ -121,9 +115,9 @@ fun main() {
println("从左上角到右下角的最小路径和为 $res") println("从左上角到右下角的最小路径和为 $res")
// 记忆化搜索 // 记忆化搜索
val mem = Array(n) { Array(m) { 0 } } val mem = Array(n) { IntArray(m) }
for (row in mem) { for (row in mem) {
Arrays.fill(row, -1) row.fill(-1)
} }
res = minPathSumDFSMem(grid, mem, n - 1, m - 1) res = minPathSumDFSMem(grid, mem, n - 1, m - 1)
println("从左上角到右下角的最小路径和为 $res") println("从左上角到右下角的最小路径和为 $res")

View File

@ -9,11 +9,7 @@ package chapter_dynamic_programming
import kotlin.math.max import kotlin.math.max
/* 完全背包:动态规划 */ /* 完全背包:动态规划 */
fun unboundedKnapsackDP( fun unboundedKnapsackDP(wgt: IntArray, value: IntArray, cap: Int): Int {
wgt: IntArray,
value: IntArray,
cap: Int
): Int {
val n = wgt.size val n = wgt.size
// 初始化 dp 表 // 初始化 dp 表
val dp = Array(n + 1) { IntArray(cap + 1) } val dp = Array(n + 1) { IntArray(cap + 1) }
@ -25,8 +21,7 @@ fun unboundedKnapsackDP(
dp[i][c] = dp[i - 1][c] dp[i][c] = dp[i - 1][c]
} else { } else {
// 不选和选物品 i 这两种方案的较大值 // 不选和选物品 i 这两种方案的较大值
dp[i][c] = max(dp[i - 1][c].toDouble(), (dp[i][c - wgt[i - 1]] + value[i - 1]).toDouble()) dp[i][c] = max(dp[i - 1][c], dp[i][c - wgt[i - 1]] + value[i - 1])
.toInt()
} }
} }
} }
@ -50,8 +45,7 @@ fun unboundedKnapsackDPComp(
dp[c] = dp[c] dp[c] = dp[c]
} else { } else {
// 不选和选物品 i 这两种方案的较大值 // 不选和选物品 i 这两种方案的较大值
dp[c] = dp[c] = max(dp[c], dp[c - wgt[i - 1]] + value[i - 1])
max(dp[c].toDouble(), (dp[c - wgt[i - 1]] + value[i - 1]).toDouble()).toInt()
} }
} }
} }

View File

@ -11,9 +11,9 @@ import utils.Vertex
/* 基于邻接表实现的无向图类 */ /* 基于邻接表实现的无向图类 */
class GraphAdjList(edges: Array<Array<Vertex?>>) { class GraphAdjList(edges: Array<Array<Vertex?>>) {
// 邻接表key顶点value该顶点的所有邻接顶点 // 邻接表key顶点value该顶点的所有邻接顶点
val adjList: MutableMap<Vertex, MutableList<Vertex>> = HashMap() val adjList = HashMap<Vertex, MutableList<Vertex>>()
/* 构造函数 */ /* 构造方法 */
init { init {
// 添加所有顶点和边 // 添加所有顶点和边
for (edge in edges) { for (edge in edges) {
@ -70,7 +70,7 @@ class GraphAdjList(edges: Array<Array<Vertex?>>) {
fun print() { fun print() {
println("邻接表 =") println("邻接表 =")
for (pair in adjList.entries) { for (pair in adjList.entries) {
val tmp = ArrayList<Int>() val tmp = mutableListOf<Int>()
for (vertex in pair.value) { for (vertex in pair.value) {
tmp.add(vertex.value) tmp.add(vertex.value)
} }
@ -82,7 +82,7 @@ class GraphAdjList(edges: Array<Array<Vertex?>>) {
/* Driver Code */ /* Driver Code */
fun main() { fun main() {
/* 初始化无向图 */ /* 初始化无向图 */
val v: Array<Vertex?> = Vertex.valsToVets(intArrayOf(1, 3, 2, 5, 4)) val v = Vertex.valsToVets(intArrayOf(1, 3, 2, 5, 4))
val edges = arrayOf( val edges = arrayOf(
arrayOf(v[0], v[1]), arrayOf(v[0], v[1]),
arrayOf(v[0], v[3]), arrayOf(v[0], v[3]),

View File

@ -10,10 +10,10 @@ import utils.printMatrix
/* 基于邻接矩阵实现的无向图类 */ /* 基于邻接矩阵实现的无向图类 */
class GraphAdjMat(vertices: IntArray, edges: Array<IntArray>) { class GraphAdjMat(vertices: IntArray, edges: Array<IntArray>) {
val vertices: MutableList<Int> = ArrayList() // 顶点列表,元素代表“顶点值”,索引代表“顶点索引” val vertices = mutableListOf<Int>() // 顶点列表,元素代表“顶点值”,索引代表“顶点索引”
val adjMat: MutableList<MutableList<Int>> = ArrayList() // 邻接矩阵,行列索引对应“顶点索引” val adjMat = mutableListOf<MutableList<Int>>() // 邻接矩阵,行列索引对应“顶点索引”
/* 构造函数 */ /* 构造方法 */
init { init {
// 添加顶点 // 添加顶点
for (vertex in vertices) { for (vertex in vertices) {
@ -37,7 +37,7 @@ class GraphAdjMat(vertices: IntArray, edges: Array<IntArray>) {
// 向顶点列表中添加新顶点的值 // 向顶点列表中添加新顶点的值
vertices.add(value) vertices.add(value)
// 在邻接矩阵中添加一行 // 在邻接矩阵中添加一行
val newRow: MutableList<Int> = mutableListOf() val newRow = mutableListOf<Int>()
for (j in 0..<n) { for (j in 0..<n) {
newRow.add(0) newRow.add(0)
} }
@ -50,7 +50,8 @@ class GraphAdjMat(vertices: IntArray, edges: Array<IntArray>) {
/* 删除顶点 */ /* 删除顶点 */
fun removeVertex(index: Int) { fun removeVertex(index: Int) {
if (index >= size()) throw IndexOutOfBoundsException() if (index >= size())
throw IndexOutOfBoundsException()
// 在顶点列表中移除索引 index 的顶点 // 在顶点列表中移除索引 index 的顶点
vertices.removeAt(index) vertices.removeAt(index)
// 在邻接矩阵中删除索引 index 的行 // 在邻接矩阵中删除索引 index 的行
@ -65,7 +66,8 @@ class GraphAdjMat(vertices: IntArray, edges: Array<IntArray>) {
// 参数 i, j 对应 vertices 元素索引 // 参数 i, j 对应 vertices 元素索引
fun addEdge(i: Int, j: Int) { fun addEdge(i: Int, j: Int) {
// 索引越界与相等处理 // 索引越界与相等处理
if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) throw java.lang.IndexOutOfBoundsException() if (i < 0 || j < 0 || i >= size() || j >= size() || i == j)
throw IndexOutOfBoundsException()
// 在无向图中,邻接矩阵关于主对角线对称,即满足 (i, j) == (j, i) // 在无向图中,邻接矩阵关于主对角线对称,即满足 (i, j) == (j, i)
adjMat[i][j] = 1; adjMat[i][j] = 1;
adjMat[j][i] = 1; adjMat[j][i] = 1;
@ -75,7 +77,8 @@ class GraphAdjMat(vertices: IntArray, edges: Array<IntArray>) {
// 参数 i, j 对应 vertices 元素索引 // 参数 i, j 对应 vertices 元素索引
fun removeEdge(i: Int, j: Int) { fun removeEdge(i: Int, j: Int) {
// 索引越界与相等处理 // 索引越界与相等处理
if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) throw java.lang.IndexOutOfBoundsException() if (i < 0 || j < 0 || i >= size() || j >= size() || i == j)
throw IndexOutOfBoundsException()
adjMat[i][j] = 0; adjMat[i][j] = 0;
adjMat[j][i] = 0; adjMat[j][i] = 0;
} }

View File

@ -11,24 +11,24 @@ import java.util.*
/* 广度优先遍历 */ /* 广度优先遍历 */
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点 // 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
fun graphBFS(graph: GraphAdjList, startVet: Vertex): List<Vertex> { fun graphBFS(graph: GraphAdjList, startVet: Vertex): MutableList<Vertex?> {
// 顶点遍历序列 // 顶点遍历序列
val res: MutableList<Vertex> = ArrayList() val res = mutableListOf<Vertex?>()
// 哈希表,用于记录已被访问过的顶点 // 哈希表,用于记录已被访问过的顶点
val visited: MutableSet<Vertex> = HashSet() val visited = HashSet<Vertex>()
visited.add(startVet) visited.add(startVet)
// 队列用于实现 BFS // 队列用于实现 BFS
val que: Queue<Vertex> = LinkedList() val que = LinkedList<Vertex>()
que.offer(startVet) que.offer(startVet)
// 以顶点 vet 为起点,循环直至访问完所有顶点 // 以顶点 vet 为起点,循环直至访问完所有顶点
while (!que.isEmpty()) { while (!que.isEmpty()) {
val vet = que.poll() // 队首顶点出队 val vet = que.poll() // 队首顶点出队
res.add(vet) // 记录访问顶点 res.add(vet) // 记录访问顶点
// 遍历该顶点的所有邻接顶点 // 遍历该顶点的所有邻接顶点
for (adjVet in graph.adjList[vet]!!) { for (adjVet in graph.adjList[vet]!!) {
if (visited.contains(adjVet)) continue // 跳过已被访问的顶点 if (visited.contains(adjVet))
continue // 跳过已被访问的顶点
que.offer(adjVet) // 只入队未访问的顶点 que.offer(adjVet) // 只入队未访问的顶点
visited.add(adjVet) // 标记该顶点已被访问 visited.add(adjVet) // 标记该顶点已被访问
} }
} }

View File

@ -15,11 +15,12 @@ fun dfs(
res: MutableList<Vertex?>, res: MutableList<Vertex?>,
vet: Vertex? vet: Vertex?
) { ) {
res.add(vet) // 记录访问顶点 res.add(vet) // 记录访问顶点
visited.add(vet) // 标记该顶点已被访问 visited.add(vet) // 标记该顶点已被访问
// 遍历该顶点的所有邻接顶点 // 遍历该顶点的所有邻接顶点
for (adjVet in graph.adjList[vet]!!) { for (adjVet in graph.adjList[vet]!!) {
if (visited.contains(adjVet)) continue // 跳过已被访问的顶点 if (visited.contains(adjVet))
continue // 跳过已被访问的顶点
// 递归访问邻接顶点 // 递归访问邻接顶点
dfs(graph, visited, res, adjVet) dfs(graph, visited, res, adjVet)
} }
@ -27,14 +28,11 @@ fun dfs(
/* 深度优先遍历 */ /* 深度优先遍历 */
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点 // 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
fun graphDFS( fun graphDFS(graph: GraphAdjList, startVet: Vertex?): MutableList<Vertex?> {
graph: GraphAdjList,
startVet: Vertex?
): List<Vertex?> {
// 顶点遍历序列 // 顶点遍历序列
val res: MutableList<Vertex?> = ArrayList() val res = mutableListOf<Vertex?>()
// 哈希表,用于记录已被访问过的顶点 // 哈希表,用于记录已被访问过的顶点
val visited: MutableSet<Vertex?> = HashSet() val visited = HashSet<Vertex?>()
dfs(graph, visited, res, startVet) dfs(graph, visited, res, startVet)
return res return res
} }