zoukankan      html  css  js  c++  java
  • 排序算法全(Java)

    排序算法

    冒泡排序(Bubble Sort)--稳定    实质:把小(大)的元素往前(后)调

     步骤一:比较相邻的元素。如果第一个比第二个大,就交换他们两个。

     步骤二:对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。 

     步骤三: 针对所有的元素重复以上的步骤,除了最后一个。 

     步骤四: 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

    package org.hrose.sort;
    
    import java.util.Arrays;
    
    public class BuddleSort {
        public static void main(String[] args) {
    int  [] array = {54,8,5,45,5,95,15};
    BuddleSort(array);
        }
        public static void BuddleSort(int [] array){
            boolean flag =false;
            for(int i =0;i<array.length;i++){
                for(int j =0;j<array.length-1-i;j++){
                    if(array[j+1]<array[j]){
                        flag=true;
                        int temp = array[j+1];
                        array[j+1] = array[j];
                        array[j] = temp;
                    }
    
                }if(!flag){
                    break;
                }else{
                    flag=false;
                }//
            }
            System.out.println(Arrays.toString(array));
        }
    }

    选择排序(Selection Sort)--不稳定 

     步骤一:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置

     步骤二:再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

     步骤。。。 :以此类推,直到所有元素均排序完毕。

    package org.hrose.sort;
    
    import java.util.Arrays;
    
    public class SelectSort {
        public static void main(String[] args) {
    int [] array ={45,8,8,8,84,846,4,94};
    SelectSort(array);
        }
    
        public static void SelectSort(int[] array) {
            for (int j =0;j<array.length-1;j++) {
                int minIndex = j;
                int min = array[j];
                for (int i=j+1; i < array.length; i++) {
                    if (min > array[i]) {
                        min = array[i];
                        minIndex = i;
                    }
                }
                if(minIndex!=0){
                    array[minIndex] = array[j];
                    array[j]=min;
    
                }
            }
            System.out.println(Arrays.toString(array));
        }
    }

    插入排序(Insertion Sort)--稳定  适用于已经有部分数据已经排好,并且排好的部分越大越好。一般在输入规模大于1000的场合下不建议使用插入排序

    基本思想:

       插入排序的工作方式像许多人排序一手扑克牌。开始时,我们的左手为空并且桌子上的牌面向下。然后,我们每次从桌子上拿走一张牌并将它插入左手中正确的位置。为了找到一张牌的正确位置,我们从右到左将它与已在手中的每张牌进行比较。拿在左手上的牌总是排序好的,原来这些牌是桌子上牌堆中顶部的牌 。
        最优 On
      插入排序是指在待排序的元素中,假设前面n-1(其中n>=2)个数已经是排好顺序的,现将第n个数插到前面已经排好的序列中,然后找到合适自己的位置,使得插入第n个数的这个序列也是排好顺序的。按照此法对所有元素进行插入,直到整个序列排为有序的过程,称为插入排序  。
    package org.hrose.sort;
    
    import java.util.Arrays;
    
    public class InsertSort {
        public static void main(String[] args) {
            int[] array = {78, 88, 68, 2, 5, 3};
            insertSort(array);
        }
    
        public static void insertSort(int[] array) {
            for (int i =1;i<array.length;i++) {
                int insertValue = array[i];
                int initIndex=i-1;
                while (initIndex>=0&&insertValue<array[initIndex]){
                    array[initIndex+1]=array[initIndex];
                    initIndex--;
                }
                array[initIndex+1]=insertValue;
            }
            System.out.println(Arrays.toString(array));
        }
    }

    希尔排序(Shell's Sort) --不稳定  是直接插入排序算法的一种更高效的改进版本

    希尔排序是基于插入排序的以下两点性质而提出改进方法的:

    1. 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
    2. 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。

    不稳定原因:

     由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

    排序过程:

     步骤一:先取一个正整数d1<n,把所有序号相隔d1的数组元素放一组,组内进行直接插入排序

     步骤二:然后取d2<d1,重复上述分组和排序操作;

     步骤。。。:直至di=1,即所有记录放进一个组中排序为止。

    package org.hrose.sort;
    
    import java.util.Arrays;
    
    public class ShellSort {
        public static void main(String[] args) {
          int [] array ={515,78,8,84,96,49,49,8,498};
          ShellSort2(array);
        }
    
        public static void ShellSort2(int [] array){
            for(int gap = array.length/2;gap>0;gap /=2){
                for(int i = gap;i<array.length;i++){
                    int j =i;
                    int temp = array[j];
                    if(array[j]<array[j-gap]){
                           while(j-gap>=0&&array[j]<array[j-gap]){
                               array[j] = array[j-gap];
                               j -= gap;
                           }
                           array[j] = temp;
                    }
                }
            }
            System.out.println(Arrays.toString(array));
        }

    快速排序(Quicksort)冒泡的改进  呃。。。

    快速排序算法通过多次比较和交换来实现排序,其排序流程如下:
     
     步骤一:首先设定一个分界值,通过该分界值将数组分成左右两部分。
     
     步骤二:将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界                 值。
     步骤三:然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数                 组数据也可以做类似处理。 
     步骤四:重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完                  成了。
    package org.hrose.sort;
    
    import java.util.Arrays;
    
    public class QuickSort {
        public static void main(String[] args) {
            int[] array = {15, 33, 18, 47, 66, 28,18,93,24};
            QuickSort(array, 0, array.length - 1);
            System.out.println("array" + Arrays.toString(array));
        }
        public static void QuickSort(int [] array , int left, int right){
            int l =left;
            int r = right;
            int povit = array[(l+r)/2];
            while(l<r){
                while(array[l]<povit){
                    l+=1;
                }
                while(array[r]>povit){
                    r-=1;
                }
                if(l>=r){
                    break;
                }
                int temp = array[l];
                array[l] = array[r];
                array[r] = temp;
                if(array[l] ==povit){
                    r-=1;
                }
                if(array[r]==povit){
                    l+=1;
                }
            }
            if(l==r){
                l+=1;
                r-=1;
            }
            if(right>l){
                QuickSort(array,l,right);
            }
            if(left<r){
                QuickSort(array,left,r);
            }
        }
    }

    归并排序*(Merge Sort)--稳定

     该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

    归并操作的工作原理如下:
    步骤一:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
    步骤二:设定两个指针,最初位置分别为两个已经排序序列的起始位置
    步骤三:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
    步骤。。。:重复步骤三直到某一指针超出序列尾  ,将另一序列剩下的所有元素直接复制到合并序列尾
    package org.hrose.sort;
    
    import java.util.Arrays;
    
    public class MergeSort {
        public static void main(String[] args) {
    
            int [] array={41,8,4,89,48,8,84,8,6,6,8,48,45,8,4};
            int [] temp = new int [array.length];
            mergeSort(array,0,array.length-1,temp);
            System.out.println(Arrays.toString(array));
        }
        public static void mergeSort(int [] arry,int left,int right,int []temp){
         if(left<right){
     int mid=(left+right)/2;
          mergeSort(arry,left,mid,temp);
        mergeSort(arry,mid+1,right,temp);
             merge(arry,left,mid,right,temp);
         }
    
        }  public static void merge(int [] arry,int left,int mid,int right,int []temp){
            int i =left;
            int j =mid+1;
            int t =0;
    
            while(i<=mid&&j<=right){
              if(arry[i]<arry[j]){
                  temp[t]=arry[i];
                  t+=1;
                  i+=1;
    
              }else {
                  temp[t] = arry[j];
                      j+=1;
                      t+=1;
              }
            }
    while(i<=mid){
        temp[t]=arry[i];
        t+=1;
        i+=1;
    }
    while(j<=right){
        temp[t] = arry[j];
        j+=1;
        t+=1;
    }
      t=0;
     int templeft =left;
    while(templeft<=right){
     arry[templeft] = temp[t];
      t+=1;
    templeft+=1;
    }
    
      }
    }

    堆排序(Heapsort)

    利用这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

    堆的操作

    • 最大堆调整(Max Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点
    • 创建最大堆(Build Max Heap):将堆中的所有数据重新排序
    • 堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算 
    package org.hrose.sort;
    
    import java.util.Arrays;
    
    /**
     * 代码来源于网络
     */
    public class HeapSort {
        public static void main(String[] args) {
            int [] array={41,8,4,89,48,8,84,8,6,6,8,48,45,8,4};
            int[] a = heapSort(array);
            System.out.println(Arrays.toString(a));
    
        }
        public static int[] heapSort(int[] array) {
            //这里元素的索引是从0开始的,所以最后一个非叶子结点array.length/2 - 1
            for (int i = array.length / 2 - 1; i >= 0; i--) {
                adjustHeap(array, i, array.length);  //调整堆
            }
    
            // 上述逻辑,建堆结束
            // 下面,开始排序逻辑
            for (int j = array.length - 1; j > 0; j--) {
                // 元素交换,作用是去掉大顶堆
                // 把大顶堆的根元素,放到数组的最后;换句话说,就是每一次的堆调整之后,都会有一个元素到达自己的最终位置
                swap(array, 0, j);
                // 元素交换之后,毫无疑问,最后一个元素无需再考虑排序问题了。
                // 接下来我们需要排序的,就是已经去掉了部分元素的堆了,这也是为什么此方法放在循环里的原因
                // 而这里,实质上是自上而下,自左向右进行调整的
                adjustHeap(array, 0, j);
            }
            return array;
        }
    
        /**
         * 整个堆排序最关键的地方
         * @param array 待组堆
         * @param i 起始结点
         * @param length 堆的长度
         */
        public static void adjustHeap(int[] array, int i, int length) {
            // 先把当前元素取出来,因为当前元素可能要一直移动
            int temp = array[i];
            for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {  //2*i+1为左子树i的左子树(因为i是从0开始的),2*k+1为k的左子树
                // 让k先指向子节点中最大的节点
                if (k + 1 < length && array[k] < array[k + 1]) {  //如果有右子树,并且右子树大于左子树
                    k++;
                }
                //如果发现结点(左右子结点)大于根结点,则进行值的交换
                if (array[k] > temp) {
                    swap(array, i, k);
                    // 如果子节点更换了,那么,以子节点为根的子树会受到影响,所以,循环对子节点所在的树继续进行判断
                    i  =  k;
                } else {  //不用交换,直接终止循环
                    break;
                }
            }
        }
    
        /**
         * 交换元素
         * @param arr
         * @param a 元素的下标
         * @param b 元素的下标
         */
        public static void swap(int[] arr, int a, int b) {
            int temp = arr[a];
            arr[a] = arr[b];
            arr[b] = temp;
        }
    }

    基数排序(radix sort) --稳定

    原理:

     将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成 一个有序序列。
    基数排序的方式可以采用LSD(最低位优先)或MSD(最高位优先),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。
    package org.hrose.sort;
    
    import java.util.Arrays;
    
    public class RadixSort {
        public static void main(String[] args) {
    int [] array = {50,5,8,4,9,2,8,7,66,88,44,93};
    radixSort(array);
        }
    
    
        public static void radixSort(int[] array) {
            int max = array[0];
            for (int i = 0; i < array.length; i++) {
                if (max < array[i]) {
                    max = array[i];
    
                }
            }
            int maxLength = (max + "").length();
    
                int[][] bucket = new int[10][array.length];
                int[] bucketElementCount = new int[10];
            for (int i =0,n=1;i<maxLength;i++,n*=10 ) {
                for (int j = 0; j < array.length; j++) {
                    int digitOfElement = array[j] / n % 10;
                    bucket[digitOfElement][bucketElementCount[digitOfElement]] = array[j];
                    bucketElementCount[digitOfElement]++;
                }
                int index = 0;
                for (int k = 0; k < bucketElementCount.length; k++) {
                    if (bucketElementCount[k] != 0) {
                        for (int l = 0; l < bucketElementCount[k]; l++) {
                            array[index++] = bucket[k][l];
                        }
                    }
                    bucketElementCount[k]=0;
                }
                System.out.println(Arrays.toString(array));
    
            }
        }
    }
     
     
  • 相关阅读:
    曾今的代码系列——获取当天最大流水号存储过程
    曾今的代码系列——生产者消费者模式
    利用Microsoft.VisualBasic中TextFieldParser解析器把CSV格式倒入数据库
    曾今的代码系列——自己的分页控件+存储过程实现分页
    ASP.NET那点不为人知的事(四)
    SharePoint下用C#代码上传文档至文档库的子文件夹中
    Entity Framework 4 in Action读书笔记——第四章:使用LINQ to Entities查询:使用函数
    Entity Framework 4 in Action读书笔记——第四章:使用LINQ to Entities查询:预先加载和延迟加载
    这几天Colorbox让我寝食难安
    使用ASP.NET MVC3+EF+Jquery制作文字直播系统(四)——完成篇
  • 原文地址:https://www.cnblogs.com/smallores/p/smalloresforsort.html
Copyright © 2011-2022 走看看