排序算法

衡量排序算法的优劣:

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.基数排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值