算法01 七大排序之:冒泡排序和快速排序
排序是我们生活中经常会面对的问题。同学们做操时会按照从矮到高排列;老师查看上课出勤情况时,会按学生学号顺序点名;高考录取时,会按成绩总分降序依次录取等。排序是数据处理中经常使用的一种重要的运算,它在我们的程序开发中承担着非常重要的角色。
排序分为以下四类共七种排序方法:
交换排序:
① 冒泡排序 ② 快速排序
选择排序:
③ 直接选择排序 ④ 堆排序
插入排序:
⑤ 直接插入排序 ⑥ 希尔排序
合并排序:
⑦ 合并排序
这篇文章主要总结的是交换排序(即冒泡排序和快速排序),交换排序的基本思想是:两两比较待排序元素,如果发现两个元素的次序相反时即进行交换,直到所有元素都没有反序时为止。我会从以下几个方面进行总结:
1、冒泡排序及算法实现
2、快速排序及算法实现
3、冒泡排序VS快速排序
1、冒泡排序及算法实现
什么是冒泡排序呢?冒泡排序是一种简单的排序方法,它的基本思想是:通过相邻两个元素之间的比较和交换,使较大的元素逐渐从前面移向后面(升序),就像水底下的气泡一样逐渐向上冒泡,所以被称为“冒泡”排序。冒泡排序的最坏时间复杂度为O(n2),平均时间复杂度为O(n2)
下面以一张图来展示冒泡排序的全过程,其中方括号内为下一轮要排序的元素,方括号后面的第一个元素为本轮排序浮出来的最大元素。
1-1、示意图
1-2、代码
冒泡排序算法的代码实现:
BubbleSort.java
public class BubbleSort {
public static void main(String[] args) {
int[] list = {36, 28, 45, 13, 67, 37, 18, 56};
System.out.println("************冒泡排序************");
System.out.println("排序前:");
display(list);
System.out.println("排序后:");
bubbleSort(list);
display(list);
}
/**
* 遍历打印
*/
public static void display(int[] list) {
System.out.println("********展示开始********");
if (list != null && list.length > 0) {
for (int num :
list) {
System.out.print(num + " ");
}
System.out.println("");
}
System.out.println("********展示结束********");
}
/**
* 冒泡排序算法
*/
public static void bubbleSort(int[] list) {
int temp;
// 做多少轮排序(最多length-1轮)
for (int i = 0; i < list.length - 1; i++) {
// 每一轮比较多少个
for (int j = 0; j < list.length - 1 - i; j++) {
if (list[j] > list[j + 1]) {
// 交换次序
temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
}
}
}
}
}
测试结果:
2、快速排序及算法实现
快速排序(Quick Sort) 是对冒泡排序的一种改进方法,在冒泡排序中,进行元素的比较和交换是在相邻元素之间进行的,元素每次交换只能移动一个位置,所以比较次数和移动次数较多,效率相对较低。而在快速排序中,元素的比较和交换是从两端向中间进行的,较大的元素一轮就能够交换到后面的位置,而较小的元素一轮就能交换到前面的位置,元素每次移动的距离较远,所以比较次数和移动次数较少,速度较快,故称为“快速排序”。
快速排序的基本思想是:通过一轮排序将待排序元素分割成独立的两部分, 其中一部分的所有元素均比另一部分的所有元素小,然后分别对这两部分的元素继续进行快速排序,以此达到整个序列变成有序序列。快速排序的最坏时间复杂度为O(n2),平均时间复杂度为O(n*log2n)
2-1、示意图
2-2、代码
快速排序算法的代码实现:
QuickSort.java
public class QuickSort {
public static void main(String[] args) {
int[] list = {6, 1, 2, 7, 9, 3, 4, 5, 10, 8};
System.out.println("************快速排序************");
System.out.println("排序前:");
display(list);
System.out.println("排序后:");
quickSort(list, 0, list.length - 1);
display(list);
}
/**
* 快速排序算法
*/
public static void quickSort(int[] list, int left, int right) {
if (left < right) {
// 分割数组,找到分割点
int point = partition(list, left, right);
// 递归调用,对左子数组进行快速排序
quickSort(list, left, point - 1);
// 递归调用,对右子数组进行快速排序
quickSort(list, point + 1, right);
}
}
/**
* 分割数组,找到分割点
*/
public static int partition(int[] list, int left, int right) {
// 用数组的第一个元素作为基准数
int first = list[left];
while (left < right) {
while (left < right && list[right] >= first) {
right--;
}
// 交换
swap(list, left, right);
while (left < right && list[left] <= first) {
left++;
}
// 交换
swap(list, left, right);
}
// 返回分割点所在的位置
return left;
}
/**
* 交换数组中两个位置的元素
*/
public static void swap(int[] list, int left, int right) {
int temp;
if (list != null && list.length > 0) {
temp = list[left];
list[left] = list[right];
list[right] = temp;
}
}
/**
* 遍历打印
*/
public static void display(int[] list) {
System.out.println("********展示开始********");
if (list != null && list.length > 0) {
for (int num :
list) {
System.out.print(num + " ");
}
System.out.println("");
}
System.out.println("********展示结束********");
}
}
测试结果:
3、冒泡排序VS快速排序
代码如下:
BubbleVsQuick.java
public class BubbleVsQuick {
public static void main(String[] args) {
testQuick();
testBubble();
}
/**
* 测试快速排序耗费的时间
*/
public static void testQuick() {
int[] list = new int[10000];
for (int i = 0; i < 10000; i++) {
list[i] = (int) (Math.random() * 100000);
}
// 快速排序
long start = System.currentTimeMillis();
QuickSort.quickSort(list, 0, list.length - 1);
long end = System.currentTimeMillis();
System.out.println("快速排序耗费的时间:" + (end - start));
display(list);
}
/**
* 测试冒泡排序耗费的时间
*/
public static void testBubble() {
int[] list = new int[10000];
for (int i = 0; i < 10000; i++) {
list[i] = (int) (Math.random() * 100000);
}
// 冒泡排序
long start = System.currentTimeMillis();
BubbleSort.bubbleSort(list);
long end = System.currentTimeMillis();
System.out.println("冒泡排序耗费的时间:" + (end - start));
display(list);
}
/**
* 遍历打印前10个数
*/
public static void display(int[] list) {
System.out.println("********排序之后的前10个数start********");
if (list != null && list.length > 0) {
for (int i = 0; i < 10; i++) {
System.out.print(list[i] + " ");
}
System.out.println("");
}
System.out.println("********排序之后的前10个数end**********");
System.out.println("");
}
}
测试结果:
可见,快速排序的速度比冒泡排序更快。
- Leetcode-Easy 657. Judge Route Circle
- 洛谷P1138 第k小整数
- Leetcode-Easy 796. Rotate String
- 2017.10.23解题报告
- Leetcode-Easy 461.Hamming Distance
- 洛谷P1439 最长公共子序列(LCS问题)
- Leetcode-Easy 575. Distribute Candies
- 洛谷P2115 [USACO14MAR]破坏Sabotage
- 修改nw.js的exe文件使其请求管理员权限
- Leetcode-Easy 728. Self Dividing Numbers
- Leetcode-Easy 412. Fizz Buzz
- 洛谷P2678 跳石头
- 洛谷P2863 [USACO06JAN]牛的舞会The Cow Prom
- 洛谷P1908 逆序对(归并排序)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- R语言实现输出文本的多样式
- 学习|Unity3d的导航实现循环线路移动
- 【redis】闲得无聊,来聊聊当下爆火的 redis集群,顺便搭一个玩玩呗
- 【redis入门】Centos下安装redis
- LeetCode精选好题(五)
- 【leetcode两题选手】MySQL类题目(一)
- 【LeetCode每日一题】(8.11)被围绕的区域
- 二叉树的前中后序遍历(迭代法)(带动画)
- 【LeetCode两题选手】算法类题目(8.8)
- 【LeetCode每日一题】(8.9)复原IP地址(回溯)
- 【回溯算法】N叉树相关技巧
- 【回溯算法】回溯,从入门到入土,七道试题精选、精讲、精练
- 数据结构练手小项目(AVL树、哈希表、循环链表、MySQL数据库)
- 【LeetCode】每日一题(8.2)二叉树展开为链表
- 【小技巧】argc和argv的用法