1.冒泡排序
原理:临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,这样一趟过去后,最大或最小的数字被交换到了最后一位,然后再从头开始进行两两比较交换,直到倒数第二位时结束
时间复杂度:平均情况:O(n2) 最好情况:O(n) 最坏情况:O(n2)
空间复杂度:O(1)
稳定性:稳定
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//JavaScript语法vararray = [23,0,32,45,56,75,43,0,34];for(vari = 0; i < array.length; i++){varisSort =
true;for(varj = 0; j < array.length - 1 - i; j++){if(array[j] > array[j+1]){isSort =false;vartemp = array[j];array[j] = array[j + 1];array[j + 1] = temp;}}if(isSort){break;}}console.log(array); |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<?php$array= [23,0,32,45,56,75,43,0,34];for($i= 0;
$i < count($array);$i++){$isSort= true;for($j= 0;
$j < count($array) - 1;$j++){if($array[$j]
> $array[$j+1]){$isSort= false;$temp=
$array[$j];$array[$j] =$array[$j+
1];$array[$j+ 1] =
$temp;}}if($isSort){break;}}var_dump($array);?> |
2.简单选择排序
原理:通过n-i次关键字之间的比较,从n-i+1 个记录中选择关键字最小的记录,并和第i(1<=i<=n)个记录交换 简单选择排序的性能要略优于冒泡排序
时间复杂度:平均情况:O(n2) 最好情况:O(n) 最坏情况:O(n2)
空间复杂度:O(1)
稳定性:不稳定
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//JavaScriptvararray = [23,0,32,45,56,75,43,0,34];for(vari = 0; i < array.length - 1; i++){varpos = i;for(varj = i + 1; j < array.length;j++){if(array[j] < array[pos]){pos=j;}}vartemp=array[i];array[i]=array[pos];array[pos]=temp;}console.log(array); |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<?php$array= [23,0,32,45,56,75,43,0,34];for($i= 0;
$i < count($array);$i++){$pos=
$i;for($j=
$i + 1;$j
< count($array);$j++){if($array[$j]
< $array[$pos]){$pos=
$j;}}$temp=
$array[$i];$array[$i] =$array[$pos];$array[$pos] =$temp;}var_dump($array);?> |
3.直接插入排序
原理:将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。 比冒泡法和选择排序的性能要更好一些
时间复杂度:平均情况:O(n2) 最好情况:O(n) 最坏情况:O(n2)
空间复杂度:O(1)
稳定性:稳定
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//JavaScriptvararray = [23,0,32,45,56,75,43,0,34];for(varj = 0;j < array.length;j++) {varkey = array[j];vari = j - 1;while(i > -1 && array[i] > key){array[i + 1] = array[i];i = i - 1;}array[i + 1] = key;}console.log(array); |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<?php//直接插入排序$array= [23,0,32,45,56,75,43,0,34];for($i= 0;
$i < count($array);$i++){$key=
$array[$i];$j=$i
- 1;while($j> -1 &&
$array[$j] >$key){$array[$j+1] =
$array[$j];$j=
$j - 1;}$array[$j+ 1] =
$key;}var_dump($array);?> |
4.快速排序
原理:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
时间复杂度:平均情况:O(nlog2n) 最好情况:O(nlog2n) 最坏情况:O(n2)
空间复杂度:O(nlog2n)
稳定性:不稳定
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//JavaScript 快速排序vararray = [23,0,32,45,56,75,43,0,34];varquickSort =
function(arr) {if(arr.length <= 1) {
returnarr; }//检查数组的元素个数,如果小于等于1,就返回。varpivotIndex = Math.floor(arr.length / 2);//varpivot = arr.splice(pivotIndex,1)[0];//选择"基准"(pivot),并将其与原数组分离,varleft = [];//定义两个空数组,用来存放一左一右的两个子集varright = [];for(var
i = 0; i < arr.length; i++)//遍历数组,小于"基准"的元素放入左边的子集,大于基准的元素放入右边的子集。{if(arr[i] < pivot) {left.push(arr[i]);}else
{right.push(arr[i]);}}returnquickSort(left).concat([pivot], quickSort(right));//使用递归不断重复这个过程,就可以得到排序后的数组。};varnewArray=quickSort(array);console.log(newArray); |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<?php$array= [23,0,32,45,56,75,43,0,34];functionquick_sort($arr) {//先判断是否需要继续进行$length=
count($arr);if($length<= 1) {return$arr;}$base_num=
$arr[0];//选择一个标尺 选择第一个元素//初始化两个数组$left_array=
array();//小于标尺的$right_array=
array();//大于标尺的for($i=1;$i<$length;$i++)
{ //遍历 除了标尺外的所有元素,按照大小关系放入两个数组内if($base_num>
$arr[$i]) {//放入左边数组$left_array[] =$arr[$i];}else
{//放入右边$right_array[] =$arr[$i];}}//再分别对 左边 和 右边的数组进行相同的排序处理方式//递归调用这个函数,并记录结果$left_array= quick_sort($left_array);$right_array= quick_sort($right_array);//合并左边 标尺 右边returnarray_merge($left_array,array($base_num),$right_array);}$newArray=quick_sort($array);var_dump($newArray);?> |
5.希尔排序
原理:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。。
时间复杂度:平均情况:O(n√n) 最好情况:O(nlog2n) 最坏情况:O(n2)
空间复杂度:O(1)
稳定性:不稳定
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//JavaScript 希尔排序vararray = [23,0,32,45,56,75,43,0,34];varshellSort =
function(arr){varlength=arr.length;varh=1;while(h<length/3){h=3*h+1;//设置间隔}while(h>=1){for(vari=h; i<length; i++){for(varj=i; j>=h && arr[j]<arr[j-h]; j-=h){vartemp =arr[j-h];arr[j-h]=arr[j];arr[j]=temp;}}h=(h-1)/3;}returnarr;}varnewArray = shellSort(array);console.log(newArray); |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
<?php//希尔排序$array= [23,0,32,45,56,75,43,0,34];functionshellSort($arr){$length=count($arr);$h=1;while($h<$length/3){$h=3*$h+1;//设置间隔}while($h>=1){for($i=$h;$i<$length;$i++){for($j=$i;$j>=$h&&
$arr[$j]<$arr[$j-$h];$j-=$h){$temp=$arr[$j-$h];$arr[$j-$h]=$arr[$j];$arr[$j]=$temp;}}$h=($h-1)/3;}return$arr;}$newArray= shellSort($array);var_dump($newArray)?> |
6.归并排序
原理:假设初始序列含有n个记录,则可以看成n个有序的子序列,每个子序列的长度为1,然后两两归并,得到(不小于n/2的最小整数)个长度为2或1的有序子序列,再两两归并,...如此重复,直至得到一个长度为n的有序序列为止
时间复杂度:平均情况:O(nlog2n) 最好情况:O(nlog2n) 最坏情况:O(nlog2n)
空间复杂度:O(1)
稳定性:稳定
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
//JavaScript 归并排序functionisArray1(arr){if(Object.prototype.toString.call(arr) =='[object Array]'){returntrue;}else{returnfalse;}}functionmerge(left,right){varresult=[];if(!isArray1(left)){left = [left];}if(!isArray1(right)){right = [right];}while(left.length > 0&& right.length >0){if(left[0]<right[0]){result.push(left.shift());}else{result.push(right.shift());}}returnresult.concat(left).concat(right);}functionmergeSort(arr){varlen=arr.length;varlim ,work=[];vari,j,k;if(len ==1){returnarr;}for(i=0;i<len;i++){work.push(arr[i]);}work.push([]);for(lim=len;lim>1;){//lim为分组长度for(j=0,k=0;k<lim;j++,k=k+2){work[j]=merge(work[k],work[k+1]);}work[j]=[];lim=Math.floor((lim+1)/2);}returnwork[0];}vararray = [23,0,32,45,56,75,43,0,34];console.log(mergeSort(array)); |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
<?php //归并排序functionmergeSort(&$arr) {$len=
count($arr);//求得数组长度mSort($arr, 0,$len-1);}//实际实现归并排序的程序functionmSort(&$arr,$left,
$right) {if($left<
$right) {//说明子序列内存在多余1个的元素,那么需要拆分,分别排序,合并//计算拆分的位置,长度/2 去整$center=
floor(($left+$right) / 2);//递归调用对左边进行再次排序:mSort($arr,$left,
$center);//递归调用对右边进行再次排序mSort($arr,$center+1,
$right);//合并排序结果mergeArray($arr,$left,
$center,$right);}}//将两个有序数组合并成一个有序数组functionmergeArray(&$arr,$left,
$center,$right) {//设置两个起始位置标记$a_i=
$left;$b_i=
$center+1;while($a_i<=$center&&
$b_i<=$right) {//当数组A和数组B都没有越界时if($arr[$a_i]
< $arr[$b_i]) {$temp[] =$arr[$a_i++];}else
{$temp[] =$arr[$b_i++];}}//判断 数组A内的元素是否都用完了,没有的话将其全部插入到C数组内:while($a_i<=
$center) {$temp[] =$arr[$a_i++];}//判断 数组B内的元素是否都用完了,没有的话将其全部插入到C数组内:while($b_i<=
$right) {$temp[] =$arr[$b_i++];}//将$arrC内排序好的部分,写入到$arr内:for($i=0,$len=count($temp);$i<$len;$i++)
{$arr[$left+$i]
= $temp[$i];}}$arr=
array(23,0,32,45,56,75,43,0,34);mergeSort($arr);var_dump($arr);?> |
7.堆排序
原理:堆排序就是利用堆进行排序的方法.基本思想是:将待排序的序列构造成一个大顶堆.此时,整个序列的最大值就是堆顶 的根结点.将它移走(其实就是将其与堆数组的末尾元素交换, 此时末尾元素就是最大值),然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素的次大值.如此反复执行,便能得到一个有序序列了
时间复杂度:平均情况:O(nlog2n) 最好情况:O(nlog2n) 最坏情况:O(nlog2n)
空间复杂度:O(1)
稳定性:不稳定
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
//JavaScript 堆排序
vararray = [23,0,32,45,56,75,43,0,34];functionheapSort(array){for(var
i = Math.floor(array.length / 2); i >= 0; i--){heapAdjust(array, i, array.length - 1);//将数组array构建成一个大顶堆}for(i = array.length - 1; i >= 0; i--){/*把根节点交换出去*/vartemp = array[i];array[i] = array[0];array[0] = temp;/*余下的数组继续构建成大顶堆*/heapAdjust(array, 0, i - 1);}returnarray;}functionheapAdjust(array, start, max){vartemp = array[start];//temp是根节点的值for(var
j = 2 * start; j < max; j *= 2){if(j < max && array[j] < array[j + 1]){//取得较大孩子的下标++j;}if(temp >= array[j])break;array[start] = array[j];start = j;}array[start] = temp;}varnewArray = heapSort(array);console.log(newArray); |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
<?php//堆排序functionheapSort(&$arr) {#初始化大顶堆initHeap($arr, 0,count($arr)
- 1);#开始交换首尾节点,并每次减少一个末尾节点再调整堆,直到剩下一个元素for($end=
count($arr) - 1;$end
> 0; $end--) {$temp=
$arr[0];$arr[0] =$arr[$end];$arr[$end] =$temp;ajustNodes($arr, 0,$end
- 1);}}#初始化最大堆,从最后一个非叶子节点开始,最后一个非叶子节点编号为 数组长度/2 向下取整functioninitHeap(&$arr) {$len=
count($arr);for($start=
floor($len/ 2) - 1;
$start>= 0;
$start--) {ajustNodes($arr,$start,
$len- 1);}}#调整节点#@param$arr
待调整数组#@param$start
调整的父节点坐标#@param$end
待调整数组结束节点坐标functionajustNodes(&$arr,$start,
$end) {$maxInx=
$start;$len=
$end + 1; #待调整部分长度$leftChildInx= ($start
+ 1) * 2 - 1; #左孩子坐标$rightChildInx= ($start
+ 1) * 2; #右孩子坐标#如果待调整部分有左孩子if($leftChildInx+ 1 <=
$len) {#获取最小节点坐标if($arr[$maxInx]
< $arr[$leftChildInx]) {$maxInx=
$leftChildInx;}#如果待调整部分有右子节点if($rightChildInx+ 1 <=
$len) {if($arr[$maxInx]
< $arr[$rightChildInx]) {$maxInx=
$rightChildInx;}}}#交换父节点和最大节点if($start!=
$maxInx) {$temp=
$arr[$start];$arr[$start] =$arr[$maxInx];$arr[$maxInx] =$temp;#如果交换后的子节点还有子节点,继续调整if(($maxInx+ 1) * 2 <=
$len) {ajustNodes($arr,$maxInx,
$end);}}}$arr=
array(23,0,32,45,56,75,43,0,34);heapSort($arr);var_dump($arr);?> |
8.基数排序
原理:将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。
时间复杂度:平均情况:O(d(r+n)) 最好情况:O(d(n+rd)) 最坏情况:O(d(r+n)) r:关键字的基数 d:长度 n:关键字个数
空间复杂度:O(rd+n)
稳定性:稳定
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
<?php#基数排序,此处仅对正整数进行排序,至于负数和浮点数,需要用到补码,各位有兴趣自行研究#计数排序#@param$arr
待排序数组#@param$digit_num
根据第几位数进行排序functioncounting_sort(&$arr,$digit_num
= false) {if($digit_num
!== false) { #如果参数$digit_num不为空,则根据元素的第$digit_num位数进行排序for($i
= 0; $i
< count($arr);$i++) {$arr_temp[$i] = get_specific_digit($arr[$i],$digit_num);}}else
{$arr_temp=
$arr;}$max= max($arr);$time_arr=
array(); #储存元素出现次数的数组#初始化出现次数数组for($i
= 0; $i
<= $max;
$i++) {$time_arr[$i] = 0;}#统计每个元素出现次数for($i
= 0; $i
< count($arr_temp);$i++) {$time_arr[$arr_temp[$i]]++;}#统计每个元素比其小或相等的元素出现次数for($i
= 0; $i
< count($time_arr) - 1;$i++) {$time_arr[$i+ 1] +=
$time_arr[$i];}#利用出现次数对数组进行排序for($i=
count($arr) - 1;$i
>= 0; $i--) {$sorted_arr[$time_arr[$arr_temp[$i]]
- 1] = $arr[$i];$time_arr[$arr_temp[$i]]--;}$arr=
$sorted_arr;ksort($arr); #忽略这次对key排序的效率损耗}#计算某个数的位数functionget_digit($number) {$i= 1;while($number
>= pow(10, $i)) {$i++;}return$i;}#获取某个数字的从个位算起的第i位数functionget_specific_digit($num,$i)
{if($num
< pow(10, $i
- 1)) {return0;}returnfloor($num% pow(10,
$i) / pow(10,$i
- 1));}#基数排序,以计数排序作为子排序过程functionradix_sort(&$arr) {#先求出数组中最大的位数$max= max($arr);$max_digit= get_digit($max);for($i
= 1; $i
<= $max_digit;
$i++) {counting_sort($arr,$i);}}$arr=
array(23,0,32,45,56,75,43,0,34);radix_sort($arr);var_dump($arr);?> |
本文详细介绍了包括冒泡排序、简单选择排序、直接插入排序、快速排序、希尔排序、归并排序、堆排序和基数排序在内的八种经典排序算法。每种算法都包含了其实现原理、时间与空间复杂度分析及稳定性讨论。
172

被折叠的 条评论
为什么被折叠?



