复习排序with javascript
最近又翻看了一下数据结构(数据结构学渣)。
以前总是看不懂,连冒泡和选择排序都要纠结半天,后来才慢慢有意识能区分开来。
当真的理解了快速排序之后,才觉得,这是个很赞的排序,很容易理解。
于是简单的,模仿c的做法,实现了javascript上的排序,目前只有冒泡、选择和快速排序。//不过貌似快速排序用到了传递的性质,也许我应该改改。
function bubbleSort(arr){
console.log("冒泡排序:");
var len = arr.length;
for(var i=0; i<len-1;i++){
for(var j=0; j<len-i-1; j++){
if(arr[j]>arr[j+1]){
var temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
function chooseSort(arr){
console.log("选择排序:");
var len = arr.length;
for(var i=0; i<len-1;i++){
for(var j=i+1; j<len; j++){
if(arr[i]>arr[j]){
var temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
return arr;
}
function quickSort(arr, left, right){
if(undefined===left){
console.log("快速排序改实参版:");
left=0;
}
if(undefined===right){
right = arr.length-1;
}
if(left>right){
return;
}
//移动左右索引变量
var i = left;
var j = right;
var midKey = arr[left];
while(i<j){
while(i<j&&midKey<=arr[j]){
j--;
}
while(i<j&&midKey>=arr[i]){
i++;
}
if(i<j){
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
//交换中间数与中轴数
arr[left] = arr[i];
arr[i] = midKey;
//递归左右,分治思想
quickSort(arr, left, i-1);
quickSort(arr, i+1, right);
return arr;
}
function quickSortArr(arr){
if(arr.length==1){
return arr;
}
if(arr.length==0){
return [];
}
var left = [],
right = [];
var povit = arr[0];
for(var i=1;i<arr.length;i++){
if(arr[i]<=povit){
left.push(arr[i]);
}else{
right.push(arr[i]);
}
}
var re = quickSortArr(left).concat([povit],quickSortArr(right));
return re;
}
function timeIt(fn, arr){
var start = new Date().getTime();
arr = fn(arr);
var end = new Date().getTime();
console.log("cost(ms):" +(end-start)+" result:"+arr[0]+ " " + arr[1] +" "+arr[2]+"..."+arr[arr.length-1]);
}
function callArraySort(arr){
console.log("Array内置排序:");
//console.log(arr[0]);
return Array.prototype.sort.call(arr, compareByArray);
//console.log(b[0]);
//console.log(b.length);
}
function compareByArray(a,b){
var i = parseInt(a);
var j = parseInt(b);
return i-j;
} function heapSort(arr){
function maxHeapify(arr, index, len){
var left = getLeft(index);
var right = getRight(index);
var largest;
if(left<len&&arr[left]>arr[index]){
largest = left;
}else{
largest = index;
}
if(right<len&&arr[right]>arr[largest]){
largest = right;
}
if(largest!=index){
swapElement(arr, largest, index);
maxHeapify(arr, largest, len); // 如果改变了位置,递归改变的子树调整
}
}
function swapElement(arr,index0, index1){
var temp = arr[index0];
arr[index0] = arr[index1];
arr[index1] = temp;
}
function getLeft(eleIndex){
return 2*eleIndex+1;
}
function getRight(eleIndex){
return 2*(eleIndex+1);
}
if(arr.length<=1){
return;
}
var len = arr.length;
for(var i=len/2+1;i>=0;--i){
maxHeapify(arr, i, len);
} for(var i=len-1;i>=1;--i){
swapElement(arr, 0, i);
maxHeapify(arr, 0, --len);
}
return arr;
}
var a = [2,5,3,2,2,8,5,9,4,6,3,1,3,7];
//console.log(bubbleSort(a));
timeIt(bubbleSort, a);
a = [2,5,3,2,2,8,5,9,4,6,3,1,3,7];
timeIt(chooseSort, a);//console.log(chooseSort(a));
a = [2,5,3,2,2,8,5,9,4,6,3,1,3,7];
timeIt(quickSort, a);//console.log(quickSort(a));
a = [2,5,3,2,2,8,5,9,4,6,3,1,3,7];
console.log("快速排序不改原参数版:");
timeIt(quickSortArr, a);
a = [2,5,3,2,2,8,5,9,4,6,3,1,3,7];
timeIt(callArraySort, a);
a = [2,5,3,2,2,8,5,9,4,6,3,1,3,7];
console.log("堆排序:");
timeIt(heapSort, a);
var randArr = [];
for(var i=0;i<10000; i++){
randArr[i] = Math.floor(Math.random()*100000);
}
a = randArr.slice();
timeIt(bubbleSort, a)
a = randArr.slice();
timeIt(chooseSort, a);//console.log(chooseSort(a));
a = randArr.slice();
timeIt(quickSort, a);
a = randArr.slice();
console.log("快速排序不改原参数版:");
timeIt(quickSortArr, a);
a = randArr.slice();
timeIt(callArraySort, a);
a = randArr.slice();
console.log("堆排序:");
timeIt(heapSort, a);
冒泡跟选择以前容易混淆,是因为不明白怎样叫冒泡,实际上,冒泡就是对整个序列,进行一趟前后元素两两比较的形式,大的数后移(或者小的),这样达到一趟实现了把大的数(或者小的数)移到了尾部,那整一个序列看成尾部朝上,往后一趟序列,从头开始一直到倒数第n个数进行两两比较,犹如关键元素(最大值或者最小值)往上冒泡的样子 ,因此叫冒泡。
而选择排序,则是对序列的每个数,从头开始,针对该位置与剩下的数进行比较, 如果有出现大于(小于)该位置的数,则交换位置,这样每一趟下来,就能确定固定位置该放置的数。 //这个解释感觉跟选择没多大关联,姑且当做是选择位置吧。
那么快速排序,就是直接用效率命名了。为什么快呢?看代码实现 ,while里面还有while,还有递归,感觉不快的样子,关于时间复杂度的问题,我还没嚼透。
快排思想是分而治之,既然一个分散的序列,假设通过比较某个值,分别将大于和小于该数的分到一边,就成了两部分,然后同样的道理,各部分再按切分大小方法再细分成两部分……以此推下去,直到变成了最小的部分就是三个数,a<b<c,这个时候各个细小部分组合起来,明显就是一个排序好的序列了。
最后贴一下代码在chrome console运行的结果,快排最后秒杀全场
2014-06-20 更新: 快排加入另一种实现,利用array的api,不过似乎速度不尽如人意,但是做到了不破坏实参数组的效果,而且不过在元素大的时候还是比冒泡选择强:
function quickSortArr(arr){
if(arr.length==1){
return arr;
}
if(arr.length==0){//这两句if实际上可以写成一句的
return [];
}
var left = [],
right = [];
var povit = arr[0];
for(var i=1;i<arr.length;i++){
if(arr[i]<=povit){
left.push(arr[i]);
}else{
right.push(arr[i]);
}
}
var re = quickSortArr(left).concat([povit],quickSortArr(right));
return re;//这里为了调试才加的变量,实际可以不用
}
测试的时候,没留意到不改变原数组的问题,打印出原数组 ,我一度以为是自己写错,囧。好吧,too simple。
又更新,傻了,居然没把Array内置排序也加进去玩玩,不过出现点小插曲,就是sort方法的参数,默认是按元素的编码比较,单位数比较可能没发觉,但是多位数比较就会发现,不设置比较函数的话,10是小于2的,事关10的1确实小于2 = =||
没关系,我们再加个比较函数进去就可以了,如下:(整体代码更新到第一个代码区了。)
function callArraySort(arr){
console.log("Array内置排序:");
return Array.prototype.sort.call(arr, compareByArray); }
function compareByArray(a,b){//其实直接return a-b;应该也可以。
var i = parseInt(a);
var j = parseInt(b);
return i-j;
}
一开始没留意,后来查了mdn才意识到。MDN入口>>
贴一下排序结果:似乎内置排序比实际快排快,但比改实参版的慢哦。
新更新,加入了堆排序,实现是参考的这里>>
function heapSort(arr){
function maxHeapify(arr, index, len){//对以arr[index]为根的子树的最大堆生成,如果交换了父节点,就再整理被交换的子节点
var left = getLeft(index);
var right = getRight(index);
var largest;
if(left<len&&arr[left]>arr[index]){
largest = left;
}else{
largest = index;
}
if(right<len&&arr[right]>arr[largest]){
largest = right;
}
if(largest!=index){
swapElement(arr, largest, index);
maxHeapify(arr, largest, len); // 如果改变了位置,递归改变的子树调整
}
}
function swapElement(arr,index0, index1){//交换位置
var temp = arr[index0];
arr[index0] = arr[index1];
arr[index1] = temp;
}
function getLeft(eleIndex){//获取eleIndex节点的左子节点
return 2*eleIndex+1;
}
function getRight(eleIndex){//获取eleIndex节点的右子节点 以0为起始下标
return 2*(eleIndex+1);
}
if(arr.length<=1){//排序起始,只有一个或者没有的数组,本来就不需要排序
return arr;
}
var len = arr.length;
for(var i=len/2+1;i>=0;--i){//首先是对无序的数组进行堆顶树的构造;len/2 + 1,我认为取的是树的最后一层的第一个叶子节点,后续叶子会在其父节点时比较
maxHeapify(arr, i, len);
} for(var i=len-1;i>=1;--i){
swapElement(arr, 0, i);
maxHeapify(arr, 0, --len);
}
return arr;
}
看了下,堆排序貌似还比内置排序快一点,比快排轻版块的慢一点:
复习排序with javascript的更多相关文章
- 十大排序算法JavaScript实现总结
花费了几周的时间断断续续的练习和模仿与使用JavaScript代码实现了十大排序算法. 里面有每种算法的动图和静态图片演示,看到图片可以自己先按照图片的思路实现一下. github中正文链接,点击查看 ...
- 十大经典排序算法(Javascript实现)
前言 总括: 本文结合动图详细讲述了十大经典排序算法用Javascript实现的过程. 原文博客地址:十大经典排序算法 公众号:「菜鸟学前端」,回复「666」,获取一揽子前端技术书籍 人生有情泪沾衣, ...
- 秒杀9种排序算法(JavaScript版)
一:你必须知道的 1> JS原型 2> 排序中的有序区和无序区 3> 二叉树的基本知识 如果你不知道上面三个东西,还是去复习一下吧,否则,看下面的东西有点吃力. 二:封装丑陋的原型方 ...
- 二维坐标点排序(JavaScript)
今天给大家分享下最近web项目中出现的一个技术难点问题--坐标排序: 如下图所示,要求在前端页面上按顺序将下面5个模块的坐标依次保存至数据库 现在已知信息如下: 1.每个模块分别为一个div 2.每个 ...
- 汉字按首字母排序(javascript,php,mysql实现)
1.javascript实现 var a = ["啊","得啊_123","得啊_0124","波啊","婆& ...
- 选择排序之javascript
选择排序(Selection-sort)是一种简单直观的排序算法.它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放 ...
- Java复习第一天---Javascript的基本知识点
1.HelloWord: 2.基础语法: 3.嵌入HTML 借助window.onload事件在整个窗体载入完毕之后运行程序代码 4.事件驱动: 5.DOM操作 5.1 查找元素节点 5.1.1 依据 ...
- javascript数组去重 String字符串去掉两端空格 javascript Array二分法排序 比较 javascript 求和
通过原形添加方法: ==================数组去重(对象去重法)======================= Array.prototype.unique=function(){ va ...
- 选择排序的JavaScript实现
思想 原址比较的排序算法.即首先找到数结构中的最小值并将其放置在第一位,然后找到第二小的值将其放置在第二位...以此类推. 代码 function selectionSort(arr) { const ...
随机推荐
- Unity3D 响应摇杆
if (Input.GetKeyUp(KeyCode.Joystick1Button0)) { Debug.Log("Joystick1Button0"); } if (Input ...
- 简单的sql server连接
private string constring="data source=112.74.73.122;initial catalog=qzyData;user id=sa;password ...
- 关于计算机改名无法连接TFS的问题
今天重新导入了两台服务器, 修改了机器名,结果VS2012链接TFS报错 --------------------------- Microsoft Visual Studio ----------- ...
- 修复win10升级时断电inaccessible boot device
代码提示0xc0000001 这里的解决方法对系统以及个人的没有文件丢失的影响,没有重装以及重置上丢失东西的顾虑 解决方法: WINDOWS/system32/config/RegBack/SYSTE ...
- Centos YUM 升级PHP
升级到5.3.3 1.删除已安装文件 yum remove php-* 2.安装 PHP 5.3 yum -y install php53* 升级到5.6 1.删除已安装文件 ...
- Jmeter发送Java请求
1.创建一个Java工程 2.把Jmeter的lib\ext目录下的ApacheJMeter_java.jar.ApacheJMeter_core.jar文件添加进该项目的Build Path 3.创 ...
- oracle undo回滚段详解
1.Undo是干嘛用的? 在介绍undo之前先说一下另外一个东西 transaction ,翻译成交易或事务.我们在进行一个事务的过程中需要申请许多资源,一个复杂的事务也需要很多步来完成.那么一个 ...
- Java中的private protected public和default的区别
转至:http://blog.sina.com.cn/s/blog_74c571240101jaf5.html 类内部 本包 子类 外部包 public √ √ √ √ pro ...
- 1250 Super Fast Fourier Transform(湘潭邀请赛 暴力 思维)
湘潭邀请赛的一题,名字叫"超级FFT"最终暴力就行,还是思维不够灵活,要吸取教训. 由于每组数据总量只有1e5这个级别,和不超过1e6,故先预处理再暴力即可. #include&l ...
- Office文档在线预览
工具说明:通过传入文档的Web地址,即可进行Office文档的在线预览. 使用方式: 在http://office.qingshanboke.com地址后,通过url参数传入您想预览的文件路径. 如: ...