diff --git a/sort/bubble-sort-test.mjs b/sort/bubble-sort-test.mjs new file mode 100644 index 0000000..d5c32e1 --- /dev/null +++ b/sort/bubble-sort-test.mjs @@ -0,0 +1,10 @@ +import {generateRandomArray, measureTime} from "../util/index.mjs" +import { bubbleSort, bubbleSort2, bubbleSort3 } from "./bubble-sort.mjs" + + +const arr = generateRandomArray(10000) +const arr2 = generateRandomArray(10000) +const arr3 = generateRandomArray(10000) +measureTime(bubbleSort, arr) +measureTime(bubbleSort2, arr2) +measureTime(bubbleSort3, arr3) diff --git a/sort/bubble-sort.mjs b/sort/bubble-sort.mjs new file mode 100644 index 0000000..810a0ba --- /dev/null +++ b/sort/bubble-sort.mjs @@ -0,0 +1,48 @@ +import {swap} from "../util/index.mjs" + +export function bubbleSort(arr) { + let n = arr.length + for (let i = 1;i < n; i++) { // 理解为何i从1开始,因为冒泡排序是两两比较的,此循环只是限制比较的次数 + for(let j = 0;j < n-i;j++) { // 此循环才是排序的关键,当当前值大于后一个值时交换位置,没做完一遍最后一个值永远是本轮循环最大的 + if (arr[j] > arr[j+1]){ + swap(arr, j, j+1) + } + } + } +} + +// 优化方案1 +export function bubbleSort2(arr) { + let n = arr.length; + for (let i = 1;i arr[j+1]) { + swap(arr, j, j+1) + hasSort = false // 交换元素之后,设置标志位为无序状态 + } + } + if (hasSort == true) { + break + } + } +} + +// 优化方案2 +export function bubbleSort3(arr) { + let n = arr.length, k = n-1, swapPos = 0; + for (let i = 1;i arr[j+1]) { + swap(arr, j, j+1) + hasSort = false // 交换元素之后,设置标志位为无序状态 + swapPos = j // 记录最后一次交换的元素的位置 + } + } + if (hasSort == true) { + break + } + k = swapPos // 把最后一次交换的位置给k,之后的排序支队1 - n-k的元素进行比较,因为之后的元素都是有序的 + } +} diff --git a/sort/sort.md b/sort/sort.md new file mode 100644 index 0000000..0e4e20c --- /dev/null +++ b/sort/sort.md @@ -0,0 +1,2 @@ +#排序算法 +##冒泡排序 \ No newline at end of file diff --git a/util/index.mjs b/util/index.mjs new file mode 100644 index 0000000..861ae76 --- /dev/null +++ b/util/index.mjs @@ -0,0 +1,74 @@ +/** + * + * @param {number[]} array - 要操作的数组 + * @param {number} a - 要操作的下标 + * @param {number} b - 要操作的下标 + * @description 交换数组中两个数的位置 + */ +export function swap(array, a, b) { + let temp = array[a] + array[a] = array[b] + array[b] = temp +} + +/** + * @param {Array} array - 待操作的数组 + * @returns {number[]} - 打乱后的数组 + * @description 打乱数组内容 + */ + function shuffle(arr) { + // 创建数组的副本,以防止修改原始数组 + const shuffledArray = arr.slice(); + + // Fisher-Yates 洗牌算法 + for (let i = shuffledArray.length - 1; i > 0; i--) { + const a =Math.random() * (i + 1) + console.log(a); + const j = Math.floor(a); + // 交换元素 + [shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]]; + } + + return shuffledArray; +} + +/** + * @description 生成指定长度的随机数组。 + * + * @param {number} len - 数组的长度。 + * @param {boolean} decimal - 是否生成包含小数的随机数,默认为 true。 + * @param {number} decimals - 保留的小数位数,默认为 2。 + * @returns {number[]} - 生成的随机数组。 + */ + export function generateRandomArray(len, decimal = false, decimals = 2) { + const randomArray = []; + + for (let i = 0; i < len; i++) { + const randomNumber = decimal + ? parseFloat((Math.random() * 10000).toFixed(decimals)) + : Math.floor(Math.random() * 10000); + + randomArray.push(randomNumber); + } + + return randomArray; + } + + export function measureTime(func, ...args) { + // 记录函数开始执行的时间戳 + const startTime = performance.now(); + + // 执行传入的函数,使用 apply 或 call 传入参数 + func(...args); + + // 计算函数执行所花费的时间 + const endTime = performance.now(); + const elapsedTime = endTime - startTime; + + // 打印执行时间 + console.log(`Function execution time: ${elapsedTime} milliseconds`); + } + + + +