常用排序算法
闲来无事,把一些常用的排序算法整理了一遍,以供自己日后温习之用
//**********************************选择排序***************************************
//直接选择排序,不稳定,时间复杂度n^2
class SelectSort{
public static void selsectSort(int[] array){
for(int i=0;i<array.length-1;i++){
int k=i,temp;
for(int j=i+1;j<array.length;j++){ //在后面元素中选择最小的元素
if(array[j]<array[k]){
k=j; //更新最小元素位置
}
}
if(k!=i){ //将最小元素交换到队首
temp=array[k];
array[k]=array[i];
array[i]=temp;
}
}
}
}
//堆排序(选择排序),不稳定,时间复杂度nlog2n
class HeapSort{
public static void heapSort(int[] array){
for(int i=0;i<array.length;i++){
buildMaxHeap(array,array.length-i); //循环建堆
int temp=array[0]; //交换堆顶和最后一个元素
array[0]=array[array.length-i-1];
array[array.length-i-1]=temp;
}
}
//建立大根堆
private static void buildMaxHeap(int[] array,int len){
for(int i=(len-2)/2;i>=0;i--){ //遍历非叶子结点
int temp;
int k=i; //暂存父结点
for(int j=2*k+1;j<len;j=j*2+1){ //遍历各父结点下的子结点
if(j<len-1 && array[j]<array[j+1]){ //判断哪个子结点较大
j++; //选择较大的子结点
}
if(array[k]>=array[j]){ //父结点与子结点进行比较
break;
}else{ //如果子结点比父结点大则交换
temp=array[k];
array[k]=array[j];
array[j]=temp;
k=j; //暂存子结点,用以向下筛选
}
}
}
}
}
//**********************************交换排序***************************************
//冒泡排序(交换排序),稳定,时间复杂度n^2
class BubbleSort{
public static void bubbleSort(int[] array){
int temp;
boolean flag;
for(int i=0;i<array.length-1;i++){
flag=true; //设置标志位(非常重要)
for(int j=0;j<array.length-1-i;j++){
if(array[j+1]<array[j]){
temp=array[j+1];
array[j+1]=array[j];
array[j]=temp;
flag=false;
}
}
if(flag){ //若本次遍历后没发生交换,说明已经有序
return;
}
}
}
}
//快速排序(交换排序),不稳定,时间复杂度nlog2n,空间复杂度log2n
class QuickSort{
public static void quickSort(int[] array,int low,int high){
if(low>=high){ //递归出口
return;
}
int index=array[low]; //谁知key进行划分
int i=low;
int j=high;
while(i<j){
while(i<j && index<array[j]){ //判断右边元素
j--;
}
array[i]=array[j];
while(i<j && index>array[i]){ //判断左边元素
i++;
}
array[j]=array[i];
}
array[i]=index;
quickSort(array, low, i-1); //进行递归
quickSort(array, i+1, high);
}
}
//**********************************插入排序***************************************
//直接插入排序,稳定,时间复杂度n^2
class InsertSort{
public static void insertSort(int[] array){
int temp,i,j;
for(i=0;i<array.length-1;i++){
temp=array[i+1]; //取出待插入的元素
for(j=i;j>=0 && temp<array[j];j--){ //向前查询待插入位置
array[j+1]=array[j]; //向后移位
}
array[j+1]=temp; //复制到插入位置
}
}
}
//折半插入排序,稳定,时间复杂度n^2(相比直接插入排序减少了比较次数)
class BinaryInsertSort{
public static void binaryInsertSort(int[] array){
int temp,low,high,mid,i,j;
for(i=0;i<array.length-1;i++){
temp=array[i+1]; //取出待插入的元素
low=0;
high=i;
while(low<=high){ //折半查找
mid=(low+high)/2;
if(array[mid]>temp){ //查找左半子表
high=mid-1;
}else{ //查找右半子表
low=mid+1;
}
}
for(j=i;j>=low;j--){
array[j+1]=array[j]; //移动元素
}
array[j+1]=temp; //插入操作
}
}
}
//希尔排序(插入排序),不稳定,时间复杂度取决于步长函数
class ShellSort{
public static void shellSort(int[] array){
for(int c=array.length/2;c>=1;c=c/2){ //步长变化
int i,j,temp;
for(i=0;i<array.length-c;i++){
temp=array[i+c];
for(j=i;j>=0 && temp<array[j];j=j-c){
array[j+c]=array[j]; //记录后移
}
array[j+c]=temp; //插入操作
}
}
}
}
//二路归并排序,稳定,时间复杂度nlog2n,空间复杂度n
class MergeSort{
public static void mergeSort(int[] array){
sort(array,0,array.length-1);
}
public static void sort(int[] array,int left,int right){
if(left<right){
int mid=(left+right)/2; //从中间划分两个子序列
sort(array,left,mid); //对左侧子序列进行递归排序
sort(array,mid+1,right); //对右侧子序列进行递归排序
Merge(array,left,mid,right); //归并
}
}
//将两个相邻的表合并
public static void Merge(int[] array,int left,int mid,int right){
int[] b=new int[array.length];
int i,j,k;
for(i=0;i<array.length;i++){
b[i]=array[i]; //将元素复制到数组b中
}
for(i=left,j=mid+1,k=i;i<=mid && j<=right;k++){
if(b[i]<b[j]){ //比较b的左右两段中的元素
array[k]=b[i++]; //将较小值复制到原数组中
}else{
array[k]=b[j++];
}
}
while(i<=mid){ //若第一个表未检测完,复制
array[k++]=b[i++];
}
while(j<=right){ //若第二个表未检测完,复制
array[k++]=b[j++];
}
}
}
//一个扯淡的排序算法,利用多线程实现
class SleepSort implements Runnable{
int ms=0;
public SleepSort(int ms){
this.ms=ms;
}
public void run() {
try {
Thread.sleep(ms*20); //如果你的排序数很小的话,必须将其扩大,否则不准确
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(ms+" ");
}
public static void sleepSort(int[] array){
SleepSort[] sleepSorts=new SleepSort[array.length];
for(int i=0;i<array.length;i++){
sleepSorts[i]=new SleepSort(array[i]);
}
for(int i=0;i<array.length;i++){
new Thread(sleepSorts[i]).start();
}
}
}
public class Test {
public static void main(String[] args) {
System.out.println("------------------直接选择排序---------------------");
int[] a={9,79,46,30,58,49,67,34,22,2,3,5,12,78,345,0};
SelectSort.selsectSort(a);
print(a);
System.out.println("------------------堆排序---------------------");
int[] b={9,79,46,30,58,49,67,34,22,2,3,5,12,78,345,0};
HeapSort.heapSort(b);
print(b);
System.out.println("------------------冒泡排序---------------------");
int[] c={9,79,46,30,58,49,67,34,22,2,3,5,12,78,345,0};
BubbleSort.bubbleSort(c);
print(c);
System.out.println("------------------快速排序---------------------");
int[] d={9,79,46,30,58,49,67,34,22,2,3,5,12,78,345,0};
QuickSort.quickSort(d, 0, d.length-1);
print(d);
System.out.println("------------------直接插入排序---------------------");
int[] e={9,79,46,30,58,49,67,34,22,2,3,5,12,78,345,0};
InsertSort.insertSort(e);
print(e);
System.out.println("------------------折半插入排序---------------------");
int[] f={9,79,46,30,58,49,67,34,22,2,3,5,12,78,345,0};
BinaryInsertSort.binaryInsertSort(f);
print(f);
System.out.println("------------------希尔排序---------------------");
int[] g={9,79,46,30,58,49,67,34,22,2,3,5,12,78,345,0};
ShellSort.shellSort(g);
print(g);
System.out.println("------------------二路归并排序排序---------------------");
int[] h={9,79,46,30,58,49,67,34,22,2,3,5,12,78,345,0};
MergeSort.mergeSort(h);
print(h);
System.out.println("------------------SleepSort排序---------------------");
int[] i={9,79,46,30,58,49,67,34,22,2,3,5,12,78,345,0};
SleepSort.sleepSort(i);
}
//打印函数
private static void print(int[] array){
for(int num:array){
System.out.print(num+" ");
}
System.out.println();
}
}