一、冒泡排序
1、排序原理
①从第一个元素开始,把当前元素和下一个索引的元素比较,如果当前元素大于下一个元素,则把当前元素和下一个元素互换位置,以此类推,直到比较到最后一个元素,此时,最后一个元素就是数组中的最大的元素。
②循环①中的排序流程,但要注意的是第一轮排序之后,最后一个元素已经是最大的,所以第二轮排序时只用排序到第length-1
个元素。
③下一轮重复②中的操作,排序最后位置依次减1.
2、代码实现
//元素交换位置
function swap(arr, left, right) {
let mid_value = arr[left]
arr[left] = arr[right]
arr[right] = mid_value
}
function bubble(arr) {
for(let j = arr.length-1; j>0; j--){
for(let i=0; i<j; i++){
if(arr[i]>arr[i+1]){
swap(arr, i, i+1)
}
}
}
return arr
}
运行结果:
二、快速排序
1、排序原理
①选取系列中的第一个元素作为基准值,并存入变脸x中;
②从待排序序列右侧扫描,把小于基准值的元素移动到序列左侧;
③从待排序序列左侧扫描,把大于基准值的元素移到序列右侧;
④把变量x中的值插入分界处,到此就完成了一趟快排;
⑤通过第一趟快排后,序列就被划分成了两个子表,且基准值左侧的元素均小于基准值,右侧的元素均大于基准值。
⑥分别对左子表和右子表继续按上述①-⑤规则继续进行分割,直到所有子表长度不超过1为止,此时也就完成了快速排序。
代码实现:
let arr=[8,9,5,6,2,7,10,15,19]
function quickPass(arr, low, high) {
let x,i=1
x=arr[low]
while(low<high){
while(low<high &&arr[high]>x){
high--
}
if(low<high){
arr[low]=arr[high]
low++
}
while(low<high && arr[low]<x){
low++
}
if(low<high) {
arr[high]=arr[low]
high--
}
i++
}
arr[low]=x
return low
}
function quickSort(arr, low, high){
if(low<high){
let pos = quickPass(arr, low, high)
quickSort(arr, low, pos-1)
quickSort(arr, pos+1, high)
}
return arr
}
运行结果:
三、归并排序
基本思想: 归并排序是基于合并,将两个或两个以上有序表合并成一个新的有序表。
排序原理:假设初始序列有n个记录。①将n个记录看成n个有序的子序列,每个子序列的长度为1。②然后两两归并,当n为偶数时,得到n/2个长度为2的有序子序列,当n为奇数时,得到floor(n/2)个长度为2的有序子序列加1个长度为1的子序列。③在此基础上,再对长度为2的有序子序列进行两两归并,得到若干长度为4的有序子序列。如此重复,直到得到一个长度为n的有序序列为止。
代码实现:
function merge(left, right){
var result=[];
while(left.length>0 && right.length>0){
if(left[0]<right[0]){
/*shift()方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。*/
result.push(left.shift());
}else{
result.push(right.shift());
}
}
return result.concat(left).concat(right);
}
function mergeSort(items){
if(items.length == 1){
return items;
}
var middle = Math.floor(items.length/2),
left = items.slice(0, middle),
right = items.slice(middle);
return merge(mergeSort(left), mergeSort(right));
}
运行结果:
四、插入排序
基本思想:在一个已排好序的记录子集的基础上,每一步将下一个待排序的记录有序插入到已排好序的记录子集中,直到将所有待排记录全部插入为止。例如,打扑克牌时的抓牌就是插入排序的一个很好的例子,每抓一张牌,插入到合适位置,直到抓完牌为止,即可得到一个有序序列。
排序过程:①将第i个(从第一个开始)记录视为已排好序的单元素子集盒。②将第i+1个记录存入辅助变量x中(视为待排序记录)。③将x与前面的记录顺次比较,将所有大于x的记录依次向后移动一个位置,直到遇到一个小于或者等于x的记录,此时此记录后面的位置为空,则将x插入此位置,到此就完成了一个待排记录的插入排序。④循环上述②-③,直到所有待排记录全部插入为止。
代码实现:
let x, j
function insSort(arr) {
for(let i=0;i<arr.length-1;i++){
x= arr[i+1]
j =i
while(x<arr[j]) {
arr[j+1]=arr[j]
j--
}
arr[j+1] = x
}
return arr
}
运行结果:
五、希尔排序
基本思想:先将待排序记录序列以增量(一般初次取序列的一半,以后每次减半,直到为1)为间隔,分割成若干个“较稀疏的”子序列,分别进行直接插入排序。经过对分组的排序,整个序列中的记录已经基本有序,最后再对全部记录进行一次直接插入排序。
排序过程:①取序列的一半(Math.floor(n/2))
为增量d1
。②把所有索引相隔d1
的记录放一组,组内进行直接插入排序。③取d1
的一半(Math.floor(d1/2))
为增量d2
,重复上述②中的步骤。④重复上述②-③步骤,直到增量为1
,即所有记录放同一组里。⑤最后对这组记录进行直接插入排序,即可完成序列的希尔排序。
代码实现:
function shellSort(arr) {
let len = arr.length
for(let d=Math.floor(len/2); d>0; d=Math.floor(d/2)) {
for(let i=d; i<len; i++) {
for(let j=i-d; j>=0&&arr[j]>arr[j+d]; j-=d) {
let temp = arr[j]
arr[j] = arr[d+j]
arr[d+j] = temp
}
}
}
return arr
}
运行结果: