目录
<script>
//创建列表类
function ArrayList() {
//属性
this.array = []
//方法
//将数据可以插入到数组中的方法
ArrayList.prototype.insert = function(item) {
this.array.push(item)
}
//toString
ArrayList.prototype.toString = function() {
return this.array.join('-')
}
ArrayList.prototype.swap = function(m, n) {
var temp = this.array[m]
this.array[m] = this.array[n]
this.array[n] = temp
}
}
</script>
一、冒泡排序
//冒泡排序
ArrayList.prototype.bubblesort = function() {
//1.获取数组的长度
var length = this.array.length;
//第一次进来:i=0,比较i=0和i=1位置的两个数据,如果0位置大
//最后一次进来:i=length-2;比较length-2和length-1
for (var j = length - 1; j >= 0; j--) {
for (var i = 0; i < j; i++) {
if (this.array[i] > this.array[i + 1]) {
//交换两个数据的位置
var temp = this.array[i]
this.array[i] = this.array[i + 1];
this.array[i + 1] = temp;
}
}
}
}
冒泡排序的效率(对于N个数据项 )
1.比较次数
(N-1)+(N-2)+(N-3)+...+1=N*(N-1)/2
大O形式为:O(N^2)
2.交换次数
真实次数N*(N-1)/4,常量不算在大O表示法中,最终可认为是O(N^2)
二、选择排序
每次选择出符合要求的
思路:
选定第一个索引位置,然后和后面元素依次比较
如果后面的元素,小于第一个索引未知的元素,则交换位置
经过一轮的比较后,可以确定第一个位置是最小的
然后使用同样的方法把剩下的元素逐个比较即可
可以看出选择排序,第一轮会选出最小值,第二轮会选出第二下的值
//选择排序
ArrayList.prototype.selectsort = function() {
//1.获取数组的长度
var length = this.array.length;
//2. 外层循环:从0位置开始取出数据,直到length - 2位置
for (j = 0; j < length - 1; j++) {
var min = j;
//3.内层循环:从i+1位置开始,和后面的内容比较
for (var i = min + 1; i < length; i++) {
if (this.array[min] > this.array[i]) {
min = i
}
}
this.swap(min, j)
}
}
选择排序的效率
1.比较次数
真实次数:N*(N-1)/2,大O形式为:O(N^2)
2.交换次数:
选择排序每次进行选择的时候,最多交换一次,一共遍历N-1次
选择排序的交换次数只有N-1次,大O表示法:O(N)
三、插入排序
//插入排序
ArrayList.prototype.insertionSort = function() {
//1.获取数组的长度
var length = this.array.length;
//2.外层循环:从第一个位置开始获取数据,向前面局部有序进行插入
for (var i = 1; i < length; i++) {
//3. 内层循环,获取位置i的元素,和前面的数据依次进行比较
var temp = this.array[i]
var j = i;
while (this.array[j - 1] > temp && j > 0) {
this.array[j] = this.array[j - 1]
j--
}
// //4.将j位置的数据,放置temp
this.array[j] = temp
}
}
插入排序的效率
1.比较次数
第一趟需要的最多次数是1,第二趟最多次数是2,依次类推,最后一趟是N-1次
所以最多次数是:1+2+3+4+...+N-1=N*(N-1)/2
每趟发现插入点之前,平均只有全体数据项的一半需要进行比较,所以比较次数是:
N*(N-1)/4
2.复制次数
做多是:N*(N-1)/2
平均次数是
N*(N-1)/4
四、希尔排序
希尔排序是插入排序的一种高效的改进版,并且效率比插入排序更快
希尔排序的历史~
希尔排序的思路
希尔排序是基于插入排序,
首先来看一下插入排序存在的问题:
假设一个很小的数据项在很靠近右端的位置,本来这里应该是较大的数据项的位置,把这个小数据项移动到左边的正确位置,所有的中间项数据都必须向右移动一位,这样执行效率很低。
希尔排序的思路:
比如下面的数组:81,94,11,96,12,35,17,95,28,58,41,75,15
//希尔排序
ArrayList.prototype.shellSort = function() {
//1.获取数组的长度
var length = this.array.length;
//2. 初始化增量
var gap = Math.floor(length / 2)
//3. while(gap不断减小)
while (gap >= 1) {
//4.以gap作为间隔,进行分组,对分组进行插入排序
for (var i = gap; i < length; i++) {
var temp = this.array[i]
var j = i
while (this.array[j - gap] > temp && j > gap - 1) {
this.array[j] = this.array[j - gap]
j -= gap
}
//5.将j位置的元素复制temp
this.array[j] = temp
}
//6.增量变化/2
gap = Math.floor(gap / 2)
}
}
希尔排序的效率
最坏的情况下,时间复杂度为O(N^2),通常情况下都好于O(N^2)
五、快速排序 非常重要
快速排序可以看成冒泡排序的升级版
基本思想:
选定pivot中心轴
将大于pivot的数字放在Pivot的右边
将小于pivot的数字放在Pivot的左边
分别对左右子序列重复前三步的操作
以第一个数为基准数快速排序算法javascript实现_wiilman的博客-优快云博客_js快速排序算法
function quick_sort(arr, from, to) {
var i = from; //哨兵i
var j = to; //哨兵j
var key = arr[from]; //标准值
if (from >= to) { //如果数组只有一个元素
return;
}
while (i < j) {
while (arr[j] > key && i < j) { //从右边向左找第一个比key小的数,找到或者两个哨兵相碰,跳出循环
j--;
}
while (arr[i] <= key && i < j) { //从左边向右找第一个比key大的数,找到或者两个哨兵相碰,跳出循环,
//这里的=号保证在本轮循环结束前,key的位置不变,否则的话跳出循环,
//交换i和from的位置的时候,from位置的上元素有可能不是key
i++;
}
/**
代码执行道这里,1、两个哨兵到找到了目标值。
2、j哨兵找到了目标值。3、两个哨兵都没找到(key是当前数组最小值)
**/
if (i < j) { //交换两个元素的位置
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
arr[from] = arr[i]
arr[i] = key;
quick_sort(arr, from, i - 1);
quick_sort(arr, i + 1, to);
}
选中间值作为pivot
// 1. 选择枢纽
ArrayList.prototype.medium = function(left, right) {
// 1. 取出中间的位置
var center = Math.floor((left + right) / 2);
// 2. 判断大小,并且进行交换
if (this.array[left] > this.array[center]) {
this.swap(left, center);
};
if (this.array[left] > this.array[right]) {
this.swap(left, right);
};
if (this.array[center] > this.array[right]) {
this.swap(center, right);
};
// 3.将center换到right-1的位置
this.swap(center, right - 1)
return this.array[right - 1]
};
// 2. 快速排序的实现
ArrayList.prototype.quickSort = function() {
this.quick(0, this.array.length - 1);
};
ArrayList.prototype.quick = function(left, right) {
// 1. 结束条件
if (left >= right) {
return
};
// 2. 获取枢纽
var pivot = this.medium(left, right);
// 3. 定义变量,用于当前找到的位置
var i = left;
var j = right - 1;
// 4. 开始进行交换
while (i < j) {
while (this.array[++i] < pivot) {};
while (this.array[--j] > pivot) {};
if (i < j) {
this.swap(i, j);
} else {
break;
};
}
// 5. 将枢纽放置在正确的位置,i的位置
this.swap(i, right - 1);
// 6. 分而治之
this.quick(left, i - 1);
this.quick(i + 1, right);
};
快速排序的效率
最坏的情况:
每次枢纽选择都是最左边或者最右边,效率等同于冒泡排序
快速排序的平均效率:
O(N*logN)
稳定的排序算法:冒泡排序、直接插入排序、归并排序
不稳定的排序算法:选择排序、希尔排序、快速排序、堆排序