1、算法与数据结构之冒泡排序
var arr = [];
for (var n = 1; n <= 100000; n++) {
arr.unshift(n); // 数据大的在前面;在后面我们要对数据进行从小到大排序
}
let a = Date.now(); // 在程序执行前,获取当前时间戳,排序执行完再获取一个
//var arr = [12, 34, 12, 3, 23, 1, 21, 23, 41, 35, 26]
/* 以小到大为例:
冒泡排序:
1、遍历数组,相邻的两个元素依次比较大小,如果前面的大于后面的,交换两者位置,直到把最大的放在最后面,然后循环继续
2、当最大值选出来了后,下一次操作的长度是从0 - 到个数减1(长度减2)
*/
var temp = 0;
for (let i = arr.length - 1; i > 0; i--) { // 每次选出最大值后,需要排序的元素就少一个了,
for (let j = 0; j < i; j++) {
if (arr[j] > arr[j + 1]) { // 相邻的两个元素比较,把前面大的往后面 推
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
let b = Date.now();// 排序完成,获取时间戳
console.log(b - a + "毫秒"); // 计算运行时间 23332毫秒
//console.log(arr);
2、算法与数据结构之选择排序
var arr = [];
for (var n = 1; n <= 100000; n++) {
arr.unshift(n); // 数据大的在前面;在后面我们要对数据进行从小到大排序
}
let a = Date.now(); // 在程序执行前,获取当前时间戳,排序执行完再获取一个
//var arr = [12, 34, 12, 3, 23, 1, 21, 23, 41, 35, 26]
/*
选择排序(小到大为例):
1、每次遍历,都假设第一个元素是最小的,索引为 0,依次和后面的元素比较,如果这个最小大于比较的数,两者交换索引
2、交换两个值
*/
for (var i = 0; i < arr.length - 1; i++) {
var min = i;
for (var j = i + 1; j < arr.length; j++) {
if (arr[min] > arr[j]) {
min = j;
}
}
[arr[min], arr[i]] = [arr[i], arr[min]]; // 数组的解构,交换两个值
}
let b = Date.now();// 排序完成,获取时间戳
console.log(b - a + "毫秒");; // 计算运行时间 19995毫秒
//console.log(arr)
3、算法与数据结构之插入排序排序
var arr = [];
for (var n = 1; n <= 100000; n++) {
arr.unshift(n); // 数据大的在前面;在后面我们要对数据进行从小到大排序
}
let a = Date.now(); // 在程序执行前,获取当前时间戳,排序执行完再获取一个
//var arr = [12, 34, 12, 3, 23, 1, 21, 23, 41, 35, 26];
/*
插入排序:相当于把数据分成了两个数组,一个排序的,一个未排序的
1、初始时,默认数组元素第一个是排序的,后面的元素都未排序
2、用第二元素(需要插的值)和 已排序的数组中的最后一个元素比较,如果插入的值小,那么最后一个元素和插值交换,然后插值又和倒数第二个元素比较..直到,找到小于自己的,然后就停下。
3、用第三个元素和已排序的数组中的元素倒叙 进行比较重复上面操作
4、直到,原始数组中所有元素都比较完毕结束
*/
for (var i = 1; i < arr.length; i++) { // 插值最初的下标为 1, 默认第0个元素是已排序的
for (var j = i; j > 0; j--) {// 倒叙遍历已排序的数组 与 插值比较,寻找合适的位置
var temp;
if (arr[j] < arr[j - 1]) { //如果 插值依次和前面的值比较,如果插值小,则两者交换位置,插值继续和前面的比较。重复
temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp
}
}
}
let b = Date.now();// 排序完成,获取时间戳
console.log(b - a + "毫秒");; // 计算运行时间 24443毫秒
//console.log(arr);
// 插入排序,按照最坏结果,总执行次数为: N^2 - N ;
// 算法时间复杂度为: O(n^2)
4、算法与数据结构之希尔排序
var arr = [];
for (var n = 1; n <= 100000; n++) {
arr.unshift(n); // 数据大的在前面;在后面我们要对数据进行从小到大排序
}
let a = Date.now(); // 在程序执行前,获取当前时间戳,排序执行完再获取一个
//var arr = [12, 34, 12, 3, 23, 1, 21, 23, 41, 35, 26]
// 选择一个增长量 h ,作为分组的的依据, 增长量的值为 h=arr.length/2 ,初始值可以设置为 1,通过循环,改变
var h = 1;
while (h < arr.length / 2) { // arr.length/2 有可能是小数,
h = 2 * h + 1;
//console.log(h);
}
// 希尔排序
// 当 h < 1 的时候,结束循环,h>=1的时候,一直进行排序
while (h >= 1) {
//console.log(h);
for (var i = h; i < arr.length; i++) {// 通过增长量分组后,每一组最后下标为 h,下标为 h 的元素就只是分组中,待插 的值
for (var j = i; j >= h; j -= h) { // 每组的量,最小是 h
// 每组最后的元素(插值),倒叙和前面的元素比较大小,如果小,就交换位置
var temp;
if (arr[j] < arr[j - h]) {
temp = arr[j];
arr[j] = arr[j - h];
arr[j - h] = temp;
} else {
break; // 如果后面大,就说明 插值 找到合适的位置,并是有序的,跳出本轮循环,
}
}
}
h = parseInt(h / 2); // 减小 h 的值,削减增长量 ;
// 在java中,一个属不能整除另一个数,结果会保留整数部分,JavaScript中,会得到小数,所以,需要对 h 进行取整
}
let b = Date.now();// 排序完成,获取时间戳
console.log(b - a + "毫秒");; // 计算运行时间 31毫秒
//console.log(arr);
上面是 10万数据量,冒泡排序 23332毫秒,选择排序 19995毫秒,插入排序 24443毫秒。希尔排序31毫秒
如果数据量非常少的情况下,随便哪个排序都可以,如果在海量数据的情况下,希尔排序比较优势,花费时间少,冒泡排序、选择排序、插入排序的时间复杂度都是 O(n^2),数据量大的情况下,时间消耗成平方花费。