常见的的排序算法有直接插入排序、希尔排序、简单选择排序、堆排序、冒泡排序、快速排序、归并排序、基数排序这八种。其中代码量很少的有冒泡、插入、选择这三种,写出来也比较简单,理解起来也不复杂,不需要考虑太多的细节。这里会列出这三种排序算法。
算法用文字描述有些困难,可以看一下视频教程:
链接:https://pan.baidu.com/s/1NwMqpD5Yk5_Q-uddJRrAnQ
提取码:kr1n
1、冒泡排序
冒泡是最简单的一种。思想就是将两个相邻的数进行比较,如果前一个数比后一个数大,就进行交换。假设有如下数组:
{21,4,54,5,51,20};
那么拿21和4(索分别是0和1)比较,发现21比4大,于是进行交换,得到如下结果:
{4,21,54,5,51,20};
。同样的接下来,拿索引为1和2的比较、拿索引为2和3的比较、拿索引为3和4的比较、拿索引为4和5的比较。前一个数比后一个数大,就交换。
经历了第一趟,事情没玩,只是找到了最大的一个数,放置在了数组的最后面。
第二趟的目标是找出第二大的数放在数组的倒数第二位,第三趟的目标是找出第三大的数放在数组的倒数第三位……
对于上面的数组,它有6个元素,经历5趟,整个数组就是有序的了。
代码:
int [] arr= {21,4,54,5,51,20};
for (int i = 0; i < arr.length-1; i++) //因为要经历arr.length-1趟排序
{
for (int j = 0; j < arr.length-i-1; j++)//这里不减i也行,但是会增加无意义的比较,增加排序的时间。因为最大的数已经放在最后,你还去比较就是浪费时间,前面的数肯定不比后面的数大。
{
if (arr[j]>arr[j+1]) //如果前一个数比后一个数大,就交换
{
int temp=arr[j];//先把前面的数保存在一个临时变量中
arr[j]=arr[j+1];//后面的数赋值给前面的数。此时前面的数已经被覆盖掉了,但是别慌,数据没有丢失,因为上一步已经用一个临时变量把前面数保存起来了
arr[j+1]=temp;//把前面的数赋值给后面的数
}
}
}
2、插入排序
插入排序的切入点就是,一开始将数组分成两部分,第一部分是有序的,第二部分是无序的。
{21,4,54,5,51,20};
对于上面的数组,把21当成是有序的,把剩余的当成是无序的。接下来就是从无序的部分拿出一个数,插入到前面的有序的部分中去。比如说第一趟,我们拿出4插入到前面中去:
{21,21,54,5,51,20};//找到插入的位置之后,那个元素往后移
{4,21,54,5,51,20};//插入到指定位置
我们发现找到了插入的位置之后,那个数据会往后移,但是数据4并没有丢失,因为我们用一个临时变量保存起来了。
说起来简单,但是用代码实现的话,是怎么找到插入的位置的?
拿上面的步骤来说,它是拿4和21进行比较,如果拿出来的数比有序的那部分中的元素小的话,就一直循环,直到拿出来的数据比有序的部分中的元素大为止。这个有点难说明,详情见代码中的注释。
代码:
int [] arr= {21,4,54,5,51,20};
for (int i = 1; i < arr.length; i++)//从第二个数开始拿
{
int temp=arr[i];//用一个临时变量保存拿出来的数
int index=i-1;//用于记录插入的位置,并且用于倒序遍历有序的那部分数据。
while (index>=0&&temp<arr[index])//这是在倒序遍历有序的部分,如果拿出来的数比有序的部分中的数小的话,就一直循环。
{
arr[index+1]=arr[index];//元素往后移
index--;
}
//while循环遍历完之后就进行插入
arr[index+1]=temp;//这里为啥是index+1?举个例子,上面的索引可能会变成-1,那么就是将数据插入到索引为0的位置。
}
3、选择排序
选择排序是从剩余的部分选择最小的数,来和前面的有序的部分的最后一个数进行交换。前面的插入排序是直接选取无序的部分的第一个数,插入到有序的部分当中去。这是选择排序和插入排序最明显区别的地方。选择排序相对来说更好理解一些。
{21,4,54,5,51,20};
对于上面的数组,第一趟选择排序是这样的:
从索引 0~5中选中最小的一个数,来和21交换。显然最小的数时21,那么交换后如下:
{4,21,54,5,51,20};
第二趟是从索引 1~5中,选择一个最小的数,来和21交换。
……
经历了arr.lengh-1次选择、交换之后,整个数组就是有序的了。
代码:
int [] arr= {21,4,54,5,51,20};
for (int i = 0; i < arr.length; i++)
{
int min=arr[i];//最小的那个数要保存在一个变量中,因为涉及到元素的交换
int minIndex=i;//最小的元素的索引也要记录下来,不然交换不了,因为元素会被覆盖
for (int j = i+1; j < arr.length; j++) //在后面无序的部分中找出一个最小的数
{
if (arr[j]<min)//如果遍历到的数比min还小
{
min=arr[j];
minIndex=j;//记录最小的那个数的索引
}
}
arr[minIndex]=arr[i];//把前面的数扔到后面
arr[i]=min;//把后面那个最小的数扔到前面,完成了交换
}