zoukankan      html  css  js  c++  java
  • 排序算法

    排序一:直接插入排序

      每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。

      1、第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 

      2、第二趟把第三个数据与前两个数从前向后扫描,把第三个数按大小插入到有序表中;

      3、依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。

      直接插入排序属于稳定的排序,最坏时间复杂度为O(n^2),空间复杂度为O(1)。

    下面按从小到大排序:

    public class Sort {
        public static void main(String[] args) {
            int[] data = { 31, 23, 89, 10, 47, 68, 8, 22 };
            insert_sort(data);
            showData(data);
        }
        
        //打印数组
        private static void showData(int[] data) {
            for (int i = 0; i < data.length; i++) {
                System.out.println(data[i]);
            }
        }
    
        // 直接插入排序
        private static void insert_sort(int[] data) {
            int t;
            int j;
            for (int i = 1; i < data.length; i++) {// i表示插入次数,共进行data.length-1次插入
                t = data[i];// 把待排序元素赋给t
                j = i-1;
                while ((j >= 0) && (t < data[j])) {
                    data[j+1] = data[j];
                    j--;
                }// 顺序比较和移动
                data[j+1] = t;
            }
        }
            
    }

    排序二:折半插入排序

      折半插入排序是对插入排序算法的一种改进,由于排序算法过程中,就是不断的依次将元素插入前面已排好序的序列中。由于前半部分为已排好序的数列,这样我们不用按顺序依次寻找插入点,可以采用折半查找的方法来加快寻找插入点的速度。

      具体操作:在将一个新元素插入已排好序的数组的过程中,寻找插入点时,将待插入区域的首元素设置为a[low],末元素设置为a[high],则轮比较时将待插入元素与a[m],其中m=(low+high)/2相比较,如果比参考元素小,则选择a[low]到a[m-1]为新的插入区域(即high=m-1),否则选择a[m+1]到a[high]为新的插入区域(即low=m+1),如此直至low<=high不成立,即将此位置之后所有元素后移一位,并将新元素插入a[high+1]。

    下面按从小到大排序:

    public class Sort {
        public static void main(String[] args) {
            int[] data = { 31, 23, 89, 10, 47, 68, 8, 22 };
            binarySearchInsertion(data);
            showData(data);
        }
        
        //打印数组
        private static void showData(int[] data) {
            for (int i = 0; i < data.length; i++) {
                System.out.println(data[i]);
            }
        }
    
        private static void binarySearchInsertion(int data[]) {
            int middle = 0;
            for (int i = 1; i < data.length; i++) {
                int low = 0;
                int high = i - 1;
                int t = data[i];
                while (low <= high) {
                    middle = (low + high) / 2;
                    if (t < data[middle]) {
                        high = middle - 1;
                    }else {
                        low = middle + 1;
                    }
                }
                for (int j = i; j > middle; j--) {
                    data[j] = data[j-1];
                }
                data[high + 1] = t;// 此处用data[low] = t;也可
            }
        }    
    }

    序列:

             31 23 89 10 47 68 8 22

      i = 1:  23 31 89 10 47 68 8 22

      i = 2:  23 31 89 10 47 68 8 22

      i = 3:  10 23 31 89 47 68 8 22

      i = 4:  10 23 31 47 89 68 8 22

      i = 5:  10 23 31 47 68 89 8 22

      i = 6:  8 10 23 31 47 68 89 22

      i = 7:  8 10 22 23 31 47 68 89

      这样数组从小到大就排序好了。

    排序三:希尔排序

      希尔排序(Shell Sort)是插入排序的一种。是针对直接插入排序算法的改进。该方法又称缩小增量排序

      基本思想:先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。

      一般的初次取序列的一半为增量,以后每次减半,直到增量为1。

    从小到大排序:

    public class Sort {
        public static void main(String[] args) {
            int[] data = { 31, 23, 89, 10, 47, 68, 8, 22 };
            shell(data);
            showData(data);
        }
        
        //打印数组
        private static void showData(int[] data) {
            for (int i = 0; i < data.length; i++) {
                System.out.print(data[i] +" ");
            }
        }
    
        // 希尔排序
            private static void shell(int data[]) {
                int k = data.length  / 2;// k值代表前文中的增量d值 , 一般的初次取序列的一半为增量,以后每次减半,直到增量为1
                int j;
                while (k >= 1) {// 当增量k值变化到0,结束循环……
                    int t;
                    for (int i = k; i < data.length; i++) {
                        t = data[i];
                        j = i - k;
                        while ((j >= 0) && (t < data[j])) {
                            data[j + k]  = data[j];
                            j = j - k;
                        }
                        data[j + k] = t;
                    }
                    k = k / 2;
                }
            }
    }

    序列:

    31 23 89 10 47 68 8 22

    31 23 89 10 47 68 8 22

    31 23 89 10 47 68 8 22

    31 23 8 10 47 68 89 22

    31 23 8 10 47 68 89 22

    8 23 31 10 47 68 89 22

    8 10 31 23 47 68 89 22

    8 10 31 23 47 68 89 22

    8 10 31 23 47 68 89 22

    8 10 31 23 47 68 89 22

    8 10 31 22 47 23 89 68

    8 10 31 22 47 23 89 68

    8 10 31 22 47 23 89 68

    8 10 22 31 47 23 89 68

    8 10 22 31 47 23 89 68

    8 10 22 23 31 47 89 68

    8 10 22 23 31 47 89 68

    8 10 22 23 31 47 68 89

    最后排序也就出来了。

    排序四:冒泡排序

    冒泡排序算法:

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

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

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

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

    public class Sort {
        public static void main(String[] args) {
            int[] data = { 31, 23, 89, 10, 47, 68, 8, 22 };
            bubbleSort(data);
            showData(data);
        }
    
        // 打印数组
        private static void showData(int[] data) {
            for (int i = 0; i < data.length; i++) {
                System.out.print(data[i] + " ");
            }
        }
    
        // 冒泡排序
        private static void bubbleSort(int[] data) {
            boolean exchange;// 交换标志
            int t;
            for (int i = 1; i < data.length; i++) {// 最多做n-1趟排序
                exchange = false;// 本趟排序开始前,交换标志应为假
                for (int j = 1; j <= data.length - i; j++) {
                    // 对当前无序区R[i..n]自下向上扫描
                    if (data[j] < data[j - 1]) {// 交换记录
                        t = data[j]; // t仅做暂存单元
                        data[j] = data[j - 1];
                        data[j - 1] = t;
                        exchange = true; // 发生了交换,故将交换标志置为真
                    }
                }
                if (!exchange) {// 本趟排序未发生交换,提前终止算法
                    return;
                }
            }
        }
    }

    排序五:快速排序

      快速排序是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

    下面从小到大排序:

    public class Sort {
        public static void main(String[] args) {
            int[] data = { 31, 23, 89, 10, 47, 68, 8, 22 };
            quickSort(data, 0, data.length - 1);
            showData(data);
        }
    
        // 打印数组
        private static void showData(int[] data) {
            for (int i = 0; i < data.length; i++) {
                System.out.print(data[i] + " ");
            }
        }
    
        // 快速排序
            private static void quickSort(int[] data, int low, int high) {
                // 对data[low..high]快速排序,low,high表示下标数
                int k;                // 划分后的基准记录的位置
                if (low < high) {    // 仅当区间长度大于1时才须排序
                    k = quickPass(data, low, high);    // 对R[low..high]做划分
                    quickSort(data, low, k - 1);    // 对左区间递归排序
                    quickSort(data, k + 1, high);    // 对右区间递归排序
                }
            }
            
            private static int quickPass(int data[], int i, int j) {
                int t = data[i];    // 用区间的第1个记录作为基准
                while (i < j) {        // 从区间两端交替向中间扫描,直至i=j为止
                    while (i < j && data[j] >= t) {    // t相当于在位置i上
                        j--;        // 从右向左扫描,查找第1个关键字小于t的记录data[j]
                    }
                    if (i < j) {    // 表示找到的data[j]的关键字<t
                        data[i++] = data[j];    // 相当于交换data[i]和data[j],交换后i指针加1
                    }
                    while (i < j && data[i] <= t) {    // t相当于在位置j上
                        i++;        // 从左向右扫描,查找第1个关键字大于t的记录data[i]
                    }
                    if (i < j) {    // 表示找到了data[i],使data[i]>t
                        data[j--] = data[i];    // 相当于交换data[i]和data[j],交换后j指针减1
                    }
                }
                data[i] = t;        // 基准记录已被最后定位
                return i;
            }
    }

    序列:

    交换后:22 23 8 10 31 68 47 89 

    交换后:10 8 22 23 31 68 47 89 

    交换后:8 10 22 23 31 68 47 89 

    交换后:8 10 22 23 31 47 68 89 

    最后快速排序就结束了,从小到大为:8 10 22 23 31 47 68 89 。

  • 相关阅读:
    第三方驱动备份与还原
    Greenplum 解决 gpstop -u 指令报错
    yum安装(卸载)本地rpm包的方法(卸载本地安装的greenplum 5.19.rpm)
    Java JUC(java.util.concurrent工具包)
    netty 详解(八)基于 Netty 模拟实现 RPC
    netty 详解(七)netty 自定义协议解决 TCP 粘包和拆包
    netty 详解(六)netty 自定义编码解码器
    netty 详解(五)netty 使用 protobuf 序列化
    netty 详解(四)netty 开发 WebSocket 长连接程序
    netty 详解(三)netty 心跳检测机制案例
  • 原文地址:https://www.cnblogs.com/ycclmy/p/3215301.html
Copyright © 2011-2022 走看看