废话不多说,直接看代码
import java.util.ArrayList;
public class Sort {
static int[] a= {-1,1,41,3,3,3,1,2,5,23,345,12,3,4,53,2,41};
//static int[] a = {2, 1,-1};
public static void main(String[] args){
quickSort(a);
printArray();
}
/** *冒泡排序 *1.从第一个开始比较相邻的元素。如果后置位比前置位小,进行交换。 *2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。 *3.重复步骤1,每次遍历长度减一(末尾的数已经有序,不需要进行交换)。 */
public static void bubbleSort(int[] a){
for(int i = 0; i<a.length; i++){
boolean sorted= true;
for(int j = 0; j<a.length-1-i; j++){
if(a[j]>a[j+1]){
sorted = false;
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
if(sorted){
break; //所有数已经有序,可退出循环
}
}
}
/** *插入排序 *1.从第一元素,将第一个元素归为已排序集合A *2.取出下一个元素temp,在已经排序的元素集合中中从后向前遍历 *3.比较当前元素与temp的大小,若temp元素小于当前元素,则当前元素后移,否则将temp插入当前元素之后 *********************** * 复杂度分析 * 最优情况,数组已排好序,复杂度O(n) * 平均时间复杂度,O(n^2) */
public static void insertionSort(int[] a) {
int length = a.length;
for (int i = 1; i < length; i++) {
int temp = a[i];
int j;
for (j = i; j >0 && temp<a[j-1]; j--) {
a[j] = a[j-1];
}
a[j] = temp;
}
}
/** * 选择排序 *每次遍历从未排序数组中选出最小值放到已排序数组的末尾 * ************** * 复杂度分析 * 需要完整进行两次遍历,时间复杂度O(n^2) */
public static void selectionSort(int[] a) {
int length = a.length;
for (int i = 0; i < length; i++) {
int min = i;
for (int j = i + 1; j < length; j++) {
if (a[j]-a[min]< 0) {
min = j;
}
}
int temp = a[min];
a[min] = a[i];
a[i] = temp;
}
}
/** * 希尔排序 * 希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本,希尔排序是非稳定排序算法 * 步上的选择是希尔排序的重要组成部分 * ********** * 算法复杂度和步长的选择相关,详细可参阅维基百科,希尔排序在小数组中比快速排序和堆排序还快,但是在涉及大量数据时希尔排序还是比快速排序慢 */
public static void shellSort(int[] a){
int gap = 1, i, j, len = a.length;
int temp;
while(gap<len/3) {
gap = gap * 3 + 1; //1,4,7,10,13
}
for(;gap>0;gap/=3){
for(i=gap;i<len;i++){
temp =a[i];
for(j = i-gap;j>=0&&a[j]>temp;j-=gap){
a[j+gap] = a[j];
}
a[j+gap] = temp;
}
}
}
/* 堆树的定义如下: (1)堆树是一颗完全二叉树; (2)堆树中某个节点的值总是不大于或不小于其孩子节点的值; (3)堆树中每个节点的子树都是堆树。 当父节点的键值总是大于或等于任何一个子节点的键值时为最大堆。 当父节点的键值总是小于或等于任何一个子节点的键值时为最小堆。如下图所示,左边为最大堆,右边为最小堆。 */
/** *1.将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区; *2.将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n]; *3.由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将堆顶R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。 * ********** * 利用堆排序可以很容易地从无序中选择最大记录(大堆排序)或最小记录(小堆排序) * ********** * 复杂度分析: * 时间复杂度:o(nlogn) ,最优时间复杂度o(nlogn),平均时间复杂度o(nlogn) */
public static void heapSort(int[] a){
int len = a.length;
int temp;
for (int i = 0;i<len;i++){
buildHeap(a,len-i);
temp = a[0]; //取出堆顶(最大数)
a[0] = a[len-i-1];
a[len-i-1] = temp;
}
}
//最后一个非叶子节点索引是(size-2)/2
public static void buildHeap(int[] a,int size){
int leftChild;
int rightChild;
int temp;
for(int i=(size-2)>>1; i>=0; i--){
leftChild = (i<<1)+1;
rightChild = (i<<1)+2;
if((rightChild>=size||a[rightChild]<a[leftChild])&&a[i]<a[leftChild]){ //没有右孩子节点
temp = a[i];
a[i] = a[leftChild];
a[leftChild] = temp;
}else if(rightChild<size&&a[rightChild]>a[i]){
temp = a[i];
a[i] = a[rightChild];
a[rightChild] = temp;
}
}
}
/** *归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 *************** * 算法复杂度: * 时间复杂度:O(nlogn),最优时间复杂度:O(n),平均时间复杂度:O(nlogn),空间复杂度O(n) */
//先看合并算法,a,b合并到c ,a[first,mid] b(mid,last]
public static void mergeArray(int[] a, int first, int mid, int last){
int i = first, j = mid+1 ,k=0;
int[] temp =new int[last-first+1];
while(i<=mid&&j<=last){
if(a[i]>a[j]){
temp[k++] = a[j++];
}else{
temp[k++] = a[i++];
}
}
while(i<=mid){
temp[k++] = a[i++];
}
while(j<=last){
temp[k++] = a[j++];
}
int len = temp.length;
for(k = 0;k<len;k++){
a[first+k] = temp[k];
}
}
//再看分治算法
public static void mergeSort(int[] a){
mergeSort(a,0,a.length-1);
}
public static void mergeSort(int[] a,int first,int last){
if(first<last){
int mid = (first+last)>>1;
mergeSort(a,first,mid);
mergeSort(a,mid+1,last);
mergeArray(a,first,mid,last);
}
}
/** * 快速排序 *1.从数列中挑出一个元素,称为"基准"(pivot), *2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。 *3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。 */
public static void quickSort(int[] a){
quickSort(a,0,a.length-1);
}
private static void quickSort(int[] a,int lo, int hi){
if(hi<=lo){
return;
}
int i = partition(a, lo, hi);
quickSort(a, lo, i - 1);
quickSort(a, i + 1, hi);
}
private static int partition(int[] a,int lo, int hi){
int i = lo, j=hi;
int pivot = a[lo];
int temp;
while(true) {
while (i<j) {
if(a[j]<=pivot){
a[i] = a[j];
break;
}
j--;
}
while(i<j){
if(a[i]>pivot){
a[j] = a[i];
break;
}
i++;
}
if(i>=j){
a[i] = pivot;
break;
}
}
return i; //返回基准位置
}
public static void printArray(){
for (int i=0;i<a.length;i++) {
System.out.print(a[i]+"\t");
}
System.out.println("\n");
}
}