冒泡
执行方式:
- 1.比较相邻的俩个元素,第一个大于第二个,交换位置
- 2对每个相邻的元素做同样的动作,从开始到最后一对,完成之后,最后一个元素是最大的
- 3.重复上一个步骤,除了最后一个
- 4.持续上述步骤,直到没有任何数字比较
5,3,2,1
i = 0| 5>3 3 5 2 1
i = 1| 5>2 3 2 5 1
i = 2| 5>1 3 2 1 5
[0,len-1]
i = 0| 3>2 2 3 1 5
i = 1| 3>1 2 1 3 5
[0,len-1-1]
i = 0| 2>1 1 2 3 5
[0,len-1-1-1]
function sortArray(nums: number[]): number[] {
let len = nums.length;
if ((len <= 1)) {
return nums;
}
for (let i = 0; i < len - 1; i++) {
for (let j = 0; j < len - 1 - i; j++) {
if (nums[j] > nums[j + 1]) {
[nums[j],nums[j+1]] = [nums[j+1],nums[j]]
}
}
}
return nums
}
console.log(sortArray([5,3,2,1]));
时间复杂度为:O(n^2) 空间复杂度为:因为是俩俩交换,没有改变位置。 O(1)
快排
思路:分区交换排序,把一个序列分为较小和较大2个子序列,递归排序2个子序列
- 1.基准值:从数列中挑出一个元素
- 2.分割,比基准值小的放基准前面,大的放后面,相等的随便
- 3.递归排序子序列:递归将小于基准值元素的子序列和大于基准值的子序列排序
- 判断条件,递归到底部时数列的大小为0||1
quickSort(nums,left:左边的下标,right:右边的下标)
25743698
p:3
2 3 574698
p:6
23 54 6 798
p1:4 p2: 9
23 4 5 6 78 9
「简版」
function quickSort(nums: number[]): number[] {
if (nums.length <= 1) {
return nums;
}
let p = nums[Math.floor(nums.length / 2)];
let leftList = [];
let rightList = [];
for (let i = 0; i < nums.length; i++) {
if (nums[i] < p) {
leftList.push(nums[i]);
}
if (nums[i] > p) {
rightList.push(nums[i]);
}
}
console.log(p, leftList, rightList);
return quickSort(leftList).concat([p], quickSort(rightList));
}
console.log(quickSort([2, 5, 7, 4, 3, 6, 9, 8]));
「复杂版」
sortArray([2, 5, 7, 4, 3, 6, 9, 8]);
function sortArray(nums: number[]) {
let len = nums.length;
if (len <= 1) {
return nums;
}
sort(nums, 0, len - 1);
function sort(nums: number[], left: number, right: number) {
if (left < right) {
//获取基准的下标
let pIndex = getPivot(nums, left, right);
//左子序列,此序列必定比p(基准值)小
sort(nums, left, pIndex - 1);
//右子序列,此序列必定比p(基准值)大
sort(nums, pIndex + 1, right);
}
}
function getPivot(nums: number[], left: number, right: number) {
let p = nums[left];//默认基准为最左边的数
let i = left;
let j = right + 1;//因为数组最后一个元素也要参与比较,如果是下标经过--j那就是往左一个元素和nums[i]比较
//i和j要从俩边遍历和p对比,那么当i>=j的时候数组的元素就都和p比较过了。所以结束条件为i>=j
while (1) {
//从左向右遍历,当i>p的时候,i左边的元素必定都是小于p的元素
while (nums[++i] < p) {
if (i === right) {
break;
}
}
//从右向左遍历,当j<p的时候,j右边的元素必定都是大于p的元素
while (nums[--j] > p) {
if (j === left) {
break;
}
}
if (i >= j) {
break;
}
//i<j,说明i和j之间还有没比较的元素,先对比一下i和j。
//因为nums[i]<p,nums[j]>p,当他俩交合说明交合处坐标的左边小于p,右边大于p
//所以基准坐标必定在i和j的交界处,所以nums[i]<nums[j]不满足就替换
[nums[i], nums[j]] = [nums[j], nums[i]];
}
//j就是基准坐标,基准值nuns[left]就该放到j的位置,因为i>=j,此时nums[j]必定小于基准
[nums[left], nums[j]] = [nums[j], nums[left]];
return j;
}
}
export {}
「运行过程」
5(p)(i),4,3,2,6,undefined(j)
num[++i] < p
4 < 5 i=1
3 < 5 i=2
2 < 5 i=3
6 > 5【break】 i=4
nums[--j] >p
6 > 5 j=4
2 < 5 【break】j=3
i > j
nums:24356
2(p)(i) 4 3,undfined(j)
num[++i] < p
4 > 2【break】i=1
nums[--j] >p
3 > 2 j=2
4>2 j=1
2=2 【break】j=0
i>j
nums:24356
4(p)(i) 3 undfined(j)
num[++i] < p
3 < 4 i=1
und 【break】i=2
nums[--j] >p
3 < 4 【break】j=1
i > j
nums:23456
时间复杂度:O(nlogN) 空间复杂度:O(logN)