Java算法-排序-选择排序

昨天写了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 - 1
		for(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>() {
			@Override
			public 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>() {
			@Override
			public int compare(Integer a, Integer b) {
				return a > b ? 1 : (a < b ? -1 : 0);
			}
		});
		long end3 = System.currentTimeMillis();
		System.out.println("堆排序耗时:" + (end3 - start3));
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值