排序算法(未完成)

一、交换排序

冒泡排序(BubbleSort)

思想:通过循环依次比较相邻的两个元素,若不符合规则就互换位置。
平均时间复杂度:O(n2)
最坏时间复杂度:O(n2)
最好时间复杂度:O(n)
Java代码实现:

public static int [] BubbleSort(int [] a){
    for(int i=0;i<a.length-1;i++){
        for(int j=0;j<a.length-1-i;j++){
            if(a[j]>a[j+1]){
                int temp = a[j];
                a[j]=a[j+1];
                a[j+1]=temp;
            }
        }
    }
    return a;
}
快速排序(QuickSort)

1、简单的快速排序
思想:采用分治法对序列依次拆分来进行排序,通过一次排序后将序列分成两个子序列,再分别对子序列进行同样的操作
平均时间复杂度:O(nlog2n)
最坏时间复杂度:O(n2)
最好时间复杂度:O(nlog2(n))
Java代码实现:

//使用方法:定义一个数组,然后直接调用下方的QuickSort函数
//拆分序列函数:根据分界点拆分序列
public static int Partition(int [] a,int left,int right){
    int base=a[left];
    while(left!=right){
        //从右边依次寻找比当前基数小的元素
        while(a[right] >= base && left<right){
            right--;
        }
        //若找到与left互换值
        a[left] = a[right];
        //从左边依次寻找比当前基数大的元素
        while(a[left] <= base && left<right){
            left++;
        }
        //若找到与right互换值
        a[right] = a[left];
    }
    //将当前left所在的重复值换成基数base
    a[left]=base;
    //返回当前停止的地方,返回left或者right都行,因为此时left=right
    return left;
}

//快速排序:递归调用拆分函数
public static void QuickSort(int [] a,int left,int right){
    //判断函数是否结束
    if(left > right)
        return ;
    //获取当前拆分一次后停止的地方
    int index = Partition(a,left,right);
    //采用递归的方式对拆分出来的子序列进行再次拆分
    QuickSort(a,left,index-1);
    //减1的目的是为了避免子序列有重复元素
    QuickSort(a,index+1,right);
}

2、快速排序算法的改进
改进的方法即基数的选取标准:固定切分,随机切分和三取样切分。上述快速排序即采用固定切分。
(跟上面的代码比较只是增加了第6-19行代码,采用三数取中来选择基数)
Java代码实现:

//根据分界点拆分序列
/*
 * 快速排序的改进:改进的关键在于基数的选取,在此选用三数取中法选取基数
 * */
 public static int Partition(int [] a,int left,int right){
     //获取中间数的索引
     int mid = (left+right)/2;
     //对左中右三个数进行排序,并按照从左到右递增的顺序互换位置
     if(a[left]>a[mid]){
         swap(a,left,mid);
     }
     if(a[left]>a[right]){
         swap(a,left,right);
     }
     if(a[right]<a[mid]){
         swap(a,right,mid);
     }
     //交换之后将选中的基数a[mid]跟第一个元素即a[left]互换位置,目的是方便记下来的排序
     swap(a,left,mid);
     //此时基数为a[left]
     int base=a[left];
     while(left!=right){
         //从右边依次寻找比当前基数小的元素
         while(a[right] >= base && left<right){
             right--;
         }
         //若找到与left互换值
         a[left] = a[right];
         //从左边依次寻找比当前基数大的元素
         while(a[left] <= base && left<right){
             left++;
         }
         //若找到与right互换值
         a[right] = a[left];
     }
     //将当前left所在的重复值换成基数base
     a[left]=base;
     //返回当前停止的地方,返回left或者right都行,因为此时left=right
     return left;
 }

 //快速排序
 public static void QuickSort(int [] a,int left,int right){
     //判断函数是否结束
     if(left > right)
         return ;
     //获取当前拆分一次后停止的地方
     int index = Partition(a,left,right);
     //采用递归的方式对拆分出来的子序列进行再次拆分
     QuickSort(a,left,index-1);
     QuickSort(a,index+1,right);

 }

 //通用的数值交换函数
 private static void swap(int[] arr, int a, int b) {
     int temp = arr[a];
     arr[a] = arr[b];
     arr[a] = arr[b];
     arr[b] = temp;
 }

二、选择排序

简单选择排序(SelectSort)

思想:从剩余未排序的序列中选择最小(或最大的)依次插入已排序列的末尾(开始时已排序列为空,剩余序列为当前序列)。
平均时间复杂度:O(n2)
最坏时间复杂度:O(n2)
最好时间复杂度:O(n2)
注:因为无论如何寻找最小值的for循环都会执行一遍(n次),再加上外层循环(n次)所以时间复杂度最好最坏都是O(n2)

public static int [] SelectSort(int [] a){
    for(int i = 0;i<a.length;i++){
        //min代表当前未排序序列中最小值的索引,初始值为i即未排序序列的第一个元素
        int min=i,temp;
        //这个for循环目的是在未排序序列中找到最小值的索引并赋值给min
        for(int j=i+1;j<a.length;j++){
            if(a[min]>a[j]){
                min=j;
            }
        }
        //在已排序序列的末尾处让刚才在未排序序列中找到的a[min]互换值,以达到排序的目的
        temp = a[i];
        a[i]=a[min];
        a[min]=temp;
    }
    return a;
}

三、插入排序

插入排序

算法思想:将元素逐个插入到前面已经排好序的子序列中(默认第一个元素已经排序)
平均时间复杂度:O(n2)
最坏时间复杂度:O(n2)
最好时间复杂度:O(n)

public static int[] InsertSort(int [] a){
	for(int i=1;i<a.length;i++){
	    int pre = i-1;
	    int cur = a[i];
	    //将当前元素依次跟已排好序的元素比较,找到该元素应该的位置
	    while(pre>=0 && cur < a[pre]){
	        //将大于该元素的元素往后挪一位
	        a[pre+1]=a[pre];
	        //比较下一个元素
	        pre--;
	    }
	    //将当前元素赋给空出来的位置
	    a[pre+1]=cur;
	}
	return a;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值