初级排序算法

9 篇文章 0 订阅

初级排序算法

模板:定义了基本的辅助函数

传入了实现了Comparable接口的数据类型的数组

class Sort{
    public void sort(Comparable [] a){}
    public  static boolean less(Comparable v,Comparable w){
        return v.compareTo(w)<0;
    }
    public  static void exch(Comparable[] a,int i ,int j){
        Comparable t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
    public static void show(Comparable []a ){
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i]+" ");
        }
        System.out.println();
    }
}

冒泡排序

实现

重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

时间复杂度分析

若数组的初始状态是正序的,一趟扫描既可以完成排序,所需的比较次数C和记录移动次数M均达到最小值,Cmin = n-1,Mmin=0,因此冒泡排序的时间复杂度为O(n)

若数组的初始状态为反序的,需要进行n-1趟排序,每趟排序要进行n-i次关键字的比较,且每次都需要三次对记录的交换来交换位置,这种情况下,比较和移动的次数均达到最大值

Cmax = n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n1) = O(n2)

Mmax = 3 n ( n − 1 ) 2 \frac{3n(n-1)}{2} 23n(n1) = O(n2)

冒泡排序的最坏时间复杂度为O(n2)

稳定性:由于不换交换相等的数据,因此冒泡排序是稳定的排序

class BubbleSort extends Sort{
    public void sort (Comparable [] a) {
        int N = a.length;
        boolean flag = false;//判断本次冒泡是否有交换数据
        for(int i = 0;i<N;i++){
            flag = false;//重置为没有交换
            for(int j = 0;j<N-1-i;j++){//每次循环最后一个数据都为最大的数字
                if(a[j].compareTo(a[j+1])>0){
                    exch(a,j,j+1);
                    flag = true;
                }
            }
            if(flag == false){//如果这次排序没有调换数据,证明序列已经有序
                return;
            }
        }
    }
}

选择排序

实现:

第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。

时间复杂度分析:

选择的比较次数O(n2),总的比较次数为N=(n-1)+(n-2)+…+1 = n ∗ ( n − 1 ) 2 \frac{n*(n-1)}{2} 2n(n1)

交换次数是O(n)

最好情况:已经有序,交换0次;最坏情况交换n-1次,逆序交换 n 2 \frac{n}{2} 2n次,交换次数比冒泡排序少

**稳定性:**不稳定排序,在交换的时候,可能将相等的值往后面交换。例如58529,这种排序,选择排序会破坏算法的稳定性。

class Selection extends Sort{
//    public Selection(){}
    public void sort(Comparable [] a){
        int N = a.length;
        for (int i = 0; i < N; i++) {
            int min = i;
            for (int j = i+1; j < N; j++) {
                //寻找最小的数
                if(less(a[j],a[min]))min = j;
            }
            //将最小的数与遍历的下标交换
            exch(a,i,min);
        }
    }
}

插入排序

思路:

每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

时间复杂度分析:

如果数组最开始是有序的,那么比较次数为Cmin=n-1,移动次数Mmin=0

如果数组最开始是无序的,那么复制度为O(n2)

Cmax=(n-1)+(n-2)+…+1= n ∗ ( n − 1 ) 2 \frac{n*(n-1)}{2} 2n(n1) = O(n2)

Mmax = 3 n ( n − 1 ) 2 \frac{3n(n-1)}{2} 23n(n1) = O(n2)

稳定性:

稳定算法,每次的交换都发生在一个数字和一个已经有序的数组中。

class Insertion extends Sort{
    public void sort(Comparable [] a) {
        int N = a.length;
        for (int i = 1; i < N; i++) {//将a[i]插入到前面的排好序的序列中,这个循环只是提供前面排好序的下标,真正进行交换的是下面一个循环
            //比较已经排序的前面的数组
            for (int j = i; j > 0; j--) {
                //从边界开始与已经有序的数组比较,如果比前面的小,一直交换,直到到达指定位置
                if(a[j].compareTo(a[j-1])<0)
                    exch(a,j,j-1);
            }
        }
    }

希尔排序

思路:

对于大规模的乱序数组的插入排序很慢,因为他们只会交换相邻的元素,因此元素只能一点一点的从数组的一端移动到另外一个端。希尔排序为了加快速度简单的改进了插入排序,交换不相邻的元素以对数组的局部进行排序,并最终插入排序将局部有序的数组排序。希尔排序的思想就是使数组中任意间隔为h的元素都是有序的。算法实现冲N/3开始递减至1

稳定性

不稳定,由于h有序数组,排序后相同的数字的顺序可能会被打乱

class Shell extends Sort{
    public void sort(Comparable[] a) {
        int N = a.length;
        int  h = 1;
        while(h<N/3) h = h * 3 + 1;//让h从N/3开始递减到1
        while (h >= 1) {
            //形成h有序数组,做法与插入排序相似,只是以h为间隔
            for (int i = h; i < N; i++) {
                for (int j = i; j >= h; j -= h) {
                    if(less(a[j],a[j-1]))
                        exch(a,j,j-1);
                }
            }
            h = h/3;//循环直到h为1,就是进行最后的插入排序了
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值