排序

⭐时间复杂度

1、常数阶O(1)

只要代码中没有复杂的循环条件,无论代码的函数是多少,一律为常数阶O(1)。

1 for(int i=0;i<n;i++){
2     int j=o;
3     j++;
4 }

2、对数阶O(log2n)

存在循环体,在不考虑循环体的代码执行情况,该循环体本该执行n次,但是循环体将改变循环变量i的大小,每执行一次,i就扩到两倍,即i=i*2,这样就导致循环体会加速趋近终止条件n;假设经过x次后,退出循环体,则有2x>=n,因此,x=log2n;同理,当i=i∗3时,x=log3n,退出循环的速度更快,时间复杂度更小。

1 while(i<n){
2     i=i*2;
3 }

3、线性阶O(n)

存在循环体。循环体内代码执行的次数随着规模n的变化而变化,并且是线性变化。

1 for(int i=0;i<n;i++){
2     int j=o;
3     j++;
4 }

4、线性对数阶O(nlog2n)

将时间复杂度为O(log2n)的代码重复执行n次,即为线性对数阶O(nlog2n)。

1 //n为一个固定的常数
2 //i和j均为循环变量
3 while(i<n){//线性节阶
4     while(j<n){//对数阶
5         j=j*2;
6     }
7 }

5、平方阶O(n2)

 复杂度为O(n)的代码执行了n次。

1 for(int i=0;i<n;i++){//执行n次
2     for(int j=0;j<n;j++){//执行n次
3         int m=0;
4         m++;
5     }
6 }

6、立方阶O(n3)

和平方阶原理一样,时间复杂度为O(n2)的代码执行n次。

1 for(int i=0;i<n;i++){//执行n次
2     for(int j=0;j<n;j++){//执行n次
3         for(int k=0;k<n;k++){
4             int m=0;
5             m++;
6         }
7     }
8 }        

O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(nk)

⭐空间复杂度

1、O(1)

1 let a = 1;
2 let b = 1;
3 let c = 1;
4 let d = 1;

2、O(n)

1 let arr = Array(n)

3、O(n2)

1 let arr=[]
2 for (var i = 0; i < n; i++) {
3   arr[i]=i
4   for (var j = 0; j < n; j++) {
5     arr[i][j]=j
6   }
7 }

排序前数组的准备:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 
 4 <head>
 5     <meta charset="UTF-8">
 6     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 7     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 8     <title>Document</title>
 9 </head>
10 
11 <body>
12     <script>
13         let arr = [];
14         for (let i = 0, len = 10; i < len; i++) {
15             let num = Math.floor(Math.random() * 100);
16             arr.push(num);
17         }
18         console.log('arr', arr);
19 
20         console.time('a');
21 
22         //排序算法位置
23         //排序算法位置
24 
25         console.timeEnd('a');
26         console.log('arr', arr);
27     </script>
28 </body>
29 
30 </html>

⭐冒泡排序

从第一个元素开始,把当前元素和下一个索引元素进行比较。如果当前元素大,那么就交换位置,重复操作直到比较到最后一个元素。

1         for (let i = arr.length - 1; i > 0; i--) {
2             for (let j = 0; j < i; j++) {
3                 if (arr[j] > arr[j + 1]) {
4                     [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
5                 }
6             }
7         }

⭐插入排序

第一个元素默认是已排序元素,取出下一个元素和当前元素比较,如果当前元素大就交换位置。那么此时第一个元素就是当前的最小数,所以下次取出操作从第三个元素开始,向前对比,重复之前的操作。

自己写的:

 1        for (let i = 1, len = arr.length; i < len; i++) {
 2             for (let j = i - 1; j >= 0; j--) {
 3                 if (arr[i] < arr[0]) {
 4                     let temp = arr[i];
 5                     arr.splice(i, 1);
 6                     arr.unshift(temp);
 7                     break;
 8                 }
 9                 if (arr[i] > arr[j - 1] && arr[i] < arr[j]) {
10                     let temp = arr[i];
11                     arr.splice(i, 1);
12                     arr.splice(j, 0, temp);
13                     break;
14                 }
15             }
16         }

正规的:

 1         for (let i = 1, len = arr.length; i < len; i++) {
 2             let nowPosition = i;
 3             let nowData = arr[i];
 4             for (let j = i - 1; j >= 0; j--) {
 5                 if (arr[j] > nowData) {
 6                     arr[nowPosition] = arr[j];
 7                     arr[j] = nowData;
 8                     nowPosition = j
 9                 }
10             }
11         }

⭐选择排序

遍历数组,设置最小值的索引为0,如果取出的值比当前最小值小,就替换最小值索引,遍历完成后,将第一个元素和最小值索引上的值交换。如上操作后,第一个元素就是数组中的最小值,下次遍历就可以从索引 1 开始重复上述操作。

1         for (let i = 0, len = arr.length - 1; i < len; i++) {
2             for (let j = i + 1, len = arr.length; j < len; j++) {
3                 if (arr[j] < arr[i]) {
4                     let a = arr[j];
5                     arr[j] = arr[i];
6                     arr[i] = a;
7                 }
8             }
9         }

⭐快速排序

在数据集之中,找一个基准点,建立两个数组,分别存储左边和右边的数组,利用递归进行下次比较。

 1        function quickSort(theArr) {
 2             let len = theArr.length;
 3             if (len < 2) {
 4                 return theArr;
 5             };
 6             let middleNum = Math.floor(len / 2);
 7             let left = [];
 8             let right = [];
 9             let middle = theArr[middleNum];
10             for (let i = 0; i < len; i++) {
11                 if (i !== middleNum && theArr[i] < middle) {
12                     left.push(theArr[i]);
13                 } else if (i !== middleNum && theArr[i] >= middle) {
14                     right.push(theArr[i]);
15                 }
16             }
17             return quickSort(left).concat(middle, quickSort(right));
18         }
19         arr = quickSort(arr);

⭐希尔排序

按增量序列个数 k,对序列进行 k 趟排序;

每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1时,整个序列作为一个表来处理,表长度即为整个序列的长度。

 1         let gap = Math.floor(arr.length / 2);
 2         do {
 3             for (let i = 0, len = arr.length - gap; i < len; i++) {
 4                 let nowPosition = i;
 5                 let nowData = arr[i];
 6                 for (let j = i + gap, len = arr.length; j < len; j = j + gap) {
 7                     if (nowData > arr[j]) {
 8                         arr[nowPosition] = arr[j];
 9                         arr[j] = nowData;
10                         nowPosition = j;
11                     }
12                 }
13             }
14             gap = Math.floor(gap / 2);
15         } while (gap >= 1);

⭐归并排序

(1)把长度为n的输入序列分成两个长度为n/2的子序列;

(2)对这两个子序列分别采用归并排序;

(3)将两个排序好的子序列合并成一个最终的排序序列。

 1         function Merge(theArr) {
 2             if (theArr.length < 2) {
 3                 return theArr;
 4             }
 5             let middle = Math.floor(theArr.length / 2);
 6             let left = theArr.slice(0, middle);
 7             let right = theArr.slice(middle);
 8             return MergeSort(Merge(left), Merge(right));
 9         }
10 
11         function MergeSort(left, right) {
12             let sortData = [];
13             while (left.length !== 0 && right.length !== 0) {
14                 if (left[0] < right[0]) {
15                     sortData.push(left.shift());
16                 } else {
17                     sortData.push(right.shift());
18                 }
19             }
20             return sortData.concat(left, right);
21         }
22 
23         arr = Merge(arr);

⭐二分排序

在插入第i个元素时,对前面的0~i-1元素进行折半,先跟他们中间的那个元素比,如果小,则对前半再进行折半,否则对后半 进行折半,直到left>right,然后再把第i个元素前1位与目标位置之间的所有元素后移,再把第i个元素放在目标位置上。

 1         for (let i = 1, len = arr.length; i < len; i++) {
 2             let temp = arr[i];
 3             if (arr[i] < arr[0]) {
 4                 arr.splice(i, 1);
 5                 arr.unshift(temp);
 6             } else if (arr[i] > arr[i - 1]) {
 7                 continue;
 8             } else {
 9                 let position = DichotomySort(0, i - 1, temp);
10                 arr.splice(i, 1);
11                 arr.splice(position, 0, temp);
12             }
13         }
14 
15         function DichotomySort(left, right, value) {
16             if (left === right) {
17                 return left;
18             }
19             let middle = Math.floor((right + left) / 2);
20             if (value < arr[middle]) {
21                 return DichotomySort(left, middle, value);
22             } else {
23                 return DichotomySort(middle + 1, right, value);
24             }
25         }

Array自带的sort()和reverse()

1、Array.reverse()倒序。

2、Array.sort():不给参数按ascii码排序。Array.sort(function(a,b){return b - a}):降序。

原文地址:https://www.cnblogs.com/sxushy2016/p/14986718.html