目录
前言
首先感谢您的阅览,本篇主要介绍冒泡,选择,插入,快速这基本的四大排序算法的原理,排序流程及代码实现,个人能力有限,只能尽己所能详细阐述,如有不足,欢迎您的补充与指正。也希望小小的笔记能够解决您的困惑问题。
一.冒泡排序
1. 冒泡简介
冒泡排序(Bubble Sort)也是一种简单直观的排序算法。
它重复的遍历过要排序的数列,一次比较相邻的两个元素,如果他们的顺序错误就把他们交换过来。
这个算法的名字由来是因为越大的元素会经由交换慢慢"浮"到最后面。
2. 算法步骤
- 相邻的元素两两比较,大的放右边,小的放左边
- 第一轮比较完毕之后,最大值就已经确定,第二轮可以少循环一次,后面以此类推
- 如果数组中有n个数据,总共我们只要执行n-1轮的代码就可以
3. 图解流程
下面动图更加方便的解释了排序流程
动图若不好理解,我又画了详细的流程图
总结算法注意点
- 相邻的元素两两比较,大的放右边,小的放左边
- 第一轮比较完毕之后,最大值已经确定,第二轮可以少循环一次,后面依次类推
- 如果数组中有n个数据,总共我们只需要执行n-1轮代码就可以
4. 代码实现
public static void main(String[] args) {
/*
冒泡排序代码实现
*/
int[] arr ={2, 4, 5, 3, 1};
//外循环:表示我要执行多少轮。 如果有n个数据,那么执行n - 1 轮
for (int i = 0; i < arr.length - 1; i++){
//内循环:每一轮中我如何比较数据并找到当前的最大值
//-1:为了防止索引越界
//-i:提高效率,每一轮执行的次数应该比上一轮少一次
for (int j = 0; j < arr.length - 1 - i; j++){
if (arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
二.选择排序
1. 算法步骤
- 从0索引开始,跟后面的元素一一比较
- 小的放前面,大的放后面
- 第一次循环结束后,最小的数据已经确定
- 第二次循环从1索引开始以此类推
- 第三轮循环从2索引开始以此类推
- 第四轮循环从3索引开始以此类推。
2. 图解流程
3. 代码实现
public static void main(String[] args) {
int[] arr = {2, 4, 5, 3, 1};
//外循环:几轮
//i:表示这一轮中,我拿着哪个索引上的数据跟后面的数据进行比较并交换
for (int i = 0; i < arr.length - 1; i++) {
//内循环:每一轮我要干什么事情?
//拿着i跟i后面的数据进行比较交换
for (int j = i; j < arr.length; j++) {
if (arr[i] > arr[j]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
三.插入排序
1.插入简介
插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑克牌的人都应该能够秒懂。插入排序是一种最简单直观的排序算法,它的工作原理是通过创建有序序列和无序序列,然后再遍历无序序列得到里面每一个数字,把每一个数字插入到有序序列中正确的位置。
插入排序在插入的时候,有优化算法,在遍历有序序列找正确位置时,可以采取二分查找
2.算法步骤
将0索引的元素到N索引的元素看做是有序的,把N+1索引的元素到最后一个当成是无序的。
遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面。
N的范围:0~最大索引
3.流程图解
4.代码实现
public static void main(String[] args) {
int[] arr = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
int index = -1;
//1.找到无序的哪一组数组是从哪个索引开始的
for (int i = 0; i < arr.length - 1; i++){
if (arr[i] > arr[i + 1]){
index = i + 1;
break;
}
}
//2.遍历从startIndex开始到最后一个元素,依次得到无序的哪一组数据中的每一个元素
for (int i = index; i < arr.length; i++){
//j为记录当前要插入数据的索引
for (int j = i; j > 0 && arr[j] < arr[j - 1]; j--){
int temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
}
System.out.println(Arrays.toString(arr));
}
四.快速排序
1.递归算法
递归(Recursion),在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。
使用递归要设置出口,否则会内存溢出
下面是从1加到100的和,用递归的方式
public static void main(String[] args) {
System.out.println(getSum(100));
}
private static int getSum(int number) {
if (number == 1){
return 1;
}else {
number = number + getSum(number - 1);
return number;
}
}
注释: number = 100时,它要用100+调用这个getSum方法,传入99,而99 + getSum这个方法,也是递归要先得到下面的值,最后一直减到1,这次递归的方法得到返回值为1,后面的都有值可以加上去了。
简而言之,就是方法体内又调用了该方法
快速排序又是一种分而治之思想在排序算法上的典型应用。
快速排序的名字起的是简单粗暴,因为一听到这个名字你就知道它存在的意义,就是快,而且效率高!
它是处理大数据最快的排序算法之一了。
2.算法步骤
- 从数列中挑出一个元素,一般都是左边第一个数字,称为 “基准数”;
- 创建两个指针,一个从前往后走,一个从后往前走。
- 先执行后面的指针,找出第一个比基准数小的数字
- 再执行前面的指针,找出第一个比基准数大的数字
- 交换两个指针指向的数字
- 直到两个指针相遇
- 将基准数跟指针指向位置的数字交换位置,称之为:基准数归位。
- 第一轮结束之后,基准数左边的数字都是比基准数小的,基准数右边的数字都是比基准数大的。
- 把基准数左边看做一个序列,把基准数右边看做一个序列,按照刚刚的规则递归排序
3.流程图解
这个动图配合上面的步骤看的更清晰
4.代码实现
快排,效率高,比较重要,22年下半期软考程序员的下午编程题第二大题的第2问,整个就是快排流程,总共9分,您说重要不重要吧。
代码虽然稍许复杂,有点难度,但多看一遍,多揣摩一番,那必然会霍然开朗的
public static void main(String[] args) {
int[] arr = {6, 1, 2, 7, 9, 3, 4, 5, 10, 8};
quickSort(arr, 0, arr.length-1);
System.out.print(Arrays.toString(arr));
}
public static void quickSort(int[] arr, int i, int j){
//定义两个变量记录要查找的范围
int start = i;
int end = j;
//递归出口
if (start > end){
return;
}
//记录基准数
int baseNumber = arr[i];
//利用循环找到要交换的数字
while (start != end){
//利用end,从后往前开始找,找比基准数小的数字
while (true){
if (end <= start || arr[end] < baseNumber){
break;
}
end--;
}
//利用start,从前往后找,找比基准数大的数字
while (true){
if (start >= end || arr[start] > baseNumber){
break;
}
start++;
}
//交互二者位置
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}
//当start和end指向了同一个元素的时候,那么上面的循环就会结束
//表示已经找到了基准数在数组应存入的位置
//基准数归位
int temp = arr[i]; //arr[i]仍然是第一个数,基准值
arr[i] = arr[start]; //这里的start=end,已经到中间位置了
arr[start] = temp;
//确定6左边范围,重复刚才第一轮操作
quickSort(arr, i, start - 1);
//确定6右边范围,重复刚才第一轮操作
quickSort(arr, start + 1, j);
}
下图是程序第一轮运行结果,后面只需要6之前一个范围,6之后一个范围,递归调用即可
总结
最后,感谢您的阅览,愿您能有所收获,能帮助到各位正是文章的价值所在