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 。

  • 相关阅读:
    c# 方法重载
    c# propertyGrid下拉选项
    c# 枚举类型
    c# socket编程
    读书笔记之ado.net entity framework
    c# delegate的invoke和bejinInvoke的区别
    C# 读书笔记之类与结构体
    c#笔记之启动新线程
    c# listview的使用
    visual studio2013 改变匹配括号的颜色
  • 原文地址:https://www.cnblogs.com/ycclmy/p/3215301.html
Copyright © 2011-2022 走看看