排序算法总结

排序算法总结

来自瞎搞的枣儿

部分代码是我自己写的,如果道友发现错误望指出,谢谢~

排序大概可以分为内部排序和外部排序,其中内部排序主要有插入排序、冒泡排序、选择排序、归并排序、快速排序、堆排序(二叉堆)、桶排序、基数排序。外部排序主要是对较大文件的数据的处理

为什么学排序

  • First, sorting algorithms illustrate many creative approaches to problem solving, and these approaches can be applied to solve other problems.
  • Second, sorting algorithms are good for practicing fundamental programming techniques using selection statements, loops, methods, and arrays.
  • Third, sorting algorithms are excellent examples
    to demonstrate algorithm performance.
    翻译:
  • 首先,排序算法阐明了许多解决问题的创造性的方法,并且这些方法还可以解决其他问题;
  • 其次,排序算法有助于使用选择语句、循环语句、方法和数组来练习基本的程序设计技术;
  • 最后,排序算法是演示算法性能几号的例子
ps.以下均为升序排序

插入排序

定义:将新元素插入到已排好序的子线性表中,直至整个表排好序

bad:

list2[0]=list1[0];
    for(int i=1;i<list1.length;i++){
        for(int j=0;j<i;j++){
            list2[i]=list1[i];
            if(list1[i]<list2[j]){
                for(int k=i;k>j;)   list2[k]=list2[--k];
                list2[j]=list1[i];
            }
        }
    }

good:

for(int i=1;i<list.length;i++){
            int currentElement=list[i];
            int k;
            for(k=i-1;k>0&&lsit[k]>currentElement;k--){
                list[k+1]=list[k];
            }
            list[k+1]=currentElement;
        }

比较:多余数组,未考虑到从后向前比较并赋值

时间复杂度O( n2


冒泡排序(下沉排序)

定义:多次遍历数组,在每次遍历中连续比较相邻的元素,如果元素间并未按规定的顺序排列,则互换他们的位置

算法实现:

//每次遍历后,最大的数在后边,所以第N次只要比较list.length-N次
int tmp=0;
    for(int i=1;i<list.length;i++0{
        for(int j=0;j<list.length-i;j++){
            if(list[j]>list[j+1]){
                tmp=lsit[j];
                list[j]=list[j+1];
                list[J+1]=tmp;
            }
        }
    }

优化版:

//如果某次遍历未发生交换则说明list中的元素已经按照规定的顺序排列好了

    Boolean bo=true;//判断是否发生排序
    int tmp=0;
    for(int i=1;i<list.length&&bo;i++){
        bo=false;
        for(int j=0;j<list.length-i;j++){
            if(list[j]>list[j+1]){
                tmp=lsit[j];
                list[j]=list[j+1];
                list[J+1]=tmp;
                bo=true;
            }
        }
    }

时间复杂度: 最优情况下,只进行一次遍历,比较了N-1次,O(n);
最坏的情况下,进行了N-1次遍历,第一次比较了N-1次,第二次比较了N-2次。。。以此类推,时间为O( n2


选择排序(旋转)

定义:找出最小的数和第一个元素交换,接下来在剩下的数中找到最小的数,将它和第二个元素交换,以此类推,知道数列中仅剩一个数为止

算法实现:

public static selectionSort(int[] list){
    for(int i=0;i<list.length-1;i++){
        int currentMin=list[i];
        int currentMinIndex=i;

        for(int j=i+1;j<list.length;j++){
            if(currentMin>list[j]){
                currentMin=list[j];
                currentMinIndex=j;
            }
        }

        if(currentMinIndex!=i){
            list[currentMinIndex]=list[i];
            list[i]=currentMin;
        }
    }
}

时间复杂度:O( n2


归并排序

定义:将数组分为两半,对每部分递归地应用归并排序,在两部分都排好序后,对他们进行归并

算法实现:

public static void mergeSort(int[] list){
        if(list.length>1){
            int[] firstHalf=new int[list.length/2];
            int[] secondHalf=new int[list.length-list.length/2];
            System.arraycopy(list,0,firstHalf,o,list.length/2);
            System.arraycopy(list,0,scondHalf,o,list.length-list.length/2);

            mergeSort(firstHalf);
            mergeSort(secondHalf);

            merge(firstHalf,secondHalf,list);
        }
    }
    //归并
    public static void merge(int list1,int list2,int tmp){
        int current1=0;
        int current2=0;
        int current=0;

        while(current1<list1.length&&current2<list2.length){
            if(list1[current1]<lsit2[current2])
                tmp[current++]=list1[current1++];
            else    tmp[current++]=list2[current2++];
        }
        while(current1<list1.length)    
            tmp[current++]=list1[current1++];
        while(current2<list2.length)
            tmp[current++]=list2[current2++];
    }

并行高效处理(待补充)

时间复杂度:O(nlogn)

ps:java.util.Arrays类中的sort方法是使用归并排序实现的


快速排序

定义:选择一个主元,将数组分成两部分,一部分大于主元,一部分小于主元,分别对两部分递归地应用快速排序算法

算法实现:

//假定第一数为主元
    public static void quickSort(int[] list){
        if(list.length>1){
            int privot=list[0];
            int m=0;
            int n=0;
            for(int i=1;i<list.length;i++){
                if(list[i]<=privot) m++;
                else    n++;
            }
            int[] list1=new int[m];
            int[] list2=new int[n];
            m=n=0;
            for(int i=1;i<list.length;i++){
                if(list[i]<=privot) list1[m++]=list[i];
                else    list2[n++]=list[i];
            }
            quickSort(list1);
            quickSort(list2);
            for(int i=0;i<list.length;i++){
                if(i<m) list[i]=list1[i];
                else if(i>m) list[i]=list2[i-m-1];
                else list[i]=privot;
            }
        }
    }

时间复杂度:O(nlogn)

归并排序和快速排序均采用了分而治之。在最差的情况下归并排序效率高于快速排序,但在平均情况下,两者效率相同。
归并排序在归并两个子数组时需要一个临时数组,而快速排序不需要额外的数组空间,因此,快速排序的效率高于归并排序


堆排序

定义:使用的是二叉堆,它首先将所有的元素添加到一个堆上,然后不断移除最大的元素以获得一个排好序的线性表

二叉堆是一棵具有以下属性的二叉树:
1.形状属性,他是一棵完全二叉树
2.堆属性:每个结点大于或等于它的任意一个孩子

完全二叉树:如果一棵二叉树的每一层都是满的,或者最后一层可以不填满并且最后一层的叶子都是靠左放置的,那么这就是一棵完全二叉树

二叉树的存储及结点的增删(待补充)

算法实现:

public class Heap<E extends Comparable<E>>{
    private java.util.ArrayList<E> list=new java.util.ArrayList<>();

    //最好自己写默认的构造器
    public Heap(){
    }

    public Heap(E[] objects){
        for(int i=0;i<objects.length;i++)
            add(objects[i]);
    }

    //增
    public void add(E newObjects){
        list.add(newObjects);
        int curretnIndex=list.size()-1;
        while(currentIndex>0){
            int parentIndex=(currentIndex-1)/2;
            //交换位置
            if(list.get(currentIndex).compareTo(list.ger(parentIndex))>0){
                E tmp=list.get(currentIndex);
                list.set(currentIndex,list.get(parentIndex));
                list.set(parentIndex,tmp);
            }
            else break;
        }
    }

    //删根节点
    public E remove(){
        if(list.size()==0) return null;

        E removedObject=list.get(0);
        list.set(0,list.get(list.size()-1));
        list.remove(list.size()-1);

        int currentIndex=0;
        while(currentIndex<list.size()){
            int leftChildIndex=2*currentIndex+1;
            int rightChildIndex=2*currentIndex+2;
            if(leftChildIndex>=list.size()) break;
            int maxIndex=leftChileIndex;
            if(rightChileIndex<list.size()){
                if(list.get(maxIndex).compareTo(list,get(rightChildIndex))<0){
                    maxIndex=rightChileIndex;
                }
            }

            if(list.get(currentIndex).compareTo(lsit.get(maxIndex))<0){
                E tmp=list.get(maxIndex);
                list.set(maxIndex,list.get(currentIndex));
                list.set(currentIndex,tmp);
            }
            else break;
        }
        return removeObject;
    }

    public int getSize(){
        return list.size;
    }
}

时间复杂度O(nlogn)

堆排序的空间效率高于归并排序


桶排序和基数排序

这两种排序均是对整数进行排序的高效算法

简单来说,桶排序就是将对应数值放入对应编号的桶中,再将数据一个个从桶中取出
为应对数值大的数据,基数排序就派上用场了,基数排序需要十个桶,每次分别按从低位到高位,按对应位上数值的大小放入桶中,进行一次排序,直至最高位,最后得到排好序的数据


外部排序

针对大型外部数据的排序

参考《Java语言程序设计 进阶篇 》第十版
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值