1. 简单排序

1.1 插入排序

原理:

1)选择第二个元素依次同前面的元素比较,小于则互换,大于则退出6>4,直接退出,不再进行比较

2)选择第三个元素依次同前面的元素比较,小于则互换,大于则退出3<6,将第三个元素同第二个元素互换,继续比较第二个元素同第一个元素比较,3<4,互换元素

3)选择第四个元素依次同前面的元素比较,小于则互换,大于则退出1<6,互换1<4,互换1<3,互换

4)选择第五个元素依次同前面的元素比较,小于则互换,大于则退出最后一步2>1,结束比较

5)选择第六个元素依次同前面的元素比较,小于则互换,大于则退出5>4,结束比较

事实上可以看出每轮比较完后,左边的元素都是有序排序的。所以下一轮比较时需要比当前元素小的元素时可以停止继续向下比较了。

代码实现:

/*** 插入排序*/
public class Insertion {
/*** 对数组A中的元素进行排序* @param a*/
public static void sort(Comparable[] a){
for (int i = 0; i < a.length-1; i++) {
for (int j = i+1; j >0 ; j--) {
if (greater(a[j-1],a[j])){
exch(a,j-1,j);
}else {
break;
}
}
}
}
/*** 比较v是否大于w元素* @param v* @param w* @return*/
private static boolean greater(Comparable v,Comparable w){
return v.compareTo(w)>0;
}
/*** 元素i,j交换位置* @param a* @param i* @param j*/
private static void exch(Comparable[] a,int i,int j){
Comparable temp;
temp =a[i];
a[i]=a[j];
a[j]=temp;
}
}

测试:

public class InsertionTest {
public static void main(String[] args) {
Integer[] a={4,6,3,1,2,5,7};
Insertion.sort(a);
System.out.println(Arrays.toString(a));
}
}

1.2 选择排序

选择排序的思路是选择最小的元素放在索引的第一个位置,然后依次找出第二、第三小的元素,直到排序完所有的元素。

1)第一轮比较,获取最小元素位置并同第一个元素交换交换后的序列

2)第二轮比较,从第二元素开始获取除第一个元素的最小元素位置元素位置并同第而个元素交换,后面重复此类操作。交换后的结果

代码实现:

/*** 选择排序的代码实现*/
public class Selection {
/*** 对数组A中的元素进行排序* @param a*/
public static void sort(Comparable[] a){
for (int i=0;i
int minIndex=i;
for (int j=i+1;j
if(greater(a[minIndex],a[j])){
minIndex=j;
}
}
//交换最小元素所在索引 exch(a,i,minIndex);
}
}
/*** 比较v是否大于w元素* @param v* @param w* @return*/
private static boolean greater(Comparable v,Comparable w){
return v.compareTo(w)>0;
}
/*** 元素i,j交换位置* @param a* @param i* @param j*/
private static void exch(Comparable[] a,int i,int j){
Comparable temp;
temp =a[i];
a[i]=a[j];
a[j]=temp;
}
}

测试:

public class SelectionTest {
public static void main(String[] args) {
Integer[] arr={4,6,3,1,2,5,7};
Selection.sort(arr);
System.out.println(Arrays.toString(arr));
}
}

1.3 冒泡排序

原理:

选择排序是寻找小元素依次放在最前面,而冒泡排序是通过相邻元素依次比较使最大值位于后边。

1)第一轮比较,使最大值位于最右边

2)第二轮比较,使除去最右边元素后的最大值位于右边第二个位置,交换过程同上面一样只是不需要比较最后一个元素。后面的步骤同上只是每一轮比较次数都有依次减一

3)第三轮比较

4)第四轮比较

5)第五轮比较

6)最后一轮比较

代码实现如下:

/*** 冒泡排序算法的实现*/
public class Bubble {
/*** 对数组A中的元素进行排序* @param a*/
public static void sort(Comparable[] a){
for (int i=a.length-1;i>0;i--){
for (int j=0;j
if (greater(a[j],a[j+1])){
exch(a,j,j+1);
}
}
}
}
/*** 比较v是否大于w元素* @param v* @param w* @return*/
private static boolean greater(Comparable v,Comparable w){
return v.compareTo(w)>0;
}
/*** 元素i,j交换位置* @param a* @param i* @param j*/
private static void exch(Comparable[] a,int i,int j){
Comparable temp;
temp =a[i];
a[i]=a[j];
a[j]=temp;
}
}

测试:

public class BubbleTest {
public static void main(String[] args) {
Integer[] arr={4,6,3,1,2,5,7};
Bubble.sort(arr);
System.out.println(Arrays.toString(arr));
}
}

2. 高级排序

2.1 希尔排序

排序原理:

1.选定一个增长量h,按照增长量h作为数据分组的依据,对数据进行分组;

2.对分好组的每一组数据完成插入排序;

3.减小增长量,最小减为1,重复第二步操作。

/*** 高级排序算法--希尔排序*/
public class Shell {
public static void sort(Comparable a[]){
//增长量h的确定:增长量h的值每一固定的规则,我们这里采用以下规则: //根据数组a的长度,确定增长量h的初始化 int h=1;
while (h
h=h*2+1;
}
//2.希尔排序 while (h>=1){
//排序 for (int i=h;i
for (int j=i;j>=h;j-=h){
if (greater(a[j-h],a[j])){
exch(a,j-h,j);
}else {
break;
}
}
}
//减小h的值 h=h/2;
}
}
/*** 判断元素v是否大于w* @param v* @param w* @return*/
public static boolean greater(Comparable v,Comparable w){
return v.compareTo(w)>0;
}
/*** 数组元素i和j的交换* @param a* @param i* @param j*/
public static void exch(Comparable a[],int i,int j){
Comparable temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}

测试:

public class ShellTest {
public static void main(String[] args) {
Integer[] a={4,3,2,10,12,1,5,6};
Shell.sort(a);
System.out.println(Arrays.toString(a));
}
}

2.2 归并排序

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

排序原理:

1.尽可能的一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组的元素个数是1为止。

2.将相邻的两个子组进行合并成一个有序的大组;

3.不断的重复步骤2,直到最终只有一个组为止。

/*** 归并排序*/
public class Merge {
private static Comparable[] assist;
public static void sort(Comparable[] a){
//1.初始化辅助数组assist assist=new Comparable[a.length];
//2.定义一个lo变量和hi变量,分别记录数组中最小的索引和最大的索引; int lo=0;
int hi=a.length-1;
//3.调用sort重载算法完成数组a中,从索引lo到索引hi的排序 sort(a,lo,hi);
}
private static void sort(Comparable[] a,int lo,int hi){
//安全性校验 if (hi<=lo){
return;
}
int mid = lo+(hi-lo)/2;
sort(a,mid+1,hi);
sort(a,lo,mid);
//归并 merge(a,lo,mid,hi);
}
/*** 归并函数* @param a* @param lo* @param mid* @param hi*/
private static void merge(Comparable[] a,int lo,int mid,int hi){
//定义三个指针 int i=lo;
int p0=lo;
int p1=mid+1;
while (p0<=mid && p1<=hi){
if (less(a[p0],a[p1])){
assist[i++]=a[p0++];
}else {
assist[i++]=a[p1++];
}
}
//判断哪一边的序列先走完 while(p0<=mid){
assist[i++]=a[p0++];
}
while (p1<=hi){
assist[i++]=a[p1++];
}
for (int index=lo;index<=hi;index++){
a[index]=assist[index];
}
}
/*** 判断元素v是否小于w* @param v* @param w* @return*/
private static boolean less(Comparable v,Comparable w){
return v.compareTo(w)<0;
}
/*** 交换元素* @param a* @param i* @param j*/
private static void exch(Comparable[] a,int i,int j){
Comparable temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}

2.3 快速排序

接下来将4的左右数组分别进行上述操作(递归操作,递归退出条件是最大索引小于等于最小索引)

代码实现如下:

public class Quick {
public static void sort(Comparable[] a){
int lo=0;
int hi=a.length-1;
sort(a,lo,hi);
}
private static void sort(Comparable[] a,int lo,int hi){
if (hi<=lo){
return;
}
//获取中间索引 int partition = partition(a, lo, hi);
sort(a,lo,partition-1);
sort(a,partition+1,hi);
}
private static int partition(Comparable[] a,int lo,int hi){
//定义左指针和右指针 int left=lo;
int right=hi+1;
Comparable key=a[lo];
while (true){
while (less(key,a[--right])){
if (right==lo){
break;
}
}
while (less(a[++left],key)){
if(left==hi){
break;
}
}
//交换左右两边元素 if (right>left){
exch(a,left,right);
}else {
break;
}
}
exch(a,lo,right);
return right;
}
/*** 判断元素v是否小于w* @param v* @param w* @return*/
private static boolean less(Comparable v,Comparable w){
return v.compareTo(w)<0;
}
/*** 交换元素* @param a* @param i* @param j*/
private static void exch(Comparable[] a,int i,int j){
Comparable temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}

参考