简单排序:冒泡排序、选择排序和插入排序

package structure;

/**
 * 简单排序的几种方式:冒泡排序、选择排序和插入排序,时间复杂度基本都为O(n*n)<br>
 * 冒泡排序效率最低,选择排序则减少了元素交换的次数,而插入排序是3种方式中效率最高的<br>
 * 特别是当元素基本有序的情况下, 插入排序其平均时间复杂度接近O(n) <br />
 * 
 * 除此之外复杂但更高效的排序方式还有:希尔排序和快速排序
 * 
 * @author yli
 * 
 */
public class SortDemo {

	public static void main(String[] args) {
		// 冒泡排序:升序
		popSortAsc();
		// 冒泡排序:降序
		popSortDesc();

		// 选择排序:升序
		selectedSortAsc();
		// 选择排序:降序
		selectedSortDesc();

		// 插入排序:升序
		insertSortAsc();
		// 插入排序:降序
		insertSortDesc();
	}

	/**
	 * 冒泡排序:升序方式排序<br>
	 * 冒泡排序特点:n个元素需要执行(n-1)次冒泡排序,第i轮冒泡有 (n-1-i)个元素需要两两比较<br>
	 * 并且两两比较,只要满足比较条件,则相邻元素就交换,这其实就是和选择排序最大的区别
	 */
	public static void popSortAsc() {
		int[] a = { 10, 4, 3, 6, 5, 7, 2, 1, 9, 8 };
		int temp;
		// n 个元素,需要执行 n-1 轮冒泡排序
		int popCount = a.length - 1;
		for (int i = 0; i < popCount; i++) {
			// 第i轮冒泡就还有 (n-1-i)个元素需要两两比较
			for (int j = 0; j < popCount - i; j++) {
				if (a[j] > a[j + 1]) {
					// 相邻两个元素比较只要符合条件,那么两个元素就进行交换
					// 并且发现外层循环和内部循环中的元素没有关系
					// 因此外层循环是计算:总共需要执行多少轮冒泡排序
					// 而内部循环是:对剩余还未排序的元素进行一轮冒泡排序
					temp = a[j];
					a[j] = a[j + 1];
					a[j + 1] = temp;
				}
			}
		}

		print(a);
	}

	/**
	 * 冒泡排序:降序方式排序
	 */
	public static void popSortDesc() {
		int[] a = { 10, 4, 3, 6, 5, 7, 2, 1, 9, 8 };
		int temp;
		int popCount = a.length - 1;
		for (int i = 0; i < popCount; i++) {
			for (int j = 0; j < popCount - i; j++) {
				// 升序和降序,只要改变比较方式即可
				if (a[j] < a[j + 1]) {
					temp = a[j];
					a[j] = a[j + 1];
					a[j + 1] = temp;
				}
			}
		}

		print(a);
	}

	/**
	 * 比较排序:升序方式排序<br>
	 * 比较排序特点:和冒泡排序类似,n个元素,需要执行(n-1)轮选择排序<br>
	 * 执行第i轮排序,假设a[i]为最小元素,从剩余的a[i+1]到a[len-1]中记录比a[i]还小的元素的位置<br>
	 * 最后再拿a[i]和a[minIndex]进行交换,和冒泡排序相比,速度更快,因为节省了多次交换的时间<br>
	 * 对于那些交换需要花费更多时间的编程语言来说,选择排序无疑比冒泡排序更优<br>
	 */
	public static void selectedSortAsc() {
		int[] a = { 10, 4, 3, 6, 5, 7, 2, 1, 9, 8 };
		int minIndex;
		int temp;
		for (int i = 0; i < a.length - 1; i++) {
			// 假设a[i]是当前最小元素
			minIndex = i;

			// 从a[i+1]到a[len-1]中选出比a[i]还小的元素
			for (int j = i + 1; j < a.length; j++) {

				// 和冒泡排序相比,只从待排序元素中选出最小元素,并记录其位置
				if (a[minIndex] > a[j]) {
					minIndex = j;
				}
			}
			// 等一轮选择排序执行完之后再交换
			if (i != minIndex) {
				temp = a[i];
				a[i] = a[minIndex];
				a[minIndex] = temp;
			}
		}

		print(a);
	}

	/**
	 * 比较排序:降序方式排序
	 */
	public static void selectedSortDesc() {
		int[] a = { 10, 4, 3, 6, 5, 7, 2, 1, 9, 8 };
		int minIndex;
		int temp;
		for (int i = 0; i < a.length - 1; i++) {
			minIndex = i;
			for (int j = i + 1; j < a.length; j++) {
				if (a[minIndex] < a[j]) {
					minIndex = j;
				}
			}
			if (i != minIndex) {
				temp = a[i];
				a[i] = a[minIndex];
				a[minIndex] = temp;
			}
		}

		print(a);
	}

	/**
	 * 插入排序:升序方式排序<br>
	 * 插入排序的特点:局部有序,待排序的元素在有序的元素中找到一个合适的位置插入<br>
	 * 大约比冒泡排序快1倍,比选择排序略快<br>
	 * 这种排序方式特别适合基本有序的元素排序,其排序速度接近 O(n)<br>
	 * 不过正常情况下,其排序速度也要计算为 O(n*n)
	 * 
	 */
	public static void insertSortAsc() {
		int[] a = { 10, 4, 3, 6, 5, 7, 2, 1, 9, 8 };
		int j;
		int temp;
		// 假设a[0]为局部有序的元素(因为只有一个,所以肯定是有序)
		// 然后从a[1]开始往局部有序的元素中插入新元素
		for (int i = 1; i < a.length; i++) {
			j = i;
			// 第[i]轮排序,要插入的新元素就是 a[i]
			temp = a[i];
			// 然后找到新元素在局部有序元素中的位置
			while (j > 0 && a[j - 1] > temp) {
				a[j] = a[j - 1];
				j--;
			}
			a[j] = temp;
		}

		print(a);
	}

	/**
	 * 插入排序:降序方式排序
	 */
	public static void insertSortDesc() {
		int[] a = { 10, 4, 3, 6, 5, 7, 2, 1, 9, 8 };
		int j;
		int temp;
		for (int i = 1; i < a.length; i++) {
			j = i;
			temp = a[i];
			// 升序和降序,只要改变比较方式即可
			while (j > 0 && a[j - 1] < temp) {
				a[j] = a[j - 1];
				j--;
			}
			a[j] = temp;
		}

		print(a);
	}

	private static void print(int[] arr) {
		for (int temp : arr) {
			System.out.print(temp + "\t");
		}
		System.out.println();
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值