Java程序员面试笔试宝典之排序

常用的排序算法有:冒泡排序选择排序直接插入排序希尔排序堆排序归并排序快速排序

public class Sort {

    /**
     * 冒泡排序(由小到大排序)
     * 思路:对于给定的n个记录,从最后一个记录开始依次对相邻的两个记录进行比较,当后面的记录小于前面的记录时,交换位置,
     * 进行一轮比较和换位后,n个记录中的最小记录位于第1位;然后对后n-1个记录进行第二轮比较;重复该过程直到进行比较的记录只剩下一个为止。
     */
    public void bubbleSort(int [] array){

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

    }
    /**
     * 选择排序(由小到大排序)
     * 思路:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置交换;
     *      接着对不包括第一个记录的其他记录进行第二轮比较,得到最小记录并与第二个记录进行位置交换;
     *      重复该过程,直到进行比较的记录只有一个时为止。
     */
    public void selectSort(int [] array){

        for(int i=0;i<array.length-1;i++){
            int min=array[i];
            int flag=i;
            for(int j=i+1;j<array.length;j++){
                if(min>array[j]){
                    min=array[j];
                    flag=j;
                }
            }
            if(flag!=i){
                array[flag]=array[i];
                array[i]=min;
            }
        }

    }
    /**
     * 插入排序(由小到大排序)
     * 思路:对于给定的一组记录,初始时假设第一个记录自成一个有序序列,其余记录为无序序列;
     *     接着从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直到最后一个记录插入到有序序列中为止。
     */
    public void insertSort(int [] array){
        for(int i=1;i<array.length;i++){
            if(array[i]<array[i-1]){
                int temp=array[i];
                int j=i;
                while(j>=1 && array[j-1]>temp){
                    array[j]=array[j-1];
                    j--;
                }
                array[j]=temp;
            }
        }
    }
    /**
     * 希尔排序(由小到大排序)
     * 思路:先将待排序的数组元素分成多个子序列,使得每个子序列的元素个数相对较少,然后对各个子序列分别进行直接插入排序,
     *      待整个待排序序列“基本有序后”,最后再对所有元素进行一次直接插入排序。
     * 希尔排序具体步骤:
     * 1.选择一个步长序列t1,t2,...,tk,满足ti>tj (i<j),且tk=1
     * 2.按步长序列个数k,对待排序序列进行k趟排序
     * 3.每趟排序,根据对应的步长ti,将待排序列分割成ti个子序列,分别对各个子序列进行直接插入排序。
     */
    public void shellSort(int [] array){
        int len=array.length;
        for(int h=len/2;h>0;h=h/2){//h表示步长
            for(int i=h;i<len;i++){
                int temp=array[i];
                int j=i;
                while(j>=h && array[j-h]>temp){
                    array[j]=array[j-h];
                    j-=h;
                }
                array[j]=temp;
            }
        }
    }
    /**
     * 堆排序(由小到达排序)
     * 思路:对于给定的n个记录,初始时把这些记录看作一棵顺序存储的二叉树,然后将其调整为一个大顶堆,
     *     然后将堆的最后一个元素与堆顶元素(即二叉树的根节点)进行交换后,堆的最后一个元素即为最大记录;
     *     接着将前n-1个元素(即不包括最大记录)重新调整为一个大顶堆,再将堆顶元素与当前堆的最后一个元素进行交换后得到次最大记录;
     *     重复该过程直到调整的堆中只剩一个元素时为止,该元素即为最小记录,此时得到一个有序序列。
     * 简化思路:1.建立大顶推2.交换第一个元素和最后一个元素的值3.重复以上步骤,不过每次参与建堆的元素个数比上一次减一
     */
    public void heapSort(int [] array){
        int len=array.length;
        for(int i=len/2;i>=0;i--){//从下往上,从右往左建立初始大顶堆
            heapAdjust(array,i,len-1);
        }
        //
        for(int i=len-1;i>=0;i--){
            int temp=array[0];
            array[0]=array[i];
            array[i]=temp;
            heapAdjust(array,0,i-1);
        }
    }
    public void heapAdjust(int [] array,int parent,int len){
        int temp=array[parent];
        for(int i=2*parent+1;i<=len;i*=2+1){
            if(i+1<=len && array[i+1]>array[i]){
                i++;
            }
            if(array[i]<=temp){
                break;
            }
            array[parent]=array[i];
            array[i]=temp;
            parent=i;
        }       
    }
    /**
     * 归并排序(由小到大排序)
     * 思路:对于给定的n个记录,首先将每两个相邻的长度为1的子序列进行归并,得到n/2(向上取整)个长度为2或1的有序子序列,
     *      再将其两两归并,反复执行此过程,直到得到一个有序序列。
     * 归并排序的关键两步:1.划分半子表;2.合并半子表
     */
    public void mergeSort(int [] list){
        for(int gap=1;gap<list.length;gap*=2){
            mergeSort1(list,gap);
        }
    }
    public void mergeSort1(int [] list,int gap){
        int i;
        for(i=0;i+2*gap-1<list.length;i+=2*gap){
            merge(list,i,i+gap,i+2*gap-1);
        }
        if(i+gap<list.length){
            merge(list,i,i+gap,list.length-1);
        }
    }
    public void merge(int [] list,int low,int mid,int high){
        if(low>=mid || mid>high) return ;
        int i=low,j=mid,n=0;
        int [] temp=new int[high-low+1];
        while(i<mid && j<=high){
            if(list[i]<=list[j]){
                temp[n++]=list[i++];
            }else{
                temp[n++]=list[j++];
            }
        }
        while(i<mid) temp[n++]=list[i++];
        while(j<=high) temp[n++]=list[j++];

        //
        for(int k=0;k<high-low+1;k++){      
            list[low+k]=temp[k];
        }
    }
    /**
     * 快速排序(由小到大排序)
     * 思路:对于给定的n个记录,通过一趟排序后,将原序列分为两部分,其中前一部分的所有记录均比后一部分的所有记录小,
     *      然后再依次对前后两部分的记录进行快速排序,递归该过程,直到序列中所有记录均有序为止。
     * 算法具体步骤:
     * 1.分解:将输入的序列array[m...n]划分成两个非空子序列array[m...k]和array[k+1...n],
     * 使array[m...k]中任一元素的值不大于array[k+1...n]中的任一元素的值;
     * 2.递归求解:通过递归调用快速排序算法分别对array[m...k]和array[k+1...n]进行排序
     * 3.合并:由于对分解出的两个子序列的排序是就地进行的,所以在array[m...k]和array[k+1...n]都排好后不需要执行任何计算array[m...n]就已经排好序。
     */
    public void quickSort(int [] array){
        quickSort1(array,0,array.length-1);
    }
    public void quickSort1(int [] array,int start,int end){
        if(start>=end){
            return ;
        }
        int pivot=partition(array,start,end);
        quickSort1(array,start,pivot-1);
        quickSort1(array,pivot+1,end);
    }
    public int partition(int [] array,int low,int high){
        int temp=array[low];
        int left=low,right=high;
        while(left<right){
            while(right>left && array[right]>=temp){
                right--;
            }
            if(right>left){
                array[left]=array[right];
            }
            while(left<right && array[left]<=temp){
                left++;
            }
            if(left<right){
                array[right]=array[left];
            }
        }
        array[left]=temp;
        return left;

    }

    public static void main(String [] args){
        Sort s=new Sort();
        int [] a={5,2,3,7,8,1,4};
        s.quickSort(a);
        for(int i=0;i<a.length;i++){
            System.out.println(a[i]);
        }
    }

}

本博客的内容来自《Java程序员面试笔试宝典》
关于各种排序算法的性能可以参看此博客:各种排序算法的稳定性和时间复杂度小结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值