《数据结构和Java集合框架第三版》读书笔记(十)简单排序

对数组x进行排序

一,冒泡排序Bubble Sort

不要用冒泡排序,它非常没效率。


每趟排序遵循这样的规则:

1,从最左边开始比较相邻两个元素。

2,如果左边元素小,就交换两个元素的位置。

3,向右移动一个位置,比较相邻两个元素的大小。

这样一直比较到数组最右边。使得最大的元素已经移动到了最右边。

再从左往右开始第二趟排序、第三趟。。。

直到排序完成。


每趟排序需要N-1、N-2、N-3。。。1次比较。总共N(N-1)/2次

交换和比较次数都和N^2成正比,最坏运行时间和平均运行时间都是O(N^2)

二,选择排序Selection Sort

在待排序的数组中,每次选出最小或最大的元素。

用pos来标记最小元素的位置。最初pos指向x[i]。遍历x[i+1]到最后一个元素,每次都将x[pos]和它们进行比较,如果有更小的,pos就指向新的最小值的位置。这样最终找到最小值x[pos],将x[pos]和x[i]交换位置。

public static void selectionSort(int[] x) {
		// Make x [0 . . . i] sorted and <= x [i + 1] . . .x [x.length –1]:
		for (int i = 0; i < x.length - 1; i++) {
			int pos = i;
			for (int k = i + 1; k < x.length; k++)
				if (x[k] < x[pos])
					pos = k;
			swap(x, i, pos);
		} // for i
	} 
选择排序和冒泡排序执行了相同次数的比较N(N-1)/2
选择排序的比较次数是O(N^2),但是交换次数是O(N)。

选择排序比冒泡要快。

三,插入排序

从数组x左边开始,x[1]和x[0]比较,看插入到x[0]之前还是之后。

x[2]和已经排好序的x[0]、x[1]比较,找到x[2]的插入位置。

......

x[i]和已经排好序的x[0]、x[1]、x[2]...x[i-1]比较,找到x[i]的插入位置。

如果用off表示开始插入排序的索引值,用len表示将被排序的元素数量,上述过程可表示为外循环

for(int i=off;i<off+len;i++){

x[i]和已经排好序的x[off]、x[off+1]、...x[i-2]、x[i-1]比较,找到x[i]的插入位置。

}

for循环中的比较过程可用一个内循环表示。x这个内循环从右往左进行,x[i]先和x[i-1]比较,如果x[i]小,则交换x[i]和x[i-1]的位置,x[i]向左移动,再和x[i-2]比较......直到x[i]不小于某元素为止。这样实现了从小到大的排序

for(int j=i;j>off&&x[j]<x[j-1];j--){

swap(x,j,j-1);

}

完整的代码就是:

public static void insertSort(int[] x, int off, int len) {
		for (int i = off; i < off + len; i++) {
			for (int j = i; j > off && x[j] < x[j - 1]; j--) {
				swap(x, j, j - 1);
			}
		}
	}

	private static void swap(int x[], int a, int b) {
		int tmp = x[a];
		x[a] = x[b];
		x[b] = tmp;
	}

插入排序的最坏时间和平均时间是O(n^2),最坏循环次数是n(n-1)/2,但是平均循环次数是n(n-1)/4。插入排序的速度比冒泡要快一倍,比选择要稍快。

在Java集合框架中,插入排序用于元素个数小于7的子数组排序。


上述程序用于比较整数数组。可以改写成对对象进行排序,用comparator比较。

public static void selectionSort (T [ ] x, Comparator comp){
// Make x [0 . . . i] sorted and <= x [i + 1] . . .x [x.length –1]:
	for (int i = 0; i < x.length –1; i++){
		int pos = i;
		for (int k = i + 1; k < x.length; k++)
			if (comp.compare (x [k], x [pos]) < 0)
				pos = k;
		swap (x, i, pos);
	} // for i
} 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值