冒泡排序
冒泡排序作为排序中相对简单的排序方法,也应该是我们最先接触到的排序方法。
首先我们应该了解冒泡排序的原理才能够将这种逻辑思想通过程序代码实现出来,所谓算法,无非就是通过将很多个1+1堆叠起来而产生的高于1+1的东西。
通过下面可以粗略知道这张动图了解冒泡的思想。
首先将一组数两两组队比较。(以数组为例,假设数组长度为15,数组元素和顺序如下图)
我们将a[i]和a[i+1]组合起来比较,如果a[i]>a[i+1],就将两数调换位置,之后将i自增,这样,a[i+1]又可以和a[i+2]组成一队进行比较。当我们判断完一轮后,我们可以将该数组中最大的数放到数组最后面。由于排序方法的有点像鱼吐泡泡,慢慢从最低端浮到最顶端(每次都是从第一个元素开始运行,并将运算完一轮后最大的值放在末尾),因此取名冒泡排序。
程序部分则需要注意几个部分:
冒泡排序每轮都会输出一个最大值到数组末尾,因此需要进行a.length-1轮,又因为每次判断一个值,所以需要进行a.length-1次比较,但是,由于每进行一轮都会减少一个需要继续判断的值,因此内层循环的判断条件使用a.length-1-i可以减少数据的运算。
简而言之就是外层控制运算轮数(有多少个数运算多少轮,最后一轮只有一个数),内层控制交换次数和交换方法。
package com.yuhang;
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int[] arr= {9,3,4,6,1,5};
for(int i=0;i<arr.length-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));
}
}
直接插入排序
什么叫直接插入排序?
直接插入排序就是将一个无序的数组中的元素通过逐个取出的方式,往有序区域逐个插入的过程。
直接插入排序原理:
就是从a[1]开始,逐个取出,然后和左边的数比较,如果遇到比取出数大的,则进行后移操作,直到遇到判断完有序区域内所有元素。因此,每次进行都会在取出数前产生一片有序区域,取出数后即为无序区域。
程序部分可能出现的问题:
程序中需要记录取出值的下标,需要移动的是自此下标之前所有满足条件的数(前面的值如果有比取出值大的,即进行后移操作)
我刚开始的误区觉得同样是判断,从a[i-1]判断比a[i](取出值)大的值和从a[0]开始判断比a[i]小的值,当遇到a[j-1]<a[i]且a[j]>a[i]的情况,这记录需要这个需要插入位置的下标,然后在进行插入操作。这样的方式虽然可以实现,但是在程序上比从a[i-1]判断比a[i]大后,直接将a[i-1]后移要来的麻烦。
package com.yuhang;
import java.util.Arrays;
public class InsertSort {
public static void main(String[] args) {
int[] a= {9,7,8,2,5,1,3,6,4};
//思路:
//1.首先取值,从第二个值开始取a[1]
//2.从a[1]开始取数,查询合适的位置插入
//3.查询条件是:依次判断所取值之前的数和所取值的大小
//4.如果有数比需要插入的数大,则将较大的数往后移动(其实就是在判断的过程中交换位置)
//直接找比需要插入值小的数,然后判断后面的值是否比需要插入的值大
for(int i=1;i<a.length;i++)//每次插入一个值
{
int insertNum=a[i];//i记录原本的位置
for(int j=i-1;j>=0;j--)//检测i之前的元素
{
if(a[j]>insertNum)//如果存在大于insertNum的值,就将它向后移
{
a[j+1]=a[j];
a[j]=insertNum;
}
}
}
System.out.println(Arrays.toString(a));
}
}
快速排序
快速排序的原理思想:
快速排序和二分法的思路类似,不过二分法是查找,可以排除掉不符合查找范围的值,而快速排序因为是排序,所以要考虑到所有值。
如图所示,快速排序的排序方法,是将数组arr[start]的值使用temp变量保存,使用两个指针分别标记数组首位和数组末尾,通过比较来移动数据,进而移动指针,最终在首未指针相遇时将temp的值保存进去,从而实现首尾指针相遇的位置的左端都是小于temp的值,右端都是大于temp的值。然后将数组分为左右两小段,重复执行上面的方法,直到每段小数组都只有一个数据,就结束排序。
package com.fastSort;
import java.util.Arrays;
public class FastSort {
//快速排序的思路:
// 1.以第一个数字为基准进行第一次排序
// 2.排序规则:取一个数为基准赋值给temp,准备两个指针,分别指向数组首位i和数组末尾j
// 首先将数组尾部的数与temp比较,若temp较小,则j指针向前移动(j--)
// 若temp较大,则将j位置的值赋值给i位置,再从i+1的位置和temp比较,若temp
// 较大则将i向后移动(i++),若temp较小则将i位置的数值赋值给j位置,在将j位置
// 的数与temp比较,以此循环,直到i==j,将temp赋值给i的位置,实现所有temp
// 左边的值均小于temp,右边的值军大与temp
// 3.记录位置,将temp左右的数列进行2的操作
public static int getIndex(int[] arr,int start,int ends)//用于记录每次划分数组的分界
{
int temp;
temp=arr[start];
while(start<ends)
{
while(temp<arr[ends]&&start<ends)
{
ends--;
}
arr[start]=arr[ends];
while(temp>arr[start]&&start<ends)
{
start++;
}
arr[ends]=arr[start];
}
arr[start]=temp;
return start;
}
public static void fastSort(int[] arr,int start,int ends)//递归实现数组快排
{
if(start<ends)
{
int index=getIndex(arr, start, ends);
fastSort(arr,start,index-1);
fastSort(arr,index+1,ends);
}
}
public static void main(String[] args) {
int[] arr= {1,5,4,3,2,6,7,8,9};
fastSort(arr,0,8);
System.out.println(Arrays.toString(arr));
}
}
未完待续……