排序算法Java实现

  • 插入排序
  1. 直接插入排序   
  2. 希尔排序
public class InsertSort {

//    直接插入排序
    private static void directInsertSort(int[] array) {
        for(int i=1;i<array.length;i++){//从头部第一个当做已经排好序的,把后面的一个一个的插到已经排好的列表中去。
            int j;
            int temp=array[i];//x为待插入元素
            for( j=i;  j>0 && temp<array[j-1];j--){//通过循环,逐个后移一位找到要插入的位置。
                array[j]=array[j-1];
            }
            array[j]=temp;//插入
            }
        }
    public static void binaryInsertSort(int[] array) {
        for (int i = 1; i < array.length; i++) {
            if (array[i] < array[i - 1]) {
                // 缓存i处的元素值
                int tmp = array[i];
                // 记录搜索范围的左边界
                int low = 0;
                // 记录搜索范围的右边界
                int high = i - 1;
                while (low <= high) {
                    // 记录中间位置
                    int mid = (low + high) / 2;
                    // 比较中间位置数据和i处数据大小,以缩小搜索范围
                    if (array[mid] < tmp) {
                        low = mid + 1;
                    } else {
                        high = mid - 1;
                    }
                }
                //将low~i处数据整体向后移动1位
                for (int j = i; j > low; j--) {
                    array[j] = array[j - 1];
                }
                array[low] = tmp;
            }
        }
    }


    /**
     * shell排序算法
     * 增量h=(h*3)+1; 这个增量公式是由Knuth给出的
     */
    public static void shellSort(int[] array)
    {
        //首先根据数组的长度确定增量的最大值
        int dk=1;
        // 按dk * 3 + 1得到增量序列的最大值
        while(dk <= array.length / 3)
            dk = dk * 3 + 1;

        //进行增量查找和排序
        while(dk>=1){
            for(int i=dk;i<array.length;i++){
                if(array[i]<array[i-dk]){
                    int j;
                    int temp=array[i];//x为待插入元素
                    for(j=i;  j-dk>=0 && temp<array[j-dk];j=j-dk){//通过循环,逐个后移一位找到要插入的位置。
                        array[j]=array[j-dk];
                    }
                    array[j]=temp;//插入
                }
            }
            dk= dk/3;
        }

    }

    //        输出数组
    public void print(int a[]){
        for(int i=0;i<a.length;i++){
            System.out.print(a[i]+" ");
        }
    }
//      测试函数
        public static void main(String args[])
        {
            //
            int a[] = {3,1,5,7,2,4,9,6,10,8};
            InsertSort  obj=new InsertSort();
            System.out.println("a的初始值:");
            obj.print(a);
            obj.directInsertSort(a);
            System.out.println("\na 直接插入排序后:");
            obj.print(a);
           //
            int b[]={1,2,3,4,6,7,8,9,10,5};
            System.out.println("\nb的初始值:");
            obj.print(b);
            obj.binaryInsertSort(b);
            System.out.println("\nb二分插入排序后:");
            obj.print(b);
           //
            int c[] = {3,1,5,7,2,4,9,6,10,8};
            System.out.println("\nc的初始值:");
            obj.print(c);
            obj.shellSort(c);
            System.out.println("\n c希尔排序后:");
            obj.print(c);

        }
    }

  • 交换排序
  1. 冒泡排序
  2. 快速排序
public class SwapSort {

    public static void  BubbleSort(int [] array){
        int length=array.length;
        for(int i=0;i<length-1;i++){//趟数n-1
            boolean changeFlag=false;//表示本趟冒泡是否交换了元素
            for(int j=0;j<length-1-i;j++){
                if(array[j]>array[j+1]){//一趟排序确定一个最大元素,当然也可以是确定最小的元素,不过要改for循环从后往前遍历
                    int temp=array[j];
                    array[j]=array[j+1];
                    array[j+1]=temp;
                    changeFlag=true;
                }
            }
            if(changeFlag==false)return ;//若没交换,则说明元素已经有序
        }
        return ;

    }
//快速排序第一次划分算法
    public static int partition(int []array,int low,int high){
        //固定的切分方式
        int key=array[low];//轴值
        while(low<high){
            while(array[high]>=key&&high>low){//从后半部分向前扫描
                high--;
            }
            array[low]=array[high];//将较小记录交换到前面
            while(array[low]<=key&&high>low){//从前半部分向后扫描
                low++;
            }
            array[high]=array[low];//将较大记录交换到后面
        }
        array[high]=key;//用high记录轴值的最终位置
        return high;
    }

    public static void  quickSort(int[] array,int low,int high){
        if(array.length>0)
        {
            if(low<high)
            {
                int pivot=partition(array,low,high);//第一次划分
                quickSort(array,low,pivot);
                quickSort(array,pivot+1,high);

            }

        }

    }

    //        输出数组
    public void print(int a[]){
        for(int i=0;i<a.length;i++){
            System.out.print(a[i]+" ");
        }
    }
    //      测试函数
    public static void main(String args[])
    {
        //
        int a[] = {3,1,5,7,2,4,9,6,10,8};
        SwapSort  obj=new SwapSort();
        System.out.println("a的初始值:");
        obj.print(a);
        obj.BubbleSort(a);
        System.out.println("\n a冒泡排序后:");
        obj.print(a);
        //
        int b[] = {3,1,5,7,2,4,9,6,10,8};
        System.out.println("\nb的初始值:");
        obj.print(b);
        obj.quickSort(b,0,b.length-1);
        System.out.println("\n b快速排序后:");
        obj.print(b);

    }
}
  • 选择排序
  1. 简单选择排序
  2. 堆排序
public class SelectSort {
        //简单选择排序
        public static void SimpleSelectSort(int[] array){
            int index;
            int temp;
            for (int i=0;i<array.length-1;i++){ //对n个记录进行n-1趟简单排序
                index=i;
                for(int j=i+1;j<array.length;j++){
                    if(array[j]<array[index]) index=j;//寻找最小记录
                }
                if(index!=i){
                 temp=array[i];
                 array[i]=array[index];
                 array[index]=temp;
                }
            }
        }

        //堆排序
        /*三步走:1,将无序元素构造成一个堆,2.取对顶元素,3.重新构造堆
        * */
        /*参数array存储堆结构数据,k为当前筛选节点的编号,m为堆中节点长度*/
        //筛选法调整一个堆
        public static void  Sift(int[]  array,int k,int m)
        {
            int parent=k;int child =2*parent+1;//i指向当前要筛选的节点,j指向其左孩子
            while (child<m){//筛选还没进行到叶子节点
                if(child+1<m && array[child]<array[child+1]){
                    child++;//比i的左右孩子,将j标记在较大者
                }

                if(array[parent]>=array[child]) break;//根节点已经大于左右孩子中的较大者
                else {
                    //将根节点与左右孩子中的较大者交换
                    int temp =array[parent];
                    array[parent]=array[child];
                    array[child]=temp;
                    parent=child;child=2*parent+1;//被筛选节点位于原来j的位置
                }


            }
        }
        //堆排序算法
        public static void HeapSort(int[] array,int n ){
            //所以的叶子节点都已经是堆,所以从n/2个记录开始进行上述的筛选过程,直到根节点
            for (int i=n/ 2-1;i>=0;i--){//初始建堆,从最后一个非叶子节点开始至根节点
                Sift(array,i,n);
            }
            //重复执行移走对顶和重建堆的操作
            //堆顶元素为arry[1]
            // 进行n-1次循环,完成排序
            // 堆中最后一个元素和第一元素进行交换也就是将堆顶元素取出来加入有序区,这时候堆中元素减少一个,有序区增加一个元素
            //然后再重建堆
            for (int i=n-1;i>0;i--){
                // 最后一个元素和第一元素进行交换
                int temp=array[0];
               array[0]=array[i];
               array[i]=temp;
               Sift(array,0,i);
            }
        }

        //        输出数组
        public void print(int a[]){
            for(int i=0;i<a.length;i++){
                System.out.print(a[i]+" ");
            }
        }
        //      测试函数
        public static void main(String args[])
        {
            //
            int a[] = {3,1,5,7,2,4,9,6,10,8};
            SelectSort  obj=new SelectSort();
            System.out.println("a的初始值:");
            obj.print(a);
            obj.SimpleSelectSort(a);
            System.out.println("\n a简单选择排序后:");
            obj.print(a);
            //
            int b[] = {3,1,5,7,2,4,9,6,10,8};
            System.out.println("\nb的初始值:");
            obj.print(b);
            obj.HeapSort(b,b.length);
            System.out.println("\n b堆排序后:");
            obj.print(b);

        }

    }

  • 归并排序
  1. 二路归并排序非递归实现
  2. 二路排序递归实现
//归并排序算法
public class MergeSort {

    //一次归并算法的实现
    //将两个有序数组合并成一个有序数组
    //数组有序,合并时候维护几个指针就可以了
    public  static  void  Merge(int[] array,int  left,int mid,int right){
        
        //两个相邻的有序序列 array[ left]~array[mid] 和array[mid+1]~array[right] 归并成一个有序序列
        //i j 分别指向两个有序序列的第一个元素,k 指向存放归并结果的temp的位置
        //左半边的指针
        int i= left;
        //右半边的指针
        int j=mid+1;
        //合并后数组的指针
        int k= 0;
        //temp数组用于暂存合并的结果
        int[] temp = new int[right - left + 1];
        //将记录由小到大地放进temp数组
        while (i<=mid&&j<=right){
            if (array[i]<array[j]) temp[k++]=array[i++];//取array[i]和array[j]较小者存入temp[k]中
            else temp[k++]=array[j++];
        }
        if (i<=mid) while (i<=mid) temp[k++]=array[i++];//若第一个子序列较长,没处理完,则进行收尾操作
        if (j<=right) while (j<=right) temp[k++]=array[j++];//若第二个子序列较长,没处理完,则进行收尾操作

        //将temp数组中的元素写入到待排数组中
        for(int l = 0; l < temp.length; l++)
            array[left + l] = temp[l];
    }

    //完成一趟归并算法
    //MergePass方法负责将数组中的相邻的有h个元素的子序列进行归并
    //n表示待排序的序列总长度,h表示需要归并的有序子序列长度,除最后一个有序子序列外,其他子序列长度相同,记为h
    public static void MergePass(int[] array,int n,int h){
        int i=0;//指向待归并序列的第一个记录
        //从前往后,将2个长度为h的子序列合并为1个
        //边界值 假设 h=2,n=10, 若i=6则刚好剩有两个长度为2的序列,若i=7,则有一个子序列只有一个元素,所以这里应该是 i<7
        while (i<n-2*h+1){//待归并序列至少有两个长度为h的子序列
            Merge(array,i,i+h-1,i+2*h-1);
            i+=2*h;
        }
        if(i<n-h) Merge(array,i,i+h-1,n-1);//待归并序列只有一个序列,长度小于等于h
    }

    //二路归并排序非递归算法
    //从切分的数组长度为1开始,一次归并变回原来长度的2倍,直到完成整个数组的归并
    public static void MergeSort_Nrecall(int[] array,int n){
        int h=1;
        while (h<n){
            MergePass(array,n,h);
            h=h*2;

        }
    }

    //二路归并排序递归算法
    public static void MergeSort_Recall(int[] array,int left,int right){
        //使用递归的方式进行归并排序,所需要的空间复杂度是O(N+logN)
        int mid ;
        if(left<right){
            mid=(left+right)/2;
            //递归地对左右两边进行排序
            MergeSort_Recall(array,left,mid);
            MergeSort_Recall(array,mid+1,right);
            //合并
            Merge(array,left,mid,right);
        }
    }

    //        输出数组
    public void print(int a[]){
        for(int i=0;i<a.length;i++){
            System.out.print(a[i]+" ");
        }
    }
    //      测试函数
    public static void main(String args[])
    {
        //
        int a[] = {3,1,5,7,2,4,9,6,10,8};
        MergeSort  obj=new MergeSort();
        System.out.println("a的初始值:");
        obj.print(a);
        obj.MergeSort_Nrecall(a,a.length);
        System.out.println("\n a归并排序非递归算法排序后:");
        obj.print(a);
//        //
        int b[] = {3,1,5,7,2,4,9,6,10,8};
        System.out.println("\nb的初始值:");
        obj.print(b);
        obj.MergeSort_Recall(b,0,b.length-1);
        System.out.println("\n b归并排序递归算法排序后::");
        obj.print(b);

    }
}

猜你喜欢

转载自blog.csdn.net/renlinyu3495/article/details/80952161
今日推荐