>[warning]冒泡排序(最经典的算法)
----
> 相邻比较, 多跑几次
----
看图说话
![](https://box.kancloud.cn/5a15e1d04745123a0cc6de5a90e881d9_580x580.gif)
这里使用JavaScript代码实现:
1. 先学会交换2个变量的值
~~~
let a = 10, b = 20;
let c = a;
a = b;
b = c;
console.log(a, b);
~~~
2. 遍历数组, 交换相邻2个位置元素的值
~~~
let arr = [2, 5, 8, 1, 3, 4, 10, 9];
for (let i = 0; i < arr.length - 1; i++){
let c = arr[i + 1];
arr[i + 1] = arr[i];
arr[i] = c;
}
console.log(arr);
// 注意遍历时长度要-1, 当i到7时i+1超出数组下标了, 会动态导致arr.length变大, 导致死循环
~~~
3. 遍历一个数组, 当i位置元素大于i+1位置元素, 再交换相邻2个元素位置
~~~
let arr = [2, 5, 8, 1, 3, 4, 10, 9];
for (let i = 0; i < arr.length - 1; i++){
if (arr[i] > arr[i + 1]){
let c = arr[i + 1];
arr[i + 1] = arr[i];
arr[i] = c;
}
}
console.log(arr);
~~~
4. 我们只需要让上面的for循环的代码多执行几次, 就可以排好整个数组呢?
~~~
let arr = [2, 5, 8, 1, 3, 4, 10, 9];
for (let h = 0; h < arr.length; h++) {
for (let i = 0; i < arr.length - 1; i++) {
if (arr[i] > arr[i + 1]) {
let c = arr[i + 1];
arr[i + 1] = arr[i];
arr[i] = c;
}
}
}
console.log(arr);
~~~
-----------
## 扩展1:
~~~
// 外层循环可以优化
// 最坏情况, 当h的值为7时, 其实这个时候数组已经排好序了, 没有必要再执行了, 所以最外层-1
~~~
优化后代码
~~~
let arr = [2, 5, 8, 1, 3, 4, 10, 9];
for (let h = 0; h < arr.length - 1; h++) {
for (let i = 0; i < arr.length - 1; i++) {
if (arr[i] > arr[i + 1]) {
let c = arr[i + 1];
arr[i + 1] = arr[i];
arr[i] = c;
}
}
}
console.log(arr);
~~~
-----
## 扩展2:
~~~
// 内层循环可以优化
/*
* h的值, 数组结果
* 0 [2, 5, 1, 3, 4, 8, 9, 10]
* 1 [2, 1, 3, 4, 5, 8, 9, 10]
* h为1时, 下角标为7的元素, 不必再参加下次比较了, 因为它已经是最大了, 所以内层循环不光-1 还要 -h
*/
~~~
优化后代码:
~~~
let arr = [2, 5, 8, 1, 3, 4, 10, 9];
for (let h = 0; h < arr.length - 1; h++) {
for (let i = 0; i < arr.length - 1 - h; i++) {
if (arr[i] > arr[i + 1]) {
let c = arr[i + 1];
arr[i + 1] = arr[i];
arr[i] = c;
}
}
}
console.log(arr);
~~~
-----
## 扩展3:
~~~
// 上面的代码可以优化, 思考, 每次for循环后数组最新的情况得知
/*
* h的值; 数组结果
* 0 [2, 5, 1, 3, 4, 8, 9, 10]
* 1 [2, 1, 3, 4, 5, 8, 9, 10]
* 2 [1, 2, 3, 4, 5, 8, 9, 10]
* */
// 我们发现执行3次就排好序了, 但是代码会继续执行完毕, 直到h大于8才停止. 所以
// 如果内层if, 没发生过交换, 就让最外层循环停下来吧
~~~
优化后代码:
~~~
let arr = [2, 5, 8, 1, 3, 4, 10, 9];
let flag = true; // 标记发生没发生过交换
for (let h = 0; h < arr.length - 1 && flag; h++) {
flag = false;
for (let i = 0; i < arr.length - 1 - h; i++) {
if (arr[i] > arr[i + 1]) {
let c = arr[i + 1];
arr[i + 1] = arr[i];
arr[i] = c;
flag = true; // 发生交换了, 因为if里执行了
}
}
}
~~~
- web前端
- CSS问题
- 布局
- 双飞翼布局_flex方式
- 双飞翼布局_margin方式
- 圣杯布局_flex方式
- 圣杯布局_margin方式
- 子元素居中问题
- 弹性布局
- 概念_
- 标准模式与混杂模式
- 各种FC
- line-height
- vertical-align
- CSS3新特性
- 效果
- div添加箭头
- CSS绘制三角形
- JavaScript
- 兼容
- 事件相关
- 原理
- Ajax原理
- 继承原理
- 原型链继承
- 组合继承
- 寄生组合继承
- 数据绑定
- 1单向数据绑定m到c到v
- 2伪双向数据绑定
- 3双向数据绑定
- socket.io
- 运行时
- this指向
- 0.1+0.2问题
- 对象/数组-深拷贝&浅拷贝
- 事件循环
- typeof
- instanceof
- 概念
- 闭包
- 回调函数
- Promise
- 原生对象
- Attribute和property区别
- 防抖函数
- 节流函数
- 语言类型
- Vue
- Vue优缺点
- 仿Vue源码
- 1数据绑定_Observe
- 2数据绑定_订阅者&观察者定义
- 3数据绑定_Vue类实现
- 4数据绑定_Vue访问data更改
- 5DOM编译_Compile_双大括号模板讲解
- 6DOM编译_v-model讲解
- 7DOM编译_v-on:事件绑定讲解
- 项目总结
- 使用Svg图标
- vueCli环境_真机测试
- vueCli集成环信SDK
- 父子组件双向绑定
- React
- React优缺点
- 我的组件库
- Vue的组件库
- 环信_聊天组件
- 面试题
- HTML_分类
- CSS_分类
- JavaScript_分类
- VueJS_分类
- ReactJS_分类
- AngularJS_分类
- 浏览器端
- 笔试题
- CSS
- 特殊布局
- JavaScript_
- 经典_宏任务_微任务
- 浏览器问题
- CORS
- web服务器
- Apache
- 开启跨域
- Nginx
- 常用命令
- 正向代理
- 反向代理
- 负载均衡
- mac安装Nginx
- 配置80端口
- 算法
- 冒泡排序
- 选择排序
- 合并对象_排序
- 杨辉三角
- 红黑树
- 计算机基础
- 网络相关
- OSI七层模型
- http协议
- http工作原理
- https协议
- GET和POST区别
- hosts文件
- php相关
- session机制
- Linux
- 阿里云服务器
- linux使用Mysql
- 安装mysql
- 导入.sql文件
- 远程连接mysql
- linux使用xampp
- 安装Xampp
- 配置web访问
- 域名绑定服务器
- linux搭建git服务器_apache下
- 代码管理
- 什么是git
- 命令行_使用git
- .gitignore文件讲解
- 软件
- VSCode的安装
- 理财
- 基金
- 摄影