mirror of
https://gitee.com/coder-xiaomo/algorithm-visualization
synced 2025-01-25 19:00:29 +08:00
添加插入排序算法;添加弹出弹回动画;动画参数放入全局settings变量中;添加debugMode全局变量
This commit is contained in:
parent
4e7a355e93
commit
8f4d77af6d
@ -10,6 +10,7 @@ function getSortClassList() {
|
|||||||
QuickSort,
|
QuickSort,
|
||||||
BubbleSort,
|
BubbleSort,
|
||||||
SelectionSort,
|
SelectionSort,
|
||||||
|
InsertionSort
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,3 +268,64 @@ class SelectionSort extends Sort {
|
|||||||
return array
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -40,6 +40,7 @@ var sortAlgorithm = {
|
|||||||
quicksort: new QuickSort(animation),
|
quicksort: new QuickSort(animation),
|
||||||
bubblesort: new BubbleSort(animation),
|
bubblesort: new BubbleSort(animation),
|
||||||
selectionSort: new SelectionSort(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 input = JSON.parse(JSON.stringify(element))
|
||||||
// 进行排序
|
// 进行排序
|
||||||
var result = sortAlgo.sort(input)
|
var result = sortAlgo.sort(input)
|
||||||
console.log(input, result)
|
console.log("before", element, "after", result)
|
||||||
// 与结果进行对比,判断是否正确
|
// 与结果进行对比,判断是否正确
|
||||||
if (data.indexOf(element) > -1) {
|
if (data.indexOf(element) > -1) {
|
||||||
var rightSortResult = check[data.indexOf(element)];
|
var rightSortResult = check[data.indexOf(element)];
|
||||||
|
@ -162,7 +162,7 @@ class Shape {
|
|||||||
type: "linkedList",
|
type: "linkedList",
|
||||||
oneUnit: oneUnit,
|
oneUnit: oneUnit,
|
||||||
gsapTimeline: gsap.timeline({
|
gsapTimeline: gsap.timeline({
|
||||||
onStart:function(){
|
onStart: function () {
|
||||||
consoleClear()
|
consoleClear()
|
||||||
},
|
},
|
||||||
onComplete: function () {
|
onComplete: function () {
|
||||||
@ -202,6 +202,16 @@ class Shape {
|
|||||||
.attr("height", oneUnit)
|
.attr("height", oneUnit)
|
||||||
.attr("fill", settings.colorMap["text"])
|
.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().getBBox())
|
||||||
// console.log(text.node().getBoundingClientRect())
|
// console.log(text.node().getBoundingClientRect())
|
||||||
}
|
}
|
||||||
@ -272,17 +282,12 @@ class VectorAnimation {
|
|||||||
var deltaX = customAttr.oneUnit * (fromIndex - toIndex);
|
var deltaX = customAttr.oneUnit * (fromIndex - toIndex);
|
||||||
var deltaY = customAttr.oneUnit * 1.08
|
var deltaY = customAttr.oneUnit * 1.08
|
||||||
|
|
||||||
var animateSettings = {
|
var animateSettings = this.workSpace.settings.animation.getConf()
|
||||||
duration: 0.2,
|
|
||||||
ease: "sine.inOut",
|
|
||||||
delay: 0,
|
|
||||||
yoyo: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果是相邻的两个元素交换,或者要交换的两个元素是同一个元素
|
// 如果是相邻的两个元素交换,或者要交换的两个元素是同一个元素
|
||||||
if (Math.abs(fromIndex - toIndex) <= 1) {
|
if (Math.abs(fromIndex - toIndex) <= 1) {
|
||||||
deltaY /= 2
|
deltaY /= 2
|
||||||
animateSettings.duration = 0.25
|
animateSettings.duration *= 0.6
|
||||||
}
|
}
|
||||||
|
|
||||||
var that = this
|
var that = this
|
||||||
@ -333,13 +338,6 @@ class VectorAnimation {
|
|||||||
customAttr.gsapTimeline.add(timeline)
|
customAttr.gsapTimeline.add(timeline)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 比较数组元素
|
|
||||||
compareLinkedListItems(id, index1, index2) {
|
|
||||||
this.highlightLinkedListItems(id, [index1, index2], function () {
|
|
||||||
consoleLog(`比较索引为 ${index1} 和 ${index2} 的两个元素`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 高亮数组元素
|
// 高亮数组元素
|
||||||
highlightLinkedListItems(id, indexList, onStartCallback) {
|
highlightLinkedListItems(id, indexList, onStartCallback) {
|
||||||
let linkedList = document.getElementById(id)
|
let linkedList = document.getElementById(id)
|
||||||
@ -356,12 +354,7 @@ class VectorAnimation {
|
|||||||
hightlightElementList_fill.push(gList[index].childNodes[0])
|
hightlightElementList_fill.push(gList[index].childNodes[0])
|
||||||
hightlightElementList_text.push(gList[index].childNodes[1])
|
hightlightElementList_text.push(gList[index].childNodes[1])
|
||||||
}
|
}
|
||||||
var animateSettings = {
|
var animateSettings = this.workSpace.settings.animation.getConf()
|
||||||
duration: 0.2,
|
|
||||||
ease: "sine.inOut",
|
|
||||||
delay: 0,
|
|
||||||
yoyo: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
let timeline = gsap.timeline({
|
let timeline = gsap.timeline({
|
||||||
onStart: function () {
|
onStart: function () {
|
||||||
@ -371,7 +364,7 @@ class VectorAnimation {
|
|||||||
onStartCallback()
|
onStartCallback()
|
||||||
},
|
},
|
||||||
onComplete: function () {
|
onComplete: function () {
|
||||||
console.log("hightlight done")
|
console.log("animation done (hightlight)")
|
||||||
}
|
}
|
||||||
}).add([
|
}).add([
|
||||||
gsap.to(hightlightElementList_fill, { ...animateSettings, fill: settings.colorMap["fill_focus"] }),
|
gsap.to(hightlightElementList_fill, { ...animateSettings, fill: settings.colorMap["fill_focus"] }),
|
||||||
@ -383,4 +376,92 @@ class VectorAnimation {
|
|||||||
|
|
||||||
customAttr.gsapTimeline.add(timeline)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@
|
|||||||
// 全局变量
|
// 全局变量
|
||||||
var settings = {
|
var settings = {
|
||||||
container: d3.select("#container"),
|
container: d3.select("#container"),
|
||||||
|
debugMode: false,
|
||||||
outerSize: { // 不带单位
|
outerSize: { // 不带单位
|
||||||
width: 800,
|
width: 800,
|
||||||
height: 600
|
height: 600
|
||||||
@ -35,8 +36,14 @@ var settings = {
|
|||||||
"green": "#0f0",
|
"green": "#0f0",
|
||||||
},
|
},
|
||||||
animation: {
|
animation: {
|
||||||
duration: 2000, // 不带单位,单位是毫秒
|
getConf: function () { // gsap动画传入默认设置
|
||||||
easing: "ease-in-out"
|
return {
|
||||||
|
duration: 0.3, // 单位是秒
|
||||||
|
ease: "sine.inOut",
|
||||||
|
delay: 0,
|
||||||
|
yoyo: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
console: {
|
console: {
|
||||||
maxLine: 30,
|
maxLine: 30,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user