1. 选择排序
i从0-max循环
每次都把(i+1)~ max中最小的值找出来,然后和i位置的元素进行交换
解:3, 5, 1, 2, 4, 7, 6
step 1:1 5 3 2 4 7 6
step 2:1 3 5 2 4 7 6 | 1 2 5 3 4 7 6
step 3:1 2 3 5 4 7 6
step 4:1 2 3 4 5 7 6
step 5:1 2 3 4 5 7 6
step 6:1 5 3 2 4 6 7
function simpleSelectionSort(a) { //选择排序
var tem;
for(var i=0; i<a.length-1; i++) {
for(var j=i+1; j<a.length; j++)
if(a[j]<a[i]) {
tem = a[i];
a[i] = a[j];
a[j] = tem;
}
}
return a;
}
test:
var a = [3, 5, 1, 2, 4, 7, 6]
console.log(simpleSelectionSort(a))
2. 冒泡
bubble是算法和职业生涯中必不可少的,面试中9.9次会被问到,表示倒背如流,还有二分查找。
function bubbleSort(a) {
var n = a.length;
for(var i=0; i<n-1; i++) {
for(var j=0; j<n-i-1; j++) {
if(a[j+1]<a[j]) {
a[j] = [a[j+1],a[j+1]=a[j]][0]
//[a[j],a[i]] = [a[i],a[j]] #ie不支持
}
}
}
return a;
}
test:
var a = [3, 5, 1, 2, 4, 7, 6]
console.log(bubbleSort(a))
3. 堆排序(其实就是二叉树)
用递归的办法,比如说深度为depth次,那么循环depth次:
1:比较左右孩子节点,如果左孩子>右孩子,则交换
2:比较此节点与左孩子节点,如果此节点>左孩子,则交换
3:重复1
这样的一个循环可以得出最小的节点的值,把这个节点存入新的数组a2,并把此节点从原有的数组中抛出,得出的新节点再去做上面的循环。
总共需要做a.length次。
以前上学时候学习算法,虽然努力学习,但是并不知道实际中到底怎么应用,直到去年要写个分类的列表,看起来很简单,就是父节点下有最多五个子节点,然后每个子节点又最多有五个子节点,然后列表深度最大为500。要做的操作是父节点选中,子节点全部选中,子节点有一个没有选中,那么父节点是没有选中的状态,子节点全部选中,那么父节点当然也是选中的状态,就这样往上层继续查找。作为一个大学期间学习过很长很长时间算法的人来说,我还是花了将近三天多时间来才写出了这个页面,比预期的两天延期了大半天。教训深重。。。and else。。。
代码如下:
function getLog(a, r) { //用于求得二叉树深度
var i = 0;
while(true) {
if(Math.pow(a,i)==r)
return i;
else if(Math.pow(a,i)<r && Math.pow(a,i+1)>r)
return i+1;
else
i++;
}
}
function tarHeapSort(a) {
var n = a.length;
var left, right;
var depth = getLog(2, n);
var j = depth;
while(--j>=0) {
for(var i=0; i<n; i++) {
left = i*2+1, right = i*2+2;
if(right<n && a[left]>a[right]) {
[a[left], a[right]] = [a[right], a[left]];
}
if(left<n && a[left]<a[i]) {
[a[left], a[i]] = [a[i], a[left]]
}
if(right<n && a[left]>a[right]) {
[a[left], a[right]] = [a[right], a[left]];
}
}
}
return a;
}
function heapSort(a) {
var n = a.length;
var a2=[];
var j = n;
while(--j>=0) {
a = tarHeapSort(a)
a2.push(a[0])
a.shift();
}
return a2;
}
test:
var a = [10,9, 8, 7, 6, 5, 4, 3, 2, 1]
a = [2,1,3,4,5,2,1,4,10,3,-1,3]
console.log(heapSort(a))
4. 快速排序(分治、递归)
看过经典的快排算法,我自己写的时候另外定义了left和right数组,这样是又占用了空间,但是很好理解,个人觉得也是快排。
function quickSort(a) {
var n = a.length;
var soilder = a[n-1];
var left=[], right=[soilder];
var allIsEqual = 1;
for(var i=0; i<n-1; i++) {
if(a[i]<soilder) {
left.push(a[i])
} else {//right数组不可能为空,如果和soilder相等,都是放在right里
right.push(a[i]);
if(a[i]==soilder) {
allIsEqual++;
}
}
}
if(allIsEqual==n) { //如果这个数组里面的额数字全部相等,就不用再比了
return a;
} else {
if(left.length>1)
left = quickSort(left);
if(right.length>1)
right = quickSort(right);
return left.concat(right);
}
}
test:
var a = [10,9, 8, 7, 6, 5, 4, 3, 2, 1]
a = [2,1,3,4,5,2,1,3,-1,2,100,2,1,3,4,0]
a = [1,2,1,2,3,1,1,1,1,1,1,1]
console.log(quickSort(a))
5. 基数排序(桶排序)
以前一直不理解基数排序,不能静下心去想,今天终于有心思看明白了,并把代码写了出来。支持多位数的数字。
基数排序就是先定义10个桶,编号0-9,然后把数组a中个位数等于桶的编号的数字放入对应桶中,最后按照桶的顺序把数字再重新放回数组a中。
然后清空桶,再把新的数组a中十位数字等于桶的编号的数字放入对应桶中,最后按照桶的顺序把数字再重新放回数组a中。
。。。
依次循环
在第一次循环的时候,遍历数组的同时会找到最大的数字位数。比方说是3(百位数),那么上面的循环进行三次。
代码如下:
//基数排序(桶排序)
function radixSort(a) {
var n = a.length;
var bucketCount = 10;
var bucket = [], radix;
var remainder = 1, maxDigit = 1;
while(true) {
bucket = [];
for(var i=0; i<n; i++) {
if(remainder==1 && getNoLength(a[i])>maxDigit) {
maxDigit = getNoLength(a[i]);
}
radix = getNoDigit(a[i],remainder-1);
if(typeof bucket[radix] == "object") {
bucket[radix].push(a[i]);
} else {
bucket[radix] = [a[i]];
}
}
a = []
for(var i=0; i<10; i++) {
if(typeof bucket[i] == "object") {
a = a.concat(bucket[i])
}
}
if(remainder==maxDigit) {
break;
} else {
remainder++;
}
}
return a;
}
function getNoLength(n) {//获得数字的长度
var s = n + "";
return s.length;
}
function getNoDigit(n,i) {//获得数字n的倒数第i位,i从0开始
var s = (n + "");
s = s.split("").reverse();
if(i>s.length-1) {
return 0;
} else {
return s[i];
}
}
6. 归并排序(又是递归、分治)
五一节后第一天,工作依然没什么事情,无奈,继续写排序,除此之外,不知道做什么了。。。归并排序其实很简单,就是把一个数组先拆成有序数组,然后再合并有序数组。
function mergeSort(a) {
var n = a.length;
if(n<=1) {
return a;
} else if(n==2) {
if(a[0]>a[1]) {
[a[0], a[1]] = [a[1], a[0]]
}
return a;
} else {
var mid = Math.floor(n/2);
var left = a.slice(0,mid), right = a.slice(mid);
left = mergeSort(left);
right = mergeSort(right);
a = mergeArray(left, right);
return a;
}
}
function mergeArray(left, right) {//合并两个有序数组
var a = [];
var nl = left.length, nr = right.length;
var i = 0, j = 0;
while(i<nl&&j<nr) {
if(left[i]<right[j]) {
a.push(left[i++]);
} else {
a.push(right[j++]);
}
}
a = a.concat(left.slice(i,nl));
a = a.concat(right.slice(j,nr));
return a;
}
test:
var a = [10,9, 8, 7, 6, 5, 4, 3, 2, 1]
//a = [2,1,3,4,5,2,1,3,-1,2,100,2,1,3,4,0]
//a = [1,5,2,3,4]
console.log(mergeSort(a))
7. 直接插入排序
直接插入排序应该是最简单的了,另设置一个数组长度为1的有序数组tem,tem[0]就是a[0],然后往里面顺序插入a[i]function insertSort(a) {
if(a.length<1) {
return a;
}
var tem = [a[0]];
for(var i=1; i<a.length; i++) {
tem = insertToSortedArray(a[i], tem);
}
return tem;
}
function insertToSortedArray(n, a) {//把n插入有序数组a中
var i;
for(i=0; i<a.length; i++) {
if(a[i]>n) {//插入a[i]前
break;
}
}
for(var j=a.length; j>i; j--) {
a[j] = a[j-1];
}
a[i] = n;
return a;
}
8. shell排序
function shellSort(a) {var gap = parseInt(a.length/2);
while(gap>=1) {
a = shellInsertSort(a, gap)
gap = parseInt(gap/2);
}
return a;
}
function shellInsertSort(a, gap) {
var j, tem;
for(var i=gap; i<a.length; i++) {
if(a[i]<a[i-gap]) {
j = i-gap;
tem = a[i];
a[i] = a[j];
while(tem<a[j]) {
a[j+gap] = a[j];
j -= gap;
}
a[j+gap] = tem;
}
}
return a;
}