Java算法-排序-选择排序

来源:互联网 发布:matlab编程实例 编辑:程序博客网 时间:2024/05/18 03:20

昨天写了5大排序的交换排序,女朋友给我一个大大的赞,今天一天激情满满。下班了,有时间整理一下另外的排序算法,今晚就写写选择排序吧


二.选择排序(直接选择排序+堆排序)

1.直接选择排序

直接选择排序的核心思想是在无序序列中选择最大(小)值,然后和第一个值进行交换

根据比较类Comparator来判断是升序排列还是降序排列
当Comparator中的compare函数是 a > b ? 1 : (a < b ? -1 : 0)时,则是升序排列
compare函数是a > b ? -1 : (a < b ? 1 : 0)时,则是降序排列

直接选择排序的思路:

①整个数组都是无序区域
②从无序区域的最开始元素开始遍历
③找出无序区域最开始元素后的元素中的最小值
④最小值和无序区域最开始元素交换位置
⑤无序区域最开始元素加入到有序区域
⑥重复①~⑤


时间复杂度:O(n^2)

空间复杂度:O(1)


public static <T> void selectSort(T[] t, Comparator<? super T> comparator) {int size = t == null ? 0 : t.length;T temp = null;for(int i = 0; i < size; i++) {int k = i;for(int j = size - 1; j > i; j--) {if(comparator.compare(t[j], t[k]) < 0) k = j;  // 相当于t[k]总是最小值}// 找出最小值后,和序列开始的值进行交换temp = t[i];t[i] = t[k];t[k] = temp;}}

2.堆排序

根据比较类Comparator类判断是升序序列还是降序序列
若Comparator中的compare函数的返回值是 a > b ? 1 : (a < b ? -1 : 0),则是升序序列
若compare函数的返回值是 a > b ? -1 : (a < b ? 1 : 0),则是降序序列

堆排序的思路:

初始时把n个数的序列看成一棵顺序排列的二叉树,取出堆顶元素,然后再重新组成一棵新的二叉树
1.如何将排序序列组成一棵顺序排列的二叉树,即建立初始堆
①n个节点的完全二叉树,则最后一个节点是(int)n/2个节点的子节点
②从(int)n/2个节点为根的子树开始,使子树成为堆
③依次向前对各节点为根的子树进行筛选,使子树成为堆
④直到根节点为止,就建立了初始堆
2.取出堆顶元素后,二叉树结构已经被破坏,如何重新组成一棵新的顺序排列的二叉树
⑤取出堆顶元素,并将堆底元素送入堆顶(取巧了,将最后一个元素和堆顶元素交换)
⑥将根结点与左、右子树中较小元素的进行交换
⑦若与左子树交换:如果左子树堆被破坏,即左子树的根结点不满足堆的性质,则重复方法⑥
⑧若与右子树交换,如果右子树堆被破坏,即右子树的根结点不满足堆的性质。则重复方法⑥
⑨直到叶子节点为止,堆建成

时间复杂度:O(nlog2n)

空间复杂度:O(1)

public static <T> void heapSort(T[] t, Comparator<? super T> comparator) {int size = t == null ? 0 : t.length;/**********建立初始堆*************/// 最后一个有孩子节点的位置 length / 2 - 1for(int i = (size / 2 - 1); i >= 0; i--) {adjustHeap(t, i, size, comparator);}/**********取出堆顶元素,并重新建立堆************/// 从最后一个元素开始对序列进行调整for(int i = size - 1; i > 0; i--) {//交换堆顶元素t[0]和堆中最后一个元素T temp = t[0];t[0] = t[i];t[i] = temp;// 重新调整堆adjustHeap(t, 0, i, comparator);}}/** * 调整t[position],根据comparator使其成为小(大)顶堆.即将对第position个结点为根的子树筛选 * @param t 待调整的堆数组 * @param position 待调整的数组元素的位置 * @param length 待调整的数组的长度 * @param comparator 比较类 * @date 2017年3月7日 */private static <T> void adjustHeap(T[] t, int position, int length, Comparator<? super T> comparator) {T temp = t[position];   // 记录d待调整数组元素的值,即根节点的值int child = 2 * position + 1;  // 左孩子的位置while(child < length) {// 找出左孩子和右孩子中的较小(大)值if(child + 1 < length && comparator.compare(t[child + 1], t[child]) > 0) {child++;}// 如果左孩子和右孩子中的较小(大)值比根节点小(大),则进行替换if(comparator.compare(t[child], t[position]) > 0) {t[position] = t[child];   // 将较小(大)值和根节点进行交换position = child;         // 重新设置position ,即待调整的下一个结点的位置child = 2 * position + 1; // 重新设置左孩子的位置} else {break;  // 如果当前待调整结点小(大)于它的左右孩子,则不需要调整,直接退出}t[position] = temp;  // 将孩子节点设置成根节点}}

测试程序

disturbOrder(T[] t)请查看java算法-排序-交换排序

public static void main(String[] args) {Integer[] numbers = new Integer[9999];for(int i = 0; i < numbers.length; i++) {numbers[i] = i;}disturbOrder(numbers);long start2 = System.currentTimeMillis();selectSort(numbers, new Comparator<Integer>() {@Overridepublic int compare(Integer a, Integer b) {return a > b ? 1 : (a < b ? -1 : 0);}});long end2 = System.currentTimeMillis();System.out.println("选择排序耗时:" + (end2 - start2));disturbOrder(numbers);long start3 = System.currentTimeMillis();heapSort(numbers, new Comparator<Integer>() {@Overridepublic int compare(Integer a, Integer b) {return a > b ? 1 : (a < b ? -1 : 0);}});long end3 = System.currentTimeMillis();System.out.println("堆排序耗时:" + (end3 - start3));}

2 0
原创粉丝点击