diff --git a/codes/dart/chapter_searching/binary_search_edge.dart b/codes/dart/chapter_searching/binary_search_edge.dart new file mode 100644 index 000000000..4b2481315 --- /dev/null +++ b/codes/dart/chapter_searching/binary_search_edge.dart @@ -0,0 +1,50 @@ +/** + * File: binary_search_edge.dart + * Created Time: 2023-06-01 + * Author: liuyuxin (gvenusleo@gmail.com) + */ + +/* 二分查找最左一个元素 */ +int binarySearchLeftEdge(List nums, int target) { + int i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1] + while (i <= j) { + int m = i + (j - i) ~/ 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; +} + +/* 二分查找最右一个元素 */ +int binarySearchRightEdge(List nums, int target) { + int i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1] + while (i <= j) { + int m = i + (j - i) ~/ 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 < 0 || nums[j] != target) return -1; // 未找到目标元素,返回 -1 + return j; +} + +/* Driver Code */ +void main() { + int target = 6; + List nums = [1, 3, 6, 6, 6, 6, 6, 10, 12, 15]; + + // 二分查找最左一个元素 + int indexLeft = binarySearchLeftEdge(nums, target); + print("数组中最左一个元素 6 的索引 = $indexLeft"); + // 二分查找最右一个元素 + int indexRight = binarySearchRightEdge(nums, target); + print("数组中最右一个元素 6 的索引 = $indexRight"); +} diff --git a/codes/dart/chapter_sorting/heap_sort.dart b/codes/dart/chapter_sorting/heap_sort.dart new file mode 100644 index 000000000..0eef5d081 --- /dev/null +++ b/codes/dart/chapter_sorting/heap_sort.dart @@ -0,0 +1,49 @@ +/** + * File: heap_sort.dart + * Created Time: 2023-06-01 + * Author: liuyuxin (gvenusleo@gmail.com) + */ + +/* 堆的长度为 n ,从节点 i 开始,从顶至底堆化 */ +void siftDown(List nums, int n, int i) { + while (true) { + // 判断节点 i, l, r 中值最大的节点,记为 ma + int l = 2 * i + 1; + int r = 2 * i + 2; + int 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; + // 交换两节点 + int temp = nums[i]; + nums[i] = nums[ma]; + nums[ma] = temp; + // 循环向下堆化 + i = ma; + } +} + +/* 堆排序 */ +void heapSort(List nums) { + // 建堆操作:堆化除叶节点以外的其他所有节点 + for (int i = nums.length ~/ 2 - 1; i >= 0; i--) { + siftDown(nums, nums.length, i); + } + // 从堆中提取最大元素,循环 n-1 轮 + for (int i = nums.length - 1; i > 0; i--) { + // 交换根节点与最右叶节点(即交换首元素与尾元素) + int tmp = nums[0]; + nums[0] = nums[i]; + nums[i] = tmp; + // 以根节点为起点,从顶至底进行堆化 + siftDown(nums, i, 0); + } +} + +/* Driver Code */ +void main() { + List nums = [4, 1, 3, 1, 5, 2]; + heapSort(nums); + print("堆排序完成后 nums = $nums"); +} diff --git a/codes/dart/chapter_sorting/selection_sort.dart b/codes/dart/chapter_sorting/selection_sort.dart new file mode 100644 index 000000000..df939d894 --- /dev/null +++ b/codes/dart/chapter_sorting/selection_sort.dart @@ -0,0 +1,29 @@ +/** + * File: selection_sort.dart + * Created Time: 2023-06-01 + * Author: liuyuxin (gvenusleo@gmail.com) + */ + +/* 选择排序 */ +void selectionSort(List nums) { + int n = nums.length; + // 外循环:未排序区间为 [i, n-1] + for (int i = 0; i < n - 1; i++) { + // 内循环:找到未排序区间内的最小元素 + int k = i; + for (int j = i + 1; j < n; j++) { + if (nums[j] < nums[k]) k = j; // 记录最小元素的索引 + } + // 将该最小元素与未排序区间的首个元素交换 + int temp = nums[i]; + nums[i] = nums[k]; + nums[k] = temp; + } +} + +/* Driver Code */ +void main() { + List nums = [4, 1, 3, 1, 5, 2]; + selectionSort(nums); + print("选择排序完成后 nums = $nums"); +}