From 8f4d77af6dc0aeb37d4f71d03b1f354f3dae6a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E5=B0=8F=E5=A2=A8?= <2291200076@qq.com> Date: Wed, 18 May 2022 21:28:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8F=92=E5=85=A5=E6=8E=92?= =?UTF-8?q?=E5=BA=8F=E7=AE=97=E6=B3=95=EF=BC=9B=E6=B7=BB=E5=8A=A0=E5=BC=B9?= =?UTF-8?q?=E5=87=BA=E5=BC=B9=E5=9B=9E=E5=8A=A8=E7=94=BB=EF=BC=9B=E5=8A=A8?= =?UTF-8?q?=E7=94=BB=E5=8F=82=E6=95=B0=E6=94=BE=E5=85=A5=E5=85=A8=E5=B1=80?= =?UTF-8?q?settings=E5=8F=98=E9=87=8F=E4=B8=AD=EF=BC=9B=E6=B7=BB=E5=8A=A0d?= =?UTF-8?q?ebugMode=E5=85=A8=E5=B1=80=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/js/algorithm/sort.js | 62 ++++++++++++++++ src/assets/js/algorithm/test.js | 3 +- src/assets/js/class.js | 125 ++++++++++++++++++++++++++------ src/assets/js/index.js | 11 ++- 4 files changed, 176 insertions(+), 25 deletions(-) diff --git a/src/assets/js/algorithm/sort.js b/src/assets/js/algorithm/sort.js index d31a423..2be0226 100644 --- a/src/assets/js/algorithm/sort.js +++ b/src/assets/js/algorithm/sort.js @@ -10,6 +10,7 @@ function getSortClassList() { QuickSort, BubbleSort, SelectionSort, + InsertionSort ] } @@ -267,3 +268,64 @@ class SelectionSort extends Sort { return array } } + + + +/** + * 插入排序算法 Insertion Sort v0.1.0 + * + * @author coder-xiaomo + * @date 2022-05-18 + */ +class InsertionSort extends Sort { + + info() { + return { + name: "插入排序算法" + } + } + + /* + 将第一个元素标记为已排序 + 对于每一个未排序的元素 X + “提取” 元素 X + i = 最后排序过元素的索引 到 0 的遍历 + 如果当前元素 j > X + 将排序过的元素向右移一格 + 跳出循环并在此插入 X + */ + sort(array) { + if (array.length == 0) + return array + console.log(array) + for (let i = 1; i < array.length; i++) { + let X = array[i] + let j = i - 1 + while (array[j] >= 0 && array[j] > X) { + array[j + 1] = array[j] + j-- + } + array[j + 1] = X + } + return array + } + + sortWithAnimation(customAttr, array) { + if (array.length == 0) + return array + console.log(array) + for (let i = 1; i < array.length; i++) { + let X = array[i] + animation.popupLinkedListItems(customAttr.id, i, {}) + let j = i - 1 + while (array[j] >= 0 && array[j] > X) { + array[j + 1] = array[j] + animation.exchangeLinkedListItems(customAttr.id, j + 1, j) + j-- + } + array[j + 1] = X + animation.popupLinkedListItems(customAttr.id, j + 1, { popBack: true }) + } + return array + } +} diff --git a/src/assets/js/algorithm/test.js b/src/assets/js/algorithm/test.js index ddf1968..fff7d0e 100644 --- a/src/assets/js/algorithm/test.js +++ b/src/assets/js/algorithm/test.js @@ -40,6 +40,7 @@ var sortAlgorithm = { quicksort: new QuickSort(animation), bubblesort: new BubbleSort(animation), selectionSort: new SelectionSort(animation), + insertionSort: new InsertionSort(animation), } // 遍历每一种算法 @@ -51,7 +52,7 @@ Object.values(sortAlgorithm).forEach(sortAlgo => { var input = JSON.parse(JSON.stringify(element)) // 进行排序 var result = sortAlgo.sort(input) - console.log(input, result) + console.log("before", element, "after", result) // 与结果进行对比,判断是否正确 if (data.indexOf(element) > -1) { var rightSortResult = check[data.indexOf(element)]; diff --git a/src/assets/js/class.js b/src/assets/js/class.js index a7166a6..78a474e 100644 --- a/src/assets/js/class.js +++ b/src/assets/js/class.js @@ -162,7 +162,7 @@ class Shape { type: "linkedList", oneUnit: oneUnit, gsapTimeline: gsap.timeline({ - onStart:function(){ + onStart: function () { consoleClear() }, onComplete: function () { @@ -202,6 +202,16 @@ class Shape { .attr("height", oneUnit) .attr("fill", settings.colorMap["text"]) + // 调试用 + if (settings.debugMode) + _g.append("svg:text") + .text(i) + .attr("x", i * oneUnit) + .attr("y", oneUnit) + .attr("width", oneUnit) + .attr("height", oneUnit) + .attr("fill", "black") + // console.log(text.node().getBBox()) // console.log(text.node().getBoundingClientRect()) } @@ -272,17 +282,12 @@ class VectorAnimation { var deltaX = customAttr.oneUnit * (fromIndex - toIndex); var deltaY = customAttr.oneUnit * 1.08 - var animateSettings = { - duration: 0.2, - ease: "sine.inOut", - delay: 0, - yoyo: true, - } + var animateSettings = this.workSpace.settings.animation.getConf() // 如果是相邻的两个元素交换,或者要交换的两个元素是同一个元素 if (Math.abs(fromIndex - toIndex) <= 1) { deltaY /= 2 - animateSettings.duration = 0.25 + animateSettings.duration *= 0.6 } var that = this @@ -333,13 +338,6 @@ class VectorAnimation { customAttr.gsapTimeline.add(timeline) } - // 比较数组元素 - compareLinkedListItems(id, index1, index2) { - this.highlightLinkedListItems(id, [index1, index2], function () { - consoleLog(`比较索引为 ${index1} 和 ${index2} 的两个元素`) - }) - } - // 高亮数组元素 highlightLinkedListItems(id, indexList, onStartCallback) { let linkedList = document.getElementById(id) @@ -356,12 +354,7 @@ class VectorAnimation { hightlightElementList_fill.push(gList[index].childNodes[0]) hightlightElementList_text.push(gList[index].childNodes[1]) } - var animateSettings = { - duration: 0.2, - ease: "sine.inOut", - delay: 0, - yoyo: true, - } + var animateSettings = this.workSpace.settings.animation.getConf() let timeline = gsap.timeline({ onStart: function () { @@ -371,7 +364,7 @@ class VectorAnimation { onStartCallback() }, onComplete: function () { - console.log("hightlight done") + console.log("animation done (hightlight)") } }).add([ gsap.to(hightlightElementList_fill, { ...animateSettings, fill: settings.colorMap["fill_focus"] }), @@ -383,4 +376,92 @@ class VectorAnimation { customAttr.gsapTimeline.add(timeline) } + + // 比较数组元素 + compareLinkedListItems(id, index1, index2) { + this.highlightLinkedListItems(id, [index1, index2], function () { + consoleLog(`比较索引为 ${index1} 和 ${index2} 的两个元素`) + }) + } + + // 弹出/弹回 数组元素 + popupLinkedListItems(id, index, { popBack = false }) { + let linkedList = document.getElementById(id) + let customAttr = linkedList.customAttr + var gList = linkedList.childNodes + + var deltaY = customAttr.oneUnit * 1.08 + if (popBack) deltaY = 0 + + let timeline = gsap.timeline({ + onStart: function () { + if (typeof (onStartCallback) === "function") + onStartCallback() + }, + onComplete: function () { + console.log("animation done (popup)") + } + }).add([ + gsap.to(gList[index], { ...this.workSpace.settings.animation.getConf(), y: deltaY }), + ]) + + customAttr.gsapTimeline.add(timeline) + } + + // 交换相邻数组元素位置(仅在水平方向呼唤,垂直方向不做调整) 【fromIndex 是y方向上突出的元素】 + exchangeLinkedListItems(id, fromIndex, toIndex) { + if (fromIndex < toIndex) + [fromIndex, toIndex] = [toIndex, fromIndex] + + var settings = this.workSpace.settings + let linkedList = document.getElementById(id) + let customAttr = linkedList.customAttr + // console.log(customAttr) + + var gList = linkedList.childNodes + + let from = gList[fromIndex] + let to = gList[toIndex] + + var deltaX = customAttr.oneUnit * (fromIndex - toIndex); + + var deltaY = customAttr.oneUnit * 1.08 // 要跟 popupLinkedListItems 函数中的 deltaY 完全一致 + var animateSettings = settings.animation.getConf() + + var that = this + let timeline = gsap.timeline({ + onStart: function () { + displayCurrentArray(customAttr.nodes) + + consoleLog(`交换索引为 ${fromIndex} 和 ${toIndex} 的两个元素`) + }, + onComplete: function () { + // 交换DOM元素中的值 + that.swapElementInnerHTML(from.childNodes[1], to.childNodes[1]) + + // 交换 node 列表中的值 + // console.log(customAttr.nodes) + let tmp = customAttr.nodes[fromIndex] + customAttr.nodes[fromIndex] = customAttr.nodes[toIndex] + customAttr.nodes[toIndex] = tmp + + // console.log(customAttr.nodes) + displayCurrentArray(customAttr.nodes) + + console.log("animation done (exchange)") + } + }).add([ + gsap.to(from.childNodes, { ...animateSettings, x: -deltaX }), + gsap.to(to.childNodes, { ...animateSettings, x: deltaX }), + ]).add([ + // 恢复到动画之前的状态 + gsap.to(from.childNodes, { ...animateSettings, duration: 0, x: 0 }), + gsap.to(to.childNodes, { ...animateSettings, duration: 0, x: 0 }), + // 由于两个元素一个突出,一个不突出,所以还要交换两个y + gsap.to(from, { ...animateSettings, duration: 0, y: 0 }), + gsap.to(to, { ...animateSettings, duration: 0, y: deltaY }), + ]) + + customAttr.gsapTimeline.add(timeline) + } } \ No newline at end of file diff --git a/src/assets/js/index.js b/src/assets/js/index.js index 37761ef..282f088 100644 --- a/src/assets/js/index.js +++ b/src/assets/js/index.js @@ -2,6 +2,7 @@ // 全局变量 var settings = { container: d3.select("#container"), + debugMode: false, outerSize: { // 不带单位 width: 800, height: 600 @@ -35,8 +36,14 @@ var settings = { "green": "#0f0", }, animation: { - duration: 2000, // 不带单位,单位是毫秒 - easing: "ease-in-out" + getConf: function () { // gsap动画传入默认设置 + return { + duration: 0.3, // 单位是秒 + ease: "sine.inOut", + delay: 0, + yoyo: true, + } + } }, console: { maxLine: 30,