1.冒泡排序
对未排序的各个元素从头到尾依次比较相邻两个元素的大小关系
如果左边高,则交换两个元素的位置
然后右移一格,比较下面的两个
当移动到最右端(未排序的最右端) ,那么最大值就应该在这,那么这个最右端的就是已排序的
然后从未排序的中继续寻找
关于最外层循环的个数个计算:
排
arr.length
个数,且最后一个不要排,所以要排arr.length-1
次未排序的最右端的计算:
第一次:i=0 最大值放在
arr.length-1
上 计算arr.length-1-0
第二次:i=0 最大值放在
arr.length-2
上 计算arr.length-1-1
...
总结为:
arr.length-1-i
*/
function bubble_sort (arr) {
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
let flag = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = flag;
}
}
}
return arr
}
let result = bubble_sort([2, 1, 62, 4, 3, 7, 5, 88, 65, 0]);
console.log(result);
2.选择排序
function selectioin_sort (arr) {
for (let i = 0; i < arr.length - 1; i++) {
//不需要频繁交换,每趟都检测,是否应该换位置,如果要换位置,就把需要换的位置记录下来
let recordIndex = i;
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
recordIndex = j;
}
}
// 将记录下来的位置和i比较,如果不一致,就说明应该交换
if (recordIndex != i) {
let temp = arr[i];
arr[i] = arr[recordIndex];
arr[recordIndex] = temp;
}
}
return arr;
}
let result = selectioin_sort([2, 1, 62, 4, 3, 7, 5, 88, 65, 0, -1, 33]);
console.log(result);
3.直接插入排序
思路(从小到大):
首先第一次的时候,默认第一位是已经排好序的
然后从第二个开始(前面是已排序的,后面是未排序的 ,而且每次都要用一个变量temp来记录这个未排序中的第一个数),与前面的已排序的进行比较(从已排序的最后一个开始比较 ,用j记录
),如果比第二个大(arr[j] > temp
),则向后移动一格(arr[j+1] = arr[j]
),然后j--
,再比较,直到最后找到一个小于temp,就停止。然后交换(arr[j+1] = temp
)
接着取下一组未排序中的第一个值,重复第二步,直到最后一个,就完成排序。
临界条件:temp比第一个(下标值为0
)还小,那么继续j--
(此时下标值为-1
) , 此时应该停止,这就说明,当j>=0
的时候是不停止的
function inser_sort (arr) {
for (let i = 1; i < arr.length; i++) {
let temp = arr[i];
let j = i - 1;//j在for循环外面,保证在下面可以用到
for (j; j >= 0 && arr[j] > temp; j--) {
arr[j + 1] = arr[j];
}
//因为每次比较的时候都是arr[j] > temp , 当遇到arr[j] <= temp的时候,已经是不需要移动了,所以要+1插入到后面的一个空位
arr[j + 1] = temp;
}
return arr;
}
let result = inser_sort([2, 1, 62, 4, 3, 7, 5, 88, 65, 0]);
console.log(result);
4.希尔排序
希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法
该方法实质上是一种分组插入方法
比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。
一般的初次取序列的一半为增量,以后每次减半,直到增量为1。 ----------------来自百度
这个版本是在找资料过程中发现的一个比较好的,思路清晰,比其他的读起来更加容易一点
function shell_sort (arr) {
let length = arr.length;
for (let gap = parseInt(length / 2); gap > 0; gap = parseInt(gap / 2)) {
for (let i = gap; i < length; i++) {
insert_sort(arr, i, gap);
}
}
return arr;
}
function insert_sort (arr, index, gap) {
// 为什么这里不能用j=index,然后用index来记录需要插入的值,因为index虽然是不该变得,但是如果平移之后,index里所对应的值就改变了
let insert = arr[index];
let j;
for (j = index - gap; j >= 0 && arr[j] > insert; j -= gap) {
arr[j + gap] = arr[j];
}
arr[j + gap] = insert;
}
let arr = [2, 1, 62, 4, 3, 7, 5, 88, 65, 0]
let result = shell_sort(arr);
console.log(arr);
5.快速排序
注:从小到大
此代码来自b站coderwhy的数据结构
基准选择:
取left
, right
, mid = parseInt((left + right) / 2)(将其转化为整数)
, 然后将这三个位置上的数,从小到大排列,mid就是基准值
,
为了不让基准值到最后或者是最前面 , 将mid与length-1位置上的数交换,最后将基准值返回出去。
// 基准判定的函数
function pivotFunc (arr, left, right) {
let mid = parseInt((right + left) / 2);
if (arr[left] > arr[mid]) {
[arr[left], arr[mid]] = [arr[mid], arr[left]];
}
if (arr[left] > arr[right]) {
[arr[left], arr[right]] = [arr[right], arr[left]];
}
// 前两个if是确定第一位是最小的
// 下面的if只要做两个数大小的判断
if (arr[mid] > arr[right]) {
[arr[mid], arr[right]] = [arr[right], arr[mid]]
}
// 让基准数再放倒数第二个
[arr[mid], arr[right - 1]] = [arr[right - 1], arr[mid]]
return arr[right - 1];
}
进行快速排序:
快速排序大多数使用递归,递归的终止条件是,left>=right . 当left >=right的时候,说明到最后,每组只有一个数据。
首先要明白的一点,pivot的左边是小于pivot的,右边是大于等于pivot的
然后,先获取 let pivot = pivotFunc(arr, left, right);
,记住现在的pivot已经被记录下来了
用i=left来记录左边的位置
用j=right-1来记录右边的位置(j=right-1的原因是,right是大于基准值的,right-1是基准值得位置,)
然后从i开始,如果arr[i] < pivot,就说明没有大于基准值,所以i++,当arr[i]>=pivot的时候,需要暂停i这边的,然后从j往前找有没有小于pivot的,如果有,就将他们两个交换,如果没有,j--
找到j<pivot就交换arr[i]和arr[j]
然后接着重复以上步骤,直到i<j不成立。
function quick_sort (arr, left, right) {
if (left >= right) return;
let pivot = pivotFunc(arr, left, right);
let i = left;
let j = right - 1;
while (true) {
while (i < j && arr[i] < pivot) i++;
while (i < j && arr[j] > pivot) j--;
if (i < j) {
[arr[i], arr[j]] = [arr[j], arr[i]]
} else {
break;
}
}
[arr[i], pivot] = [pivot, arr[i]];
quick_sort(arr, left, i - 1);
quick_sort(arr, i + 1, right);
return arr;
}
全部代码:
// 基准判定的函数
function pivotFunc (arr, left, right) {
let mid = parseInt((right + left) / 2);
if (arr[left] > arr[mid]) {
[arr[left], arr[mid]] = [arr[mid], arr[left]];
}
if (arr[left] > arr[right]) {
[arr[left], arr[right]] = [arr[right], arr[left]];
}
// 前两个if是确定第一位是最小的
// 下面的if只要做两个数大小的判断
if (arr[mid] > arr[right]) {
[arr[mid], arr[right]] = [arr[right], arr[mid]]
}
// 让基准数再放倒数第二个
[arr[mid], arr[right - 1]] = [arr[right - 1], arr[mid]]
return arr[right - 1];
}
function quick_sort (arr, left, right) {
if (left >= right) return;
let pivot = pivotFunc(arr, left, right);
let i = left;
let j = right - 1;
while (true) {
while (i < j && arr[i] < pivot) i++;
while (i < j && arr[j] > pivot) j--;
if (i < j) {
[arr[i], arr[j]] = [arr[j], arr[i]]
} else {
break;
}
}
[arr[i], pivot] = [pivot, arr[i]];
quick_sort(arr, left, i - 1);
quick_sort(arr, i + 1, right);
return arr;
}
let arr = [2, 1, 62, 4, 3, 7, 5, 88, 65, 0];
console.log(arr);
let result = quick_sort(arr, 0, arr.length - 1);
console.log(result);