排序算法

来源:互联网 发布:怪物猎人初音捏脸数据 编辑:程序博客网 时间:2024/04/30 05:08

衡量排序算法的优劣:

1.时间复杂度:分析关键字的比较次数和记录的移动次数
2.空间复杂度:分析排序算法中需要多少辅助内存
3.稳定性:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的。

常用的内部排序

1.选择排序:直接选择排序、堆排序

直接选择排序:第一次找出最小的元素放到第一个位置处,第二次找第二小的元素放到第二个位置,以此类推。
代码如下:
自定义类:

package com.v512.order;public class DataWrap implements Comparable<DataWrap>{    int data;    String flag;    public DataWrap(int data,String flag){        this.data = data;        this.flag = flag;    }    public String toString(){        return data + flag;    }    //根据data实例变量来决定两个dataWrap的大小    @Override    public int compareTo(DataWrap dw) {        return this.data > dw.data? 1 : (this.data == dw.data? 0 : -1);    }}

主函数:

package com.v512.order;/** * 直接选择排序 * @author shkstart * 2013-11-27 */public class SelectSort {    public static void selectSort(DataWrap[] data) {        System.out.println("开始排序");        int arrayLength = data.length;        for (int i = 0; i < arrayLength - 1; i++) {            for (int j = i + 1; j < arrayLength; j++) {                if (data[i].compareTo(data[j]) > 0) {                    DataWrap temp = data[i];                    data[i] = data[j];                    data[j] = temp;                }            }            System.out.println(java.util.Arrays.toString(data));        }    }    public static void main(String[] args) {        DataWrap[] data = { new DataWrap(9, ""), new DataWrap(-16, ""),                new DataWrap(21, "*"), new DataWrap(23, ""),                new DataWrap(-30, ""), new DataWrap(-49, ""),                new DataWrap(21, ""), new DataWrap(30, "*"),                new DataWrap(30, "") };        System.out.println("排序之前:\n" + java.util.Arrays.toString(data));        selectSort(data);        System.out.println("排序之后:\n" + java.util.Arrays.toString(data));    }}

运行结果:
排序之前:
[9, -16, 21*, 23, -30, -49, 21, 30*, 30]
开始排序
[-49, 9, 21*, 23, -16, -30, 21, 30*, 30]
[-49, -30, 21*, 23, 9, -16, 21, 30*, 30]
[-49, -30, -16, 23, 21*, 9, 21, 30*, 30]
[-49, -30, -16, 9, 23, 21*, 21, 30*, 30]
[-49, -30, -16, 9, 21*, 23, 21, 30*, 30]
[-49, -30, -16, 9, 21*, 21, 23, 30*, 30]
[-49, -30, -16, 9, 21*, 21, 23, 30*, 30]
[-49, -30, -16, 9, 21*, 21, 23, 30*, 30]
排序之后:
[-49, -30, -16, 9, 21*, 21, 23, 30*, 30]

堆排序
暂未写

2.交换排序:冒泡排序、快速排序

冒泡排序:
它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。(DataWrap类前面已给出)

package com.v512.order;/** * 冒泡排序 * @author shkstart * 2013-11-27 */public class BubbleSort {    public static void bubbleSort(DataWrap[] data) {        System.out.println("开始排序");        int arrayLength = data.length;        for (int i = 0; i < arrayLength - 1; i++) {            boolean flag = false;            for (int j = 0; j < arrayLength - 1 - i; j++) {                if (data[j].compareTo(data[j + 1]) > 0) {                    DataWrap temp = data[j + 1];                    data[j + 1] = data[j];                    data[j] = temp;                    flag = true;                }            }            System.out.println(java.util.Arrays.toString(data));            if (!flag)                break;        }    }    public static void main(String[] args) {        DataWrap[] data = { new DataWrap(9, ""), new DataWrap(-16, ""),                new DataWrap(21, "*"), new DataWrap(23, ""),                new DataWrap(-30, ""), new DataWrap(-49, ""),                new DataWrap(21, ""), new DataWrap(30, "*"),                new DataWrap(30, "")};        System.out.println("排序之前:\n" + java.util.Arrays.toString(data));        bubbleSort(data);        System.out.println("排序之后:\n" + java.util.Arrays.toString(data));    }}

运行结果:
排序之前:
[9, -16, 21*, 23, -30, -49, 21, 30*, 30]
开始排序
[-16, 9, 21*, -30, -49, 21, 23, 30*, 30]
[-16, 9, -30, -49, 21*, 21, 23, 30*, 30]
[-16, -30, -49, 9, 21*, 21, 23, 30*, 30]
[-30, -49, -16, 9, 21*, 21, 23, 30*, 30]
[-49, -30, -16, 9, 21*, 21, 23, 30*, 30]
[-49, -30, -16, 9, 21*, 21, 23, 30*, 30]
排序之后:
[-49, -30, -16, 9, 21*, 21, 23, 30*, 30]

快速排序
快速排序(Quicksort)是对冒泡排序的一种改进。
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列(DataWrap类前面已给出)。

package com.v512.order;/** * 快速排序 * @author shkstart * 2013-11-27 */public class QuickSort {    private static void swap(DataWrap[] data, int i, int j) {        DataWrap temp = data[i];        data[i] = data[j];        data[j] = temp;    }    private static void subSort(DataWrap[] data, int start, int end) {        if (start < end) {            DataWrap base = data[start];            int i = start;            int j = end + 1;            while (true) {                while (i < end && data[++i].compareTo(base) <= 0)                    ;                while (j > start && data[--j].compareTo(base) >= 0)                    ;                if (i < j) {                    swap(data, i, j);                } else {                    break;                }            }            swap(data, start, j);            subSort(data, start, j - 1);            subSort(data, j + 1, end);        }    }    public static void quickSort(DataWrap[] data){        subSort(data,0,data.length-1);    }    public static void main(String[] args) {        DataWrap[] data = { new DataWrap(9, ""), new DataWrap(-16, ""),                new DataWrap(21, "*"), new DataWrap(23, ""),                new DataWrap(-30, ""), new DataWrap(-49, ""),                new DataWrap(21, ""), new DataWrap(30, "*"),                new DataWrap(30, "") };        System.out.println("排序之前:\n" + java.util.Arrays.toString(data));        quickSort(data);        System.out.println("排序之后:\n" + java.util.Arrays.toString(data));    }}

3.插入排序:直接插入排序、折半插入排序、Shell排序

直接插入排序:每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 第二趟把第三个数据与前两个数从后向前扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。直接插入排序是由两层嵌套循环组成的。外层循环标识并决定待比较的数值。内层循环为待比较数值确定其最终位置。直接插入排序是将待比较的数值与它的前一个数值进行比较,所以外层循环是从第二个数值开始的。当前一数值比待比较数值大的情况下继续循环比较,直到找到比待比较数值小的并将待比较数值置入其后一位置,结束该次循环。
过程示例

折半插入排序
折半插入排序是对直接插入排序的简单改进。
此处介绍的折半插入,其实就是通过不断地折半来快速确定第i个元素的插入位置,这实际上是一种查找算法:折半查找。Java的Arrays类里的binarySearch()方法,就是折半查找的实现,用于从指定数组中查找指定元素,前提是该数组已经处于有序状态。
与直接插入排序的效果相同,只是更快了一些,因为折半插入排序可以更快地确定第i个元素的插入位置。
代码:`package com.v512.order;
/**
* 折半插入排序
* @author shkstart
* 2013-11-27
*/

public class BinaryInsertSort {
public static void binaryInsertSort(DataWrap[] data) {
System.out.println(“开始排序”);
int arrayLength = data.length;
for (int i = 1; i < arrayLength; i++) {
DataWrap temp = data[i];
int low = 0;
int high = i - 1;
while (low <= high) {
int mid = (low + high) / 2;//mid为已排序数组的中间元素
if (temp.compareTo(data[mid]) > 0) {
low = mid + 1;
} else {
high = mid - 1;
}
}
for (int j = i; j > low; j–) {
data[j] = data[j - 1];
}
data[low] = temp;
System.out.println(java.util.Arrays.toString(data));
}

}public static void main(String[] args) {    DataWrap[] data = { new DataWrap(9, ""), new DataWrap(-16, ""),            new DataWrap(21, "*"), new DataWrap(23, ""),            new DataWrap(-30, ""), new DataWrap(-49, ""),            new DataWrap(21, ""), new DataWrap(30, "*"),            new DataWrap(30, "")};    System.out.println("排序之前:\n" + java.util.Arrays.toString(data));    binaryInsertSort(data);    System.out.println("排序之后:\n" + java.util.Arrays.toString(data));}

}
`

运行结果:
排序之前:
[9, -16, 21*, 23, -30, -49, 21, 30*, 30]
开始排序
[-16, 9, 21*, 23, -30, -49, 21, 30*, 30]
[-16, 9, 21*, 23, -30, -49, 21, 30*, 30]
[-16, 9, 21*, 23, -30, -49, 21, 30*, 30]
[-30, -16, 9, 21*, 23, -49, 21, 30*, 30]
[-49, -30, -16, 9, 21*, 23, 21, 30*, 30]
[-49, -30, -16, 9, 21, 21*, 23, 30*, 30]
[-49, -30, -16, 9, 21, 21*, 23, 30*, 30]
[-49, -30, -16, 9, 21, 21*, 23, 30, 30*]
排序之后:
[-49, -30, -16, 9, 21, 21*, 23, 30, 30*]

shell排序
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
代码:

package com.v512.order;/** * Shell排序 * @author shkstart * 2013-11-27 */public class ShellSort {    public static void ShellSort(DataWrap[] data) {        System.out.println("开始排序");        int arrayLength = data.length;        int h = 1;        while (h <= arrayLength / 3) {            h = h * 3 + 1;        }        while (h > 0) {            System.out.println("===h的值:" + h + "===");            for (int i = h; i < arrayLength; i++) {                DataWrap temp = data[i];                if (data[i].compareTo(data[i - h]) < 0) {                    int j = i - h;                    for (; j >= 0 && data[j].compareTo(temp) > 0; j -= h) {                        data[j + h] = data[j];                    }                    data[j + h] = temp;                }                System.out.println(java.util.Arrays.toString(data));            }            h = (h - 1) / 3;        }    }    public static void main(String[] args) {        DataWrap[] data = {                 new DataWrap(9, ""), new DataWrap(-16, ""),                new DataWrap(21, "*"), new DataWrap(23, ""),                new DataWrap(-30, ""), new DataWrap(-49, ""),                new DataWrap(21, ""), new DataWrap(30, "*"),                new DataWrap(30, "")};        System.out.println("排序之前:\n" + java.util.Arrays.toString(data));        ShellSort(data);        System.out.println("排序之后:\n" + java.util.Arrays.toString(data));    }}

运行结果:
排序之前:
[9, -16, 21*, 23, -30, -49, 21, 30*, 30]
开始排序
===h的值:4===
[-30, -16, 21*, 23, 9, -49, 21, 30*, 30]
[-30, -49, 21*, 23, 9, -16, 21, 30*, 30]
[-30, -49, 21*, 23, 9, -16, 21, 30*, 30]
[-30, -49, 21*, 23, 9, -16, 21, 30*, 30]
[-30, -49, 21*, 23, 9, -16, 21, 30*, 30]
===h的值:1===
[-49, -30, 21*, 23, 9, -16, 21, 30*, 30]
[-49, -30, 21*, 23, 9, -16, 21, 30*, 30]
[-49, -30, 21*, 23, 9, -16, 21, 30*, 30]
[-49, -30, 9, 21*, 23, -16, 21, 30*, 30]
[-49, -30, -16, 9, 21*, 23, 21, 30*, 30]
[-49, -30, -16, 9, 21*, 21, 23, 30*, 30]
[-49, -30, -16, 9, 21*, 21, 23, 30*, 30]
[-49, -30, -16, 9, 21*, 21, 23, 30*, 30]
排序之后:
[-49, -30, -16, 9, 21*, 21, 23, 30*, 30]

4.归并排序
代码:
归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。
这里写图片描述

package com.v512.order;/** * 归并排序 *  * @author shkstart  * 2013-11-27 */public class MergeSort {    public static void mergeSort(DataWrap[] data) {        // 归并排序        sort(data, 0, data.length - 1);    }    // 将索引从left到right范围的数组元素进行归并排序    private static void sort(DataWrap[] data, int left, int right) {        if(left < right){            //找出中间索引            int center = (left + right)/2;            sort(data,left,center);            sort(data,center+1,right);            //合并            merge(data,left,center,right);        }    }    // 将两个数组进行归并,归并前两个数组已经有序,归并后依然有序    private static void merge(DataWrap[] data, int left, int center, int right) {        DataWrap[] tempArr = new DataWrap[data.length];        int mid = center + 1;        int third = left;        int temp = left;        while (left <= center && mid <= right) {            if (data[left].compareTo(data[mid]) <= 0) {                tempArr[third++] = data[left++];            } else {                tempArr[third++] = data[mid++];            }        }        while (mid <= right) {            tempArr[third++] = data[mid++];        }        while (left <= center) {            tempArr[third++] = data[left++];        }        while (temp <= right) {            data[temp] = tempArr[temp++];        }    }    public static void main(String[] args) {        DataWrap[] data = { new DataWrap(9, ""), new DataWrap(-16, ""),                new DataWrap(21, "*"), new DataWrap(23, ""),                new DataWrap(-30, ""), new DataWrap(-49, ""),                new DataWrap(21, ""), new DataWrap(30, "*"),                new DataWrap(30, "") };        System.out.println("排序之前:\n" + java.util.Arrays.toString(data));        mergeSort(data);        System.out.println("排序之后:\n" + java.util.Arrays.toString(data));    }}

今天先写到这,明天补完!(文中代码有些引自尚硅谷,在此致谢!)

5.桶式排序

6.基数排序

0 0
原创粉丝点击