算法分类
十种常见排序算法可以分为两大类:
1.非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序。
2.线性时间非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此称为线性时间非比较类排序。
算法复杂度:
图片名词解释:
n: 数据规模
k:“桶”的个数
In-place: 占用常数内存,不占用额外内存
Out-place: 占用额外内存
稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。
1、冒泡排序(Bubble Sort)
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
1.1 算法描述
- 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
- 针对所有的元素重复以上的步骤,除了最后一个;
- 重复步骤1~3,直到排序完成。
1.2 动图演示
![](https://i-blog.csdnimg.cn/blog_migrate/9a152a7e13500cf688efd8e5297f9f6e.gif)
1.3 代码实现
1.3.1、JAVA版
public class BubbleSort {
// 冒泡排序---基础版
public int[] bubbleSort1(int[] arr) {
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
// 冒泡排序---进阶版1
public int[] bubbleSort2(int[] arr) {
int i=arr.length-1;//初始时,最后位置保持不变
while(i>0){
int flag =0;//每趟开始时,无记录交换
for(int j=0;j<i;j++){
if (arr[j] > arr[j + 1]) {
flag=j;//记录交换的位置
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
i=flag; //为下一趟排序作准备
}
return arr;
}
// 冒泡排序---进阶版2
public int[] bubbleSort3(int[] arr) {
int low=0;
int high=arr.length-1;//设置变量的初始值
while(low<high){
int f1 =0,f2 =0;//每趟开始时,无记录交换
for (int i= low; i< high; ++i) { //正向冒泡,找到最大者
if (arr[i]> arr[i+1]) {
int tmp = arr[i]; arr[i]=arr[i+1];arr[i+1]=tmp;
f1=i;
}
}
high = f1;// 记录上次位置
for (int j=high; j>low; --j) { //反向冒泡,找到最小者
if (arr[j]<arr[j-1]) {
int tmp = arr[j]; arr[j]=arr[j-1];arr[j-1]=tmp;
f2=j;
}
}
low = f2; //修改low值
}
return arr;
}
// 定义一个printArray()方法用来实现此功能
public void printArray(int[] arr) {
System.out.print("{");
for (int i = 0; i < arr.length; i++) {
// 判断一下是否为数组最后一个值
if (i != arr.length - 1){
System.out.print(arr[i] + ", ");
}else{
System.out.println(arr[i] + "}");
}
}
}
}
//测试类
public class TestBubbleSort {
@Test//测试方法一:
public void testBubbleSort1() {
BubbleSort s = new BubbleSort();
int[] arr1 = {11,3,29,49,30,7,50,63,46,16};
s.bubbleSort1(arr1);
s.printArray(arr1);
}
@Test//测试方法二:
public void testBubbleSort2() {
BubbleSort s = new BubbleSort();
int[] arr2 = {11,3,29,49,30,7,50,63,46,31,22};
System.out.println("原数组:"+Arrays.toString(arr2));
s.bubbleSort2(arr2);
System.out.println("排序后:"+Arrays.toString(arr2));
}
@Test//测试方法三:
public void testBubbleSort3() {
BubbleSort s = new BubbleSort();
int[] arr3 = {11,3,29,49,30,7,50,63,46,11,1};
s.bubbleSort3(arr3);
for (int i : arr3) {
System.out.print(i+" ");//打印每个元素
}
}
}
1.3.2 JS版
//js冒泡排序--基础版
function bubbleSort1(arr) {
console.time('1:冒泡排序耗时');
var len = arr.length;
for (var i = 0; i < len; i++) {
for (var j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) { //相邻元素两两对比
var temp = arr[j + 1]; //元素交换
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
console.timeEnd('1:冒泡排序耗时');
return arr;
}
//js冒泡排序进阶版
function bubbleSort2(arr) {
console.time('2:改进后冒泡排序耗时');
var i = arr.length-1; //初始时,最后位置保持不变
while ( i> 0) {
var flag= 0; //每趟开始时,无记录交换
for (var j= 0; j< i; j++){
if (arr[j]> arr[j+1]) {
flag= j; //记录交换的位置
var tmp = arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
}
}
i= flag; //为下一趟排序作准备
}
console.timeEnd('2:改进后冒泡排序耗时');
return arr;
}
/js冒泡排序进阶版
function bubbleSort3(arr) {
var low = 0;
var high= arr.length-1; //设置变量的初始值
console.time('3.改进后冒泡排序耗时');
while (low < high) {
var f1 = 0,f2=0;
for (var i= low; i< high; ++i) { //正向冒泡,找到最大者
if (arr[i]> arr[i+1]) {
var tmp = arr[i]; arr[i]=arr[i+1];arr[i+1]=tmp;
f1=i;
}
}
high = f1;// 记录上次位置
for (var j=high; j>low; --j) { //反向冒泡,找到最小者
if (arr[j]<arr[j-1]) {
var tmp = arr[j]; arr[j]=arr[j-1];arr[j-1]=tmp;
f2=j;
}
}
low = f2; //修改low值
}
console.timeEnd('3.改进后冒泡排序耗时');
return arr;
}
//验证
var arr=[21,3,89,1,77,56,10,6,46,2,61,7,11];
console.log(bubbleSort1(arr));//耗时:0.57[1,2,3,6,7,10,11,21,46,56,61,77,89]
console.log(bubbleSort2(arr));//耗时:0.006
console.log(bubbleSort3(arr));//耗时:0.005
var arr2=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(bubbleSort1(arr2));//耗时:0.015
//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
console.log(bubbleSort2(arr2));//耗时:0.0039
console.log(bubbleSort3(arr2));//耗时:0.0032
仔细了解算法的思想及步骤,请点击(十大经典排序算法基本思想和图解(冒泡、插入、选择、快速、希尔、堆、归并)