【www.gdgbn.com--jquery】
<script>
$(function(){ // ----------------------------------------- // bubble sort // ----------------------------------------- function bubblesort(){ var array = this.values var length = array.length for(var i = length - 1; 0 < i; i--){ for(var j = 0; j < i; j++){ this.compare(j, j + 1) } } } // ----------------------------------------- // selection sort // ----------------------------------------- function selectionsort(){ var array = this.values var length = array.length for(var i = 0; i < length - 1; i++){ var minindex = i var minvalue = array[minindex] for (var j = i + 1; j < length; j++) { this.highlight(j, minindex) if (array[j] < minvalue) { minindex = j minvalue = array[minindex] } } this.compare(i, minindex) } return array } // ----------------------------------------- // shaker sort // ----------------------------------------- function shakersort(){ var array = this.values var length = array.length var left = 0 var right = length - 1 var lastswappedleft = left var lastswappedright = right while(left < right){ lastswappedright = 0 for(var i = left; i < right; i++){ if(array[i] > array[i + 1]){ this.swap(i, i + 1) lastswappedright = i }else{ this.highlight(i, i + 1) } } right = lastswappedright lastswappedleft = length - 1 for(var j = right; left < j; j--){ if(array[j - 1] > array[j]){ this.swap(j - 1, j) lastswappedleft = j }else{ this.highlight(j - 1, j) } } left = lastswappedleft } } // ----------------------------------------- // insertion sort // ----------------------------------------- function insertionsort(){ var array = this.values var length = array.length for(var i = 1; i < length; i++){ for(var j = i; 0 < j; j--){ if(array[j - 1] > array[j]){ this.swap(j - 1, j) }else{ this.highlight(j - 1, j) break } } } } // ----------------------------------------- // shell sort // ----------------------------------------- function shellsort(){ var array = this.values var length = array.length var gap = 1 while(gap < length) { gap = 3 * gap + 1 } while(gap > 1){ gap = math.floor(gap / 3) for(var i = gap; i < length; i++){ for(var j = i; 0 < j; j -= gap){ if(array[j - gap] > array[j]){ this.swap(j - gap, j) }else{ this.highlight(j - gap, j) break } } } } }
// ----------------------------------------- // quick sort // ----------------------------------------- function quicksort(first, last){ // todo: var array = this.values first = (first === undefined) ? 0 : first last = (last === undefined) ? (array.length - 1) : last
var pivotindex = math.floor((first + last) / 2) var pivotvalue = array[pivotindex] var f = first, l = last while(true){ while(true){ this.highlight(f, pivotindex) if(!(array[f] < pivotvalue)) break f++ } while(true){ this.highlight(l, pivotindex) if(!(pivotvalue < array[l])) break l-- } if(l <= f){ break } if(pivotindex === l){ pivotindex = f } if(pivotindex === l){ pivotindex = l } this.compare(f, l) f++; l-- } if(first < f - 1) quicksort.call(this, first, f - 1) if(l + 1 < last) quicksort.call(this, l + 1, last) } // ----------------------------------------- // merge sort // ----------------------------------------- function mergesort(first, last){ var array = this.values first = (first === undefined) ? 0 : first last = (last === undefined) ? array.length - 1 : last if (last - first < 1) { return } var middle = math.floor((first + last) / 2) mergesort.call(this, first, middle) mergesort.call(this, middle + 1, last) var f = first var m = middle while (f <= m && m + 1 <= last) { this.highlight(f, m + 1) if (array[f] >= array[m + 1]) { this.insertbefore(m + 1, f) m++ } f++ } } // ----------------------------------------- // heap sort // ----------------------------------------- function swapup(array, current){ var parent = math.floor((current - 1) / 2) while(current != 0){ if (!(array[current] > array[parent])) { this.highlight(current, parent) break } this.swap(current, parent) current = parent parent = math.floor((current - 1) / 2) } } function swapdown(array, current, length){ var child = current * 2 + 1 while(true){ if(array[child] < array[child + 1]){ child += 1 } if(array[current] >= array[child]){ this.highlight(current, child) break } if(length <= child){ break } this.swap(current, child) current = child child = current * 2 + 1 } } function heapify(array){ for(var i = 0; i < array.length; i++){ swapup.call(this, array, i) } } function heapsort(){ var array = this.values heapify.call(this, array) for(var i = array.length - 1; 0 < i; i--){ if(array[0] > array[i]){ this.swap(0, i) }else{ this.highlight(0, i) } swapdown.call(this, array, 0, i) } } // ----------------------------------------- // bogo sort // ----------------------------------------- function bogosort(){ var array = this.values this.bogosortcompleted = false var length = array.length // shffle for(var i = 0; i < length; i++){ var j = math.floor(math.random() * length) this.swap(i, j) } // check for(var i = 0; i < length - 1; i++){ this.highlight(i, i + 1) if(array[i] > array[i + 1]){ return // incomplete } } this.bogosortcompleted = true } bogosort.name = "bogosort"
// ----------------------------------------- // main // ----------------------------------------- var sort = graphicalsort() // default sort function sort.sortfunc = bubblesort var view = $("#view") view.width($(window).width()).height($(window).height() - 125) sort.show(view) // ----------------------------------------- // sort menu // ----------------------------------------- var sortmenu = { "气泡排序": bubblesort, "直接选择排序": selectionsort, "shaker排序": shakersort, "插入排序": insertionsort, "希尔排序": shellsort, "快速排序": quicksort, "归并排序": mergesort, "堆排序": heapsort, "猴子排序": bogosort } var menu = $("").insertbefore(view).css({ marginbottom: 10, fontsize: 12 }) $.each(sortmenu, function(name, func){ var radio = $("").attr("id", name).appendto(menu) var label = $("").attr("for", name).text(name).appendto(menu) radio.click(function(){ sort.sortfunc = func sort.displaybars() }) if(sort.sortfunc === func){ radio.attr("checked", "true") } }) menu.buttonset() }) </script>
<script type="text/javascript" src="class.js"></script>
<script type="text/javascript"> (function(){ var profile = false //var profile = true
// ----------------------------------------- // utils // ----------------------------------------- jquery.fn.swap = function(b){ b = jquery(b)[0]; var a = this[0]; var temp = a.parentnode.insertbefore(document.createtextnode(""), a); b.parentnode.insertbefore(a, b); temp.parentnode.insertbefore(b, temp); temp.parentnode.removechild(temp); return this; }
array.prototype.insert = function(value, index){ var array = this for(var i = array.length - 1; index <= i; i--){ array[i + 1] = array[i] } array[index] = value }
array.prototype.insertbefore = function(from, to){ this.insert(this[from], to) if(to < from){ from += 1 } this.splice(from, 1) } array.prototype.swap = function(a, b){ var temp = this[a] this[a] = this[b] this[b] = temp }
function range(min, max){ var array = [] while(min < max){ array.push(min) min++ } return array }
function randrange(min, max){ return math.floor(math.random() * (max - min)) + min }
function shuffle(array){ var length = array.length for(var i = 0; i < length; i++){ var j = randrange(0, length) var temp = array[i] array[i] = array[j] array[j] = temp } return array }
window.profile = { nowprofiling: false, start: function(name){ if(profile === false) return if(this.nowprofiling){ console.profileend() } this.nowprofiling = true console.profile(name) }, end: function(){ if(profile === false) return this.nowprofiling = false console.profileend() } }
// ----------------------------------------- // queue class // ----------------------------------------- var queue = class.$extend({ __init__: function(){ this.length = 0 this.i = 0 this.queue = [] }, get: function(){ if(this.length === 0) return undefined this.length-- return this.queue[this.i++] }, put: function(value){ this.queue.push(value) this.length++ } })
// ----------------------------------------- // controller class // ----------------------------------------- controller = class.$extend({ widget: $(""), reset: $.noop, onspeedchange: $.noop, onlengthchange: $.noop, __init__: function(defaults){ this.element = $("") var restart = this._createrestartbutton() var buttonset = this._createlengthbuttonset(defaults.length) var slider = this._createspeedslider(defaults.speed) this.element.append(restart).append(buttonset).append(slider) },
_createrestartbutton: function(){ var self = this var button = $("重新演示").button().click(function(){ self.restart() }) return this.widget.clone().append(button) }, _createspeedslider: function(defaultspeed){ var self = this var amount = $("").text(defaultspeed) var slider = $("") slider.slider({ min: 1, max: 300, value: defaultspeed, slide: function(event, ui){ amount.text(ui.value) self.onspeedchange(ui.value) } })
var sliderwrapper = $("").append(amount).append(slider) return this.widget.clone().text("演示速度: ").append(sliderwrapper) }, _createlengthbuttonset: function(defaultlength){ var self = this var buttonset = this.widget.clone().addclass("length-button") var radioname = "graphical-sort-radio" var _label = $("") var _radio = $("").attr("name", radioname) $.each([5, 10, 30, 50, 100, 200], function(i, length){ var label = _label.clone().text(length + "个排序").attr("for", radioname + length) var radio = _radio.clone().attr("id", radioname + length).val(length) buttonset.append(label).append(radio) }) buttonset.find("input[value=" + defaultlength + "]").attr("checked", "checked") buttonset.buttonset() buttonset.click(function(event, ui){ self.onlengthchange(parseint(event.target.value)) }) return buttonset } }) // ----------------------------------------- // bar class // ----------------------------------------- var bar = class.$extend({ __init__: function(value){ this.value = value }, createelement: function(){ var bar = $("") return bar } })
// ----------------------------------------- // bars class // ----------------------------------------- var bars = class.$extend({ __init__: function(length, container){ this.length = length this.container = container this.bars = [] var values = this.values = shuffle(range(1, length+1)) for(var i = 0; i < length; i++){ this.bars[i] = bar(values[i]) } this.elements = this._createelements() },
swap: function(a, b, command){ var classname = "highlight" var elements = this.container.find("span") elements.removeclass(classname) var bara = elements.eq(a) var barb = elements.eq(b) bara[0].classname = barb[0].classname = classname if(command === c.swap){ barb.swap(bara) } }, insert: function(from, to){ var elements = this.container.find("span").removeclass("highlight") this.container[0].insertbefore(elements.eq(from).addclass("highlight")[0], elements[to]) }, _createelements: function(){ var elements = $() var length = this.length $.each(this.bars, function(){ var bar = this var element = bar.createelement() element.css("width", 100 / length + "%") element.css("height", bar.value / length * 100 + "%") elements = elements.add(element) }) return elements } })
var command = class.$extend({ __classvars__: { highlight: "highlight", swap: "swap", insert: "insert", set: "set" } }) var c = command
// ----------------------------------------- // graphicalsort class // ----------------------------------------- graphicalsort = class.$extend({ length: 30, // default list length speed: 100, // default speed currenttaskid: -1, __init__: function(){}, // graphical api compare: function(a, b){ var command = c.highlight if(this.values[a] > this.values[b]){ this.values.swap(a, b) command = c.swap } this.task.put([a, b, command]) }, // graphical api highlight: function(a, b){ this.task.put([a, b, c.highlight]) }, // graphical api swap: function(a, b){ this.values.swap( a, b) this.task.put([a, b, c.swap]) }, // graphical api insertbefore: function(from, to){ this.values.insertbefore(from, to) this.task.put([from, to, c.insert]) }, show: function(viewelement){ if(this.sortfunc === undefined){ throw error("sort function is undefined") } this.$sort = $("") this.$sort.append(this._createcontroller().element) this.container = $("") this.$sort.append(this.container) viewelement.append(this.$sort) this.displaybars() }, displaybars: function(){ cleartimeout(this.currenttaskid) this.bars = bars(this.length, this.container) this.values = this.bars.values this.container.empty().append(this.bars.elements) this._inittask() profile.start() this._settimeout() }, complete: function(){ this.container.find("span").removeclass("highlight") if(this.sortfunc.name === "bogosort"){ if(this.bogosortcompleted === false){ this._inittask() this._settimeout() return } } profile.end() }, _createcontroller: function(){ this.controller = controller({ speed: this.speed, length: this.length }) return this._seteventtocontroller(this.controller) }, _seteventtocontroller: function(controller){ var self = this controller.onlengthchange = function(length){ self.length = length self.displaybars() } controller.onspeedchange = function(speed){ self.speed = speed } controller.restart = function(){ self.displaybars() } return controller },
_inittask: function(){ this.task = queue() this.sortfunc() }, _next: function(){ var order = this.task.get() if(order === undefined){ this.complete() return } var command = order[2] if(command === c.insert){ this.bars.insert(order[0], order[1]) }else{ this.bars.swap(order[0], order[1], command) }
this._settimeout() }, _settimeout: function(){ var self = this var interval = 2000 / this.speed this.currenttaskid = settimeout(function(){ self._next() }, interval) } })
})()
</script>
本文来源:http://www.gdgbn.com/wangyezhizuo/29853/