一、冒泡排序:两两比较,大的放后面,小的放前面;使用两个for循环,一个数就不用比了,所以第一个for循环遍历次数n-1次,第二个for比较次数n
// 冒泡排序:思路=》两两交换,大的放后面,小的放前面,第一次排序后最大值已在数组末尾
// 代码实现:两个for循环,外层循环控制排序的趟数,内层循环控制比较次数。每趟过后比较次数都应该减一
function sort (arr,n){
let temp
for(let i=0;i<n-1;i++){
for (let j=0;j<n-i-1;j++) {
if(arr[j]>arr[j+1]){
temp = arr[j+1]
arr[j+1] = arr[j]
arr[j] = temp
}
}
}
return arr
}
let arr = [3,2,5,7,9,4,1,6]
let n = arr.length
console.log(sort(arr,n));
// [1, 2, 3, 4, 5, 6, 7, 9]
function sort (arr,n){
let temp
for(let i=0;i<n-1;i++){
for (let j=i+1;j<n;j++) {
if(arr[i]<arr[j]){
temp = arr[j]
arr[j] = arr[i]
arr[i] = temp
}
}
}
return arr
}
let arr = [3,2,5,7,9,4,1,6]
let n = arr.length
console.log(sort(arr,n));
// [9, 7, 6, 5, 4, 3, 2, 1]
二、选择排序
// 选择排序:找到数组中最大的元素,与数组最后一位元素交换。当只有一个数时,则不需要选择了,所以需要n-1趟排序
// 思路:两个for循环,外层循环控制排序的趟数,内层循环找到当前趟数的最大值,随后与当前趟数数组最后的一位元素交换
function sort (arr,n){
let temp
let max=0
for(let i=0;i<n-1;i++){
for (let j=0;j<n-i;j++) {
if(arr[j]>arr[max]){
max=j
}
}
temp=arr[max]
arr[max] = arr[n-1-i]
arr[n-1-i]=temp
}
return arr
}
let arr1 = [3,2,5,7,9,4,1,6,8]
let n1 = arr1.length
console.log(sort(arr1,n1));
//[1, 2, 3, 4, 5, 6, 7, 8, 9]
三、快速排序 :取一个数作为基准值[以中间项为基准值],小于这个基准数的放在左边,大于基准值的放在右边,递归
三种实现的方式,参考如下
/*
大致分三步:
1、找基准(一般是以中间项为基准)
2、遍历数组,小于基准的放在left,大于基准的放在right
3、递归
*/
function quickSort(arr){
//如果数组<=1,则直接返回
if(arr.length<=1){
return arr
}
let pointIndex = Math.floor(arr.length/2) //基准值
let left = []
let right = []
let point = arr.splice(pointIndex,1)[0] //把基准从原来的数组中删除
for(let i=0;i<arr.length;i++){
// 小于基准的放在左边
if(arr[i]<=point){
left.push(arr[i])
}else{ //大于基准的放右边
right.push(arr[i])
}
}
//递归
return quickSort(left).concat([point],quickSort(right));
}
let arr = [3,2,5,7,9,4,1,6]
console.log(quickSort(arr));
// 快速排序:取一个数作为基准值[以中间项为基准值],小于这个基准数的放在左边,大于基准值的放在右边,递归
function sort (arr,l,r){
let i = l
let j =r
let c = Math.floor((l+r)/2) //取中间值作为指点,比较
console.log('c==='+c);
let temp
// 左右两端进行扫描,只要两端还没有交替,就一直扫描
while(i<=j){
// 寻找直到比支点大的数
while(arr[i]<arr[c]){
i++
console.log('i====='+i);
}
// 寻找直到比支点小的数
while(arr[c]<arr[j]){
j--
console.log('j===='+j);
}
// 此时找到了比支点小的数(右边),比支点大的数(左边),将他们交换位置
if(i<=j){
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
i++
j--
}
console.log(arr);
}
// “左边”再做排序,直到左边剩下一个数(递归出口)
if(l<j){
sort(arr,l,j)
}
// "右边"再做排序,直到右边剩下一个数(递归出口)
if(i<r){
sort(arr,i,r)
}
console.log(arr);
}
let arr1 = [3,2,5,7,9,4,1,6,8]
let n1 = arr1.length
sort(arr1,0,n1-1)
function quickSort(arr, left, right) {
/*
* len为数组的长度;
* left为需要数组中参与排序的起始点;right为数组中参与排序的终止点;
* left如果有传数字那么就为left,没有传参则为0;
* right如果有传参那么就为right,没有传参则为len-1;
* 有传参可能会部分排序可能不会排序,没传参默认排序整个数组;
* partitionIndex为分组界限;
*/
var len = arr.length,
partitionIndex,
left = typeof left !== 'number' ? 0 : left,
right = typeof right !== 'number' ? len - 1 : right;
// 如果需要排序的起始索引小于终止索引则执行排序;递归的终止条件;
if (left < right) {
// partition的返回值作为partitionIndex来分隔数组;
// 索引partitionIndex左边的元素均小于arr[partitionIndex];
// 右边的元素均大于arr[partitionIndex];
partitionIndex = partition(arr, left, right);
// 数组中小于arr[partitionIndex]的部分(索引left到partitionIndex-1)再次使用quickSort排序;
quickSort(arr, left, partitionIndex - 1);
// 数组中大于arr[partitionIndex]的部分(索引partitionIndex+1到right)再次使用quickSort排序;
quickSort(arr, partitionIndex + 1, right);
}
// 递归执行直到不满足left<right;返回本身;
return arr;
}
function partition(arr, left, right) {
/*
* 这部分是具体实现排序的部分;
* 将left赋值给pivot,作为参照物,因为left在最左边,只需要从左到右比较一遍即可判断整个数组;
* index索引是arr中待交换位置;
*/
var pivot = left,
index = pivot + 1;
// for循环从参照物arr[pivot]下一个元素arr[pivot+1]开始一直比较到子数组结束arr[right];
for (var i = index; i <= right; i++) {
// 循环中如果有任何小于参照物的,就将他交换到index的位置,然后index向右移动到下一个位置;
if (arr[i] < arr[pivot]) {
swap(arr, i, index);
index++;
}
}
/*
* 因为每次都是交换完后index移动到下一个位置,所以在循环结束时,index仍为待交换的位置;
* 此时索引pivot+1到index-1的元素都小于参照物arr[pivot];
*/
// 交换pivot和index-1索引的值之后index-1索引左边全都是小于arr[index-1]的元素;
swap(arr, pivot, index - 1);
// 返回index-1作为拆分子数组的分界线;
return index - 1;
}
/*
* 普通的交换,将a[i]和a[j]的数值交换;
*/
function swap(arr, i, j) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
let arr1 = [3,2,5,7,9,4,1,6,8]
let n1 = arr1.length
console.log(quickSort(arr1,0,n1-1));
插入排序
归并排序
堆排序
希尔排序
基数排序
递归