什么是数组
数组对象是使用单独的变量名来存储一系列的值。数组可以用一个变量名存储所有的值,并且可以用变量名访问任何一个值。数组中的每个元素都有自己的的ID,
创建一个数组
- 常规方式:
var citys=new Array();
citys[0]="beijing";
citys[1]="shanghai";
citys[2]="wuhan";
console.log(citys[0]); //beijing
- 简洁方式:
var citys=new Array("beijing","shanghai","wuhan");
console.log(citys[1]); //shanghai
- 字面:
var citys=["beijing","shanghai","wuhan"];
console.log(citys[2]); //wuhan
- Array.from() 方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
var arr = Array.from('shenzhen');
console.log(arr); // ["s", "h", "e", "n", "z", "h", "e", "n"]
数组排序
- sort()方法
var array = [1,4,-8,-3,6,12,9,8];
function compare(val1,val2){
return val1-val2;
};
array.sort(compare);
- 反转数组reverse()
var citys=new Array("beijing","shanghai","wuhan");
console.log(citys); // ["beijing", "shanghai", "wuhan"]
citys.reverse();
console.log(citys); // ["wuhan", "shanghai", "beijing"]
- 冒泡排序
1、比较相邻的两个元素,如果前一个比后一个大,则交换位置。
2、比较完第一轮的时候,最后一个元素是最大的元素。
3、这时候最后一个元素是最大的,所以最后一个元素就不需要参与比较大小。
function bubbleSort(arr) {
var len = arr.length;
for (var i = 0; i < len-1; i++) {
for (var j = 0; j < len - 1 - i; j++) {
// 相邻元素两两对比,元素交换,大的元素交换到后面
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
return arr;
}
//举个数组
myArr = [1, 28, 32, -9, 22];
//使用函数
bubbleSort(myArr) //[-9, 1, 22, 28, 32]
- 选择排序
1、算法简介序
选择排序是一个简单直观的排序方法,它的工作原理很简单,首先从未排序序列中找到最大的元素,放到已排序序列的末尾,重复上述步骤,直到所有元素排序完毕。
2、算法描述
1)假设未排序序列的第一个是最大值,记下该元素的位置,从前往后比较
2)若某个元素比该元素大,覆盖之前的位置
3)重复第二个步骤,直到找到未排序的末尾
4)将未排序元素的第一个元素和最大元素交换位置
5)重复前面几个步骤,直到所有元素都已经排序。
3、算法分析
选择排序的交换操作次数最好情况已经有序为0次,最坏情况逆序n-1次,因此交换操作次数位于0~(n-1)次之间;比较操作次数(n-1+…+2+1+0)为n(n-1)/2次;交换元素赋值操作为3次,逆序需要n-1趟交换,因此,赋值操作位于0~3(n-1)次之间。由于需要交换位置,所以肯定是不稳定的。
function selsetSort(arr){
var len = arr.length;
var index;
for(var i=0;i<len-1;i++){
index=i;
for(var j=i+1;j<len;j++){
if(arr[index]>arr[j]){//寻找最小值
index=j;//保存最小值的索引
}
}
if(index!=i){
var temp =arr[i];
arr[i]=arr[index];
arr[index]=temp;
}
}
return arr;
}
myArr =[5,3,6,7,9,1,23,32,11,8];
//使用函数
selsetSort(myArr) // [1, 3, 5, 6, 7, 8, 9, 11, 23, 32]
- 快速排序
数组中指定一个元素作为标尺,比它大的放到该元素后面,比它小的放到该元素前面,如此重复直至全部正序排列。
1、选基准:在数据结构中选择一个元素作为基准(pivot)
2、划分区:参照基准元素值的大小,划分无序区,所有小于基准元素的数据放入一个区间,所有大于基准元素的数据放入另一区间,分区操作结束后,基准元素所处的位置就是最终排序后它应该所处的位置
3、递归:对初次划分出来的两个无序区间,递归调用第 1步和第 2步的算法,直到所有无序区间都只剩下一个元素为止。
function quickSort(arr) {
arr = arr.concat();
if(arr.length<=1){
return arr
}
let left=[], right=[];
let basis = arr.splice(0,1);
arr.forEach(function (v) {
if(v<basis){
left.push(v)
}else{
right.push(v)
}
});
return quickSort(left).concat(basis,quickSort(right))
}
myArr = [1, 28, 32, -9, 22,48,-7848,77];
//使用函数
quickSort(myArr) // [-7848, -9, 1, 22, 28, 32, 48, 77]
- 插入排序
1,算法简介
插入排序的工作原理就是将未排序数据,对已排序数据序列从后向前扫描,找到对应的位置并插入。插入排序通常采用占位的形式,空间复杂度为O(1),因此,在从后向前扫描的过程中,需要反复的把已排序的元素逐步向后挪位,为新插入元素提供插入的位置。
2,算法描述
1)从第一个元素开始,该元素可以被认为已经被排序
2)取出下一个元素,在已经排好序的序列中从后往前扫描
3)直到找到小于或者等于该元素的位置
4)将该位置后面的所有已排序的元素从后往前依次移一位
5)将该元素插入到该位置
6)重复步骤2~5
function insertSort(arr){
var len = arr.length
for(var i=1;i<len;i++){
var temp = arr[i]
var j = i-1
while(arr[j]>temp){
arr[j+1]=arr[j]
j--
}
arr[j+1]=temp
}
return arr
}
var myArr = [5,3,2,7,8]
insertSort(myArr) //[2,3,5,7,8]
- 希尔排序
希尔(Shell)排序又称为缩小增量排序,它是一种插入排序。它是直接插入排序算法的一种威力加强版。
希尔排序的基本思想是:
把记录按步长 gap 分组,对每组记录采用直接插入排序方法进行排序。、随着步长逐渐减小,所分成的组包含的记录越来越多,当步长的值减小到1时,整个数据合成为一组,构成一组有序记录,则完成排序。
function shellSort(array) {
let gap = Math.floor(array.length / 2);
while (1 <= gap) {
// 把距离为 gap 的元素编为一个组,扫描所有组
for (let i = gap; i < array.length; i++) {
let j = 0;
let temp = array[i];
// 对距离为 gap 的元素组进行排序
for (j = i - gap; j >= 0 && temp < array[j]; j -= gap) {
array[j + gap] = array[j];
}
array[j + gap] = temp;
}
gap = Math.floor(gap / 2); // 减小增量
}
return array;
}
let arr = [98, 42, 25, 54, 15, 3, 25, 72, 41, 10, 121];
shellSort(arr); //[3, 10, 15, 25, 25, 41, 42, 54, 72, 98, 121]
- 归并排序
1、基本思想与过程:先递归的分解数列,再合并数列(分治思想的典型应用)
(1)将一个数组拆成A、B两个小组,两个小组继续拆,直到每个小组只有一个元素为止。
(2)按照拆分过程逐步合并小组,由于各小组初始只有一个元素,可以看做小组内部是有序的,合并小组可以被看做是合并两个有序数组的过程。
(3)对左右两个小数列重复第二步,直至各区间只有1个数。
下面对数组【42,20,17,13,28,14,23,15】进行归并排序,模拟排序过程如下:
第一步:拆分数组,一共需要拆分三次(logN);
第一次拆成【42,20,17,13】,【28,14,23,15】,
第二次拆成【42,20】,【17,13】,【28,14】,【23,15】,、
第三次拆成【42】,【20】,【17】,【13】,【28】,【14】,【23】,【15】;
第二步:逐步归并数组,采用合并两个有序数组的方法,每一步其算法复杂度基本接近于O(N)
第一次归并为【20,42】,【13,17】,【14,28】,【15,23】
第二次归并为【13,17,20,42】,【14,15,23,28】,
第三次归并为【13, 14, 15, 17, 20, 23, 28, 42】
function merge(left, right) {
var tmp = [];
while (left.length && right.length) {
if (left[0] < right[0])
tmp.push(left.shift());
else
tmp.push(right.shift());
}
return tmp.concat(left, right);
}
function mergeSort(a) {
if (a.length === 1)
return a;
var mid = Math.floor(a.length / 2);
var left = a.slice(0, mid);
var right = a.slice(mid);
return merge(mergeSort(left), mergeSort(right));
}
var arr = [42,20,17,13,28,14,23,15]; //[13, 14, 15, 17, 20, 23, 28, 42]
比较
| 排序算法 | 平均情况 | 最好情况 | 最坏情况 | 稳定性 |
|---|---|---|---|---|
| 冒泡排序 | O(n²) | O(n) | O(n²) | 稳定 |
| 选择排序 | O(n²) | O(n²) | O(n²) | 不稳定 |
| 插入排序 | O(n²) | O(n) | O(n²) | 稳定 |
| 希尔排序 | O(nlogn)~O(n²) | O(n^1.5) | O(n²) | 不稳定 |
| 归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | 稳定 |
| 快速排序 | O(nlogn) | O(nlogn) | O(n²) | 不稳定 |