目录
【排序算法】
简介:将一堆数据,按指定顺序排序。Sort Algorithm
分类:内部排序(将数据加载到内部存储器,如内存,进行排序),外部排序(将数据加载到外部存储器,如文件,中进行排序,适合特大数据量)
时间复杂度
时间复杂度用于评估算法执行效率,由时间频度(语句的执行次数)求得。
时间频度具有忽略常数项,忽略底次项,忽略高次项系数的特点,如:T(n)=2*n^3-n+1 可简化为 f(n)=n^3 在绝对力量(运行次数)面前,一切努力(常数项,底次项,高次项系数)都很苍白。
时间频度转时间复杂度:O(n)=O(f(n)) 如:T(n)=2*n^3-n+1 --> f(n)=n^3 -->O(n)=O((n^3))
常见时间复杂度:
1,常数阶 O(1)
int i=1;
int j=2;
i++;
++j;
int m=i+j;
2,对数阶 O(log2n)
int i=1;
while(i<n){
i=i*2;
}
3,线性阶 O(n)
for(int i=0;i<n;i++){
j+=1;
}
4,线性对数阶 O(nlogN)
for(int i=o;i<n;i++){
while(j<n){
j++;
}
}
5,平方阶
for(int i=0;i<n;i++){
for(int j=0;j<n:j++){
}
}
6,立方阶,K次阶:类似平方阶
常见时间复杂度顺序排序:O(1) < O(logN) < O(n) < O(nlogN) < O(n^2) < O(n^3) < O(n^K) < O(2^n) < O(n!)
平均时间复杂度与最坏时间复杂度:
抱最大的希望,尽最大的努力,做最坏的打算。最坏时间复杂度往往是算法抗压性能的指标,讨论时间复杂度一般均是最坏时间复杂度
空间复杂度:
算法运行时占存储空间大小的度量,一些缓存产品(redis)和算法(基数排序)本质是以空间换时间来提升程序运行速度
【冒泡排序】
依次比对相邻元素的顺序,发现逆序就交换位置。
在每一轮完成后最后一位都是当前排序队列中的最大值,其不参与下一次排序,故每次排序都比上一次减一。最大排序的轮次为数据总数-1。
另外,在排序过程中,很可能出现排序到中途就已经排序完成了,那就没必要进行接下来的排序了,使用可以引入排序判据 flag ,当上一轮发生排序时,flag为真继续排序,否则为假终止排序。这将优化冒泡排序
package cn.dataStructureAndAlgorithm.demo.sort;
import java.util.Arrays;
public class 冒泡排序_bubbleSort {
public static void main(String[] args) {
int data[]=new int[]{5,9,2,3,6,4,7};
System.out.println("排序前:"+Arrays.toString(data));
bubbleSort(data);
System.out.println("排序后:"+ Arrays.toString(data));
}
public static void bubbleSort(int data[]){
int temp;//数据交换时要用的临时变量
boolean flag=true;//优化冒泡算法的判据
for (int i=0;i<data.length-1&&flag;i++){
flag=false;//重置判据
for (int j=0;j<data.length-1-i;j++){
if (data[j]>data[j+1]){
flag=true;//发现冲突,重置判据
temp=data[j];
data[j]=data[j+1];
data[j+1]=temp;
}
}
System.out.println(Arrays.toString(data));
}
}
}
排序前:[5, 9, 2, 3, 6, 4, 7]
[5, 2, 3, 6, 4, 7, 9]
[2, 3, 5, 4, 6, 7, 9]
[2, 3, 4, 5, 6, 7, 9]
[2, 3, 4, 5, 6, 7, 9]
排序后:[2, 3, 4, 5, 6, 7, 9]
冒泡排序速度测试:以80000个【0~80000】的随机整数为数组,进行速度测试(数据以我电脑为准)
无优化前耗时:10s 优化后耗时:9s
【选择排序】
总共进行n-1轮,每 i 轮从i+1开始遍历数据,当发现有与 i 索引数据发生逆序的数据时,记录逆序者的数据与索引,在一轮结束后,交换两者位置。
package cn.dataStructureAndAlgorithm.demo.sort;
import java.util.Arrays;
public class 选择排序_selectSort {
public static void main(String[] args) {
int data[]=new int[]{5,9,2,3,6,4,7};
System.out.println("排序前:"+ Arrays.toString(data));
selectSort(data);
System.out.println("排序后:"+ Arrays.toString(data));
}
public static void selectSort(int data[]){
int min;//存储最小值
int index;//存储最小值对应的索引
for (int i=0;i<data.length-1;i++){
min=data[i];
index=i;
for (int j=i+1;j<data.length;j++){
if (min>data[j]){//发现逆序
min=data[j];//重置最小值与索引
index=j;
}
}
if (min!=data[i]){//交换位置
data[index]=data[i];
data[i]=min;
}
}
}
}
选择排序速度测试:以80000个【0~80000】的随机整数为数组,进行速度测试(数据以我电脑为准)
耗时:2s
【插入排序】
把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-l个元素排序,过程中每次从无序表中取出第一个元素,把它的大小依次与有序表元素的大小进行比较,比较过程中牵扯对有序表中数据的覆盖式移位,直到找到正确插入位置,将它插入到有序表中的适当位置,使之成为新的有序表。如数组{2,3,4,5,6,1}的排序过程:
package cn.dataStructureAndAlgorithm.demo.sort;
import java.util.Arrays;
public class 插入排序_insertSort {
public static void main(String[] args) {
int data[]=new int[]{5,9,2,3,6,4,7};
System.out.println("排序前:"+ Arrays.toString(data));
insertSort(data);
System.out.println("排序后:"+ Arrays.toString(data));
}
public static void insertSort(int data[]){
int preindex;//待插入数据的前一个位置索引
int selectVal;//待插入数据
for (int i=1;i<data.length;i++){
selectVal=data[i];
preindex=i-1;
//当前数据未处于正确位置
while (preindex>=0 && selectVal<data[preindex]){//短路与所以应该把下标判断放在首位,下标不越界,当前数据<前一个数据
data[preindex+1]=data[preindex];//覆盖式的向后移位
preindex--;//继续搜寻更前的数据
}
//当前数据处于正确位置
data[preindex+1]=selectVal;//将数据插入正确位置
}
}
}
插入排序速度测试:以80000个【0~80000】的随机整数为数组,进行速度测试(数据以我电脑为准)
耗时:510ms
舒适区结束
其他的排序算法有点复杂难懂,我将其另行整理了,可以点击下面的链接进入查找
排序算法_堆排序,该算法需要学习树的知识,可以在下面的目录链接中,自行查找
【数据结构与算法整理总结目录 :>】<-- 宝藏在此(doge)