JAVA数据结构之排序算法
冒泡算法
冒泡算法的思想是,从第一个元素出发,依次与他的下一个元素进行比较,如果大于下一个元素,则进行交换,否则不交换,指导比较到最后一个,得到的就是数组中最大的元素了,因为每一轮比较都会产生一个最大的数值,所以每一轮比较之后我们进行比较的元素都会减一。
public static void sort(Comparable[] a){
Comparable temp;
for(int i = a.length-1;i>0;i--){
for (int j = 0;j<i;j++){
if((a[j].compareTo(a[j+1]))>0){
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
}
在主函数中进行调用
Integer[] arr = {4,5,6,3,2,1};
Bubble.sort(arr);
System.out.println("冒泡排序算法------");
System.out.println(Arrays.toString(arr));
注意:Integer是一个引用类型的,在里面继承了Comparable接口,所以可以将传入的数组定义为Comparable类型。
选择排序
选择排序的思想是:
(1)首先从原始数组中选择最小的1个数据,将其和位于第1个位置的数据交换。
(2)接着从剩下的n-1个数据中选择次小的1个元素,将其和第2个位置的数据交换。
(3)然后,这样不断重复,直到最后两个数据完成交换。最后,便完成了对原始数组的从小到大的排序。
public static void SelectionSort(Comparable[] a){
for (int i=0;i< a.length-1;i++){
int min = i;
for(int j=i+1;j<a.length;j++){
if(a[min].compareTo(a[j])>0){
min = j;
}
}
Comparable temp;
temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
主函数中进行调用
Integer[] arr1 = {8,10,11,5,4,6,2,1};
Selection.SelectionSort(arr1);
System.out.println("选择排序算法------");
System.out.println(Arrays.toString(arr1));
插入排序
插入排序算法的思想:将整个数组a分为有序和无序的两个部分。前者在左边,后者在右边。开始有序的部分只有a[0] , 其余都属于无序的部分。每次取出无序部分的第一个(最左边)元素,把它加入有序部分。假设插入合适的位置p,则原p位置及其后面的有序部分元素都向右移动一个位置,有序的部分即增加了一个元素。一直做下去,直到无序的部分没有元素。
public static void insertSort(Comparable[] a){
for (int i = 1;i < a.length;i++){
for (int j = i;j > 0;j--){
if(a[j].compareTo(a[j-1])<0){
Comparable temp;
temp = a[j-1];
a[j-1] = a[j];
a[j] = temp;
}
else break;
}
}
}
在主函数中进行调用
Integer[] arr2 = {8,10,11,5,4,6,2,1};
InsertSort.insertSort(arr2);
System.out.println("插入排序算法------");
System.out.println(Arrays.toString(arr2));
希尔排序
希尔排序算法的思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。
public static void shellSort(Comparable[] a){
int N = a.length;
int h = 1;
//确定增长量
while (h<N/2){
h=2*h+1;
}
//进行排序
while (h>=1){
//排序
//找到待插入元素
for (int i = h;i < a.length;i++){
for (int j = i;j >= h;j -= h){
//如果后者小于前者进行交换元素
if(a[j].compareTo(a[j-h])<0){
Comparable temp;
temp = a[j-h];
a[j-h] = a[j];
a[j] = temp;
}else break;
}
}
//改变增长量
h=h/2;
}
}
在主函数中调用
Integer[] arr = {9,11,15,12,17,5,8,5,3,10,1};
ShellSort.shellSort(arr);
System.out.println(Arrays.toString(arr));
归并排序
归并排序算法的思想是:首先把一个数组中的元素,按照某一方法,先拆分了之后,按照一定的顺序各自排列,然后再归并到一起,使得归并后依然是有一定顺序的 。归并排序算法可以利用递归的思想或者迭代的思想去实现。首先我们先把一个无序的数组去拆分,然后利用一定的规则,去合并。类似于二叉树的结构。其总的时间复杂度为O( n log n)。空间复杂度为 S(nlogn)
private static Comparable[] assits;
public static void sortMerge(Comparable[] a){
//初始化assits
assits = new Comparable[a.length];
//最小索引和最大索引
int low = 0;
int hi = a.length - 1;
//调用排序
sort(a,low,hi);
}
public static void sort(Comparable[] a,int low,int hi){
//安全校验
if (hi<=low){
return;
}
//对数组进行分组 两组
int mid = low + (hi - low)/2;
//分别对两组进行排序
sort(a,low,mid);
sort(a,mid+1,hi);
//对每组数据进行归并
merge(a,low,mid,hi);
}
public static void merge(Comparable[] a,int low,int mid,int hi){
//定义三个指针,分别是左子组、右子组和辅组数组的指针
int i = low;
int p1 = low;
int p2 = mid+1;
//遍历两个子组的数据进行比较,然后顺序放到辅助数组里面
while (p1<=mid && p2<=hi){
if(a[p1].compareTo(a[p2])<0){
assits[i++] = a[p1++];
}else {
assits[i++] = a[p2++];
}
}
//分别遍历两个子组的指针是否走完,如果没有,把相应的数据放到辅助数组当中
while (p1<=mid){
assits[i++] = a[p1++];
}
while (p2<=hi){
assits[i++] = a[p2++];
}
//把辅助数组中的数据复制到原数组中
for (int index = low; index <= hi; index++){
a[index] = assits[index];
}
}
在主函数中调用
Integer[] a = {8,4,5,7,1,3,6,2};
Merge.sortMerge(a);
System.out.println(Arrays.toString(a));
快速排序
快速排序算法的思想是:快速排序使用分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小。之后分别对这两部分记录继续进行排序,以达到整个序列有序的目的。
快速排序的步骤:
(1)选择基准:在待排序列中,按照某种方式挑出一个元素,作为 “基准”(pivot)。
(2)分割操作:以该基准在序列中的实际位置,把序列分成两个子序列。此时,在基准左边的元素都比该基准小,在基准右边的元素都比基准大。
(3)递归地对两个序列进行快速排序,直到序列为空或者只有一个元素。
public static void sortQuick(Comparable[] a){
int low = 0;
int hi = a.length - 1;
sort(a,low,hi);
}
public static void sort(Comparable[] a,int low,int hi){
if(hi<=low){
return;
}
//找到分界值位置变换之后的索引
int partition = partition(a, low, hi);
//对分界值两边的数据进行排序
sort(a,low,partition-1);
sort(a,partition+1,hi);
}
public static int partition(Comparable[] a,int low,int hi){
//确定分界值
Comparable key = a[low];
//定义两个指针,分别进行寻找比分界值大和小的元素以及进行交换
int left = low;
int right = hi + 1;
//进行切分
while (true){
//先从右往左找,找到比分界值小的值,然后停止
while (key.compareTo(a[--right])<0){
if(right==low){
break;
}
}
//先从左往右找,找到比分界值大的值,然后停止
while (a[++left].compareTo(key)<0){
if (left==hi){
break;
}
}
//判断left>=right,如果是,则结束循环,否则进行交换元素
if (left>=right){
break;
}else {
Comparable temp;
temp = a[left];
a[left] = a[right];
a[right] = temp;
}
}
//交换分界值
Comparable temp;
temp = a[low];
a[low] = a[right];
a[right] = temp;
return right;
}
在主函数中调用
Integer[] a4 = {19,11,12,4,888,16,35,89,111,0};
QuickSort.sortQuick(a4);
System.out.println(Arrays.toString(a4));