基础排序算法总结(代码+图片分析)
Posted 温文艾尔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基础排序算法总结(代码+图片分析)相关的知识,希望对你有一定的参考价值。
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
冒泡排序
基本介绍:
冒泡排序的基本思想就是:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部
因为排序的过程中,各元素不接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志flag判断元素是否进行过交换,从而减少不必要的比较
冒泡排序图解
第一趟排序
(1) 3,9,-1,10,20 //如果相邻的元素逆序就交换
(2) 3,-1,9,10,20
(3) 3.-1,9,10,20
(4) 3,-1,9,10,20
第二趟排序
(1) -1,3,9,10,20
(2) -1,3,9,10,20
(3) -1,3,9,10,20
第三趟排序
(1) -1,3,9,10,20
(2)-1,3.9,10,20
第四趟排序
(1)-1,3,9,10,20
小结冒泡排序规则
(1)一共进行数组的大小-1次大的循环
(2)每一趟排序的次数在逐渐的减少
public static int[] method(int[] arr){
boolean flag = true;
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]){
flag=false;
int temp = 0;
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
if(flag){
return arr;
}else flag=true;
}
return arr;
}
选择排序
选择式排序也属于内部排序法,从预排序的数据中,按照指定的规则选出某一元素,再依规定交换位置后达到排序的目的
选择排序的基本思想
第一次从arr[0]-arr[n-1]中选取最小值,与arr[0]交换,第二次从arr[1]-arr[n-1]中选取最小值,与arr[1]交换,以此类推,第n-1次从arr[n-2]-arr[n-1]中选取最小值,与arr[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列
选择排序图解
原始的数组:
101,34,119,1
第一轮排序:
1,34,119,101
第二轮排序:
1, 34,119,101
第三轮排序:
1,34,101,119
说明:
1.选择排序一共有数组大小-1轮排序
2.每1轮排序,又是一个循环,循环的规则
2.1先假定当前这个数是最小数
2.2然后和后面的每个数进行比较,如果发现有比当前数更小的数,就重新确定最小数并得到下标
2.3当遍历到数组的最后时,就得到本轮最小数和下标
2.4交换
public static int[] xuanze(int[] arr){
for(int i=0;i<arr.length;i++){
for (int j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
min = j+1;
}
}
int temp = 0;
temp = arr[min];
arr[min] = arr[i];
arr[i] = temp;
}
return arr;
}
插入排序
插入排序基本介绍
插入排序属于内部排序法,是对于预排序的匀速以插入的方式找寻该元素的适当位置,已达到排序的目的
插入排序的基本思想
把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表只包含一个元素,无序表中包含n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将他插入到有序表中的适当位置,使之成为新的有序表
插入排序图解
public static int[] charu(int[] arr){
for (int i=1;i<arr.length;i++){
int insertValue = arr[i];//-1
int insertIndex = i-1;//1 0
while(insertIndex>=0&&insertValue<arr[insertIndex]){
arr[insertIndex+1] = arr[insertIndex];
insertIndex-=1;
}
//找到了要插入的位置
arr[insertIndex+1] = insertValue;
}
return arr;
}
希尔排序
希尔排序是希尔于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序
希尔排序法基本思想
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法变终止。
希尔排序示意图
交换法
public static int[] Xier(int[] arr){
//5,2,1 10/2/2/2
for(int gap = arr.length/2;gap>0;gap/=2){
for (int i=gap;i<arr.length;i++){
for (int j=i-gap;j>=0;j-=gap){
if(arr[j]>arr[j+gap]){
int temp = 0;
temp = arr[j];
arr[j] = arr[j+gap];
arr[j+gap] = temp;
}
}
}
}
return arr;
}
移位法
//移位法
public static int[] Xier3(int[] arr){
//5,2,1 10/2/2/2
for(int gap = arr.length/2;gap>0;gap/=2){
for (int i=gap;i<arr.length;i++){
//对每一组的数据进行直接插入
int insertValue = arr[i];//1
int insertIndex = i-gap;//1
while(insertIndex>=0&&insertValue<arr[insertIndex]){
arr[insertIndex+gap] = arr[insertIndex];
insertIndex-=gap;
}
arr[insertIndex+gap] = insertValue;
}
}
return arr;
}
快速排序
快速排序介绍
快速排序是对冒泡排序的一种改进
基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
快速排序法示意图
以中间值为基准
private static void quicksort(int[] arr, int l, int r) {
if(l>=r){
return;
}
int x = arr[(l+r)/2];
int i = l-1;
int j = r+1;
while (i<j){
do {
i++;
}while (arr[i]<x);
do {
j--;
}while (arr[j]>x);
if(i<j){
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
quicksort(arr,l,j);
quicksort(arr,j+1,r);
}
以数组中第一位数字为基准
//找第一个数字
public static void quicksort2(int[] arr,int l,int r){
if(l>=r){
return;
}
int value = arr[l];
int i = l;
int j = r;
while(i<j){
while (arr[j]>=value&&i<j){
j--;
}
arr[i]=arr[j];
while (arr[i]<=value&&i<j){
i++;
}
arr[j]=arr[i];
}
arr[i]=value;
quicksort2(arr,l,j);
quicksort2(arr,j+1,r);
}
归并排序
归并排序图解
private static void guibing(int[] arr,int start,int end) {
if (start>=end){
return;
}
int middle = (start+end)/2;//3 //0
guibing(arr,start,middle);
guibing(arr,middle+1,end);
//默认已经是分好的数组
int[] newArr = new int[end-start+1];
int mid = middle;//4
int i=start;
int j = mid+1;//5
int temp=0;
while (i<=mid && j<=end){
if(arr[i]<=arr[j]){
newArr[temp] = arr[i];
temp++;
i++;
} else {
newArr[temp] = arr[j];
temp++;
j++;
}
}
while (j<=end){
newArr[temp] = arr[j];
temp++;
j++;
}
while (i<=mid){
newArr[temp] = arr[i];
temp++;
i++;
}
//把临时数组中的数据重新存入原数组
for(int k=0;k<temp;k++){
arr[k+start] = newArr[k];
}
}
基数排序
- 基数排序属于“分配式排序”,又称桶排序,通过键值的各个位的值,将要排序的元素分配至某些“桶”中,达到排序的效果
- 基数排序法是属于稳定性的排序,基数排序法是效率高的稳定性排序法
- 基数排序是桶排序的扩展
- 基数排序是1887年赫尔曼.何乐礼发明的,他是这样实现的:将整数按位数切割成不同的数字,然后按每个位数分别比较
基数排序基本思想
- 将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位一直到最高位排序完成以后,数列就变成一个有序序列
- 基数排序是使用空间换时间的经典算法
基数排序的图文说明
第一轮
第二轮
第三轮
private static void jishu(int[] arr) {
//得到最大的位数
int max = arr[0];
for (int i=1;i<arr.length-1;i++){
if(max<arr[i]){
max=arr[i];
}
}
int maxLength = (max+"").length();
//定义十个桶,也就是一个二维数组
int[][] bucket = new int[10][arr.length];
//为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
int[] bucketElementCounts = new int[10];
for(int mode = 0;mode<maxLength;mode++){
//将数据放入桶
for (int i=0;i<arr.length;i++){
int index = arr[i]/(int)Math.pow(10,mode)%10;//放到第几个桶
bucket[index][bucketElementCounts[index]] = arr[i];
bucketElementCounts[index]++;
}
int index = 0;
//将数据从桶中取出来
for(int i=0;i<bucketElementCounts.length;i++){
//判断桶中是否有数据
if(bucketElementCounts[i]!=0){
for(int j=0;j<bucketElementCounts[i];j++){
arr[index++] = bucket[i][j];
}
}
//第一轮处理后将bucketElementCounts[i]清0
bucketElementCounts[i]=0;
}
}
}
各算法时间复杂度统计图
以上是关于基础排序算法总结(代码+图片分析)的主要内容,如果未能解决你的问题,请参考以下文章