https://blog.csdn.net/Hodge_Z/article/details/84673439 该大佬的博文,有代码和动态图。非常棒。
下边是我的理解(精心研究啊QAQ):
1、冒泡排序:(每趟比较都能把未排序元素中最大的沉到最底部)
1·依次比较相邻的两个元素,如:若第一个大于第二个,则交换两个元素的位置。
2·然后比较第二个和第三个元素,以此类推,直到排序完成。
3·每趟排序都会把最大的放到最后。排序完成时小的数就会“浮”到上面,大的“沉”到下面。
package com.download.demo.SuanFa;
/**
* @author:tongys
* @createTime:2020/6/9 8:16
* 冒泡排序:两两比较,符合条件则交换位置。该操作进行“元素个数-1”次。
*/
public class MaoPao {
public static void main(String[] args) {
int[] array = {8,3,1,2,7,0};//5个
int temp = 0;
for (int i = 1;i<array.length;i++){//“遍历数组两两比较”这个操作的循环次数 【元素个数-1】次
for (int k = 0;k<array.length-i;k++){ //遍历数组两两比较,每一趟需要比较的元素组数依次减少。↓
// 因为每趟排序都能把“最大的”沉到底部,这个最大的不参与下趟比较。第一趟比较【元素个数-1】次
if (array[k]>array[k+1]){
//交换
temp = array[k];
array[k] = array[k+1];
array[k+1] = temp;
}
}
}
System.out.println("排序完成后的结果:");
for (int i = 0;i<array.length;i++){
System.out.println(array[i]+",");
}
}
}
2、选择排序:(每趟比较都能找出未排序元素中最小的)
1·拿到第一个元素,向后逐个比较直到找到比它小的元素,记录该元素下标和数值。
2·然后用新的较小元素,继续向后比较,寻找比它小的元素,记录其下标和数值。
3·直到全部比较一遍,然后交换第一个元素和本次比较中发现的最小元素的位置。
4·然后拿到第二个元素,重复以上步骤,直到全部排序一遍,需要比较【元素个数-1】趟。
package com.download.demo.SuanFa;
/**
* @author:tongys
* @createTime:2020/6/9 9:10
* 选择排序:每趟排序都能选出最小的元素,然后把它放到参与排序的元素中的第一位,它在下一趟不参与排序。那么一共需要比较【元素个数-1】趟
*/
public class Xuanze {
public static void main(String[] args) {
int[] array = {8,3,1,2,7,0};//6个
int flag = 0;//记录更小的那个元素的位置
int temp = 0;//中介
for (int i =0;i<array.length-1;i++){//一共要排序【元素个数-1】趟
flag = i;
for (int k = i+1;k<array.length;k++){
if (array[flag]>array[k]){
//如果出现了更小的,就拿这个更小的去往下比较
flag = k;
}
}
//把这一趟找出来的最小元素,放到本次排序元素的最前头
temp = array[i];
array[i] = array[flag];
array[flag] = temp;
}
System.out.println("排序完成后的结果:");
for (int i = 0;i<array.length;i++){
System.out.print(array[i]+",");
}
}
}
3、插入排序:
1、理念:将数组分为左右两部分,认为左部分已经排序,右部分没有排序。
2、初始默认数组的第一个元素已经被排序。
3、拿到未排序部分的第一个元素A,向左比较直到找到小于等于A的元素,然后把A元素插到它后边。如果没有找到,则位置不变认为已被排序。
4、重复第三步。直到所有元素均被排序。
package com.download.demo.SuanFa;
/**
* @author:tongys
* @createTime:2020/6/9 9:54
* 插入排序:分为已排序(初始默认第一个元素已排序)和未排序两组,然后将未排序组中的第一个元素向左进行比较,↓
* 左边的大于它则交换位置,直到遇到小于等于它的,此时它被作为已排序的元素。
* 【注:插入排序它每次排序都能确定一个元素的位置】
*/
public class ChaRu {
public static void main(String[] args) {
int[] array = {8,3,1,2,7,0};//6个
int temp;//中介
for (int i=1;i<array.length;i++){ //插入【元素个数-1】次
int k = i-1;
temp = array[i];//保存 当前这个正在排序的元素
while (k>=0){//左边还有元素
if (array[k]>temp){//如果左边的比它大,则交换位置。然后继续向左比较
array[k+1] = array[k];
array[k] = temp;
k--;//继续向左
}else{//如果左边的小于等于它,则保持当前位置不动。认为该元素已排序完成,接下来排序下一个。
break;
}
}
}
System.out.println("插入排序完成后的结果:");
for (int i = 0;i<array.length;i++){
System.out.print(array[i]+",");
}
}
}
4、快速排序
* 快速排序:说白了就是给基准值找到它正确的位置,只要我们让左边的都小于它,右边的都大于他,那么它此时的位置就是排序完成后应在的位置。(这是一次基准定位的操作)
* 注意!个人理解!(想了好久!):
我更认为每一次调用KuaiSuSort()方法都是在以某个元素为基准,在将数据切分为左右半组(左半组都小于基准,右半组都大于基准)。
每一次递归调用KuaiSuSort()方法我们着眼的元素组都在变小,直到无法再进行切分(只有一个元素),该小组元素排序就完成了。所有小组都无法再切分时,整个数组就排序完成了。
package com.download.demo.SuanFa;
/**
* @author:tongys
* @createTime:2020/6/9 14:45
* 快速排序:说白了就是给基准值找到它正确的位置,只要我们让左边的都小于它,右边的都大于他,那么它此时的位置就是排序完成后应在的位置。(这是一次基准定位的操作)
*
* 注意!个人理解!(想了好久!):我更认为每一次调用KuaiSuSort()方法都是在以某个元素为基准,在将数据切分为左右半组(左半组都小于基准,右半组都大于基准)。
* 每一次递归调用KuaiSuSort()方法我们着眼的元素组都在变小,直到无法再进行切分,该小组元素排序就完成了。所有小组无法在切分(只有一个元素)时,整个数组就排序完成了。
*/
public class KuaiSu {
public static void main(String[] args) {
int[] array = {8,3,1,2,7,0,6,5};//6个
//外部调用为启动第一次基准位置确认与左右半组的切分。然后内部就开始通过递归,确认基准位置和不断的切分左右半组,直到无法切分左右半组,此时排序完成。
KuaiSuSort(array,0,array.length-1);
System.out.println("快速排序完成后的结果:");
for (int i = 0;i<array.length;i++){
System.out.print(array[i]+",");
}
}
static void KuaiSuSort(int[] array,int left,int right){
//每一次执行getIndex()可以确定一个元素的最终位置,利用迭代确定所有元素位置
if (left<right){
System.out.println("调用getIndex前-left:"+left);//xxxxxxxxx
System.out.println("调用getIndex前-right:"+right);//?为什么right和left会一直在变呢??xxxxxxxxxxxx
int index = getIndex(array,left,right);
System.out.println("\n");
/*下边这两行想简单一点,可以通过分析想到:不管怎么分,只要我们最终定下了index(基准值)的位置,
那么以基准值来把我们关注的这一部分元素(不要着眼于初始的整组元素)分为
两组的话,左边半组的left永远是最初传进来的left,右边半组的right永远是最初传进来的right。
在变化的只有左半组的right(为index-1),和右半组的left(为index+1)。
*/
KuaiSuSort(array,left,index-1);//负责左半部分
KuaiSuSort(array,index+1,right);//负责右半部分
System.out.println("调用自己后-left:"+left);//
System.out.println("调用自己后-right:"+right);
}
}
static int getIndex(int[] array,int left,int right){ //基准值会不断的与其他元素通过比较大小来交换位置,直到左边的元素都大于基准,右边的元素都小于基准
// System.out.println("right:"+right);
//已最左边的元素为基准,将数组进行重新分区,将小于基准的元素放到基准左边,大于基准的元素放到右边。
int temp = array[left];//基准
while (left<right){
//从最右边向左开始找,如果right位置的值大于基准,则继续向左寻找
while (left<right&&array[right]>temp){
right--;
}
//当array[right]<temp时,将array[left]赋值给array[right]
array[left] = array[right];
//紧接着,换到从左边向右开始找,如果left位置的值小于基准值,则继续向右寻找
while (left<right&&array[left]<temp){
left++;
}
if (left == right){
break;
}
//当找到array[left]>temp时,将array[left]的值赋值给array[right]
array[right] = array[left];
//利用while循环以上步骤,直到left=right,此时left和right指向的位置就是基准值应该在的最终位置。
}
//基准最后应在的位置
int index = left;
array[index] = temp;//确定位置后将基准值赋值到指定位置
// System.out.println("left:"+left);
// System.out.println("index:"+index);
// System.out.println("right:"+right);
return index;
}
}