一、基础算法 – 排序算法
冒泡排序
冒泡排序是一种简单直观的排序,其基本思想是:在一组待排序的数中,将相邻的两个数进行比较,若前面的数比后面的数大就交换两数,否则就不交换,如此重复遍历下去,直到没有交换的数完成排序
实现步骤:
- 比较相邻的元素,如果第一个比第二个大就交换
- 对每一对相邻的元素都进行同样的比较工作,直到最后一对
- 作完这一步,最后的元素是最大的元素,也就是说外层循环完成一次,就确定了一个最大的数,所以内层循环中可以把 外层循环的此时给相减,从而实现减少循环次数的目的
:::
int[] arr = {23, 123, 1, 45, 21, 35, 87, 31, 29, 56, 78};
//外层循环
for(int i = 0; i< arr.length -1;i++){
//内层循环
for(int j = 0; i<arr.length -1 - i ; j++){
//判断相邻元素第一个元素是否比第二个元素大
if(arr[j] > arr[j+1]){
//交换位置
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
int[] arr = {23, 123, 1, 45, 21, 35, 87, 31, 29, 56, 78};
boolean flag = false;
//外层循环
for(int i = 0; i< arr.length -1;i++){
//内层循环
for(int j = 0; i<arr.length -1 - i ; j++){
//判断相邻元素第一个元素是否比第二个元素大
if(arr[j] > arr[j+1]){
//交换位置
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = true;
}
}
if(!flag){
break; //无需排序,因为已经拍好了
}
}
2、鸡尾酒排序(双向冒泡排序)
鸡尾酒排序是冒泡排序的一种变体,它从低到高然后从高到低依次排序,比冒泡排序的效率稍微高一点
int[] arr = {23, 123, 1, 45, 21, 35, 87, 31, 29, 56, 78};
int start = 0; //初始位置
int end = arr.length -1;
int flag = true; //循环标识
while(flag){
flag = false;
//从左到右(确认一个最大值)
for(int i = start; i< end ; i++){
if(arr[i] > arr[i+1]){
//交换位置
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
flag = true;
}
}
//判断是否是已经排列好的
if(!flag){
break;
}
//重置标识
flag = false;
//经过一次从左到右确认一个最大值
end --;
//从右到左(确认一个最小值)
for(int i = end -1;i>=start;i--){
if(arr[i] > arr[i+1]){
//交换位置
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
flag = true;
}
}
//一次从右到左确认一个最小值
start++;
}
测试题:
冒泡排序的时间复杂度是多少? | 冒泡排序的平均时间复杂度是O(n²)。 |
---|---|
冒泡排序是稳定的排序算法吗? | 是的,因为只有当前一个元素大于后一个元素才会交换位置,相等的元素不会交换位置 |
对于已经排好序的数组,优化版冒泡排序的时间复杂度是多少? | 优化版冒泡排序的时间复杂度是O(n)。因为第一轮遍历不会发生交换,优化版会检测到这点并提前终止。 |
冒泡排序每一轮遍历后,数组尾部会有什么特点? | 数组尾部会有一个元素到达其最终位置,且是当前未排序部分中的最大元素 |
如何优化冒泡排序以提高效率? | 1、添加标识,判断是否发生位置交换,无交换则退出 2、记录交换的位置,下次遍历从上次的位置开始 3、使用鸡尾酒排序,同时将最大值上浮,最小值下沉 |